From 21b058cbcca3bbe8956acae10c24061ea010cc9e Mon Sep 17 00:00:00 2001 From: ds58 <30220598+ds58@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:12:36 -0500 Subject: [PATCH] Master branch --- .gitignore | 125 ----- .gitmodules | 3 - LICENSE | 504 ------------------ README.md | 69 --- build.gradle | 88 --- common/build.gradle | 82 --- common/java-cef | 1 - .../main/java/com/cinemamod/mcef/CefUtil.java | 139 ----- .../main/java/com/cinemamod/mcef/MCEF.java | 242 --------- .../main/java/com/cinemamod/mcef/MCEFApp.java | 38 -- .../java/com/cinemamod/mcef/MCEFBrowser.java | 443 --------------- .../java/com/cinemamod/mcef/MCEFClient.java | 149 ------ .../com/cinemamod/mcef/MCEFDownloader.java | 186 ------- .../com/cinemamod/mcef/MCEFDragContext.java | 128 ----- .../java/com/cinemamod/mcef/MCEFPlatform.java | 75 --- .../java/com/cinemamod/mcef/MCEFRenderer.java | 75 --- .../java/com/cinemamod/mcef/MCEFSettings.java | 145 ----- .../java/com/cinemamod/mcef/MIMEUtil.java | 53 -- .../java/com/cinemamod/mcef/ModScheme.java | 138 ----- .../cinemamod/mcef/example/ExampleScreen.java | 156 ------ .../mcef/internal/MCEFDownloadListener.java | 67 --- .../mcef/internal/MCEFDownloaderMenu.java | 135 ----- .../listeners/MCEFCursorChangeListener.java | 26 - .../mcef/listeners/MCEFInitListener.java | 30 -- .../mcef/mixins/CefDownloadMixin.java | 127 ----- .../cinemamod/mcef/mixins/CefInitMixin.java | 48 -- .../mcef/mixins/CefRenderUpdateMixin.java | 39 -- common/src/main/resources/icon.png | Bin 2403 -> 0 bytes common/src/main/resources/mcef.mixins.json | 17 - docs/RELEASE_CHECKLIST.md | 9 - fabric/build.gradle | 164 ------ fabric/gradle.properties | 15 - .../cinemamod/mcef/FabricMCEFClientMod.java | 34 -- .../com/cinemamod/mcef/FabricMCEFMod.java | 30 -- .../mcef/example/MCEFExampleMod.java | 51 -- fabric/src/main/resources/fabric.mod.json | 38 -- gradle.properties | 19 - gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 7 - gradlew | 249 --------- gradlew.bat | 92 ---- neoforge/build.gradle | 136 ----- neoforge/gradle.properties | 16 - .../com/cinemamod/mcef/MCEFInitEvent.java | 43 -- .../com/cinemamod/mcef/NeoForgeMCEFMod.java | 51 -- .../mcef/example/MCEFExampleMod.java | 52 -- .../resources/META-INF/neoforge.mods.toml | 29 - neoforge/src/main/resources/pack.mcmeta | 6 - settings.gradle | 11 - 49 files changed, 4380 deletions(-) delete mode 100644 .gitignore delete mode 100644 .gitmodules delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 build.gradle delete mode 100644 common/build.gradle delete mode 160000 common/java-cef delete mode 100644 common/src/main/java/com/cinemamod/mcef/CefUtil.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEF.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFApp.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFBrowser.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFClient.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFDownloader.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFDragContext.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFPlatform.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFRenderer.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MCEFSettings.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/MIMEUtil.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/ModScheme.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/example/ExampleScreen.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloadListener.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloaderMenu.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/listeners/MCEFCursorChangeListener.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/listeners/MCEFInitListener.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/mixins/CefDownloadMixin.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/mixins/CefInitMixin.java delete mode 100644 common/src/main/java/com/cinemamod/mcef/mixins/CefRenderUpdateMixin.java delete mode 100644 common/src/main/resources/icon.png delete mode 100644 common/src/main/resources/mcef.mixins.json delete mode 100644 docs/RELEASE_CHECKLIST.md delete mode 100644 fabric/build.gradle delete mode 100644 fabric/gradle.properties delete mode 100644 fabric/src/main/java/com/cinemamod/mcef/FabricMCEFClientMod.java delete mode 100644 fabric/src/main/java/com/cinemamod/mcef/FabricMCEFMod.java delete mode 100644 fabric/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java delete mode 100644 fabric/src/main/resources/fabric.mod.json delete mode 100644 gradle.properties delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100755 gradlew delete mode 100644 gradlew.bat delete mode 100644 neoforge/build.gradle delete mode 100644 neoforge/gradle.properties delete mode 100644 neoforge/src/main/java/com/cinemamod/mcef/MCEFInitEvent.java delete mode 100644 neoforge/src/main/java/com/cinemamod/mcef/NeoForgeMCEFMod.java delete mode 100644 neoforge/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java delete mode 100644 neoforge/src/main/resources/META-INF/neoforge.mods.toml delete mode 100644 neoforge/src/main/resources/pack.mcmeta delete mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore deleted file mode 100644 index bd5b18b1..00000000 --- a/.gitignore +++ /dev/null @@ -1,125 +0,0 @@ -# User-specific stuff -.idea/ - -*.iml -*.ipr -*.iws - -# IntelliJ -out/ -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -.gradle -build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Cache of project -.gradletasknamecache - -**/build/ - -# Common working directory -run/ -**/runs/ - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -curseforge_api_key.txt -mod_update_api_key.txt -hangar_api_key.txt - -/neoforge/src/main/resources/natives/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 47528bcf..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "common/java-cef"] - path = common/java-cef - url = https://github.com/CinemaMod/java-cef.git diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8000a6fa..00000000 --- a/LICENSE +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -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 -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random - Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/README.md b/README.md deleted file mode 100644 index 5a5addba..00000000 --- a/README.md +++ /dev/null @@ -1,69 +0,0 @@ -

- MCEF Logo -

- -# MCEF (Minecraft Chromium Embedded Framework) -MCEF is a mod and library for adding the Chromium web browser into Minecraft. - -MCEF is based on java-cef (Java Chromium Embedded Framework), which is based on CEF (Chromium Embedded Framework), which is based on Chromium. It was originally created by montoyo. It was rewritten and currently maintained by the CinemaMod Group. - -MCEF contains a downloader system for downloading the java-cef & CEF binaries required by the Chromium browser. This requires a connection to https://mcef-download.cinemamod.com. - -Discussion: https://discord.gg/rNrh5kW8Ty - -Current Chromium version: `116.0.5845.190` - -## Supported Platforms -- Windows 10/11 (x86_64, arm64)* -- macOS 11 or greater (Intel, Apple Silicon) -- GNU Linux glibc 2.31 or greater (x86_64, arm64)** - -*Some antivirus software may prevent MCEF from initializing. You may have to disable your antivirus or whitelist the mod files for MCEF to work properly. - -**This mod will not work on Android. - -## For Players -This is the source code for MCEF. - -Download the mod for Fabric or NeoForge on either: -- CurseForge: https://www.curseforge.com/minecraft/mc-mods/mcef -- Modrinth: https://modrinth.com/mod/mcef - -## For Modders -MCEF is LGPL, as long as your project doesn't modify or include MCEF source code, you can choose a different license. Read the full license in the LICENSE file in this directory. - -### Using MCEF in Your Project -``` -repositories { - maven { - url = uri('https://mcef-download.cinemamod.com/repositories/releases') - } - // Optional for snapshot versions - maven { - url = uri('https://mcef-download.cinemamod.com/repositories/snapshots') - } -} -``` -#### Fabric -``` -dependencies { - modCompileOnly 'com.cinemamod:mcef:2.1.5-1.21.1' - modRuntimeOnly 'com.cinemamod:mcef-fabric:2.1.5-1.21.1' -} -``` -See the [mcef-fabric-example-mod](https://github.com/CinemaMod/mcef-fabric-example-mod) for a complete example Fabric project. - -#### NeoForge -``` -dependencies { - compileOnly fg.deobf('com.cinemamod:mcef:2.1.5-1.21.1') - runtimeOnly fg.deobf('com.cinemamod:mcef-neoforge:2.1.5-1.21.1') -} -``` -### Building & Modifying MCEF -After cloning this repo, you will need to clone the java-cef git submodule. There is a gradle task for this: `./gradlew cloneJcef`. - -To run the Fabric client: `./gradlew fabricClient` -To run the NeoForge client: `./gradlew neoforgeClient` - -In-game, there is a demo browser if you press F10 after you're loaded into a world (the demo browser only exists when you're running from a development environment). diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 6607693b..00000000 --- a/build.gradle +++ /dev/null @@ -1,88 +0,0 @@ -plugins { - id 'fabric-loom' version "${fabric_loom_version}" apply false -} - -tasks.register('cloneJcef', Exec) { - commandLine 'git', 'submodule', 'update', '--init', '--recursive', 'common/java-cef' -} - -// https://gist.github.com/JonasGroeger/7620911 -def getCheckedOutGitCommitHash(Project mcefParent) { - def gitFolder = "$mcefParent.projectDir/.git/modules/common/java-cef/" - def takeFromHash = 40 - /* - * '.git/HEAD' contains either - * in case of detached head: the currently checked out commit hash - * otherwise: a reference to a file containing the current commit hash - */ - def gitHeadFile = new File(gitFolder + "HEAD"); - if (gitHeadFile.exists()) { - def head = gitHeadFile.text.split(":") // .git/HEAD - def isCommit = head.length == 1 // e5a7c79edabbf7dd39888442df081b1c9d8e88fd - // def isRef = head.length > 1 // ref: refs/heads/master - - if (isCommit) return head[0].trim().take(takeFromHash) // e5a7c79edabb - - def refHead = new File(gitFolder + head[1].trim()) // .git/refs/heads/master - refHead.text.trim().take takeFromHash - } else { - return "" - } -} - -tasks.register('publishMaven', GradleBuild) { - group = 'mcef' - tasks = [ - ':common:publish', - ':fabric:publish', - ':neoforge:publish' - ] -} - -tasks.register('publishCurseforge', GradleBuild) { - group = 'mcef' - tasks = [ - ':common:clean', - ':neoforge:clean', - ':fabric:clean', - ':neoforge:curseforge', - ':fabric:curseforge' - ] -} - -tasks.register('fabricClient', GradleBuild) { - group = 'mcef' - tasks = [ - ':fabric:runClient' - ] -} - -tasks.register('neoforgeClient', GradleBuild) { - group = 'mcef' - tasks = [ - ':neoforge:runClient' - ] -} - -tasks.register('fabricServer', GradleBuild) { - group = 'mcef' - tasks = [ - ':fabric:runServer' - ] -} - -tasks.register('neoforgeServer', GradleBuild) { - group = 'mcef' - tasks = [ - ':neoforge:runServer' - ] -} - -tasks.register('cleanAll', GradleBuild) { - group = 'mcef' - tasks = [ - ':common:clean', - ':fabric:clean', - ':neoforge:clean', - ] -} diff --git a/common/build.gradle b/common/build.gradle deleted file mode 100644 index 40ae1d44..00000000 --- a/common/build.gradle +++ /dev/null @@ -1,82 +0,0 @@ -plugins { - id 'fabric-loom' - id 'maven-publish' -} - -sourceCompatibility = JavaLanguageVersion.of(java_version as int) -targetCompatibility = JavaLanguageVersion.of(java_version as int) - -repositories { - mavenCentral() - maven { url = 'https://maven.fabricmc.net/' } - mavenLocal() - maven { - name = 'ParchmentMC' - url = 'https://maven.parchmentmc.org' - } -} - -/* - Add the following to ~/.gradle/gradle.properties - systemProp.org.gradle.s3.endpoint=https:// - MCEF_S3_PUBLISH_URL_SNAPSHOT=s3:///repositories/snapshots - MCEF_S3_PUBLISH_URL_RELEASE=s3:///repositories/releases - MCEF_S3_PUBLISH_ACCESS_KEY= - MCEF_S3_PUBLISH_SECRET_KEY= - */ -publishing { - repositories { - maven { - url ((mcef_version.toString().endsWith("SNAPSHOT")) ? findProperty('MCEF_S3_PUBLISH_URL_SNAPSHOT') : findProperty('MCEF_S3_PUBLISH_URL_RELEASE')) - credentials(AwsCredentials) { - accessKey = findProperty('MCEF_S3_PUBLISH_ACCESS_KEY') - secretKey = findProperty('MCEF_S3_PUBLISH_SECRET_KEY') - } - } - } - publications { - mavenJava(MavenPublication) { - from components.java - groupId = 'com.cinemamod' - artifactId = 'mcef' - version = mcef_version - } - } -} - -dependencies { - minecraft "com.mojang:minecraft:${minecraft_version}" - mappings loom.layered() { - officialMojangMappings() - parchment("org.parchmentmc.data:parchment-1.21:2024.07.28@zip") - } - modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" -} - -sourceSets { - jcef { - java { - srcDir "java-cef/java" - exclude "**/tests/**" - } - } - - main { - compileClasspath += jcef.output - runtimeClasspath += jcef.output - } -} - -processResources.dependsOn(processJcefResources) - -jar { - from sourceSets.jcef.output.classesDirs - from sourceSets.jcef.output.resourcesDir -} - -idea { - module { - excludeDirs += file("java-cef/java/tests") - inheritOutputDirs true - } -} \ No newline at end of file diff --git a/common/java-cef b/common/java-cef deleted file mode 160000 index d5e3cece..00000000 --- a/common/java-cef +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d5e3cece98755ff1e5af39261e6a486a5d9adb5d diff --git a/common/src/main/java/com/cinemamod/mcef/CefUtil.java b/common/src/main/java/com/cinemamod/mcef/CefUtil.java deleted file mode 100644 index 93ab48bf..00000000 --- a/common/src/main/java/com/cinemamod/mcef/CefUtil.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import net.minecraft.client.Minecraft; -import org.cef.CefApp; -import org.cef.CefClient; -import org.cef.CefSettings; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.PosixFilePermission; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -/** - * This class mostly just interacts with org.cef.* for internal use in {@link MCEF} - */ -final class CefUtil { - private CefUtil() { - } - - private static boolean init; - private static CefApp cefAppInstance; - private static CefClient cefClientInstance; - - private static final Path CACHE_PATH = Minecraft.getInstance().gameDirectory - .toPath() - .resolve("mods") - .resolve("mcef-cache"); - - private static void setUnixExecutable(File file) { - Set perms = new HashSet<>(); - perms.add(PosixFilePermission.OWNER_READ); - perms.add(PosixFilePermission.OWNER_WRITE); - perms.add(PosixFilePermission.OWNER_EXECUTE); - - try { - Files.setPosixFilePermissions(file.toPath(), perms); - } catch (IOException e) { - e.printStackTrace(); - } - } - - static boolean init() { - MCEFPlatform platform = MCEFPlatform.getPlatform(); - - // Ensure binaries are executable - if (platform.isLinux()) { - File jcefHelperFile = new File(System.getProperty("mcef.libraries.path"), platform.getNormalizedName() + "/jcef_helper"); - setUnixExecutable(jcefHelperFile); - } else if (platform.isMacOS()) { - File mcefLibrariesPath = new File(System.getProperty("mcef.libraries.path")); - File jcefHelperFile = new File(mcefLibrariesPath, platform.getNormalizedName() + "/jcef_app.app/Contents/Frameworks/jcef Helper.app/Contents/MacOS/jcef Helper"); - File jcefHelperGPUFile = new File(mcefLibrariesPath, platform.getNormalizedName() + "/jcef_app.app/Contents/Frameworks/jcef Helper (GPU).app/Contents/MacOS/jcef Helper (GPU)"); - File jcefHelperPluginFile = new File(mcefLibrariesPath, platform.getNormalizedName() + "/jcef_app.app/Contents/Frameworks/jcef Helper (Plugin).app/Contents/MacOS/jcef Helper (Plugin)"); - File jcefHelperRendererFile = new File(mcefLibrariesPath, platform.getNormalizedName() + "/jcef_app.app/Contents/Frameworks/jcef Helper (Renderer).app/Contents/MacOS/jcef Helper (Renderer)"); - setUnixExecutable(jcefHelperFile); - setUnixExecutable(jcefHelperGPUFile); - setUnixExecutable(jcefHelperPluginFile); - setUnixExecutable(jcefHelperRendererFile); - } - - String[] cefSwitches = new String[]{ - "--autoplay-policy=no-user-gesture-required", - "--disable-web-security", - "--enable-widevine-cdm" // https://canary.discord.com/channels/985588552735809696/992495232035868682/1151704612924039218 - // TODO: should probably make this configurable - // based off this page: https://magpcss.org/ceforum/viewtopic.php?f=6&t=11672 - // it seems the solution to the white screen is to add the "--disable-gpu" switch - // but that shouldn't be done on all devices, so either we need to figure out a pattern and setup code to add the switch based off that, or add it as a config, if that is the case - }; - - if (!CefApp.startup(cefSwitches)) { - return false; - } - - MCEFSettings settings = MCEF.getSettings(); - - CefSettings cefSettings = new CefSettings(); - cefSettings.windowless_rendering_enabled = true; - if (settings.isUsingCache()) cefSettings.cache_path = CACHE_PATH.toString(); - cefSettings.background_color = cefSettings.new ColorType(0, 255, 255, 255); - // Set the user agent if there's one defined in MCEFSettings - if (!Objects.equals(settings.getUserAgent(), "null")) { - cefSettings.user_agent = settings.getUserAgent(); - } else { - // If there is no custom defined user agent, set a user agent product. - // Work around for Google sign-in "This browser or app may not be secure." - cefSettings.user_agent_product = "MCEF/2"; - } - - cefAppInstance = CefApp.getInstance(cefSwitches, cefSettings); - cefClientInstance = cefAppInstance.createClient(); - - return init = true; - } - - static void shutdown() { - if (isInit()) { - init = false; - cefClientInstance.dispose(); - cefAppInstance.dispose(); - } - } - - static boolean isInit() { - return init; - } - - static CefApp getCefApp() { - return cefAppInstance; - } - - static CefClient getCefClient() { - return cefClientInstance; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEF.java b/common/src/main/java/com/cinemamod/mcef/MCEF.java deleted file mode 100644 index 23b74cfa..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEF.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.cinemamod.mcef.listeners.MCEFInitListener; -import net.minecraft.client.Minecraft; -import org.cef.misc.CefCursorType; -import org.lwjgl.glfw.GLFW; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.*; - -/** - * An API to create Chromium web browsers in Minecraft. Uses - * a modified version of java-cef (Java Chromium Embedded Framework). - */ -public final class MCEF { - public static final Logger LOGGER = LoggerFactory.getLogger("MCEF"); - private static MCEFSettings settings; - private static MCEFApp app; - private static MCEFClient client; - - private static final ArrayList awaitingInit = new ArrayList<>(); - - public static void scheduleForInit(MCEFInitListener task) { - awaitingInit.add(task); - } - - public static Logger getLogger() { - return LOGGER; - } - - /** - * Get access to various settings for MCEF. - * @return Returns the existing {@link MCEFSettings} or creates a new {@link MCEFSettings} and loads from disk (blocking) - */ - public static MCEFSettings getSettings() { - if (settings == null) { - settings = new MCEFSettings(); - try { - settings.load(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return settings; - } - - /** - * This gets called by {@link com.cinemamod.mcef.mixins.CefInitMixin}. - * This should not be called by anything else. - */ - public static boolean initialize() { - MCEF.getLogger().info("Initializing CEF on " + MCEFPlatform.getPlatform().getNormalizedName() + "..."); - if (CefUtil.init()) { - app = new MCEFApp(CefUtil.getCefApp()); - client = new MCEFClient(CefUtil.getCefClient()); - - awaitingInit.forEach(t -> t.onInit(true)); - awaitingInit.clear(); - MCEF.getLogger().info("Chromium Embedded Framework initialized"); - - app.getHandle().registerSchemeHandlerFactory( - "mod", "", - (browser, frame, url, request) -> new ModScheme(request.getURL()) - ); - - // Handle shutdown events, macOS is special - // These are important; the jcef process will linger around if not done - MCEFPlatform platform = MCEFPlatform.getPlatform(); - if (platform.isLinux() || platform.isWindows()) { - Runtime.getRuntime().addShutdownHook(new Thread(MCEF::shutdown, "MCEF-Shutdown")); - } else if (platform.isMacOS()) { - CefUtil.getCefApp().macOSTerminationRequestRunnable = () -> { - shutdown(); - Minecraft.getInstance().stop(); - }; - } - - return true; - } - awaitingInit.forEach(t -> t.onInit(false)); - awaitingInit.clear(); - MCEF.getLogger().info("Could not initialize Chromium Embedded Framework"); - shutdown(); - return false; - } - - /** - * Will assert that MCEF has been initialized; throws a {@link RuntimeException} if not. - * @return the {@link MCEFApp} instance - */ - public static MCEFApp getApp() { - assertInitialized(); - return app; - } - - /** - * Will assert that MCEF has been initialized; throws a {@link RuntimeException} if not. - * @return the {@link MCEFClient} instance - */ - public static MCEFClient getClient() { - assertInitialized(); - return client; - } - - /** - * Will assert that MCEF has been initialized; throws a {@link RuntimeException} if not. - * Creates a new Chromium web browser with some starting URL. Can set it to be transparent rendering. - * @return the {@link MCEFBrowser} web browser instance - */ - public static MCEFBrowser createBrowser(String url, boolean transparent) { - assertInitialized(); - MCEFBrowser browser = new MCEFBrowser(client, url, transparent); - browser.setCloseAllowed(); - browser.createImmediately(); - return browser; - } - - /** - * Will assert that MCEF has been initialized; throws a {@link RuntimeException} if not. - * Creates a new Chromium web browser with some starting URL, width, and height. - * Can set it to be transparent rendering. - * @return the {@link MCEFBrowser} web browser instance - */ - public static MCEFBrowser createBrowser(String url, boolean transparent, int width, int height) { - assertInitialized(); - MCEFBrowser browser = new MCEFBrowser(client, url, transparent); - browser.setCloseAllowed(); - browser.createImmediately(); - browser.resize(width, height); - return browser; - } - - /** - * Check if MCEF is initialized. - * @return true if MCEF is initialized correctly, false if not - */ - public static boolean isInitialized() { - return client != null; - } - - /** - * Request a shutdown of MCEF/CEF. Nothing will happen if not initialized. - */ - public static void shutdown() { - if (isInitialized()) { - CefUtil.shutdown(); - client = null; - app = null; - } - } - - /** - * Check if MCEF has been initialized, throws a {@link RuntimeException} if not. - */ - private static void assertInitialized() { - if (!isInitialized()) - throw new RuntimeException("Chromium Embedded Framework was never initialized."); - } - - /** - * Get the git commit hash of the java-cef code (either from MANIFEST.MF or from the git repo on-disk if in a - * development environment). Used for downloading the java-cef release. - * @return The git commit hash of java-cef - * @throws IOException - */ - public static String getJavaCefCommit() throws IOException { - // First check system property - if (System.getProperty("mcef.java.cef.commit") != null) { - return System.getProperty("mcef.java.cef.commit"); - } - - // Try to get from resources (if loading from a jar) - Enumeration resources = MCEF.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); - Map commits = new HashMap<>(1); - resources.asIterator().forEachRemaining(resource -> { - Properties properties = new Properties(); - try { - properties.load(resource.openStream()); - if (properties.containsKey("java-cef-commit")) { - commits.put(resource.getFile(), properties.getProperty("java-cef-commit")); - } - } catch (IOException e) { - e.printStackTrace(); - } - }); - - if (!commits.isEmpty()) { - return commits.get(commits.keySet().stream().toList().get(0)); - } - - // Try to get from the git submodule (if loading from development environment) - ProcessBuilder processBuilder = new ProcessBuilder("git", "submodule", "status", "common/java-cef"); - processBuilder.directory(new File("../../")); - Process process = processBuilder.start(); - - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - String[] parts = line.trim().split(" "); - return parts[0].replace("+", ""); - } - - return null; - } - - /** - * Helper method to get a GLFW cursor handle for the given {@link CefCursorType} cursor type - */ - static long getGLFWCursorHandle(CefCursorType cursorType) { - if (CEF_TO_GLFW_CURSORS.containsKey(cursorType)) return CEF_TO_GLFW_CURSORS.get(cursorType); - long glfwCursorHandle = GLFW.glfwCreateStandardCursor(cursorType.glfwId); - CEF_TO_GLFW_CURSORS.put(cursorType, glfwCursorHandle); - return glfwCursorHandle; - } - private static final HashMap CEF_TO_GLFW_CURSORS = new HashMap<>(); -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFApp.java b/common/src/main/java/com/cinemamod/mcef/MCEFApp.java deleted file mode 100644 index e613f907..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFApp.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import org.cef.CefApp; - -/** - * A wrapper around {@link CefApp} - */ -public class MCEFApp { - private final CefApp handle; - - public MCEFApp(CefApp handle) { - this.handle = handle; - } - - public CefApp getHandle() { - return handle; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFBrowser.java b/common/src/main/java/com/cinemamod/mcef/MCEFBrowser.java deleted file mode 100644 index 8bfce0e8..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFBrowser.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.cinemamod.mcef.listeners.MCEFCursorChangeListener; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.Minecraft; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefBrowserOsr; -import org.cef.callback.CefDragData; -import org.cef.event.CefKeyEvent; -import org.cef.event.CefMouseEvent; -import org.cef.event.CefMouseWheelEvent; -import org.cef.misc.CefCursorType; -import org.lwjgl.glfw.GLFW; - -import java.awt.*; -import java.nio.ByteBuffer; - -import static org.lwjgl.glfw.GLFW.*; -import static org.lwjgl.opengl.GL11.*; - -/** - * An instance of an "Off-screen rendered" Chromium web browser. - * Complete with a renderer, keyboard and mouse inputs, optional - * browser control shortcuts, cursor handling, drag & drop support. - */ -public class MCEFBrowser extends CefBrowserOsr { - /** - * The renderer for the browser. - */ - private final MCEFRenderer renderer; - /** - * Stores information about drag & drop. - */ - private final MCEFDragContext dragContext = new MCEFDragContext(); - /** - * A listener that defines that happens when a cursor changes in the browser. - * E.g. when you've hovered over a button, an input box, are selecting text, etc... - * A default listener is created in the constructor that sets the cursor type to - * the appropriate cursor based on the event. - */ - private MCEFCursorChangeListener cursorChangeListener; - /** - * Whether MCEF should mimic the controls of a typical web browser. - * E.g. CTRL+R for reload, CTRL+Left for back, CTRL+Right for forward, etc... - */ - private boolean browserControls = true; - /** - * Used to track when a full repaint should occur. - */ - private int lastWidth = 0, lastHeight = 0; - /** - * A bitset representing what mouse buttons are currently pressed. - * CEF is a bit odd and implements mouse buttons as a part of modifier flags. - */ - private int btnMask = 0; - - // Data relating to popups and graphics - // Marked as protected in-case a mod wants to extend MCEFBrowser and override the repaint logic - protected ByteBuffer graphics; - protected ByteBuffer popupGraphics; - protected Rectangle popupSize; - protected boolean showPopup = false; - protected boolean popupDrawn = false; - - public MCEFBrowser(MCEFClient client, String url, boolean transparent) { - super(client.getHandle(), url, transparent, null); - renderer = new MCEFRenderer(transparent); - cursorChangeListener = (cefCursorID) -> setCursor(CefCursorType.fromId(cefCursorID)); - - Minecraft.getInstance().submit(renderer::initialize); - } - - public MCEFRenderer getRenderer() { - return renderer; - } - - public MCEFCursorChangeListener getCursorChangeListener() { - return cursorChangeListener; - } - - public void setCursorChangeListener(MCEFCursorChangeListener cursorChangeListener) { - this.cursorChangeListener = cursorChangeListener; - } - - public boolean usingBrowserControls() { - return browserControls; - } - - /** - * Enabling browser controls tells MCEF to mimic the behavior of an actual browser. - * CTRL+R for reload, CTRL+Left for back, CTRL+Right for forward, etc... - * - * @param browserControls whether browser controls should be enabled - * @return the browser instance - */ - public MCEFBrowser useBrowserControls(boolean browserControls) { - this.browserControls = browserControls; - return this; - } - - public MCEFDragContext getDragContext() { - return dragContext; - } - - // Popups - @Override - public void onPopupShow(CefBrowser browser, boolean show) { - super.onPopupShow(browser, show); - showPopup = show; - if (!show) { - Minecraft.getInstance().submit(() -> { - onPaint(browser, false, new Rectangle[]{popupSize}, graphics, lastWidth, lastHeight); - }); - popupSize = null; - popupDrawn = false; - popupGraphics = null; - } - } - - @Override - public void onPopupSize(CefBrowser browser, Rectangle size) { - super.onPopupSize(browser, size); - popupSize = size; - this.popupGraphics = ByteBuffer.allocateDirect( - size.width * size.height * 4 - ); - } - - /** - * Draws any existing popup menu to the browser's graphics - */ - protected void drawPopup() { - if (showPopup && popupSize != null && popupDrawn) { - RenderSystem.bindTexture(renderer.getTextureID()); - if (renderer.isTransparent()) RenderSystem.enableBlend(); - - RenderSystem.pixelStore(GL_UNPACK_ROW_LENGTH, popupSize.width); - GlStateManager._pixelStore(GL_UNPACK_SKIP_PIXELS, 0); - GlStateManager._pixelStore(GL_UNPACK_SKIP_ROWS, 0); - renderer.onPaint(this.popupGraphics, popupSize.x, popupSize.y, popupSize.width, popupSize.height); - } - } - - /** - * Copies data within a rectangle from one buffer to another - * Used by repaint logic - * - * @param srcBuffer the buffer to copy from - * @param dstBuffer the buffer to copy to - * @param dirty the rectangle that needs to be updated - * @param width the width of the browser - * @param height the height of the browser - */ - public static void store(ByteBuffer srcBuffer, ByteBuffer dstBuffer, Rectangle dirty, int width, int height) { - for (int y = dirty.y; y < dirty.height + dirty.y; y++) { - dstBuffer.position((y * width + dirty.x) * 4); - srcBuffer.position((y * width + dirty.x) * 4); - srcBuffer.limit(dirty.width * 4 + (y * width + dirty.x) * 4); - dstBuffer.put(srcBuffer); - srcBuffer.position(0).limit(srcBuffer.capacity()); - } - dstBuffer.position(0).limit(dstBuffer.capacity()); - } - - // Graphics - @Override - public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { - if (!popup && (width != lastWidth || height != lastHeight)) { - // Copy buffer - graphics = ByteBuffer.allocateDirect(buffer.capacity()); - graphics.position(0).limit(graphics.capacity()); - graphics.put(buffer); - graphics.position(0); - buffer.position(0); - - // Draw - renderer.onPaint(buffer, width, height); - lastWidth = width; - lastHeight = height; - } else { - // Don't update graphics if the renderer is not initialized - if (renderer.getTextureID() == 0) return; - - // Update sub-rects - if (!popup) { - // Graphics will be updated later if it's a popup - RenderSystem.bindTexture(renderer.getTextureID()); - if (renderer.isTransparent()) RenderSystem.enableBlend(); - RenderSystem.pixelStore(GL_UNPACK_ROW_LENGTH, width); - } else popupDrawn = true; - - for (Rectangle dirtyRect : dirtyRects) { - // Check that the popup isn't being cleared from the image - if (buffer != graphics) - // Due to how CEF handles popups, the graphics of the popup and the graphics of the browser itself need to be stored separately - store(buffer, popup ? popupGraphics : graphics, dirtyRect, width, height); - - // Graphics will be updated later if it's a popup - if (!popup) { - // Upload to the GPU - GlStateManager._pixelStore(GL_UNPACK_SKIP_PIXELS, dirtyRect.x); - GlStateManager._pixelStore(GL_UNPACK_SKIP_ROWS, dirtyRect.y); - renderer.onPaint(buffer, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height); - } - } - } - - // Upload popup to GPU, must be fully drawn every time paint is called - drawPopup(); - } - - public void resize(int width, int height) { - browser_rect_.setBounds(0, 0, width, height); - wasResized(width, height); - } - - // Inputs - public void sendKeyPress(int keyCode, long scanCode, int modifiers) { - if (browserControls) { - if (modifiers == GLFW_MOD_CONTROL) { - if (keyCode == GLFW_KEY_R) { - reload(); - return; - } else if (keyCode == GLFW_KEY_EQUAL) { - if (getZoomLevel() < 9) setZoomLevel(getZoomLevel() + 1); - return; - } else if (keyCode == GLFW_KEY_MINUS) { - if (getZoomLevel() > -9) setZoomLevel(getZoomLevel() - 1); - return; - } else if (keyCode == GLFW_KEY_0) { - setZoomLevel(0); - return; - } - } else if (modifiers == GLFW_MOD_ALT) { - if (keyCode == GLFW_KEY_LEFT && canGoBack()) { - goBack(); - return; - } else if (keyCode == GLFW_KEY_RIGHT && canGoForward()) { - goForward(); - return; - } - } - } - - CefKeyEvent e = new CefKeyEvent(CefKeyEvent.KEY_PRESS, keyCode, (char) keyCode, modifiers); - e.scancode = scanCode; - sendKeyEvent(e); - } - - public void sendKeyRelease(int keyCode, long scanCode, int modifiers) { - if (browserControls) { - if (modifiers == GLFW_MOD_CONTROL) { - if (keyCode == GLFW_KEY_R) return; - else if (keyCode == GLFW_KEY_EQUAL) return; - else if (keyCode == GLFW_KEY_MINUS) return; - else if (keyCode == GLFW_KEY_0) return; - } else if (modifiers == GLFW_MOD_ALT) { - if (keyCode == GLFW_KEY_LEFT && canGoBack()) return; - else if (keyCode == GLFW_KEY_RIGHT && canGoForward()) return; - } - } - - CefKeyEvent e = new CefKeyEvent(CefKeyEvent.KEY_RELEASE, keyCode, (char) keyCode, modifiers); - e.scancode = scanCode; - sendKeyEvent(e); - } - - public void sendKeyTyped(char c, int modifiers) { - if (browserControls) { - if (modifiers == GLFW_MOD_CONTROL) { - if ((int) c == GLFW_KEY_R) return; - else if ((int) c == GLFW_KEY_EQUAL) return; - else if ((int) c == GLFW_KEY_MINUS) return; - else if ((int) c == GLFW_KEY_0) return; - } else if (modifiers == GLFW_MOD_ALT) { - if ((int) c == GLFW_KEY_LEFT && canGoBack()) return; - else if ((int) c == GLFW_KEY_RIGHT && canGoForward()) return; - } - } - - CefKeyEvent e = new CefKeyEvent(CefKeyEvent.KEY_TYPE, c, c, modifiers); - sendKeyEvent(e); - } - - public void sendMouseMove(int mouseX, int mouseY) { - CefMouseEvent e = new CefMouseEvent(CefMouseEvent.MOUSE_MOVED, mouseX, mouseY, 0, 0, dragContext.getVirtualModifiers(btnMask)); - sendMouseEvent(e); - - if (dragContext.isDragging()) - this.dragTargetDragOver(new Point(mouseX, mouseY), 0, dragContext.getMask()); - } - - // TODO: it may be necessary to add modifiers here - public void sendMousePress(int mouseX, int mouseY, int button) { - // for some reason, middle and right are swapped in MC - if (button == 1) button = 2; - else if (button == 2) button = 1; - - if (button == 0) btnMask |= CefMouseEvent.BUTTON1_MASK; - else if (button == 1) btnMask |= CefMouseEvent.BUTTON2_MASK; - else if (button == 2) btnMask |= CefMouseEvent.BUTTON3_MASK; - - CefMouseEvent e = new CefMouseEvent(GLFW_PRESS, mouseX, mouseY, 1, button, btnMask); - sendMouseEvent(e); - } - - // TODO: it may be necessary to add modifiers here - public void sendMouseRelease(int mouseX, int mouseY, int button) { - // For some reason, middle and right are swapped in MC - if (button == 1) button = 2; - else if (button == 2) button = 1; - - if (button == 0 && (btnMask & CefMouseEvent.BUTTON1_MASK) != 0) btnMask ^= CefMouseEvent.BUTTON1_MASK; - else if (button == 1 && (btnMask & CefMouseEvent.BUTTON2_MASK) != 0) btnMask ^= CefMouseEvent.BUTTON2_MASK; - else if (button == 2 && (btnMask & CefMouseEvent.BUTTON3_MASK) != 0) btnMask ^= CefMouseEvent.BUTTON3_MASK; - - CefMouseEvent e = new CefMouseEvent(GLFW_RELEASE, mouseX, mouseY, 1, button, btnMask); - sendMouseEvent(e); - - // drag&drop - if (dragContext.isDragging()) { - if (button == 0) { - finishDragging(mouseX, mouseY); - } - } - } - - // TODO: smooth scrolling - public void sendMouseWheel(int mouseX, int mouseY, double amount, int modifiers) { - if (browserControls) { - if ((modifiers & GLFW_MOD_CONTROL) != 0) { - if (amount > 0) { - if (getZoomLevel() < 9) setZoomLevel(getZoomLevel() + 1); - } else if (getZoomLevel() > -9) setZoomLevel(getZoomLevel() - 1); - return; - } - } - - // macOS generally has a slow scroll speed that feels more natural with their magic mice / trackpads - if (!MCEFPlatform.getPlatform().isMacOS()) { - // This removes the feeling of "smooth scroll" - if (amount < 0) { - amount = Math.floor(amount); - } else { - amount = Math.ceil(amount); - } - - // This feels about equivalent to chromium with smooth scrolling disabled -ds58 - amount = amount * 3; - } - - CefMouseWheelEvent e = new CefMouseWheelEvent(CefMouseWheelEvent.WHEEL_UNIT_SCROLL, mouseX, mouseY, amount, modifiers); - sendMouseWheelEvent(e); - } - - // Drag & drop - @Override - public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { - dragContext.startDragging(dragData, mask); - this.dragTargetDragEnter(dragContext.getDragData(), new Point(x, y), btnMask, dragContext.getMask()); - // Indicates to CEF to not handle the drag event natively - // reason: native drag handling doesn't work with off screen rendering - return false; - } - - @Override - public void updateDragCursor(CefBrowser browser, int operation) { - if (dragContext.updateCursor(operation)) - // If the cursor to display for the drag event changes, then update the cursor - this.onCursorChange(this, dragContext.getVirtualCursor(dragContext.getActualCursor())); - - super.updateDragCursor(browser, operation); - } - - // Expose drag & drop functions - public void startDragging(CefDragData dragData, int mask, int x, int y) { // Overload since the JCEF method requires a browser, which then goes unused - startDragging(dragData, mask, x, y); - } - - public void finishDragging(int x, int y) { - dragTargetDrop(new Point(x, y), btnMask); - dragTargetDragLeave(); - dragContext.stopDragging(); - this.onCursorChange(this, dragContext.getActualCursor()); - } - - public void cancelDrag() { - dragTargetDragLeave(); - dragContext.stopDragging(); - this.onCursorChange(this, dragContext.getActualCursor()); - } - - // Closing - public void close() { - renderer.cleanup(); - cursorChangeListener.onCursorChange(0); - super.close(true); - } - - @Override - protected void finalize() throws Throwable { - Minecraft.getInstance().submit(renderer::cleanup); - super.finalize(); - } - - // Cursor handling - @Override - public boolean onCursorChange(CefBrowser browser, int cursorType) { - cursorType = dragContext.getVirtualCursor(cursorType); - cursorChangeListener.onCursorChange(cursorType); - return super.onCursorChange(browser, cursorType); - } - - public void setCursor(CefCursorType cursorType) { - if (cursorType == CefCursorType.NONE) { - GLFW.glfwSetInputMode(Minecraft.getInstance().getWindow().getWindow(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } else { - GLFW.glfwSetInputMode(Minecraft.getInstance().getWindow().getWindow(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); - GLFW.glfwSetCursor(Minecraft.getInstance().getWindow().getWindow(), MCEF.getGLFWCursorHandle(cursorType)); - } - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFClient.java b/common/src/main/java/com/cinemamod/mcef/MCEFClient.java deleted file mode 100644 index de31702d..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFClient.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import org.cef.CefClient; -import org.cef.CefSettings; -import org.cef.browser.CefBrowser; -import org.cef.browser.CefFrame; -import org.cef.callback.CefContextMenuParams; -import org.cef.callback.CefMenuModel; -import org.cef.handler.CefContextMenuHandler; -import org.cef.handler.CefDisplayHandler; -import org.cef.handler.CefLoadHandler; -import org.cef.network.CefRequest; - -import java.util.ArrayList; -import java.util.List; - -/** - * A wrapper around {@link CefClient} - */ -public class MCEFClient implements CefLoadHandler, CefContextMenuHandler, CefDisplayHandler { - private final CefClient handle; - private final List loadHandlers = new ArrayList<>(); - private final List contextMenuHandlers = new ArrayList<>(); - private final List displayHandlers = new ArrayList<>(); - - public MCEFClient(CefClient cefClient) { - handle = cefClient; - cefClient.addLoadHandler(this); - cefClient.addContextMenuHandler(this); - cefClient.addDisplayHandler(this); - } - - public CefClient getHandle() { - return handle; - } - - public void addLoadHandler(CefLoadHandler handler) { - loadHandlers.add(handler); - } - - @Override - public void onLoadingStateChange(CefBrowser browser, boolean isLoading, boolean canGoBack, boolean canGoForward) { - for (CefLoadHandler loadHandler : loadHandlers) - loadHandler.onLoadingStateChange(browser, isLoading, canGoBack, canGoForward); - } - - @Override - public void onLoadStart(CefBrowser browser, CefFrame frame, CefRequest.TransitionType transitionType) { - for (CefLoadHandler loadHandler : loadHandlers) loadHandler.onLoadStart(browser, frame, transitionType); - } - - @Override - public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) { - for (CefLoadHandler loadHandler : loadHandlers) loadHandler.onLoadEnd(browser, frame, httpStatusCode); - } - - @Override - public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, String errorText, String failedUrl) { - for (CefLoadHandler loadHandler : loadHandlers) - loadHandler.onLoadError(browser, frame, errorCode, errorText, failedUrl); - } - - public void addContextMenuHandler(CefContextMenuHandler handler) { - contextMenuHandlers.add(handler); - } - - @Override - public void onBeforeContextMenu(CefBrowser browser, CefFrame frame, CefContextMenuParams params, CefMenuModel model) { - for (CefContextMenuHandler contextMenuHandler : contextMenuHandlers) - contextMenuHandler.onBeforeContextMenu(browser, frame, params, model); - } - - @Override - public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, CefContextMenuParams params, int commandId, int eventFlags) { - for (CefContextMenuHandler contextMenuHandler : contextMenuHandlers) - if (contextMenuHandler.onContextMenuCommand(browser, frame, params, commandId, eventFlags)) - return true; - return false; - } - - @Override - public void onContextMenuDismissed(CefBrowser browser, CefFrame frame) { - for (CefContextMenuHandler contextMenuHandler : contextMenuHandlers) - contextMenuHandler.onContextMenuDismissed(browser, frame); - } - - public void addDisplayHandler(CefDisplayHandler handler) { - displayHandlers.add(handler); - } - - @Override - public void onAddressChange(CefBrowser browser, CefFrame frame, String url) { - for (CefDisplayHandler displayHandler : displayHandlers) displayHandler.onAddressChange(browser, frame, url); - } - - @Override - public void onTitleChange(CefBrowser browser, String title) { - for (CefDisplayHandler displayHandler : displayHandlers) displayHandler.onTitleChange(browser, title); - } - - @Override - public boolean onTooltip(CefBrowser browser, String text) { - for (CefDisplayHandler displayHandler : displayHandlers) - if (displayHandler.onTooltip(browser, text)) - return true; - return false; - } - - @Override - public void onStatusMessage(CefBrowser browser, String value) { - for (CefDisplayHandler displayHandler : displayHandlers) displayHandler.onStatusMessage(browser, value); - } - - @Override - public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level, String message, String source, int line) { - for (CefDisplayHandler displayHandler : displayHandlers) - if (displayHandler.onConsoleMessage(browser, level, message, source, line)) - return true; - return false; - } - - @Override - public boolean onCursorChange(CefBrowser browser, int cursorType) { - for (CefDisplayHandler displayHandler : displayHandlers) - if (displayHandler.onCursorChange(browser, cursorType)) - return true; - return false; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFDownloader.java b/common/src/main/java/com/cinemamod/mcef/MCEFDownloader.java deleted file mode 100644 index 7e6a934f..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFDownloader.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.cinemamod.mcef.internal.MCEFDownloadListener; -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; -import org.apache.commons.io.FileUtils; - -import java.io.*; -import java.net.HttpURLConnection; -import java.net.URL; - -/** - * A downloader and extraction tool for java-cef builds. - *

- * Downloads for CinemaMod java-cef are provided by the CinemaMod Group unless changed - * in the MCEFSettings properties file; see {@link MCEFSettings}. - * Email ds58@mailbox.org for any questions or concerns regarding the file hosting. - */ -public class MCEFDownloader { - private static final String JAVA_CEF_DOWNLOAD_URL = "${host}/java-cef-builds/${java-cef-commit}/${platform}.tar.gz"; - private static final String JAVA_CEF_CHECKSUM_DOWNLOAD_URL = "${host}/java-cef-builds/${java-cef-commit}/${platform}.tar.gz.sha256"; - - private final String host; - private final String javaCefCommitHash; - private final MCEFPlatform platform; - - public MCEFDownloader(String host, String javaCefCommitHash, MCEFPlatform platform) { - this.host = host; - this.javaCefCommitHash = javaCefCommitHash; - this.platform = platform; - } - - public String getHost() { - return host; - } - - public String getJavaCefDownloadUrl() { - return formatURL(JAVA_CEF_DOWNLOAD_URL); - } - - public String getJavaCefChecksumDownloadUrl() { - return formatURL(JAVA_CEF_CHECKSUM_DOWNLOAD_URL); - } - - private String formatURL(String url) { - return url - .replace("${host}", host) - .replace("${java-cef-commit}", javaCefCommitHash) - .replace("${platform}", platform.getNormalizedName()); - } - - public void downloadJavaCefBuild() throws IOException { - File mcefLibrariesPath = new File(System.getProperty("mcef.libraries.path")); - MCEFDownloadListener.INSTANCE.setTask("Downloading Chromium Embedded Framework"); - downloadFile(getJavaCefDownloadUrl(), new File(mcefLibrariesPath, platform.getNormalizedName() + ".tar.gz")); - } - - /** - * @return true if the jcef build checksum file matches the remote checksum file (for the {@link MCEFDownloader#javaCefCommitHash}), - * false if the jcef build checksum file did not exist or did not match; this means we should redownload JCEF - * @throws IOException - */ - public boolean downloadJavaCefChecksum() throws IOException { - File mcefLibrariesPath = new File(System.getProperty("mcef.libraries.path")); - File jcefBuildHashFileTemp = new File(mcefLibrariesPath, platform.getNormalizedName() + ".tar.gz.sha256.temp"); - File jcefBuildHashFile = new File(mcefLibrariesPath, platform.getNormalizedName() + ".tar.gz.sha256"); - - MCEFDownloadListener.INSTANCE.setTask("Downloading Checksum"); - downloadFile(getJavaCefChecksumDownloadUrl(), jcefBuildHashFileTemp); - - if (jcefBuildHashFile.exists()) { - boolean sameContent = FileUtils.contentEquals(jcefBuildHashFile, jcefBuildHashFileTemp); - if (sameContent) { - jcefBuildHashFileTemp.delete(); - return true; - } - } - - jcefBuildHashFileTemp.renameTo(jcefBuildHashFile); - - return false; - } - - public void extractJavaCefBuild(boolean delete) { - File mcefLibrariesPath = new File(System.getProperty("mcef.libraries.path")); - File tarGzArchive = new File(mcefLibrariesPath, platform.getNormalizedName() + ".tar.gz"); - extractTarGz(tarGzArchive, mcefLibrariesPath); - if (delete) { - if (tarGzArchive.exists()) { - tarGzArchive.delete(); - } - } - } - - private static void downloadFile(String urlString, File outputFile) throws IOException { - try { - MCEF.getLogger().info(urlString + " -> " + outputFile.getCanonicalPath()); - - URL url = new URL(urlString); - HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); - - if (urlConnection.getResponseCode() != 200) { - throw new IOException(); - } - - int fileSize = urlConnection.getContentLength(); - - BufferedInputStream inputStream = new BufferedInputStream(url.openStream()); - FileOutputStream outputStream = new FileOutputStream(outputFile); - - byte[] buffer = new byte[2048]; - int count; - int readBytes = 0; - while ((count = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, count); - readBytes += count; - float percentComplete = (float) readBytes / fileSize; - MCEFDownloadListener.INSTANCE.setProgress(percentComplete); - buffer = new byte[Math.max(2048, inputStream.available())]; - } - - inputStream.close(); - outputStream.close(); - } catch (IOException e) { - throw new IOException("Failed to download " + urlString); - } - } - - private static void extractTarGz(File tarGzFile, File outputDirectory) { - MCEFDownloadListener.INSTANCE.setTask("Extracting"); - - outputDirectory.mkdirs(); - - long fileSize = tarGzFile.length(); - long totalBytesRead = 0; - - try (TarArchiveInputStream tarInput = new TarArchiveInputStream(new GzipCompressorInputStream(new FileInputStream(tarGzFile)))) { - TarArchiveEntry entry; - while ((entry = tarInput.getNextTarEntry()) != null) { - if (entry.isDirectory()) { - continue; - } - - File outputFile = new File(outputDirectory, entry.getName()); - outputFile.getParentFile().mkdirs(); - - try (OutputStream outputStream = new FileOutputStream(outputFile)) { - byte[] buffer = new byte[4096]; - int bytesRead; - while ((bytesRead = tarInput.read(buffer)) != -1) { - outputStream.write(buffer, 0, bytesRead); - totalBytesRead += bytesRead; - float percentComplete = (((float) totalBytesRead / fileSize) / 2.6158204f); // Roughly the compression ratio - MCEFDownloadListener.INSTANCE.setProgress(percentComplete); - buffer = new byte[Math.max(4096, tarInput.available())]; - } - } - } - } catch (IOException e) { - e.printStackTrace(); - } - - MCEFDownloadListener.INSTANCE.setProgress(1.0f); - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFDragContext.java b/common/src/main/java/com/cinemamod/mcef/MCEFDragContext.java deleted file mode 100644 index 3bd30b94..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFDragContext.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import org.cef.callback.CefDragData; -import org.cef.misc.CefCursorType; - -public class MCEFDragContext { - private CefDragData dragData = null; - private int dragMask = 0; - private int cursorOverride = -1; - private int actualCursor = -1; - - /** - * Used to prevent re-selecting stuff while dragging - * If the user is dragging, emulate having no buttons pressed - * - * @param btnMask the actual mask - * @return a mask modified based on if the user is dragging - */ - public int getVirtualModifiers(int btnMask) { - return dragData != null ? 0 : btnMask; - } - - /** - * When the user is dragging, the browser-set cursor shouldn't be used - * Instead the cursor should change based on what action would be performed when they release at the given location - * However, the browser-set cursor also needs to be tracked, so this handles that as well - * - * @param cursorType the actual cursor type (should be the result of {@link MCEFDragContext#getActualCursor()} if you're just trying to see the current cursor) - * @return the drag operation modified cursor if dragging, or the actual cursor if not - */ - public int getVirtualCursor(int cursorType) { - actualCursor = cursorType; - if (cursorOverride != -1) cursorType = cursorOverride; - return cursorType; - } - - /** - * Checks if a drag operation is currently happening - * - * @return true if the user is dragging, elsewise false - */ - public boolean isDragging() { - return dragData != null; - } - - /** - * Gets the {@link CefDragData} of the current drag operation - * - * @return the current drag operation's data - */ - public CefDragData getDragData() { - return dragData; - } - - /** - * Gets the allowed operation mask for this drag event - * - * @return -1 for any, 0 for none, 1 for copy (TODO: others) - */ - public int getMask() { - return dragMask; - } - - /** - * Gets the browser-set cursor - * - * @return the cursor that has been set by the browser, disregarding drag operations - */ - public int getActualCursor() { - return actualCursor; - } - - public void startDragging(CefDragData dragData, int mask) { - this.dragData = dragData; - this.dragMask = mask; - } - - public void stopDragging() { - dragData.dispose(); - dragData = null; - dragMask = 0; - cursorOverride = -1; - } - - public boolean updateCursor(int operation) { - if (dragData == null) return false; - - int currentOverride = cursorOverride; - - switch (operation) { - case 0: - cursorOverride = CefCursorType.NO_DROP.ordinal(); - break; - case 1: - cursorOverride = CefCursorType.COPY.ordinal(); - break; - // TODO: this is a guess, based off https://magpcss.org/ceforum/apidocs3/projects/(default)/cef_drag_operations_mask_t.html - // not sure if it's correct - case 16: - cursorOverride = CefCursorType.MOVE.ordinal(); - break; - default: // TODO: I'm not sure of the numbers for these - cursorOverride = -1; - } - - return currentOverride != cursorOverride && cursorOverride != -1; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFPlatform.java b/common/src/main/java/com/cinemamod/mcef/MCEFPlatform.java deleted file mode 100644 index 872bd6e8..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFPlatform.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import java.util.Locale; - -public enum MCEFPlatform { - LINUX_AMD64, - LINUX_ARM64, - WINDOWS_AMD64, - WINDOWS_ARM64, - MACOS_AMD64, - MACOS_ARM64; - - public String getNormalizedName() { - return name().toLowerCase(Locale.US); - } - - public boolean isLinux() { - return (this == LINUX_AMD64 || this == LINUX_ARM64); - } - - public boolean isWindows() { - return (this == WINDOWS_AMD64 || this == WINDOWS_ARM64); - } - - public boolean isMacOS() { - return (this == MACOS_AMD64 || this == MACOS_ARM64); - } - - public static MCEFPlatform getPlatform() { - String os = System.getProperty("os.name").toLowerCase(Locale.US); - String arch = System.getProperty("os.arch").toLowerCase(Locale.US); - - if (os.startsWith("linux")) { - if (arch.equals("amd64")) { - return LINUX_AMD64; - } else if (arch.equals("aarch64")) { - return LINUX_ARM64; - } - } else if (os.startsWith("windows")) { - if (arch.equals("amd64")) { - return WINDOWS_AMD64; - } else if (arch.equals("aarch64")) { - return WINDOWS_ARM64; - } - } else if (os.startsWith("mac os x")) { - if (arch.equals("x86_64")) { - return MACOS_AMD64; - } else if (arch.equals("aarch64")) { - return MACOS_ARM64; - } - } - - throw new RuntimeException("Unsupported platform: " + os + " " + arch); - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFRenderer.java b/common/src/main/java/com/cinemamod/mcef/MCEFRenderer.java deleted file mode 100644 index 240f8298..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFRenderer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.mojang.blaze3d.systems.RenderSystem; - -import java.nio.ByteBuffer; - -import static org.lwjgl.opengl.GL12.*; - -public class MCEFRenderer { - private final boolean transparent; - private final int[] textureID = new int[1]; - - protected MCEFRenderer(boolean transparent) { - this.transparent = transparent; - } - - public void initialize() { - textureID[0] = glGenTextures(); - RenderSystem.bindTexture(textureID[0]); - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - RenderSystem.texParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - RenderSystem.bindTexture(0); - } - - public int getTextureID() { - return textureID[0]; - } - - public boolean isTransparent() { - return transparent; - } - - protected void cleanup() { - if (textureID[0] != 0) { - glDeleteTextures(textureID[0]); - textureID[0] = 0; - } - } - - protected void onPaint(ByteBuffer buffer, int width, int height) { - if (textureID[0] == 0) return; - if (transparent) RenderSystem.enableBlend(); - RenderSystem.bindTexture(textureID[0]); - RenderSystem.pixelStore(GL_UNPACK_ROW_LENGTH, width); - RenderSystem.pixelStore(GL_UNPACK_SKIP_PIXELS, 0); - RenderSystem.pixelStore(GL_UNPACK_SKIP_ROWS, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); - } - - protected void onPaint(ByteBuffer buffer, int x, int y, int width, int height) { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_BGRA, - GL_UNSIGNED_INT_8_8_8_8_REV, buffer); - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MCEFSettings.java b/common/src/main/java/com/cinemamod/mcef/MCEFSettings.java deleted file mode 100644 index c99cf9eb..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MCEFSettings.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import net.minecraft.client.Minecraft; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Properties; -import java.util.concurrent.CompletableFuture; - -public class MCEFSettings { - private static final Path PATH = Minecraft.getInstance().gameDirectory - .toPath() - .resolve("config") - .resolve("mcef") - .resolve("mcef.properties"); - private static int deleteRetries = 0; - - private boolean skipDownload; - private String downloadMirror; - private String userAgent; - private boolean useCache; - - public MCEFSettings() { - skipDownload = false; - downloadMirror = "https://mcef-download.cinemamod.com"; - userAgent = null; - useCache = true; - } - - public boolean isSkipDownload() { - return skipDownload; - } - - public void setSkipDownload(boolean skipDownload) { - this.skipDownload = skipDownload; - saveAsync(); - } - - public String getDownloadMirror() { - return downloadMirror; - } - - public void setDownloadMirror(String downloadMirror) { - this.downloadMirror = downloadMirror; - saveAsync(); - } - - public String getUserAgent() { - return userAgent; - } - - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - saveAsync(); - } - - public boolean isUsingCache() { - return useCache; - } - - public void setUseCache(boolean useCache) { - this.useCache = useCache; - saveAsync(); - } - - public void saveAsync() { - CompletableFuture.runAsync(() -> { - try { - save(); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } - - public void save() throws IOException { - File file = PATH.toFile(); - - file.getParentFile().mkdirs(); - - if (!file.exists()) { - file.createNewFile(); - } - - Properties properties = new Properties(); - properties.setProperty("skip-download", String.valueOf(skipDownload)); - properties.setProperty("download-mirror", String.valueOf(downloadMirror)); - properties.setProperty("user-agent", String.valueOf(userAgent)); - properties.setProperty("use-cache", String.valueOf(useCache)); - - try (FileOutputStream output = new FileOutputStream(file)) { - properties.store(output, null); - } - } - - public void load() throws IOException { - File file = PATH.toFile(); - - if (!file.exists()) { - save(); - } - - Properties properties = new Properties(); - - try (FileInputStream input = new FileInputStream(file)) { - properties.load(input); - } - - try { - skipDownload = Boolean.parseBoolean(properties.getProperty("skip-download")); - downloadMirror = properties.getProperty("download-mirror"); - userAgent = properties.getProperty("user-agent"); - useCache = Boolean.parseBoolean(properties.getProperty("use-cache")); - } catch (Exception e) { - // Delete and re-create the file if there was a parsing error - if (deleteRetries++ > 20) - return; // Stop gap - file.delete(); - save(); - } - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/MIMEUtil.java b/common/src/main/java/com/cinemamod/mcef/MIMEUtil.java deleted file mode 100644 index 0017f94c..00000000 --- a/common/src/main/java/com/cinemamod/mcef/MIMEUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.cinemamod.mcef; - -public final class MIMEUtil { - public static String mimeFromExtension(String ext) { - // TODO: might want to port https://github.com/CinemaMod/mcef/blob/master-1.19.2/src/main/resources/assets/mcef/mime.types - // adding cases to the switch isn't the most convenient thing -// ext = ext.toLowerCase(Locale.US); -// String ret = mimeTypeMap.get(ext); -// if (ret != null) -// return ret; - - // If the mimeTypeMap couldn't be loaded, fall back to common things - return switch (ext) { - case "htm", "html" -> "text/html"; - case "css" -> "text/css"; - case "pdf" -> "application/pdf"; - case "xz" -> "application/x-xz"; - case "tar" -> "application/x-tar"; - case "cpio" -> "application/x-cpio"; - case "7z" -> "application/x-7z-compressed"; - case "zip" -> "application/zip"; - case "js" -> "text/javascript"; - case "json" -> "application/json"; - case "jsonml" -> "application/jsonml+json"; - case "jar" -> "application/java-archive"; - case "ser" -> "application/java-serialized-object"; - case "class" -> "application/java-vm"; - case "wad" -> "application/x-doom"; - case "png" -> "image/png"; - case "jpg", "jpeg" -> "image/jpeg"; - case "gif" -> "image/gif"; - case "svg" -> "image/svg+xml"; - case "xml" -> "text/xml"; - case "txt" -> "text/plain"; - case "oga", "ogg", "spx" -> "audio/ogg"; - case "mp4", "mp4v", "mpg4" -> "video/mp4"; - case "m4a", "mp4a" -> "audio/mp4"; - case "mid", "midi", "kar", "rmi" -> "audio/midi"; - case "mpga", "mp2", "mp2a", "mp3", "mp3a", "m2a" -> "audio/mpeg"; - case "mpeg", "mpg", "mpe", "m1v", "m2v" -> "video/mpeg"; - case "jpgv" -> "video/jpeg"; - case "h264" -> "video/h264"; - case "h261" -> "video/h261"; - case "h263" -> "video/h263"; - case "webm" -> "video/webm"; - case "flv" -> "video/flv"; - case "m4v" -> "video/m4v"; - case "qt", "mov" -> "video/quicktime"; - case "ogv" -> "video/ogg"; - default -> null; - }; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/ModScheme.java b/common/src/main/java/com/cinemamod/mcef/ModScheme.java deleted file mode 100644 index 396012f1..00000000 --- a/common/src/main/java/com/cinemamod/mcef/ModScheme.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.mojang.logging.LogUtils; -import org.cef.callback.CefCallback; -import org.cef.handler.CefResourceHandler; -import org.cef.misc.IntRef; -import org.cef.misc.StringRef; -import org.cef.network.CefRequest; -import org.cef.network.CefResponse; -import org.slf4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -// https://github.com/CinemaMod/mcef/blob/master-1.19.2/src/main/java/net/montoyo/mcef/example/ModScheme.java -public class ModScheme implements CefResourceHandler { - private String contentType = null; - private InputStream is = null; - - private final String url; - - public ModScheme(String url) { - this.url = url; - } - - private static final Logger LOGGER = LogUtils.getLogger(); - - @Override - public boolean processRequest(CefRequest cefRequest, CefCallback cefCallback) { - String url = this.url.substring("mod://".length()); - - int pos = url.indexOf('/'); - if (pos < 0) { - cefCallback.cancel(); - return false; - } - - String mod = removeSlashes(url.substring(0, pos)); - String loc = removeSlashes(url.substring(pos + 1)); - - if (mod.length() <= 0 || loc.length() <= 0 || mod.charAt(0) == '.' || loc.charAt(0) == '.') { - LOGGER.warn("Invalid URL " + url); - cefCallback.cancel(); - return false; - } - - // TODO: this may or may not require neoforge/fabric specific code? -// is = ModList.get().getModContainerById(mod).get().getMod().getClass().getResourceAsStream("/assets/" + mod.toLowerCase(Locale.US) + "/html/" + loc.toLowerCase()); - is = ModScheme.class.getClassLoader().getResourceAsStream("/assets/" + mod.toLowerCase(Locale.US) + "/html/" + loc.toLowerCase(Locale.US)); - if (is == null) { - LOGGER.warn("Resource " + url + " NOT found!"); - cefCallback.cancel(); - return false; // TODO: 404? - } - - contentType = null; - pos = loc.lastIndexOf('.'); - if (pos >= 0 && pos < loc.length() - 2) - contentType = MIMEUtil.mimeFromExtension(loc.substring(pos + 1)); - - cefCallback.Continue(); - return true; - } - - private String removeSlashes(String loc) { - int i = 0; - while (i < loc.length() && loc.charAt(i) == '/') - i++; - - return loc.substring(i); - } - - @Override - public void getResponseHeaders(CefResponse cefResponse, IntRef contentLength, StringRef redir) { - if (contentType != null) - cefResponse.setMimeType(contentType); - - cefResponse.setStatus(200); - cefResponse.setStatusText("OK"); - contentLength.set(0); - } - - @Override - public boolean readResponse(byte[] output, int bytesToRead, IntRef bytesRead, CefCallback cefCallback) { - try { - int ret = is.read(output, 0, bytesToRead); - if (ret <= 0) { - is.close(); - // 0 bytes read indicates to CEF/JCEF that there is no more data to read - bytesRead.set(0); - return false; - } - - // tell CEF/JCEF how many bytes were read - bytesRead.set(ret); - return true; - } catch (IOException e) { - e.printStackTrace(); - // attempt to close the stream if possible - try { - is.close(); - } catch (Throwable ignored) { - } - - return false; - } - } - - @Override - public void cancel() { - // attempt to free resources, just incase - try { - is.close(); - } catch (Throwable ignored) { - } - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/example/ExampleScreen.java b/common/src/main/java/com/cinemamod/mcef/example/ExampleScreen.java deleted file mode 100644 index d4b35130..00000000 --- a/common/src/main/java/com/cinemamod/mcef/example/ExampleScreen.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.example; - -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFBrowser; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.network.chat.Component; - -public class ExampleScreen extends Screen { - private static final int BROWSER_DRAW_OFFSET = 20; - - private MCEFBrowser browser; - - protected ExampleScreen(Component component) { - super(component); - } - - @Override - protected void init() { - super.init(); - if (browser == null) { - String url = "https://www.google.com"; - boolean transparent = true; - browser = MCEF.createBrowser(url, transparent); - resizeBrowser(); - } - } - - private int mouseX(double x) { - return (int) ((x - BROWSER_DRAW_OFFSET) * minecraft.getWindow().getGuiScale()); - } - - private int mouseY(double y) { - return (int) ((y - BROWSER_DRAW_OFFSET) * minecraft.getWindow().getGuiScale()); - } - - private int scaleX(double x) { - return (int) ((x - BROWSER_DRAW_OFFSET * 2) * minecraft.getWindow().getGuiScale()); - } - - private int scaleY(double y) { - return (int) ((y - BROWSER_DRAW_OFFSET * 2) * minecraft.getWindow().getGuiScale()); - } - - private void resizeBrowser() { - if (width > 100 && height > 100) { - browser.resize(scaleX(width), scaleY(height)); - } - } - - @Override - public void resize(Minecraft minecraft, int i, int j) { - super.resize(minecraft, i, j); - resizeBrowser(); - } - - @Override - public void onClose() { - browser.close(); - super.onClose(); - } - - @Override - public void render(GuiGraphics guiGraphics, int i, int j, float f) { - super.render(guiGraphics, i, j, f); - RenderSystem.disableDepthTest(); - RenderSystem.setShader(GameRenderer::getPositionTexColorShader); - RenderSystem.setShaderTexture(0, browser.getRenderer().getTextureID()); - Tesselator t = Tesselator.getInstance(); - BufferBuilder buffer = t.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); - buffer.addVertex(BROWSER_DRAW_OFFSET, height - BROWSER_DRAW_OFFSET, 0).setUv(0.0f, 1.0f).setColor(255, 255, 255, 255); - buffer.addVertex(width - BROWSER_DRAW_OFFSET, height - BROWSER_DRAW_OFFSET, 0).setUv(1.0f, 1.0f).setColor(255, 255, 255, 255); - buffer.addVertex(width - BROWSER_DRAW_OFFSET, BROWSER_DRAW_OFFSET, 0).setUv(1.0f, 0.0f).setColor(255, 255, 255, 255); - buffer.addVertex(BROWSER_DRAW_OFFSET, BROWSER_DRAW_OFFSET, 0).setUv(0.0f, 0.0f).setColor(255, 255, 255, 255); - BufferUploader.drawWithShader(buffer.build()); - RenderSystem.setShaderTexture(0, 0); - RenderSystem.enableDepthTest(); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - browser.sendMousePress(mouseX(mouseX), mouseY(mouseY), button); - browser.setFocus(true); - return super.mouseClicked(mouseX, mouseY, button); - } - - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - browser.sendMouseRelease(mouseX(mouseX), mouseY(mouseY), button); - browser.setFocus(true); - return super.mouseReleased(mouseX, mouseY, button); - } - - @Override - public void mouseMoved(double mouseX, double mouseY) { - browser.sendMouseMove(mouseX(mouseX), mouseY(mouseY)); - super.mouseMoved(mouseX, mouseY); - } - - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { - return super.mouseDragged(mouseX, mouseY, button, dragX, dragY); - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { - browser.sendMouseWheel(mouseX(mouseX), mouseY(mouseY), scrollY, 0); - return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - browser.sendKeyPress(keyCode, scanCode, modifiers); - browser.setFocus(true); - return super.keyPressed(keyCode, scanCode, modifiers); - } - - @Override - public boolean keyReleased(int keyCode, int scanCode, int modifiers) { - browser.sendKeyRelease(keyCode, scanCode, modifiers); - browser.setFocus(true); - return super.keyReleased(keyCode, scanCode, modifiers); - } - - @Override - public boolean charTyped(char codePoint, int modifiers) { - if (codePoint == (char) 0) return false; - browser.sendKeyTyped(codePoint, modifiers); - browser.setFocus(true); - return super.charTyped(codePoint, modifiers); - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloadListener.java b/common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloadListener.java deleted file mode 100644 index ee5dd9fd..00000000 --- a/common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloadListener.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.internal; - -import org.spongepowered.asm.mixin.Unique; - -public class MCEFDownloadListener { - // TODO: I kinda would like to keep other mods from accessing this, but mixin complicates stuff - @Unique - public static final MCEFDownloadListener INSTANCE = new MCEFDownloadListener(); - - private String task; - private float percent; - private boolean done; - private boolean failed; - - public void setTask(String name) { - this.task = name; - this.percent = 0; - } - - public String getTask() { - return task; - } - - public void setProgress(float percent) { - this.percent = percent; - } - - public float getProgress() { - return percent; - } - - public void setDone(boolean done) { - this.done = done; - } - - public boolean isDone() { - return done; - } - - public void setFailed(boolean failed) { - this.failed = failed; - } - - public boolean isFailed() { - return failed; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloaderMenu.java b/common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloaderMenu.java deleted file mode 100644 index fa440262..00000000 --- a/common/src/main/java/com/cinemamod/mcef/internal/MCEFDownloaderMenu.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.internal; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.TitleScreen; -import net.minecraft.network.chat.Component; - -public class MCEFDownloaderMenu extends Screen { - private final TitleScreen menu; - - public MCEFDownloaderMenu(TitleScreen menu) { - super(Component.literal("MCEF is downloading required libraries...")); - this.menu = menu; - } - - @Override - public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) { - renderBackground(graphics, mouseX, mouseY, partialTick); - double cx = width / 2d; - double cy = height / 2d; - - double progressBarHeight = 14; - double progressBarWidth = width / 3d; // TODO: base off screen with (1/3 of screen) - - PoseStack poseStack = graphics.pose(); - - /* Draw Progress Bar */ - poseStack.pushPose(); - poseStack.translate(cx, cy, 0); - poseStack.translate(-progressBarWidth / 2d, -progressBarHeight / 2d, 0); - graphics.fill( // bar border - 0, 0, - (int) progressBarWidth, - (int) progressBarHeight, - -1 - ); - graphics.fill( // bar padding - 2, 2, - (int) progressBarWidth - 2, - (int) progressBarHeight - 2, - -16777215 - ); - graphics.fill( // bar bar - 4, 4, - (int) ((progressBarWidth - 4) * MCEFDownloadListener.INSTANCE.getProgress()), - (int) progressBarHeight - 4, - -1 - ); - poseStack.popPose(); - - // putting this here incase I want to re-add a third line later on - // allows me to generalize the code to not care about line count - String[] text = new String[]{ - MCEFDownloadListener.INSTANCE.getTask(), - Math.round(MCEFDownloadListener.INSTANCE.getProgress() * 100) + "%", - }; - - /* Draw Text */ - // calculate offset for the top line - int oSet = ((font.lineHeight / 2) + ((font.lineHeight + 2) * (text.length + 2))) + 4; - poseStack.pushPose(); - poseStack.translate( - (int) (cx), - (int) (cy - oSet), - 0 - ); - // draw menu name - graphics.drawString( - font, - ChatFormatting.GOLD + title.getString(), - (int) -(font.width(title.getString()) / 2d), 0, - 0xFFFFFF - ); - // draw text - int index = 0; - for (String s : text) { - if (index == 1) { - poseStack.translate(0, font.lineHeight + 2, 0); - } - - poseStack.translate(0, font.lineHeight + 2, 0); - graphics.drawString( - font, - s, - (int) -(font.width(s) / 2d), 0, - 0xFFFFFF - ); - index++; - } - poseStack.popPose(); - - // TODO: if listener.isFailed(), draw some "Failed to initialize MCEF" text with an "OK" button to proceed - } - - @Override - public void tick() { - if (MCEFDownloadListener.INSTANCE.isDone() || MCEFDownloadListener.INSTANCE.isFailed()) { - onClose(); - Minecraft.getInstance().setScreen(menu); - } - } - - @Override - public boolean shouldCloseOnEsc() { - return false; - } - - @Override - public boolean isPauseScreen() { - return true; - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/listeners/MCEFCursorChangeListener.java b/common/src/main/java/com/cinemamod/mcef/listeners/MCEFCursorChangeListener.java deleted file mode 100644 index 54d9e03c..00000000 --- a/common/src/main/java/com/cinemamod/mcef/listeners/MCEFCursorChangeListener.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.listeners; - -@FunctionalInterface -public interface MCEFCursorChangeListener { - void onCursorChange(int cursorID); -} diff --git a/common/src/main/java/com/cinemamod/mcef/listeners/MCEFInitListener.java b/common/src/main/java/com/cinemamod/mcef/listeners/MCEFInitListener.java deleted file mode 100644 index fc1c9818..00000000 --- a/common/src/main/java/com/cinemamod/mcef/listeners/MCEFInitListener.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.listeners; - -@FunctionalInterface -public interface MCEFInitListener { - /** - * @param successful whether MCEF was successfully initialized - * If this is true, that means the user's platform is supported, natives downloaded registered properly, etc - */ - void onInit(boolean successful); -} diff --git a/common/src/main/java/com/cinemamod/mcef/mixins/CefDownloadMixin.java b/common/src/main/java/com/cinemamod/mcef/mixins/CefDownloadMixin.java deleted file mode 100644 index fe21bfef..00000000 --- a/common/src/main/java/com/cinemamod/mcef/mixins/CefDownloadMixin.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.mixins; - -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFDownloader; -import com.cinemamod.mcef.MCEFPlatform; -import com.cinemamod.mcef.MCEFSettings; -import com.cinemamod.mcef.internal.MCEFDownloadListener; -import net.minecraft.client.resources.ClientPackSource; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.io.File; -import java.io.IOException; - -/** - *

- * mcef.libraries.path is where MCEF will store any required binaries. By default, - * /path/to/.minecraft/mods/mcef-libraries. - *

- * jcef.path is the location of the standard java-cef bundle. By default, - * /path/to/mcef-libraries/ where normalized platform name comes from - * {@link MCEFPlatform#getNormalizedName()}. This is what java-cef uses internally to find the - * installation. Also see {@link org.cef.CefApp}. - */ -@Mixin(ClientPackSource.class) -public class CefDownloadMixin { - @Unique - private static void setupLibraryPath() throws IOException { - final File mcefLibrariesDir; - - // Check for development environment - // TODO: handle eclipse/others - // i.e. mcef-repo/neoforge/build - File buildDir = new File("../build"); - if (buildDir.exists() && buildDir.isDirectory()) { - mcefLibrariesDir = new File(buildDir, "mcef-libraries/"); - } else { - mcefLibrariesDir = new File("mods/mcef-libraries/"); - } - - mcefLibrariesDir.mkdirs(); - - System.setProperty("mcef.libraries.path", mcefLibrariesDir.getCanonicalPath()); - System.setProperty("jcef.path", new File(mcefLibrariesDir, MCEFPlatform.getPlatform().getNormalizedName()).getCanonicalPath()); - } - - @Inject(at = @At("HEAD"), method = "") - private static void sinit(CallbackInfo callbackInfo) { - try { - setupLibraryPath(); - } catch (IOException e) { - e.printStackTrace(); - } - - Thread downloadThread = new Thread(() -> { - String javaCefCommit; - - try { - javaCefCommit = MCEF.getJavaCefCommit(); - } catch (IOException e) { - e.printStackTrace(); - return; - } - - MCEF.getLogger().info("java-cef commit: " + javaCefCommit); - - MCEFSettings settings = MCEF.getSettings(); - MCEFDownloader downloader = new MCEFDownloader(settings.getDownloadMirror(), javaCefCommit, MCEFPlatform.getPlatform()); - - boolean downloadJcefBuild; - - // We always download the checksum for the java-cef build - // We will compare this with mcef-libraries/.tar.gz.sha256 - // If the contents of the files differ (or it doesn't exist locally), we know we need to redownload JCEF - try { - downloadJcefBuild = !downloader.downloadJavaCefChecksum(); - } catch (IOException e) { - e.printStackTrace(); - MCEFDownloadListener.INSTANCE.setFailed(true); - return; - } - - // Ensure the mcef-libraries directory exists - // If not, we want to try redownloading - File mcefLibrariesDir = new File(System.getProperty("mcef.libraries.path")); - downloadJcefBuild |= !mcefLibrariesDir.exists(); - - if (downloadJcefBuild && !settings.isSkipDownload()) { - try { - downloader.downloadJavaCefBuild(); - } catch (IOException e) { - e.printStackTrace(); - MCEFDownloadListener.INSTANCE.setFailed(true); - return; - } - - downloader.extractJavaCefBuild(true); - } - - MCEFDownloadListener.INSTANCE.setDone(true); - }); - downloadThread.start(); - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/mixins/CefInitMixin.java b/common/src/main/java/com/cinemamod/mcef/mixins/CefInitMixin.java deleted file mode 100644 index 25e7f5d8..00000000 --- a/common/src/main/java/com/cinemamod/mcef/mixins/CefInitMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.cinemamod.mcef.mixins; - -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.internal.MCEFDownloadListener; -import com.cinemamod.mcef.internal.MCEFDownloaderMenu; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.TitleScreen; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Minecraft.class) -public abstract class CefInitMixin { - @Shadow - public abstract void setScreen(@Nullable Screen guiScreen); - - @Inject(at = @At("HEAD"), method = "setScreen", cancellable = true) - public void redirScreen(Screen guiScreen, CallbackInfo ci) { - if (!MCEF.isInitialized()) { - if (guiScreen instanceof TitleScreen) { - // If the download is done and didn't fail - if (MCEFDownloadListener.INSTANCE.isDone() && !MCEFDownloadListener.INSTANCE.isFailed()) { - Minecraft.getInstance().execute((() -> { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - MCEF.initialize(); - })); - } - // If the download is not done and didn't fail - else if (!MCEFDownloadListener.INSTANCE.isDone() && !MCEFDownloadListener.INSTANCE.isFailed()) { - setScreen(new MCEFDownloaderMenu((TitleScreen) guiScreen)); - ci.cancel(); - } - // If the download failed - else if (MCEFDownloadListener.INSTANCE.isFailed()) { - MCEF.getLogger().error("MCEF failed to initialize!"); - } - } - } - } -} diff --git a/common/src/main/java/com/cinemamod/mcef/mixins/CefRenderUpdateMixin.java b/common/src/main/java/com/cinemamod/mcef/mixins/CefRenderUpdateMixin.java deleted file mode 100644 index 9bf782c6..00000000 --- a/common/src/main/java/com/cinemamod/mcef/mixins/CefRenderUpdateMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.mixins; - -import com.cinemamod.mcef.MCEF; -import net.minecraft.client.DeltaTracker; -import net.minecraft.client.renderer.GameRenderer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(GameRenderer.class) -public class CefRenderUpdateMixin { - @Inject(at = @At("HEAD"), method = "render") - public void preRender(DeltaTracker deltaTracker, boolean renderLevel, CallbackInfo ci) { - if (MCEF.isInitialized()) { - MCEF.getApp().getHandle().N_DoMessageLoopWork(); - } - } -} diff --git a/common/src/main/resources/icon.png b/common/src/main/resources/icon.png deleted file mode 100644 index d44bd44d44519e951f8fb9cf9a73cbaaee163981..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2403 zcmeAS@N?(olHy`uVBq!ia0y~yVB!T~4mP03UJ0KmK#H@#BeIx*f$uN~Gak=hkpdKy zEOCt}3C>R|DNig)WhgH%*UQYyE>2D?NY%?PN}v7CMv8%fLKGwlK;Z zOMGH{z*RMgt@9pR*oJ1-kn3J&5=EY_U2x%*376Z4)7Sspz5Chc!?gW-mQU}0Z?De4 zP;W6?j)CC~`$Yx@l|_sU9xlub6FS%!6a;x09F(LO8eB{m7&7Q0OKdxC$5y4atzsbZEF4e8$!!&pZ&rTarE-AN$RKHUOoDS zjUj=*f})ri&Fe$G%sc&sAtHPGT_1l23$1yyFTHgxGh6t4KOcWt_`&_E9oF;bF{~a< ifunUM9oi0cj3w^{_y6%dp8#wiF?hQAxvX - MCEF_S3_PUBLISH_URL_SNAPSHOT=s3:///repositories/snapshots - MCEF_S3_PUBLISH_URL_RELEASE=s3:///repositories/releases - MCEF_S3_PUBLISH_ACCESS_KEY= - MCEF_S3_PUBLISH_SECRET_KEY= - */ -publishing { - repositories { - maven { - url ((mcef_version.toString().endsWith("SNAPSHOT")) ? findProperty('MCEF_S3_PUBLISH_URL_SNAPSHOT') : findProperty('MCEF_S3_PUBLISH_URL_RELEASE')) - credentials(AwsCredentials) { - accessKey = findProperty('MCEF_S3_PUBLISH_ACCESS_KEY') - secretKey = findProperty('MCEF_S3_PUBLISH_SECRET_KEY') - } - } - } - publications { - mavenJava(MavenPublication) { - from components.java - groupId = 'com.cinemamod' - artifactId = 'mcef-fabric' - version = mcef_version - } - } -} - -dependencies { - minecraft "com.mojang:minecraft:${minecraft_version}" - mappings loom.officialMojangMappings() - modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" - - Set apiModules = [ - 'fabric-api-base', - 'fabric-command-api-v2', - 'fabric-lifecycle-events-v1', - 'fabric-networking-api-v1', - 'fabric-resource-loader-v0', - 'fabric-key-binding-api-v1' - ] - - apiModules.forEach { - modImplementation(fabricApi.module(it, fabric_version)) - } - - implementation project(path: ':common', configuration: 'namedElements') -} - -loom { - mixin { - defaultRefmapName = "mcef.refmap.json" - } -} - -tasks.register('generateJava', Copy) { - from project(':common').file('src/template/java') - into "${buildDir}/generated/java" - expand 'compatibility_version': mod_compatibility_version -} -sourceSets.main.java { - srcDir "${buildDir}/generated/java" -} -compileJava.dependsOn generateJava -generateJava.dependsOn('sourcesJar') - -processResources { - filesMatching('fabric.mod.json') { - expand 'mod_id': mod_id, - 'mod_name': mod_name, - 'mod_vendor': mod_vendor, - 'mod_version': mod_version, - 'java_version': java_version, - 'minecraft_dependency': minecraft_dependency, - 'fabric_loader_version': fabric_loader_version, - 'min_fabric_version': min_fabric_version - } - from project(":common").sourceSets.main.resources -} - -tasks.withType(JavaCompile).configureEach { - source(project(':common').sourceSets.main.allSource) - source(project(':common').sourceSets.jcef.allSource) -} - -tasks.withType(JavaCompile).configureEach { - it.options.encoding = 'UTF-8' - it.options.release = java_version as int -} - -java { - withSourcesJar() -} - -jar { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - manifest { - attributes(['Specification-Title' : mod_name, - 'Specification-Vendor' : mod_vendor, - 'Specification-Version' : "1", - 'Implementation-Title' : mod_name, - 'Implementation-Version' : mod_version, - 'Implementation-Vendor' : mod_vendor, - 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), - 'java-cef-commit' : project.parent.getCheckedOutGitCommitHash(project.parent) - ]) - } - from('LICENSE') { - rename { "${it}_${archivesBaseName}" } - } -} - -curseforge { - apiKey = file("${rootDir}/curseforge_api_key.txt").exists() ? file("${rootDir}/curseforge_api_key.txt").text.trim() : '' - project { - id = curse_id - releaseType = release_type - addGameVersion minecraft_version - addGameVersion 'Fabric' - addGameVersion "Java ${java_version}" - mainArtifact(file("${buildDir}/libs/${archivesBaseName}-${version}.jar")) { - displayName = "[FABRIC][${minecraft_version}] ${mod_name} ${mod_version}" - } - afterEvaluate { - uploadTask.dependsOn(remapJar) - } - } - options { - forgeGradleIntegration = false - } -} - -shadowJar { - configurations = [project.configurations.shadow] - archiveClassifier = 'shadow-dev' -} - -remapJar { - dependsOn shadowJar - inputFile = shadowJar.archiveFile.get() -} \ No newline at end of file diff --git a/fabric/gradle.properties b/fabric/gradle.properties deleted file mode 100644 index 8c7fd5ce..00000000 --- a/fabric/gradle.properties +++ /dev/null @@ -1,15 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -org.gradle.daemon=false - -minecraft_dependency=1.21.1 -curseforge_minecraft_version=1.21.1 - -fabric_version=0.104.0+1.21.1 -min_fabric_version=0.100.0+1.21 - -maven_group=com.cinemamod -archives_base_name=mcef-fabric - -curse_id=636236 -release_type=release -recommended=true diff --git a/fabric/src/main/java/com/cinemamod/mcef/FabricMCEFClientMod.java b/fabric/src/main/java/com/cinemamod/mcef/FabricMCEFClientMod.java deleted file mode 100644 index 8bd5f8b9..00000000 --- a/fabric/src/main/java/com/cinemamod/mcef/FabricMCEFClientMod.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.cinemamod.mcef.example.MCEFExampleMod; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.loader.api.FabricLoader; - -public class FabricMCEFClientMod implements ClientModInitializer { - @Override - public void onInitializeClient() { - if (FabricLoader.getInstance().isDevelopmentEnvironment()) { - new MCEFExampleMod(); - } - } -} diff --git a/fabric/src/main/java/com/cinemamod/mcef/FabricMCEFMod.java b/fabric/src/main/java/com/cinemamod/mcef/FabricMCEFMod.java deleted file mode 100644 index f1c3d542..00000000 --- a/fabric/src/main/java/com/cinemamod/mcef/FabricMCEFMod.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import net.fabricmc.api.ModInitializer; - -public class FabricMCEFMod implements ModInitializer { - @Override - public void onInitialize() { - // MCEF server-side does nothing - } -} diff --git a/fabric/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java b/fabric/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java deleted file mode 100644 index e83a544b..00000000 --- a/fabric/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.example; - -import com.mojang.blaze3d.platform.InputConstants; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.KeyMapping; -import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; -import org.lwjgl.glfw.GLFW; - -public class MCEFExampleMod { - private static final Minecraft minecraft = Minecraft.getInstance(); - - public static final KeyMapping KEY_MAPPING = new KeyMapping( - "Open Browser", InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_F10, "key.categories.misc" - ); - - public MCEFExampleMod() { - ClientTickEvents.START_CLIENT_TICK.register((client) -> onTick()); - } - - public void onTick() { - // Check if our key was pressed - if (KEY_MAPPING.isDown() && !(minecraft.screen instanceof ExampleScreen)) { - //Display the web browser UI. - minecraft.setScreen(new ExampleScreen( - Component.literal("Example Screen") - )); - } - } -} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json deleted file mode 100644 index 5cde3825..00000000 --- a/fabric/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "schemaVersion": 1, - "id": "${mod_id}", - "version": "${mod_version}", - "name": "${mod_name}", - "description": "A Minecraft mod and library for adding the Chromium web browser into the game (Minecraft Chromium Embedded Framework).", - "authors": [ - "${mod_vendor}" - ], - "contact": { - "homepage": "https://github.com/CinemaMod/mcef", - "issues": "https://github.com/CinemaMod/mcef/issues", - "sources": "https://github.com/CinemaMod/mcef", - "discord": "https://discord.gg/rNrh5kW8Ty" - }, - "license": "LGPL 2.1", - "icon": "icon.png", - "environment": "*", - "entrypoints": { - "client": [ - "com.cinemamod.mcef.FabricMCEFClientMod" - ], - "main": [ - "com.cinemamod.mcef.FabricMCEFMod" - ] - }, - "mixins": [ - "mcef.mixins.json" - ], - "depends": { - "fabricloader": ">=${fabric_loader_version}", - "minecraft": ["1.21", "1.21.1"], - "java": ">=${java_version}" - }, - "breaks": { - "fabric-api": "<${min_fabric_version}" - } -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 17a4836d..00000000 --- a/gradle.properties +++ /dev/null @@ -1,19 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -org.gradle.daemon=false - -java_version=21 -minecraft_version=1.21.1 -fabric_loader_version=0.16.5 -mod_compatibility_version=21 - -# For snapshots, append -SNAPSHOT -mcef_version=2.1.5-1.21.1 - -mod_id=mcef -mod_name=MCEF (Minecraft Chromium Embedded Framework) - -mod_vendor=CinemaMod Group - -fabric_loom_version=1.7-SNAPSHOT -cursegradle_version=1.4.0 -shadow_version=8.1.1 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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

NnX)EH+Nua)3Y(c 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 '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 7101f8e4..00000000 --- a/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/neoforge/build.gradle b/neoforge/build.gradle deleted file mode 100644 index 7c71e01b..00000000 --- a/neoforge/build.gradle +++ /dev/null @@ -1,136 +0,0 @@ -plugins { - id 'net.neoforged.gradle.userdev' version '7.0.+' - id 'com.matthewprenger.cursegradle' version "${cursegradle_version}" - id 'com.github.johnrengelman.shadow' version "${shadow_version}" - id 'maven-publish' -} - -var mod_version = mcef_version - -archivesBaseName = project.archives_base_name -version = mod_version -group = mod_packagename - -java.toolchain.languageVersion = JavaLanguageVersion.of(java_version as int) - -runs { - client { - workingDirectory project.file('run') - } - server { - workingDirectory project.file('run/server') - } -} - -/* - Add the following to ~/.gradle/gradle.properties - systemProp.org.gradle.s3.endpoint=https:// - MCEF_S3_PUBLISH_URL_SNAPSHOT=s3:///repositories/snapshots - MCEF_S3_PUBLISH_URL_RELEASE=s3:///repositories/releases - MCEF_S3_PUBLISH_ACCESS_KEY= - MCEF_S3_PUBLISH_SECRET_KEY= - */ -publishing { - repositories { - maven { - url ((mcef_version.toString().endsWith("SNAPSHOT")) ? findProperty('MCEF_S3_PUBLISH_URL_SNAPSHOT') : findProperty('MCEF_S3_PUBLISH_URL_RELEASE')) - credentials(AwsCredentials) { - accessKey = findProperty('MCEF_S3_PUBLISH_ACCESS_KEY') - secretKey = findProperty('MCEF_S3_PUBLISH_SECRET_KEY') - } - } - } - publications { - mavenJava(MavenPublication) { - from components.java - groupId = 'com.cinemamod' - artifactId = 'mcef-neoforge' - version = mcef_version - } - } -} - -sourceSets.main.resources { srcDir 'src/generated/resources' } - -configurations { - shadowMc.extendsFrom minecraftLibrary -} - -tasks.register('prepareWorkspace') { - -} - -dependencies { - implementation "net.neoforged:neoforge:${neoforge_version}" - - implementation(project(':common')) { - transitive false - } -} - -tasks.register('generateJava', Copy) { - from project(':common').file('src/template/java') - into "${buildDir}/generated/java" - expand 'compatibility_version': mod_compatibility_version -} -sourceSets.main.java { - srcDir "${buildDir}/generated/java" -} -compileJava.dependsOn generateJava - -processResources { - filesMatching('**/*.toml') { - expand 'mod_id': mod_id, - 'mod_version': mod_version, - 'mod_name': mod_name, - 'neoforge_version': neoforge_version, - 'loader_version': loader_version, - 'neoforge_dependency': 'neoforge_dependency', - 'minecraft_version': minecraft_version - } - from("${project(':common').projectDir}/src/main/resources") -} - -tasks.withType(JavaCompile).configureEach { - source(project(':common').sourceSets.main.allSource) - source(project(':common').sourceSets.jcef.allSource) -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' -} - -jar { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - manifest { - attributes(['Specification-Title' : mod_name, - 'Specification-Vendor' : mod_vendor, - 'Specification-Version' : "1", - 'Implementation-Title' : mod_name, - 'Implementation-Version' : mod_version, - 'Implementation-Vendor' : mod_vendor, - 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), - 'java-cef-commit' : project.parent.getCheckedOutGitCommitHash(project.parent) - ]) - } - from configurations.shadow.collect { it.isDirectory() ? it : zipTree(it) } -} - -curseforge { - apiKey = file("${rootDir}/curseforge_api_key.txt").exists() ? file("${rootDir}/curseforge_api_key.txt").text.trim() : '' - project { - id = curse_id - releaseType = release_type - addGameVersion minecraft_version - addGameVersion 'NeoForge' - addGameVersion "Java ${java_version}" - mainArtifact(jar) { - displayName = "[NEOFORGE][${minecraft_version}] ${mod_name} ${mod_version}" - } - } -} - -shadowJar { - configurations = [project.configurations.shadowMc] - archiveClassifier = '' -} diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties deleted file mode 100644 index 54a5625a..00000000 --- a/neoforge/gradle.properties +++ /dev/null @@ -1,16 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -org.gradle.daemon=false - -neoforge_version=21.0.145 -loader_version=[1,) -neoforge_dependency=[21.0.0-beta,) - -mod_packagename=com.cinemamod -archives_base_name=mcef-neoforge - -curse_id=636236 -release_type=release -recommended=true - -neogradle.subsystems.parchment.minecraftVersion=1.21 -neogradle.subsystems.parchment.mappingsVersion=2024.07.28 diff --git a/neoforge/src/main/java/com/cinemamod/mcef/MCEFInitEvent.java b/neoforge/src/main/java/com/cinemamod/mcef/MCEFInitEvent.java deleted file mode 100644 index 6756c39f..00000000 --- a/neoforge/src/main/java/com/cinemamod/mcef/MCEFInitEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -/* - * little unsure of if I should uncomment this or not - * basically; forge's way of doing this sorta "listening for a thing" is events - * this allows that to be used for MCEF initalization - * - * there is a fabric-equivalent-expectation for this, but it's sorta just what's already in the MCEF class if I'm remembering correctly - */ - -//package com.cinemamod.mcef; -// -//import net.minecraftforge.common.MinecraftForge; -//import net.minecraftforge.eventbus.api.Event; -// -//public class MCEFInitEvent extends Event { -// static { -// MCEF.scheduleForInit(() -> { -// MinecraftForge.EVENT_BUS.post(new MCEFInitEvent()); -// }); -// } -// -// public MCEFInitEvent() { -// } -//} diff --git a/neoforge/src/main/java/com/cinemamod/mcef/NeoForgeMCEFMod.java b/neoforge/src/main/java/com/cinemamod/mcef/NeoForgeMCEFMod.java deleted file mode 100644 index 1867003f..00000000 --- a/neoforge/src/main/java/com/cinemamod/mcef/NeoForgeMCEFMod.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef; - -import com.cinemamod.mcef.example.MCEFExampleMod; -import com.mojang.logging.LogUtils; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.common.Mod; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.fml.event.lifecycle.FMLDedicatedServerSetupEvent; -import net.neoforged.fml.loading.FMLEnvironment; -import org.slf4j.Logger; - -@Mod(NeoForgeMCEFMod.MODID) -public class NeoForgeMCEFMod { - public static final String MODID = "mcef"; - private static final Logger LOGGER = LogUtils.getLogger(); - - public NeoForgeMCEFMod(IEventBus modEventBus) { - modEventBus.addListener(this::clientSetup); - modEventBus.addListener(this::serverSetup); - } - - private void clientSetup(final FMLClientSetupEvent event) { - if (!FMLEnvironment.production) { - new MCEFExampleMod(); - } - } - - private void serverSetup(final FMLDedicatedServerSetupEvent event) { - // MCEF server-side does nothing - } -} diff --git a/neoforge/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java b/neoforge/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java deleted file mode 100644 index 908c6517..00000000 --- a/neoforge/src/main/java/com/cinemamod/mcef/example/MCEFExampleMod.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * MCEF (Minecraft Chromium Embedded Framework) - * Copyright (C) 2023 CinemaMod Group - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package com.cinemamod.mcef.example; - -import com.mojang.blaze3d.platform.InputConstants; -import net.minecraft.client.KeyMapping; -import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; -import net.neoforged.neoforge.client.event.ClientTickEvent; -import net.neoforged.neoforge.common.NeoForge; -import org.lwjgl.glfw.GLFW; - -public class MCEFExampleMod { - private static final Minecraft minecraft = Minecraft.getInstance(); - - public static final KeyMapping KEY_MAPPING = new KeyMapping( - "Open Browser", InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_F10, "key.categories.misc" - ); - - public MCEFExampleMod() { - NeoForge.EVENT_BUS.addListener(this::onTick); - } - - public void onTick(ClientTickEvent.Post event) { - // Check if our key was pressed and make sure the ExampleScreen isn't already open - if (KEY_MAPPING.isDown() && !(minecraft.screen instanceof ExampleScreen)) { - // Display the ExampleScreen web browser - minecraft.setScreen(new ExampleScreen( - Component.literal("Example Screen") - )); - } - } -} diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml deleted file mode 100644 index 9685ebcf..00000000 --- a/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ /dev/null @@ -1,29 +0,0 @@ -modLoader="javafml" -loaderVersion="${loader_version}" -license="LGPL" -issueTrackerURL="https://github.com/CinemaMod/mcef/issues" -displayURL="https://github.com/CinemaMod/mcef" -logoFile="icon.png" -# credits="" -authors="ds58" -[[mixins]] -config="mcef.mixins.json" -[[mods]] -modId="${mod_id}" -version="${mod_version}" -displayName="${mod_name}" -updateJSONURL="" -displayTest="NONE" -description='''A Minecraft mod and library for adding the Chromium web browser into the game (Minecraft Chromium Embedded Framework).''' -[[dependencies.${mod_id}]] - modId="neoforge" - mandatory=true - versionRange="${neoforge_dependency}" - ordering="NONE" - side="BOTH" -[[dependencies.${mod_id}]] - modId="minecraft" - mandatory=true - versionRange="[1.21,)" - ordering="NONE" - side="BOTH" diff --git a/neoforge/src/main/resources/pack.mcmeta b/neoforge/src/main/resources/pack.mcmeta deleted file mode 100644 index de728c5d..00000000 --- a/neoforge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "mcef resources", - "pack_format": 13 - } -} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 5d6046bc..00000000 --- a/settings.gradle +++ /dev/null @@ -1,11 +0,0 @@ -pluginManagement { - repositories { - gradlePluginPortal() - maven { url = 'https://maven.fabricmc.net/' } - maven { url = 'https://maven.neoforged.net/releases' } - mavenCentral() - } -} - -rootProject.name = 'mcef' -include('common', 'fabric', 'neoforge') \ No newline at end of file