From 397135f68774e0661d23cb608c893274635d6d6d Mon Sep 17 00:00:00 2001 From: Chicken-Bones Date: Mon, 15 Jul 2013 21:56:12 -0700 Subject: [PATCH 001/219] Initial commit --- LICENSE | 502 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 504 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..31b791c --- /dev/null +++ b/LICENSE @@ -0,0 +1,502 @@ +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) 2013 Chicken-Bones + + 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. + + {signature of Ty Coon}, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/README.md b/README.md new file mode 100644 index 0000000..1a59737 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +CodeChickenLib +============== From 0f32dd8620652c4ab6d393d46d627fff28de2bf3 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 16 Jul 2013 17:58:02 +1000 Subject: [PATCH 002/219] Initial Commit --- README.md | 2 + codechicken/lib/asm/ASMHelper.java | 332 ++++++ codechicken/lib/asm/ASMReader.java | 364 ++++++ codechicken/lib/asm/CC_ClassWriter.java | 29 + codechicken/lib/asm/ClassHeirachyManager.java | 124 ++ codechicken/lib/asm/InsnListPrinter.java | 214 ++++ .../lib/asm/InstructionComparator.java | 254 ++++ codechicken/lib/asm/ObfMapping.java | 225 ++++ codechicken/lib/colour/Colour.java | 139 +++ codechicken/lib/colour/ColourARGB.java | 34 + codechicken/lib/colour/ColourRGBA.java | 40 + codechicken/lib/colour/CustomGradient.java | 34 + codechicken/lib/config/ConfigFile.java | 153 +++ codechicken/lib/config/ConfigTag.java | 307 +++++ codechicken/lib/config/ConfigTagParent.java | 241 ++++ codechicken/lib/config/SimpleProperties.java | 150 +++ codechicken/lib/data/MCDataInput.java | 26 + codechicken/lib/data/MCDataInputStream.java | 19 + codechicken/lib/data/MCDataOutput.java | 25 + codechicken/lib/data/MCDataOutputStream.java | 19 + .../lib/data/MCOutputStreamWrapper.java | 232 ++++ codechicken/lib/data/NBTDataWrapper.java | 246 ++++ codechicken/lib/lighting/CCRBModel.java | 31 + codechicken/lib/lighting/LC.java | 59 + codechicken/lib/lighting/LazyLightMatrix.java | 28 + codechicken/lib/lighting/LightMatrix.java | 209 ++++ codechicken/lib/lighting/LightModel.java | 112 ++ .../lib/lighting/PlanarLightModel.java | 40 + codechicken/lib/math/MathHelper.java | 168 +++ codechicken/lib/packet/ICustomPacketTile.java | 6 + codechicken/lib/packet/MetaPacket.java | 55 + codechicken/lib/packet/PacketCustom.java | 1041 +++++++++++++++++ codechicken/lib/raytracer/ExtendedMOP.java | 50 + codechicken/lib/raytracer/IndexedCuboid6.java | 14 + codechicken/lib/raytracer/RayTracer.java | 193 +++ codechicken/lib/render/CCModel.java | 968 +++++++++++++++ codechicken/lib/render/CCModelLibrary.java | 93 ++ codechicken/lib/render/CCRenderState.java | 140 +++ codechicken/lib/render/ColourModifier.java | 22 + codechicken/lib/render/EntityDigIconFX.java | 106 ++ codechicken/lib/render/FontUtils.java | 69 ++ codechicken/lib/render/IFaceRenderer.java | 6 + codechicken/lib/render/IUVTransformation.java | 6 + codechicken/lib/render/IVertexModifier.java | 11 + .../lib/render/IconTransformation.java | 20 + codechicken/lib/render/ManagedTextureFX.java | 31 + .../lib/render/MultiIconTransformation.java | 41 + .../lib/render/PlaceholderTexture.java | 19 + codechicken/lib/render/RenderUtils.java | 435 +++++++ codechicken/lib/render/ShaderProgram.java | 137 +++ .../lib/render/SpriteSheetManager.java | 143 +++ codechicken/lib/render/TextureDataHolder.java | 38 + codechicken/lib/render/TextureFX.java | 67 ++ codechicken/lib/render/TextureSpecial.java | 150 +++ codechicken/lib/render/TextureUtils.java | 179 +++ codechicken/lib/render/UV.java | 71 ++ codechicken/lib/render/UVScale.java | 20 + codechicken/lib/render/UVTranslation.java | 20 + codechicken/lib/render/Vertex5.java | 57 + codechicken/lib/vec/AxisCycle.java | 21 + codechicken/lib/vec/BlockCoord.java | 180 +++ codechicken/lib/vec/Cuboid6.java | 136 +++ codechicken/lib/vec/CuboidCoord.java | 113 ++ .../IrreversibleTransformationException.java | 18 + codechicken/lib/vec/Line3.java | 47 + codechicken/lib/vec/Matrix4.java | 353 ++++++ codechicken/lib/vec/Quat.java | 156 +++ codechicken/lib/vec/Rectangle4i.java | 42 + .../lib/vec/RedundantTransformation.java | 38 + codechicken/lib/vec/Rotation.java | 238 ++++ codechicken/lib/vec/Scale.java | 67 ++ codechicken/lib/vec/SwapYZ.java | 27 + codechicken/lib/vec/Transformation.java | 51 + codechicken/lib/vec/TransformationList.java | 101 ++ .../lib/vec/TranslatedTransformation.java | 60 + codechicken/lib/vec/Translation.java | 68 ++ .../lib/vec/VariableTransformation.java | 33 + codechicken/lib/vec/Vector3.java | 423 +++++++ codechicken/lib/world/ChunkExtension.java | 85 ++ codechicken/lib/world/WorldExtension.java | 99 ++ .../lib/world/WorldExtensionInstantiator.java | 17 + .../lib/world/WorldExtensionManager.java | 256 ++++ 82 files changed, 10693 insertions(+) create mode 100644 codechicken/lib/asm/ASMHelper.java create mode 100644 codechicken/lib/asm/ASMReader.java create mode 100644 codechicken/lib/asm/CC_ClassWriter.java create mode 100644 codechicken/lib/asm/ClassHeirachyManager.java create mode 100644 codechicken/lib/asm/InsnListPrinter.java create mode 100644 codechicken/lib/asm/InstructionComparator.java create mode 100644 codechicken/lib/asm/ObfMapping.java create mode 100644 codechicken/lib/colour/Colour.java create mode 100644 codechicken/lib/colour/ColourARGB.java create mode 100644 codechicken/lib/colour/ColourRGBA.java create mode 100644 codechicken/lib/colour/CustomGradient.java create mode 100644 codechicken/lib/config/ConfigFile.java create mode 100644 codechicken/lib/config/ConfigTag.java create mode 100644 codechicken/lib/config/ConfigTagParent.java create mode 100644 codechicken/lib/config/SimpleProperties.java create mode 100644 codechicken/lib/data/MCDataInput.java create mode 100644 codechicken/lib/data/MCDataInputStream.java create mode 100644 codechicken/lib/data/MCDataOutput.java create mode 100644 codechicken/lib/data/MCDataOutputStream.java create mode 100644 codechicken/lib/data/MCOutputStreamWrapper.java create mode 100644 codechicken/lib/data/NBTDataWrapper.java create mode 100644 codechicken/lib/lighting/CCRBModel.java create mode 100644 codechicken/lib/lighting/LC.java create mode 100644 codechicken/lib/lighting/LazyLightMatrix.java create mode 100644 codechicken/lib/lighting/LightMatrix.java create mode 100644 codechicken/lib/lighting/LightModel.java create mode 100644 codechicken/lib/lighting/PlanarLightModel.java create mode 100644 codechicken/lib/math/MathHelper.java create mode 100644 codechicken/lib/packet/ICustomPacketTile.java create mode 100644 codechicken/lib/packet/MetaPacket.java create mode 100644 codechicken/lib/packet/PacketCustom.java create mode 100644 codechicken/lib/raytracer/ExtendedMOP.java create mode 100644 codechicken/lib/raytracer/IndexedCuboid6.java create mode 100644 codechicken/lib/raytracer/RayTracer.java create mode 100644 codechicken/lib/render/CCModel.java create mode 100644 codechicken/lib/render/CCModelLibrary.java create mode 100644 codechicken/lib/render/CCRenderState.java create mode 100644 codechicken/lib/render/ColourModifier.java create mode 100644 codechicken/lib/render/EntityDigIconFX.java create mode 100644 codechicken/lib/render/FontUtils.java create mode 100644 codechicken/lib/render/IFaceRenderer.java create mode 100644 codechicken/lib/render/IUVTransformation.java create mode 100644 codechicken/lib/render/IVertexModifier.java create mode 100644 codechicken/lib/render/IconTransformation.java create mode 100644 codechicken/lib/render/ManagedTextureFX.java create mode 100644 codechicken/lib/render/MultiIconTransformation.java create mode 100644 codechicken/lib/render/PlaceholderTexture.java create mode 100644 codechicken/lib/render/RenderUtils.java create mode 100644 codechicken/lib/render/ShaderProgram.java create mode 100644 codechicken/lib/render/SpriteSheetManager.java create mode 100644 codechicken/lib/render/TextureDataHolder.java create mode 100644 codechicken/lib/render/TextureFX.java create mode 100644 codechicken/lib/render/TextureSpecial.java create mode 100644 codechicken/lib/render/TextureUtils.java create mode 100644 codechicken/lib/render/UV.java create mode 100644 codechicken/lib/render/UVScale.java create mode 100644 codechicken/lib/render/UVTranslation.java create mode 100644 codechicken/lib/render/Vertex5.java create mode 100644 codechicken/lib/vec/AxisCycle.java create mode 100644 codechicken/lib/vec/BlockCoord.java create mode 100644 codechicken/lib/vec/Cuboid6.java create mode 100644 codechicken/lib/vec/CuboidCoord.java create mode 100644 codechicken/lib/vec/IrreversibleTransformationException.java create mode 100644 codechicken/lib/vec/Line3.java create mode 100644 codechicken/lib/vec/Matrix4.java create mode 100644 codechicken/lib/vec/Quat.java create mode 100644 codechicken/lib/vec/Rectangle4i.java create mode 100644 codechicken/lib/vec/RedundantTransformation.java create mode 100644 codechicken/lib/vec/Rotation.java create mode 100644 codechicken/lib/vec/Scale.java create mode 100644 codechicken/lib/vec/SwapYZ.java create mode 100644 codechicken/lib/vec/Transformation.java create mode 100644 codechicken/lib/vec/TransformationList.java create mode 100644 codechicken/lib/vec/TranslatedTransformation.java create mode 100644 codechicken/lib/vec/Translation.java create mode 100644 codechicken/lib/vec/VariableTransformation.java create mode 100644 codechicken/lib/vec/Vector3.java create mode 100644 codechicken/lib/world/ChunkExtension.java create mode 100644 codechicken/lib/world/WorldExtension.java create mode 100644 codechicken/lib/world/WorldExtensionInstantiator.java create mode 100644 codechicken/lib/world/WorldExtensionManager.java diff --git a/README.md b/README.md index 1a59737..9864c48 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ CodeChickenLib ============== +Formerly known as CodeChickenCore-Public, this is a library of systems to help make various aspects of minecraft modding easier. +It contains libraries for 3D math and transformations, model rendering, packets, config, colours, asm and a few other things. \ No newline at end of file diff --git a/codechicken/lib/asm/ASMHelper.java b/codechicken/lib/asm/ASMHelper.java new file mode 100644 index 0000000..63dd0ed --- /dev/null +++ b/codechicken/lib/asm/ASMHelper.java @@ -0,0 +1,332 @@ +package codechicken.lib.asm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LocalVariableNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TryCatchBlockNode; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +import codechicken.lib.asm.InstructionComparator.InsnListSection; + +public class ASMHelper +{ + public static class CodeBlock + { + public Label start = new Label(); + public Label end = new Label(); + } + + public static class ForBlock extends CodeBlock + { + public Label cmp = new Label(); + public Label inc = new Label(); + public Label body = new Label(); + } + + public static abstract class MethodAltercator + { + public final ObfMapping method; + + public MethodAltercator(ObfMapping method) + { + this.method = method; + } + + public abstract void alter(MethodNode mv); + } + + public static abstract class MethodWriter + { + public final int access; + public final ObfMapping method; + public final String[] exceptions; + + public MethodWriter(int access, ObfMapping method) + { + this(access, method, null); + } + + public MethodWriter(int access, ObfMapping method, String[] exceptions) + { + this.access = access; + this.method = method; + this.exceptions = exceptions; + } + + public abstract void write(MethodNode mv); + } + + public static class MethodInjector + { + public final ObfMapping method; + public final InsnList needle; + public final InsnList injection; + public final boolean before; + + public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) + { + this.method = method; + this.needle = needle; + this.injection = injection; + this.before = before; + } + } + + public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) + { + for(MethodNode mnode : cnode.methods) + if(methodmap.matches(mnode)) + return mnode; + return null; + } + + public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) + { + for(FieldNode fnode : cnode.fields) + if(fieldmap.matches(fnode)) + return fnode; + return null; + } + + public static ClassNode createClassNode(byte[] bytes) + { + return createClassNode(bytes, 0); + } + + public static ClassNode createClassNode(byte[] bytes, int flags) + { + ClassNode cnode = new ClassNode(); + ClassReader reader = new ClassReader(bytes); + reader.accept(cnode, flags); + return cnode; + } + + public static byte[] createBytes(ClassNode cnode, int flags) + { + ClassWriter cw = new CC_ClassWriter(flags); + cnode.accept(cw); + return cw.toByteArray(); + } + + public static byte[] writeMethods(String name, byte[] bytes, Multimap writers) + { + if(writers.containsKey(name)) + { + ClassNode cnode = createClassNode(bytes); + + for(MethodWriter mw : writers.get(name)) + { + MethodNode mv = findMethod(mw.method, cnode); + if(mv == null) + mv = (MethodNode) cnode.visitMethod(mw.access, mw.method.s_name, mw.method.s_desc, null, mw.exceptions); + + mv.access = mw.access; + mv.instructions.clear(); + mw.write(mv); + } + + bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + } + return bytes; + } + + public static byte[] injectMethods(String name, byte[] bytes, Multimap injectors) + { + if(injectors.containsKey(name)) + { + ClassNode cnode = createClassNode(bytes); + + for(MethodInjector injector : injectors.get(name)) + { + MethodNode method = findMethod(injector.method, cnode); + if(method == null) + throw new RuntimeException("Method not found: "+injector.method); + System.out.println("Injecting into " + injector.method + "\n" + printInsnList(injector.injection)); + + List callNodes; + if(injector.before) + callNodes = InstructionComparator.insnListFindStart(method.instructions, injector.needle); + else + callNodes = InstructionComparator.insnListFindEnd(method.instructions, injector.needle); + + if(callNodes.size() == 0) + { + throw new RuntimeException("Needle not found in Haystack: " + injector.method+"\n" + printInsnList(injector.needle)); + } + + for(AbstractInsnNode node : callNodes) + { + if(injector.before) + { + System.out.println("Injected before: "+printInsn(node)); + method.instructions.insertBefore(node, cloneInsnList(injector.injection)); + } + else + { + System.out.println("Injected after: "+printInsn(node)); + method.instructions.insert(node, cloneInsnList(injector.injection)); + } + } + } + + bytes = createBytes(cnode, ClassWriter.COMPUTE_FRAMES); + } + return bytes; + } + + public static String printInsnList(InsnList list) + { + InsnListPrinter p = new InsnListPrinter(); + p.visitInsnList(list); + return p.textString(); + } + + public static String printInsn(AbstractInsnNode insn) + { + InsnListPrinter p = new InsnListPrinter(); + p.visitInsn(insn); + return p.textString(); + } + + public static Map cloneLabels(InsnList insns) + { + HashMap labelMap = new HashMap(); + for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + if(insn.getType() == 8) + labelMap.put((LabelNode) insn, new LabelNode()); + return labelMap; + } + + public static InsnList cloneInsnList(InsnList insns) + { + return cloneInsnList(cloneLabels(insns), insns); + } + + public static InsnList cloneInsnList(Map labelMap, InsnList insns) + { + InsnList clone = new InsnList(); + for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + clone.add(insn.clone(labelMap)); + + return clone; + } + + public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) + { + ArrayList clone = new ArrayList(); + for(TryCatchBlockNode node : tcblocks) + clone.add(new TryCatchBlockNode( + labelMap.get(node.start), + labelMap.get(node.end), + labelMap.get(node.handler), + node.type)); + + return clone; + } + + public static List cloneLocals(Map labelMap, List locals) + { + ArrayList clone = new ArrayList(); + for(LocalVariableNode node : locals) + clone.add(new LocalVariableNode( + node.name, node.desc, node.signature, + labelMap.get(node.start), + labelMap.get(node.end), + node.index)); + + return clone; + } + + public static void copy(MethodNode src, MethodNode dst) + { + Map labelMap = cloneLabels(src.instructions); + dst.instructions = cloneInsnList(labelMap, src.instructions); + dst.tryCatchBlocks = cloneTryCatchBlocks(labelMap, src.tryCatchBlocks); + if(src.localVariables != null) + dst.localVariables = cloneLocals(labelMap, src.localVariables); + dst.visibleAnnotations = src.visibleAnnotations; + dst.invisibleAnnotations = src.invisibleAnnotations; + dst.visitMaxs(src.maxStack, src.maxLocals); + } + + public static byte[] alterMethods(String name, byte[] bytes, HashMultimap altercators) + { + if(altercators.containsKey(name)) + { + ClassNode cnode = createClassNode(bytes); + + for(MethodAltercator injector : altercators.get(name)) + { + MethodNode method = findMethod(injector.method, cnode); + if(method == null) + throw new RuntimeException("Method not found: "+injector.method); + + injector.alter(method); + } + + bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + } + return bytes; + } + + + public static String printInsnList(InsnListSection subsection) + { + InsnListPrinter p = new InsnListPrinter(); + p.visitInsnList(subsection); + return p.textString(); + } + + public static int getLocal(List list, String name) + { + int found = -1; + for(LocalVariableNode node : list) + { + if(node.name.equals(name)) + { + if(found >= 0) + throw new RuntimeException("Duplicate local variable: "+name+" not coded to handle this scenario."); + + found = node.index; + } + } + return found; + } + + public static void replaceMethodCode(MethodNode original, MethodNode replacement) + { + original.instructions.clear(); + if(original.localVariables != null) + original.localVariables.clear(); + if(original.tryCatchBlocks != null) + original.tryCatchBlocks.clear(); + replacement.accept(original); + } + + public static void removeBlock(InsnList insns, InsnListSection block) + { + AbstractInsnNode insn = block.first; + while(true) + { + AbstractInsnNode next = insn.getNext(); + insns.remove(insn); + if(insn == block.last) + break; + insn = next; + } + } +} diff --git a/codechicken/lib/asm/ASMReader.java b/codechicken/lib/asm/ASMReader.java new file mode 100644 index 0000000..c040935 --- /dev/null +++ b/codechicken/lib/asm/ASMReader.java @@ -0,0 +1,364 @@ +package codechicken.lib.asm; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.VarInsnNode; + + +import com.google.common.collect.ImmutableMap; + +import static org.objectweb.asm.Opcodes.*; +import static org.objectweb.asm.tree.AbstractInsnNode.*; + +public class ASMReader +{ + public static class ASMBlock + { + public InsnList insns = new InsnList(); + private HashMap labels = new HashMap(); + + public LabelNode getOrAdd(String s) + { + LabelNode l = get(s); + if(l == null) + labels.put(s, l = new LabelNode()); + return l; + } + + public LabelNode get(String s) + { + return labels.get(s); + } + + public void replace(String s, LabelNode l) + { + LabelNode old = get(s); + if(old != null) + { + Map map = ImmutableMap.of(old, l); + for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + { + switch(insn.getType()) + { + case JUMP_INSN: + case FRAME: + case LOOKUPSWITCH_INSN: + case TABLESWITCH_INSN: + case LABEL: + insns.insert(insn, insn.clone(map)); + insns.remove(insn); + } + } + } + labels.put(s, l); + } + } + + public static Map opCodes = new HashMap(); + public static byte[] TYPE; + + static + { + opCodes.put("NOP", NOP); + opCodes.put("ACONST_NULL", ACONST_NULL); + opCodes.put("ICONST_M1", ICONST_M1); + opCodes.put("ICONST_0", ICONST_0); + opCodes.put("ICONST_1", ICONST_1); + opCodes.put("ICONST_2", ICONST_2); + opCodes.put("ICONST_3", ICONST_3); + opCodes.put("ICONST_4", ICONST_4); + opCodes.put("ICONST_5", ICONST_5); + opCodes.put("LCONST_0", LCONST_0); + opCodes.put("LCONST_1", LCONST_1); + opCodes.put("FCONST_0", FCONST_0); + opCodes.put("FCONST_1", FCONST_1); + opCodes.put("FCONST_2", FCONST_2); + opCodes.put("DCONST_0", DCONST_0); + opCodes.put("DCONST_1", DCONST_1); + opCodes.put("BIPUSH", BIPUSH); + opCodes.put("SIPUSH", SIPUSH); + opCodes.put("LDC", LDC); + opCodes.put("ILOAD", ILOAD); + opCodes.put("LLOAD", LLOAD); + opCodes.put("FLOAD", FLOAD); + opCodes.put("DLOAD", DLOAD); + opCodes.put("ALOAD", ALOAD); + opCodes.put("IALOAD", IALOAD); + opCodes.put("LALOAD", LALOAD); + opCodes.put("FALOAD", FALOAD); + opCodes.put("DALOAD", DALOAD); + opCodes.put("AALOAD", AALOAD); + opCodes.put("BALOAD", BALOAD); + opCodes.put("CALOAD", CALOAD); + opCodes.put("SALOAD", SALOAD); + opCodes.put("ISTORE", ISTORE); + opCodes.put("LSTORE", LSTORE); + opCodes.put("FSTORE", FSTORE); + opCodes.put("DSTORE", DSTORE); + opCodes.put("ASTORE", ASTORE); + opCodes.put("IASTORE", IASTORE); + opCodes.put("LASTORE", LASTORE); + opCodes.put("FASTORE", FASTORE); + opCodes.put("DASTORE", DASTORE); + opCodes.put("AASTORE", AASTORE); + opCodes.put("BASTORE", BASTORE); + opCodes.put("CASTORE", CASTORE); + opCodes.put("SASTORE", SASTORE); + opCodes.put("POP", POP); + opCodes.put("POP2", POP2); + opCodes.put("DUP", DUP); + opCodes.put("DUP_X1", DUP_X1); + opCodes.put("DUP_X2", DUP_X2); + opCodes.put("DUP2", DUP2); + opCodes.put("DUP2_X1", DUP2_X1); + opCodes.put("DUP2_X2", DUP2_X2); + opCodes.put("SWAP", SWAP); + opCodes.put("IADD", IADD); + opCodes.put("LADD", LADD); + opCodes.put("FADD", FADD); + opCodes.put("DADD", DADD); + opCodes.put("ISUB", ISUB); + opCodes.put("LSUB", LSUB); + opCodes.put("FSUB", FSUB); + opCodes.put("DSUB", DSUB); + opCodes.put("IMUL", IMUL); + opCodes.put("LMUL", LMUL); + opCodes.put("FMUL", FMUL); + opCodes.put("DMUL", DMUL); + opCodes.put("IDIV", IDIV); + opCodes.put("LDIV", LDIV); + opCodes.put("FDIV", FDIV); + opCodes.put("DDIV", DDIV); + opCodes.put("IREM", IREM); + opCodes.put("LREM", LREM); + opCodes.put("FREM", FREM); + opCodes.put("DREM", DREM); + opCodes.put("INEG", INEG); + opCodes.put("LNEG", LNEG); + opCodes.put("FNEG", FNEG); + opCodes.put("DNEG", DNEG); + opCodes.put("ISHL", ISHL); + opCodes.put("LSHL", LSHL); + opCodes.put("ISHR", ISHR); + opCodes.put("LSHR", LSHR); + opCodes.put("IUSHR", IUSHR); + opCodes.put("LUSHR", LUSHR); + opCodes.put("IAND", IAND); + opCodes.put("LAND", LAND); + opCodes.put("IOR", IOR); + opCodes.put("LOR", LOR); + opCodes.put("IXOR", IXOR); + opCodes.put("LXOR", LXOR); + opCodes.put("IINC", IINC); + opCodes.put("I2L", I2L); + opCodes.put("I2F", I2F); + opCodes.put("I2D", I2D); + opCodes.put("L2I", L2I); + opCodes.put("L2F", L2F); + opCodes.put("L2D", L2D); + opCodes.put("F2I", F2I); + opCodes.put("F2L", F2L); + opCodes.put("F2D", F2D); + opCodes.put("D2I", D2I); + opCodes.put("D2L", D2L); + opCodes.put("D2F", D2F); + opCodes.put("I2B", I2B); + opCodes.put("I2C", I2C); + opCodes.put("I2S", I2S); + opCodes.put("LCMP", LCMP); + opCodes.put("FCMPL", FCMPL); + opCodes.put("FCMPG", FCMPG); + opCodes.put("DCMPL", DCMPL); + opCodes.put("DCMPG", DCMPG); + opCodes.put("IFEQ", IFEQ); + opCodes.put("IFNE", IFNE); + opCodes.put("IFLT", IFLT); + opCodes.put("IFGE", IFGE); + opCodes.put("IFGT", IFGT); + opCodes.put("IFLE", IFLE); + opCodes.put("IF_ICMPEQ", IF_ICMPEQ); + opCodes.put("IF_ICMPNE", IF_ICMPNE); + opCodes.put("IF_ICMPLT", IF_ICMPLT); + opCodes.put("IF_ICMPGE", IF_ICMPGE); + opCodes.put("IF_ICMPGT", IF_ICMPGT); + opCodes.put("IF_ICMPLE", IF_ICMPLE); + opCodes.put("IF_ACMPEQ", IF_ACMPEQ); + opCodes.put("IF_ACMPNE", IF_ACMPNE); + opCodes.put("GOTO", GOTO); + opCodes.put("JSR", JSR); + opCodes.put("RET", RET); + opCodes.put("TABLESWITCH", TABLESWITCH); + opCodes.put("LOOKUPSWITCH", LOOKUPSWITCH); + opCodes.put("IRETURN", IRETURN); + opCodes.put("LRETURN", LRETURN); + opCodes.put("FRETURN", FRETURN); + opCodes.put("DRETURN", DRETURN); + opCodes.put("ARETURN", ARETURN); + opCodes.put("RETURN", RETURN); + opCodes.put("GETSTATIC", GETSTATIC); + opCodes.put("PUTSTATIC", PUTSTATIC); + opCodes.put("GETFIELD", GETFIELD); + opCodes.put("PUTFIELD", PUTFIELD); + opCodes.put("INVOKEVIRTUAL", INVOKEVIRTUAL); + opCodes.put("INVOKESPECIAL", INVOKESPECIAL); + opCodes.put("INVOKESTATIC", INVOKESTATIC); + opCodes.put("INVOKEINTERFACE", INVOKEINTERFACE); + opCodes.put("INVOKEDYNAMIC", INVOKEDYNAMIC); + opCodes.put("NEW", NEW); + opCodes.put("NEWARRAY", NEWARRAY); + opCodes.put("ANEWARRAY", ANEWARRAY); + opCodes.put("ARRAYLENGTH", ARRAYLENGTH); + opCodes.put("ATHROW", ATHROW); + opCodes.put("CHECKCAST", CHECKCAST); + opCodes.put("INSTANCEOF", INSTANCEOF); + opCodes.put("MONITORENTER", MONITORENTER); + opCodes.put("MONITOREXIT", MONITOREXIT); + opCodes.put("MULTIANEWARRAY", MULTIANEWARRAY); + opCodes.put("IFNULL", IFNULL); + opCodes.put("IFNONNULL", IFNONNULL); + + //derived from classWriter, mapped to AbstractInsnNode + TYPE = new byte[200]; + String s = "AAAAAAAAAAAAAAAABBJ__CCCCC____________________AAAAAAAACC" + + "CCC____________________AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHCLMAA" + + "AAAAEEEEFFFFGDBDAADDAA_NHH"; + for (int i = 0; i < s.length(); i++) + TYPE[i] = (byte) (s.charAt(i) - 'A'); + } + + public static Map loadResource(String res) + { + return loadResource(ASMHelper.class.getResourceAsStream(res), res); + } + + public static Map loadResource(InputStream in, String res) + { + HashMap blocks = new HashMap(); + String current = "unnamed"; + ASMBlock block = new ASMBlock(); + try + { + BufferedReader r = new BufferedReader(new InputStreamReader(in)); + String line; + while((line = r.readLine()) != null) + { + { + int hpos = line.indexOf('#'); + if(hpos >= 0) line = line.substring(0, hpos); + } + line = line.trim(); + if(line.length() == 0) continue; + if(line.startsWith("list ")) + { + if(block.insns.size() > 0) blocks.put(current, block); + current = line.substring(5); + block = new ASMBlock(); + continue; + } + + try + { + AbstractInsnNode insn = null; + String[] split = line.replace(" : ", ":").split(" "); + Integer i_opcode = opCodes.get(split[0]); + if(i_opcode == null) + { + if(split[0].equals("LINENUMBER")) + insn = new LineNumberNode(Integer.parseInt(split[1]), block.getOrAdd(split[2])); + else if(split[0].startsWith("L")) + insn = block.getOrAdd(split[0]); + else + throw new Exception("Unknown opcode " + split[0]); + } + else + { + int opcode = i_opcode; + switch(TYPE[opcode]) + { + case INSN: + insn = new InsnNode(opcode); + break; + case INT_INSN: + insn = new IntInsnNode(opcode, Integer.parseInt(split[1])); + break; + case VAR_INSN: + insn = new VarInsnNode(opcode, Integer.parseInt(split[1])); + break; + case TYPE_INSN: + insn = new ObfMapping(split[1]).toInsn(opcode); + break; + case FIELD_INSN: + case METHOD_INSN: + insn = ObfMapping.fromDesc(split[1]).toInsn(opcode); + break; + case INVOKE_DYNAMIC_INSN: + throw new Exception("Found INVOKEDYNAMIC while reading"); + case JUMP_INSN: + insn = new JumpInsnNode(opcode, block.getOrAdd(split[1])); + break; + case LDC_INSN: + String cst = split[1]; + if(cst.contains("")) + insn = new LdcInsnNode(cst.substring(1, cst.length()-1)); + else if(cst.endsWith("L")) + insn = new LdcInsnNode(Long.valueOf(cst.substring(0, cst.length()-1))); + else if(cst.endsWith("F")) + insn = new LdcInsnNode(Float.valueOf(cst.substring(0, cst.length()-1))); + else if(cst.endsWith("D")) + insn = new LdcInsnNode(Double.valueOf(cst.substring(0, cst.length()-1))); + else + insn = new LdcInsnNode(Integer.valueOf(cst)); + break; + case IINC_INSN: + insn = new IincInsnNode(opcode, Integer.parseInt(split[1])); + break; + case LABEL: + throw new Exception("Use L# for labels"); + case TABLESWITCH_INSN: + case LOOKUPSWITCH_INSN: + throw new Exception("I don't know how to deal with this insn type"); + case MULTIANEWARRAY_INSN: + insn = new MultiANewArrayInsnNode(split[1], Integer.parseInt(split[2])); + break; + case FRAME: + throw new Exception("Use ClassWriter.COMPUTE_FRAMES"); + } + } + + if(insn != null) + block.insns.add(insn); + } + catch(Exception e) + { + System.err.println("Error while reading ASM Block "+ + current+" from "+res+", line: "+line); + e.printStackTrace(); + } + } + + r.close(); + if(block.insns.size() > 0) blocks.put(current, block); + } + catch(IOException e) + { + throw new RuntimeException("Failed to read ASM resource: "+res, e); + } + return blocks; + } +} diff --git a/codechicken/lib/asm/CC_ClassWriter.java b/codechicken/lib/asm/CC_ClassWriter.java new file mode 100644 index 0000000..22fb36c --- /dev/null +++ b/codechicken/lib/asm/CC_ClassWriter.java @@ -0,0 +1,29 @@ +package codechicken.lib.asm; + +import org.objectweb.asm.ClassWriter; + + +public class CC_ClassWriter extends ClassWriter +{ + public CC_ClassWriter(int flags) + { + super(flags); + } + + @Override + protected String getCommonSuperClass(String type1, String type2) + { + String c = type1.replace('/', '.'); + String d = type2.replace('/', '.'); + if(ClassHeirachyManager.classExtends(d, c)) + return type1; + if(ClassHeirachyManager.classExtends(c, d)) + return type2; + do + { + c = ClassHeirachyManager.getSuperClass(c); + } + while(!ClassHeirachyManager.classExtends(d, c)); + return c.replace('.', '/'); + } +} diff --git a/codechicken/lib/asm/ClassHeirachyManager.java b/codechicken/lib/asm/ClassHeirachyManager.java new file mode 100644 index 0000000..e3c890d --- /dev/null +++ b/codechicken/lib/asm/ClassHeirachyManager.java @@ -0,0 +1,124 @@ +package codechicken.lib.asm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import org.objectweb.asm.tree.ClassNode; + + +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.launchwrapper.LaunchClassLoader; + +/** + * This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed evaluation up slightly by automatically caching superclasses when they are first loaded. + */ +public class ClassHeirachyManager implements IClassTransformer +{ + public static HashSet knownClasses = new HashSet(); + public static HashMap> superclasses = new HashMap>(); + private static LaunchClassLoader cl = (LaunchClassLoader)ClassHeirachyManager.class.getClassLoader(); + + /** + * Returns true if clazz extends, either directly or indirectly, superclass. + * @param clazz The class in question + * @param superclass The class being extended + * @param bytes The bytes for the clazz. Only needed if not already defined. + * @return + */ + public static boolean classExtends(String clazz, String superclass, byte[] bytes) + { + if(!knownClasses.contains(clazz)) + new ClassHeirachyManager().transform(clazz, clazz, bytes); + + return classExtends(clazz, superclass); + } + + public static boolean classExtends(String clazz, String superclass) + { + if(clazz.equals(superclass)) + return true; + + if(clazz.equals("java.lang.Object")) + return false; + + declareClass(clazz); + + if(!superclasses.containsKey(clazz))//just can't handle this + return false; + + for(String s : superclasses.get(clazz)) + if(classExtends(s, superclass)) + return true; + + return false; + } + + private static void declareClass(String clazz) + { + try + { + if(!knownClasses.contains(clazz)) + { + try + { + byte[] bytes = cl.getClassBytes(clazz); + if(bytes != null) + new ClassHeirachyManager().transform(clazz, clazz, bytes); + } + catch(Exception e) + { + } + + if(!knownClasses.contains(clazz)) + { + Class aclass = Class.forName(clazz); + + knownClasses.add(clazz); + if(aclass.isInterface()) + addSuperclass(clazz, "java.lang.Object"); + else + addSuperclass(clazz, aclass.getSuperclass().getName()); + for(Class iclass : aclass.getInterfaces()) + addSuperclass(clazz, iclass.getName()); + } + } + } + catch(ClassNotFoundException e) + { + } + } + + @Override + public byte[] transform(String name, String tname, byte[] bytes) + { + if (bytes == null) return null; + if(!knownClasses.contains(name)) + { + ClassNode node = ASMHelper.createClassNode(bytes); + + knownClasses.add(name); + addSuperclass(name, node.superName.replace('/', '.')); + for(String iclass : node.interfaces) + addSuperclass(name, iclass.replace('/', '.')); + } + + return bytes; + } + + private static void addSuperclass(String name, String superclass) + { + ArrayList supers = superclasses.get(name); + if(supers == null) + superclasses.put(name, supers = new ArrayList()); + supers.add(superclass); + supers.add(new ObfMapping(superclass).toRuntime().javaClass()); + } + + public static String getSuperClass(String c) + { + declareClass(c); + if(!knownClasses.contains(c)) + return "java.lang.Object"; + return superclasses.get(c).get(0); + } +} diff --git a/codechicken/lib/asm/InsnListPrinter.java b/codechicken/lib/asm/InsnListPrinter.java new file mode 100644 index 0000000..5c72282 --- /dev/null +++ b/codechicken/lib/asm/InsnListPrinter.java @@ -0,0 +1,214 @@ +package codechicken.lib.asm; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; + +import org.objectweb.asm.Label; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.FrameNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.VarInsnNode; +import org.objectweb.asm.util.Textifier; + +import codechicken.lib.asm.InstructionComparator.InsnListSection; + +public class InsnListPrinter extends Textifier +{ + private boolean buildingLabelMap = false; + + public void visitInsnList(InsnList list) + { + text.clear(); + if(labelNames == null) + labelNames = new HashMap(); + else + labelNames.clear(); + + buildingLabelMap = true; + for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) + if(insn.getType() == 8) + visitLabel(((LabelNode)insn).getLabel()); + + text.clear(); + buildingLabelMap = false; + + for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) + _visitInsn(insn); + } + + public void visitInsnList(InsnListSection subsection) + { + text.clear(); + if(labelNames == null) + labelNames = new HashMap(); + else + labelNames.clear(); + + buildingLabelMap = true; + { + AbstractInsnNode insn = subsection.first; + while(true) + { + if(insn.getType() == 8) + visitLabel(((LabelNode)insn).getLabel()); + if(insn == subsection.last) + break; + insn = insn.getNext(); + } + } + + text.clear(); + buildingLabelMap = false; + + { + AbstractInsnNode insn = subsection.first; + while(true) + { + _visitInsn(insn); + if(insn == subsection.last) + break; + insn = insn.getNext(); + } + } + } + + public void visitInsn(AbstractInsnNode insn) + { + text.clear(); + if(labelNames == null) + labelNames = new HashMap(); + else + labelNames.clear(); + + _visitInsn(insn); + } + + private void _visitInsn(AbstractInsnNode insn) + { + switch(insn.getType()) + { + case 0: + visitInsn(insn.getOpcode()); + break; + case 1: + IntInsnNode iinsn = (IntInsnNode)insn; + visitIntInsn(iinsn.getOpcode(), iinsn.operand); + break; + case 2: + VarInsnNode vinsn = (VarInsnNode)insn; + visitVarInsn(vinsn.getOpcode(), vinsn.var); + break; + case 3: + TypeInsnNode tinsn = (TypeInsnNode)insn; + visitTypeInsn(tinsn.getOpcode(), tinsn.desc); + break; + case 4: + FieldInsnNode finsn = (FieldInsnNode)insn; + visitFieldInsn(finsn.getOpcode(), finsn.owner, finsn.name, finsn.desc); + break; + case 5: + MethodInsnNode minsn = (MethodInsnNode)insn; + visitMethodInsn(minsn.getOpcode(), minsn.owner, minsn.name, minsn.desc); + break; + case 6: + InvokeDynamicInsnNode idinsn = (InvokeDynamicInsnNode)insn; + visitInvokeDynamicInsn(idinsn.name, idinsn.desc, idinsn.bsm, idinsn.bsmArgs); + break; + case 7: + JumpInsnNode jinsn = (JumpInsnNode)insn; + visitJumpInsn(jinsn.getOpcode(), jinsn.label.getLabel()); + break; + case 8: + LabelNode linsn = (LabelNode)insn; + visitLabel(linsn.getLabel()); + break; + case 9: + LdcInsnNode ldcinsn = (LdcInsnNode)insn; + visitLdcInsn(ldcinsn.cst); + break; + case 10: + IincInsnNode iiinsn = (IincInsnNode)insn; + visitIincInsn(iiinsn.var, iiinsn.incr); + break; + case 11: + TableSwitchInsnNode tsinsn = (TableSwitchInsnNode)insn; + Label[] tslables = new Label[tsinsn.labels.size()]; + for(int i = 0; i < tslables.length; i++) + tslables[i] = tsinsn.labels.get(i).getLabel(); + visitTableSwitchInsn(tsinsn.min, tsinsn.max, tsinsn.dflt.getLabel(), tslables); + break; + case 12: + LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode)insn; + Label[] lslables = new Label[lsinsn.labels.size()]; + for(int i = 0; i < lslables.length; i++) + lslables[i] = lsinsn.labels.get(i).getLabel(); + int[] lskeys = new int[lsinsn.keys.size()]; + for(int i = 0; i < lskeys.length; i++) + lskeys[i] = lsinsn.keys.get(i); + visitLookupSwitchInsn(lsinsn.dflt.getLabel(), lskeys, lslables); + break; + case 13: + MultiANewArrayInsnNode ainsn = (MultiANewArrayInsnNode)insn; + visitMultiANewArrayInsn(ainsn.desc, ainsn.dims); + break; + case 14: + FrameNode fnode = (FrameNode)insn; + switch(fnode.type) + { + case -1: + case 0: + visitFrame(fnode.type, fnode.local.size(), fnode.local.toArray(), fnode.stack.size(), fnode.stack.toArray()); + break; + case 1: + visitFrame(fnode.type, fnode.local.size(), fnode.local.toArray(), 0, null); + break; + case 2: + visitFrame(fnode.type, fnode.local.size(), null, 0, null); + break; + case 3: + visitFrame(fnode.type, 0, null, 0, null); + break; + case 4: + visitFrame(fnode.type, 0, null, 1, fnode.stack.toArray()); + } + break; + case 15: + LineNumberNode lnode = (LineNumberNode)insn; + visitLineNumber(lnode.line, lnode.start.getLabel()); + break; + } + } + + @Override + public void visitLabel(Label label) + { + if(!buildingLabelMap && !labelNames.containsKey(label)) + { + labelNames.put(label, "LEXT"+labelNames.size()); + } + super.visitLabel(label); + } + + public String textString() + { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + print(pw); + pw.flush(); + return sw.toString(); + } +} diff --git a/codechicken/lib/asm/InstructionComparator.java b/codechicken/lib/asm/InstructionComparator.java new file mode 100644 index 0000000..3d4b07c --- /dev/null +++ b/codechicken/lib/asm/InstructionComparator.java @@ -0,0 +1,254 @@ +package codechicken.lib.asm; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.VarInsnNode; + +import static org.objectweb.asm.tree.AbstractInsnNode.*; + +import codechicken.lib.asm.ObfMapping; + +public class InstructionComparator +{ + public static class InsnListSection + { + public InsnListSection(AbstractInsnNode first, AbstractInsnNode last) + { + this.first = first; + this.last = last; + } + + public InsnListSection(InsnList haystack, int start, int end) + { + this(haystack.get(start), haystack.get(end)); + } + + public AbstractInsnNode first; + public AbstractInsnNode last; + } + + public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2) + { + if(insn1.var == -1 || insn2.var == -1) + return true; + + return insn1.var == insn2.var; + } + + public static boolean methodInsnEqual(AbstractInsnNode absnode, int Opcode, ObfMapping method) + { + if(!(absnode instanceof MethodInsnNode) || absnode.getOpcode() != Opcode) + return false; + + return method.matches((MethodInsnNode)absnode); + } + + public static boolean methodInsnEqual(MethodInsnNode insn1, MethodInsnNode insn2) + { + return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc); + } + + public static boolean fieldInsnEqual(FieldInsnNode insn1, FieldInsnNode insn2) + { + return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc); + } + + public static boolean ldcInsnEqual(LdcInsnNode insn1, LdcInsnNode insn2) + { + if(insn1.cst.equals("~") || insn2.cst.equals("~")) + return true; + + return insn1.cst.equals(insn2.cst); + } + + public static boolean typeInsnEqual(TypeInsnNode insn1, TypeInsnNode insn2) + { + if(insn1.desc.equals("~") || insn2.desc.equals("~")) + return true; + + return insn1.desc.equals(insn2.desc); + } + + public static boolean iincInsnEqual(IincInsnNode node1, IincInsnNode node2) + { + return node1.var == node2.var && node1.incr == node2.incr; + } + + public static boolean intInsnEqual(IntInsnNode node1, IntInsnNode node2) + { + if(node1.operand == -1 || node2.operand == -1) + return true; + + return node1.operand == node2.operand; + } + + public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) + { + if(node1.getOpcode() != node2.getOpcode()) + return false; + + switch(node2.getType()) + { + case VAR_INSN: + return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); + case TYPE_INSN: + return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); + case FIELD_INSN: + return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); + case METHOD_INSN: + return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); + case LDC_INSN: + return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); + case IINC_INSN: + return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); + case INT_INSN: + return intInsnEqual((IntInsnNode)node1, (IntInsnNode)node2); + default: + return true; + } + } + + public static InsnList getImportantList(InsnList list) + { + if(list.size() == 0) + return list; + + HashMap labels = new HashMap(); + for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) + { + if(insn instanceof LabelNode) + labels.put((LabelNode)insn, (LabelNode)insn); + } + + InsnList importantNodeList = new InsnList(); + for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) + { + if(insn instanceof LabelNode || insn instanceof LineNumberNode) + continue; + + importantNodeList.add(insn.clone(labels)); + } + return importantNodeList; + } + + public static boolean insnListMatches(InsnList haystack, InsnList needle, int start) + { + if(haystack.size()-start < needle.size()) + return false; + + for(int i = 0; i < needle.size(); i++) + { + if(!insnEqual(haystack.get(i+start), needle.get(i))) + return false; + } + return true; + } + + public static List insnListFind(InsnList haystack, InsnList needle) + { + LinkedList list = new LinkedList(); + for(int start = 0; start <= haystack.size()-needle.size(); start++) + if(insnListMatches(haystack, needle, start)) + list.add(start); + + return list; + } + + public static List insnListFindStart(InsnList haystack, InsnList needle) + { + LinkedList callNodes = new LinkedList(); + for(int callPoint : insnListFind(haystack, needle)) + callNodes.add(haystack.get(callPoint)); + return callNodes; + } + + public static List insnListFindEnd(InsnList haystack, InsnList needle) + { + LinkedList callNodes = new LinkedList(); + for(int callPoint : insnListFind(haystack, needle)) + callNodes.add(haystack.get(callPoint+needle.size()-1)); + return callNodes; + } + + public static List insnListFindL(InsnList haystack, InsnList needle) + { + HashSet controlFlowLabels = new HashSet(); + + for(AbstractInsnNode insn = haystack.getFirst(); insn != null; insn = insn.getNext()) + { + switch(insn.getType()) + { + case 8: + case 15: + break; + case 7: + JumpInsnNode jinsn = (JumpInsnNode)insn; + controlFlowLabels.add(jinsn.label); + break; + case 11: + TableSwitchInsnNode tsinsn = (TableSwitchInsnNode)insn; + for(LabelNode label : tsinsn.labels) + controlFlowLabels.add(label); + break; + case 12: + LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode)insn; + for(LabelNode label : lsinsn.labels) + controlFlowLabels.add(label); + break; + } + } + + LinkedList list = new LinkedList(); + nextsection: for(int start = 0; start <= haystack.size()-needle.size(); start++) + { + InsnListSection section = insnListMatchesL(haystack, needle, start, controlFlowLabels); + if(section != null) + { + for(InsnListSection asection : list) + if(asection.last == section.last) + continue nextsection; + + list.add(section); + } + } + + return list; + } + + private static InsnListSection insnListMatchesL(InsnList haystack, InsnList needle, int start, HashSet controlFlowLabels) + { + int h = start, n = 0; + for(;h < haystack.size() && n < needle.size(); h++) + { + AbstractInsnNode insn = haystack.get(h); + if(insn.getType() == 15) + continue; + if(insn.getType() == 8 && !controlFlowLabels.contains(insn)) + continue; + + if(!insnEqual(haystack.get(h), needle.get(n))) + return null; + n++; + } + if(n != needle.size()) + return null; + + return new InsnListSection(haystack, start, h-1); + } +} diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java new file mode 100644 index 0000000..8ebe831 --- /dev/null +++ b/codechicken/lib/asm/ObfMapping.java @@ -0,0 +1,225 @@ +package codechicken.lib.asm; + +import java.io.IOException; + +import net.minecraft.launchwrapper.LaunchClassLoader; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.commons.Remapper; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TypeInsnNode; + +import com.google.common.base.Objects; + +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; + +public class ObfMapping +{ + /** + * CCC will deal with this. + */ + public static Remapper runtimeMapper = FMLDeobfuscatingRemapper.INSTANCE; + public static Remapper mcpMapper = null; + + public static final boolean obfuscated; + + static + { + boolean obf = true; + try + { + obf = ((LaunchClassLoader)ObfMapping.class.getClassLoader()).getClassBytes("net.minecraft.world.World") == null; + } + catch(IOException iox) {} + obfuscated = obf; + } + + public String s_owner; + public String s_name; + public String s_desc; + + public boolean runtime; + + public ObfMapping(String owner) + { + this(owner, null, null); + } + + public ObfMapping(String owner, String name, String desc) + { + this.s_owner = owner; + this.s_name = name; + this.s_desc = desc; + + if(s_owner.contains(".")) + throw new IllegalArgumentException(s_owner); + + if(mcpMapper != null) + map(mcpMapper); + } + + public ObfMapping(ObfMapping descmap, String subclass) + { + this(subclass, descmap.s_name, descmap.s_desc); + } + + public static ObfMapping fromDesc(String s) + { + int lastDot = s.lastIndexOf('.'); + if(lastDot < 0) + return new ObfMapping(s, "", ""); + int sep = s.indexOf('(');//methods + int sep_end = sep; + if(sep < 0) { + sep = s.indexOf(' ');//some stuffs + sep_end = sep+1; + } + if(sep < 0) { + sep = s.indexOf(':');//fields + sep_end = sep+1; + } + if(sep < 0) + return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), ""); + + return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot+1, sep), s.substring(sep_end)); + } + + public ObfMapping subclass(String subclass) + { + return new ObfMapping(this, subclass); + } + + public boolean matches(MethodNode node) + { + return s_name.equals(node.name) && s_desc.equals(node.desc); + } + + public boolean matches(MethodInsnNode node) + { + return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc); + } + + public AbstractInsnNode toInsn(int opcode) + { + if(isClass()) + return new TypeInsnNode(opcode, s_owner); + else if(isMethod()) + return new MethodInsnNode(opcode, s_owner, s_name, s_desc); + else + return new FieldInsnNode(opcode, s_owner, s_name, s_desc); + } + + public void visitTypeInsn(MethodVisitor mv, int opcode) + { + mv.visitTypeInsn(opcode, s_owner); + } + + public void visitMethodInsn(MethodVisitor mv, int opcode) + { + mv.visitMethodInsn(opcode, s_owner, s_name, s_desc); + } + + public void visitFieldInsn(MethodVisitor mv, int opcode) + { + mv.visitFieldInsn(opcode, s_owner, s_name, s_desc); + } + + public boolean isClass(String name) + { + return name.replace('.', '/').equals(s_owner); + } + + public boolean matches(String name, String desc) + { + return s_name.equals(name) && s_desc.equals(desc); + } + + public boolean matches(FieldNode node) + { + return s_name.equals(node.name) && s_desc.equals(node.desc); + } + + public boolean matches(FieldInsnNode node) + { + return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc); + } + + public String javaClass() + { + return s_owner.replace('/', '.'); + } + + @Override + public boolean equals(Object obj) + { + if(!(obj instanceof ObfMapping)) + return false; + + ObfMapping desc = (ObfMapping)obj; + return s_owner.equals(desc.s_owner) && s_name.equals(desc.s_name) && s_desc.equals(desc.s_desc); + } + + @Override + public int hashCode() + { + return Objects.hashCode(s_desc, s_name, s_owner); + } + + @Override + public String toString() + { + if(s_name.length() == 0) + return "["+s_owner+"]"; + if(s_desc.length() == 0) + return "["+s_owner+"."+s_name+"]"; + return "["+s_owner+"."+s_name+s_desc+"]"; + } + + public boolean isClass() + { + return s_name.length() == 0; + } + + public boolean isMethod() + { + return s_desc.contains("("); + } + + public boolean isField() + { + return !isClass() && !isMethod(); + } + + public ObfMapping map(Remapper mapper) + { + if(isMethod()) + s_name = mapper.mapMethodName(s_owner, s_name, s_desc); + else if(isField()) + s_name = mapper.mapFieldName(s_owner, s_name, s_desc); + + s_owner = mapper.mapType(s_owner); + + if(!isClass()) + s_desc = mapper.mapDesc(s_desc); + + return this; + } + + public ObfMapping toRuntime() + { + if(!runtime) + map(runtimeMapper); + + runtime = true; + return this; + } + + public ObfMapping copy() + { + return new ObfMapping(s_owner, s_name, s_desc); + } +} diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java new file mode 100644 index 0000000..c1fc27c --- /dev/null +++ b/codechicken/lib/colour/Colour.java @@ -0,0 +1,139 @@ +package codechicken.lib.colour; + +import org.lwjgl.opengl.GL11; + +import codechicken.lib.math.MathHelper; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public abstract class Colour +{ + public byte r; + public byte g; + public byte b; + public byte a; + + public Colour(int r, int g, int b, int a) + { + this.r = (byte) r; + this.g = (byte) g; + this.b = (byte) b; + this.a = (byte) a; + } + + public Colour(Colour colour) + { + r = colour.r; + g = colour.g; + b = colour.b; + a = colour.a; + } + + @SideOnly(Side.CLIENT) + public void glColour() + { + GL11.glColor4ub(r, g, b, a); + } + + @SideOnly(Side.CLIENT) + public void glColour(int a) + { + GL11.glColor4ub(r, g, b, (byte) a); + } + + @SideOnly(Side.CLIENT) + @Deprecated + public void glColour(byte a) + { + GL11.glColor4ub(r, g, b, a); + } + + public abstract int pack(); + + @Override + public String toString() + { + return getClass().getSimpleName() + "[0x" + Integer.toHexString(pack()).toUpperCase() + "]"; + } + + public Colour add(Colour colour2) + { + a += colour2.a; + r += colour2.r; + g += colour2.g; + b += colour2.b; + return this; + } + + public Colour sub(Colour colour2) + { + int ia = (a & 0xFF) - (colour2.a & 0xFF); + int ir = (r & 0xFF) - (colour2.r & 0xFF); + int ig = (g & 0xFF) - (colour2.g & 0xFF); + int ib = (b & 0xFF) - (colour2.b & 0xFF); + a = (byte) (ia < 0 ? 0 : ia); + r = (byte) (ir < 0 ? 0 : ir); + g = (byte) (ig < 0 ? 0 : ig); + b = (byte) (ib < 0 ? 0 : ib); + return this; + } + + public Colour invert() + { + a = (byte) (0xFF - (a & 0xFF)); + r = (byte) (0xFF - (r & 0xFF)); + g = (byte) (0xFF - (g & 0xFF)); + b = (byte) (0xFF - (b & 0xFF)); + return this; + } + + public Colour multiply(Colour colour2) + { + a = (byte) ((a & 0xFF) * ((colour2.a & 0xFF) / 255D)); + r = (byte) ((r & 0xFF) * ((colour2.r & 0xFF) / 255D)); + g = (byte) ((g & 0xFF) * ((colour2.g & 0xFF) / 255D)); + b = (byte) ((b & 0xFF) * ((colour2.b & 0xFF) / 255D)); + return this; + } + + public Colour scale(double d) + { + a = (byte) ((a & 0xFF) * d); + r = (byte) ((r & 0xFF) * d); + g = (byte) ((g & 0xFF) * d); + b = (byte) ((b & 0xFF) * d); + return this; + } + + public Colour interpolate(Colour colour2, double d) + { + return this.add(colour2.copy().sub(this).scale(d)); + } + + public Colour multiplyC(double d) + { + r = (byte) MathHelper.clip((r & 0xFF) * d, 0, 255); + g = (byte) MathHelper.clip((g & 0xFF) * d, 0, 255); + b = (byte) MathHelper.clip((b & 0xFF) * d, 0, 255); + + return this; + } + + public abstract Colour copy(); + + public int rgb() + { + return (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); + } + + public int argb() + { + return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); + } + + public int rgba() + { + return (r & 0xFF) << 24 | (g & 0xFF) << 16 | (b & 0xFF) << 8 | (a & 0xFF); + } +} diff --git a/codechicken/lib/colour/ColourARGB.java b/codechicken/lib/colour/ColourARGB.java new file mode 100644 index 0000000..376ed0a --- /dev/null +++ b/codechicken/lib/colour/ColourARGB.java @@ -0,0 +1,34 @@ +package codechicken.lib.colour; + +public class ColourARGB extends Colour +{ + public ColourARGB(int colour) + { + super((colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF, (colour >> 24) & 0xFF); + } + + public ColourARGB(int a, int r, int g, int b) + { + super(r, g, b, a); + } + + public ColourARGB(ColourARGB colour) + { + super(colour); + } + + public ColourARGB copy() + { + return new ColourARGB(this); + } + + public int pack() + { + return pack(this); + } + + public static int pack(Colour colour) + { + return (colour.a&0xFF) << 24 | (colour.r&0xFF) << 16 | (colour.g&0xFF) << 8 | (colour.b&0xFF); + } +} diff --git a/codechicken/lib/colour/ColourRGBA.java b/codechicken/lib/colour/ColourRGBA.java new file mode 100644 index 0000000..54baf91 --- /dev/null +++ b/codechicken/lib/colour/ColourRGBA.java @@ -0,0 +1,40 @@ +package codechicken.lib.colour; + +public class ColourRGBA extends Colour +{ + public ColourRGBA(int colour) + { + super((colour >> 24) & 0xFF, (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF); + } + + public ColourRGBA(double r, double g, double b, double a) + { + super((int) (255 * r), (int) (255 * g), (int) (255 * b), (int) (255 * a)); + } + + public ColourRGBA(int r, int g, int b, int a) + { + super(r, g, b, a); + } + + public ColourRGBA(ColourRGBA colour) + { + super(colour); + } + + public int pack() + { + return pack(this); + } + + @Override + public Colour copy() + { + return new ColourRGBA(this); + } + + public static int pack(Colour colour) + { + return (colour.r&0xFF) << 24 | (colour.g&0xFF) << 16 | (colour.b&0xFF) << 8 | (colour.a&0xFF); + } +} diff --git a/codechicken/lib/colour/CustomGradient.java b/codechicken/lib/colour/CustomGradient.java new file mode 100644 index 0000000..b4a5a0b --- /dev/null +++ b/codechicken/lib/colour/CustomGradient.java @@ -0,0 +1,34 @@ +package codechicken.lib.colour; + +import java.awt.image.BufferedImage; + +import net.minecraft.util.ResourceLocation; + +import codechicken.lib.math.MathHelper; +import codechicken.lib.render.TextureUtils; + +public class CustomGradient +{ + public int[] gradient; + + public CustomGradient(ResourceLocation textureFile) + { + BufferedImage img = TextureUtils.loadBufferedImage(textureFile); + int[] data = new int[img.getWidth()]; + img.getRGB(0, 0, img.getWidth(), 1, data, 0, img.getWidth()); + gradient = new int[img.getWidth()]; + for(int i = 0; i < data.length; i++) + gradient[i] = (data[i]<<8)|(((data[i])>>24)&0xFF); + } + + public ColourRGBA getColour(double position) + { + return new ColourRGBA(getColourI(position)); + } + + public int getColourI(double position) + { + int off = (int)MathHelper.clip(gradient.length*position, 0, gradient.length-1); + return gradient[off]; + } +} diff --git a/codechicken/lib/config/ConfigFile.java b/codechicken/lib/config/ConfigFile.java new file mode 100644 index 0000000..6b84756 --- /dev/null +++ b/codechicken/lib/config/ConfigFile.java @@ -0,0 +1,153 @@ +package codechicken.lib.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; + +public class ConfigFile extends ConfigTagParent +{ + public ConfigFile(File file) + { + if(!file.exists()) + { + try + { + file.createNewFile(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + this.file = file; + newlinemode = 2; + loadConfig(); + } + + private void loadConfig() + { + loading = true; + BufferedReader reader; + try + { + reader = new BufferedReader(new FileReader(file)); + + while(true) + { + reader.mark(2000); + String line = reader.readLine(); + if(line != null && line.startsWith("#")) + { + if(comment == null || comment.equals("")) + comment = line.substring(1); + else + comment = comment+"\n"+line.substring(1); + } + else + { + reader.reset(); + break; + } + } + loadChildren(reader); + reader.close(); + + } + catch(IOException e) + { + throw new RuntimeException(e); + } + + loading = false; + } + + @Override + public ConfigFile setComment(String header) + { + super.setComment(header); + return this; + } + + @Override + public ConfigFile setSortMode(int mode) + { + super.setSortMode(mode); + return this; + } + + @Override + public String getNameQualifier() + { + return ""; + } + + public static String readLine(BufferedReader reader) throws IOException + { + String line = reader.readLine(); + if(line != null) + return line.replace("\t", ""); + return line; + } + + public static String formatLine(String line) + { + line = line.replace("\t", ""); + if(line.startsWith("#")) + { + return line; + } + else if(line.contains("=")) + { + line = line.substring(0, line.indexOf("=")).replace(" ", "")+line.substring(line.indexOf("=")); + return line; + } + else + { + line = line.replace(" ", ""); + return line; + } + } + + public static void writeLine(PrintWriter writer, String line, int tabs) + { + for(int i = 0; i < tabs; i++) + writer.print('\t'); + + writer.println(line); + } + + public void saveConfig() + { + if(loading) + return; + + PrintWriter writer; + try + { + writer = new PrintWriter(file); + } + catch(FileNotFoundException e) + { + throw new RuntimeException(e); + } + + writeComment(writer, 0); + ConfigFile.writeLine(writer, "", 0); + saveTagTree(writer, 0, ""); + writer.flush(); + writer.close(); + } + + public boolean isLoading() + { + return loading; + } + + public File file; + private boolean loading; + + public static final byte[] lineend = new byte[]{0xD, 0xA}; +} diff --git a/codechicken/lib/config/ConfigTag.java b/codechicken/lib/config/ConfigTag.java new file mode 100644 index 0000000..82987d3 --- /dev/null +++ b/codechicken/lib/config/ConfigTag.java @@ -0,0 +1,307 @@ +package codechicken.lib.config; + +import java.io.PrintWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import codechicken.lib.colour.Colour; +import codechicken.lib.colour.ColourRGBA; + +public class ConfigTag extends ConfigTagParent +{ + public ConfigTag(ConfigTagParent parent, String name) + { + this.parent = parent; + this.name = name; + qualifiedname = parent.getNameQualifier()+name; + newline = parent.newlinemode == 2; + parent.addChild(this); + } + + @Override + public String getNameQualifier() + { + return qualifiedname+"."; + } + + @Override + public void saveConfig() + { + parent.saveConfig(); + } + + /** + * Called when the tag is loaded from a config file as opposed to constructed by a mod + * @return this + */ + public ConfigTag onLoaded() + { + return this; + } + + public void setValue(String value) + { + this.value = value; + saveConfig(); + } + + public void setDefaultValue(String defaultvalue) + { + if(value == null) + { + value = defaultvalue; + saveConfig(); + } + } + + public void setIntValue(int i) + { + setValue(Integer.toString(i)); + } + + public void setBooleanValue(boolean b) + { + setValue(Boolean.toString(b)); + } + + public void setHexValue(int i) + { + setValue("0x"+Long.toString(((long)i) << 32 >>> 32, 16)); + } + + public void setColourRGB(Colour c) + { + String s = Long.toString(((long)c.rgb()) << 32 >>> 32, 16); + while(s.length() < 6) + s = "0"+s; + setValue("0x"+s.toUpperCase()); + } + + public String getValue() + { + return value; + } + + public String getValue(String defaultvalue) + { + setDefaultValue(defaultvalue); + return value; + } + + public int getIntValue() + { + return Integer.parseInt(getValue()); + } + + public int getIntValue(int defaultvalue) + { + if(value == null) + { + setIntValue(defaultvalue); + } + try + { + return getIntValue(); + } + catch(NumberFormatException nfe) + { + setIntValue(defaultvalue); + return getIntValue(); + } + } + + public boolean getBooleanValue() + { + String value = getValue(); + if(value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) + { + return true; + } + else if(value != null && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) + { + return false; + } + throw new NumberFormatException(qualifiedname+".value="+value); + } + + public boolean getBooleanValue(boolean defaultvalue) + { + if(value == null) + { + setBooleanValue(defaultvalue); + } + try + { + return getBooleanValue(); + } + catch(NumberFormatException nfe) + { + setBooleanValue(defaultvalue); + return getBooleanValue(); + } + } + + public int getHexValue() + { + return (int) Long.parseLong(getValue().replace("0x", ""), 16); + } + + public int getHexValue(int defaultvalue) + { + if(value == null) + { + setHexValue(defaultvalue); + } + try + { + return getHexValue(); + } + catch(NumberFormatException nfe) + { + setHexValue(defaultvalue); + return getHexValue(); + } + } + + private static final Pattern patternRGB = Pattern.compile("(\\d+),(\\d+),(\\d+)"); + public Colour getColourRGB() + { + Matcher matcherRGB = patternRGB.matcher(getValue().replaceAll("\\s", "")); + if(matcherRGB.matches()) + { + return new ColourRGBA( + Integer.parseInt(matcherRGB.group(1)), + Integer.parseInt(matcherRGB.group(2)), + Integer.parseInt(matcherRGB.group(3)), + 0xFF); + } + + return new ColourRGBA(getHexValue()<<8|0xFF); + } + + public Colour getColourRGB(Colour defaultvalue) + { + if(value == null) + { + setColourRGB(defaultvalue); + } + try + { + return getColourRGB(); + } + catch(NumberFormatException nfe) + { + setColourRGB(defaultvalue); + return getColourRGB(); + } + } + + public void save(PrintWriter writer, int tabs, String bracequalifier, boolean first) + { + String vname; + if(qualifiedname.contains(".") && bracequalifier.length() > 0) + vname = qualifiedname.substring(bracequalifier.length() + 1).replace(' ', '_'); + else + vname = qualifiedname; + vname.replace(' ', '_'); + + if(newline && !first) + ConfigFile.writeLine(writer, "", tabs); + + writeComment(writer, tabs); + if(value != null) + ConfigFile.writeLine(writer, vname+"="+value, tabs); + + if(!hasChildTags()) + return; + + if(brace) + { + if(value == null) + ConfigFile.writeLine(writer, vname, tabs); + ConfigFile.writeLine(writer, "{", tabs); + saveTagTree(writer, tabs+1, qualifiedname.replace(' ', '_')); + ConfigFile.writeLine(writer, "}", tabs); + } + else + { + saveTagTree(writer, tabs, bracequalifier); + } + } + + @Override + public ConfigTag setComment(String comment) + { + super.setComment(comment); + return this; + } + + @Override + public ConfigTag setSortMode(int mode) + { + super.setSortMode(mode); + return this; + } + + public ConfigTag setNewLine(boolean b) + { + newline = b; + saveConfig(); + return this; + } + + public ConfigTag useBraces() + { + brace = true; + if(parent.newlinemode == 1) + newline = true; + + saveConfig(); + return this; + } + + public ConfigTag setPosition(int pos) + { + position = pos; + saveConfig(); + return this; + } + + public boolean containsTag(String tagname) + { + return getTag(tagname, false) != null; + } + + public int getId(String name, int defaultValue) + { + return getTag(name).getIntValue(defaultValue); + } + + public int getId(String name) + { + int ret = getId(name, IDBase); + IDBase = ret+1; + return ret; + } + + public int getAcheivementId(String name, int defaultValue) + { + return getTag(name).getIntValue(defaultValue); + } + + public ConfigTag setBaseID(int i) + { + IDBase = i; + return this; + } + + public ConfigTagParent parent; + public String name; + public String qualifiedname; + public String value; + public boolean brace; + public boolean newline; + public int position = Integer.MAX_VALUE; + + private int IDBase; +} diff --git a/codechicken/lib/config/ConfigTagParent.java b/codechicken/lib/config/ConfigTagParent.java new file mode 100644 index 0000000..f3ab8d7 --- /dev/null +++ b/codechicken/lib/config/ConfigTagParent.java @@ -0,0 +1,241 @@ +package codechicken.lib.config; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import java.util.TreeMap; +import java.util.Map.Entry; + +public abstract class ConfigTagParent +{ + public static class TagOrderComparator implements Comparator + { + int sortMode; + + public TagOrderComparator(int sortMode) + { + this.sortMode = sortMode; + } + + public int compare(ConfigTag o1, ConfigTag o2) + { + if(o1.position != o2.position) + return compareInt(o1.position, o2.position); + if(o1.brace != o2.brace) + return o1.brace ? 1 : -1;//braced one goes after + switch(sortMode) + { + case 1: + if(o1.value == o2.value) + return 0; + if(o1.value == null) + return 1; + if(o2.value == null) + return -1; + return o1.value.compareTo(o2.value); + default: + return o1.name.compareTo(o2.name); + } + } + + private int compareInt(int a, int b) + { + return a == b ? 0 : a < b ? -1 : 1; + } + } + + private TreeMap childtags = new TreeMap(); + public String comment; + /** + * 0 = name, 1 = value + */ + public int sortMode = 0; + /** + * The mode for determining when child tags should leave a blank line between them and the one above + * 0 = never, 1 = when braced, 2 = always + */ + public int newlinemode = 1; + + public abstract void saveConfig(); + + public abstract String getNameQualifier(); + + public ConfigTagParent setComment(String comment) + { + this.comment = comment; + saveConfig(); + return this; + } + + public ConfigTagParent setSortMode(int mode) + { + sortMode = mode; + saveConfig(); + return this; + } + + public ConfigTagParent setNewLineMode(int mode) + { + newlinemode = mode; + for(Entry entry : childtags.entrySet()) + { + ConfigTag tag = entry.getValue(); + if(newlinemode == 0) + tag.newline = false; + else if(newlinemode == 1) + tag.newline = tag.brace; + else if(newlinemode == 2) + tag.newline = true; + } + saveConfig(); + return this; + } + + public Map childTagMap() + { + return childtags; + } + + public boolean hasChildTags() + { + return !childtags.isEmpty(); + } + + public boolean containsTag(String tagname) + { + return getTag(tagname, false) != null; + } + + public ConfigTag getNewTag(String tagname) + { + return new ConfigTag(this, tagname); + } + + public ConfigTag getTag(String tagname, boolean create) + { + tagname = tagname.replace('_', ' '); + int dotpos = tagname.indexOf("."); + String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos); + ConfigTag basetag = childtags.get(basetagname); + if(basetag == null) + { + if(!create) + return null; + + basetag = getNewTag(basetagname); + saveConfig(); + } + if(dotpos == -1) + return basetag; + + return basetag.getTag(tagname.substring(dotpos+1), create); + } + + public ConfigTag getTag(String tagname) + { + return getTag(tagname, true); + } + + public boolean removeTag(String tagname) + { + ConfigTag tag = getTag(tagname, false); + if(tag == null) + return false; + + int dotpos = tagname.lastIndexOf("."); + String lastpart = dotpos == -1 ? tagname : tagname.substring(dotpos+1, tagname.length()); + if(tag.parent != null) + return tag.parent.childtags.remove(lastpart) != null; + + return false; + } + + public void addChild(ConfigTag tag) + { + childtags.put(tag.name, tag); + } + + public ArrayList getSortedTagList() + { + ArrayList taglist = new ArrayList(childtags.size()); + for(Entry tag : childtags.entrySet()) + taglist.add((T)tag.getValue()); + + Collections.sort(taglist, new TagOrderComparator(sortMode)); + return taglist; + } + + public void loadChildren(BufferedReader reader) + { + String comment = ""; + String bracequalifier=""; + try + { + while(true) + { + String line = ConfigFile.readLine(reader); + if(line == null) + break; + if(line.startsWith("#")) + { + if(comment == null || comment.equals("")) + comment = line.substring(1); + else + comment = comment+"\n"+line.substring(1); + } + else if(line.contains("=")) + { + String qualifiedname = line.substring(0, line.indexOf("=")); + getTag(qualifiedname) + .onLoaded() + .setComment(comment) + .setValue(line.substring(line.indexOf("=")+1)); + comment = ""; + bracequalifier = qualifiedname; + } + else if(line.equals("{")) + { + getTag(bracequalifier).setComment(comment).useBraces().loadChildren(reader); + comment = ""; + bracequalifier = ""; + } + else if(line.equals("}")) + { + break; + } + else + { + bracequalifier = line; + } + } + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public void saveTagTree(PrintWriter writer, int tabs, String bracequalifier) + { + boolean first = true; + for(ConfigTag tag : getSortedTagList()) + { + tag.save(writer, tabs, bracequalifier, first); + first = false; + } + } + + public void writeComment(PrintWriter writer, int tabs) + { + if(comment != null && !comment.equals("")) + { + String[] comments = comment.split("\n"); + for(int i = 0; i < comments.length; i++) + ConfigFile.writeLine(writer, "#"+comments[i], tabs); + } + } +} diff --git a/codechicken/lib/config/SimpleProperties.java b/codechicken/lib/config/SimpleProperties.java new file mode 100644 index 0000000..aa2c34f --- /dev/null +++ b/codechicken/lib/config/SimpleProperties.java @@ -0,0 +1,150 @@ +package codechicken.lib.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map.Entry; + +public class SimpleProperties +{ + public HashMap propertyMap = new HashMap(); + public File propertyFile; + public boolean saveOnChange = false; + public String encoding; + + private boolean loading = false; + + public SimpleProperties(File file, boolean saveOnChange, String encoding) + { + propertyFile = file; + this.saveOnChange = saveOnChange; + this.encoding = encoding; + } + + public SimpleProperties(File file, boolean saveOnChange) + { + this(file, saveOnChange, Charset.defaultCharset().name()); + } + + public SimpleProperties(File file) + { + this(file, true); + } + + public void load() + { + clear(); + loading = true; + + try + { + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile), encoding)); + while(true) + { + String read = reader.readLine(); + if(read == null) + break; + + int equalIndex = read.indexOf('='); + if(equalIndex == -1) + continue; + + setProperty(read.substring(0, equalIndex), read.substring(equalIndex+1)); + } + reader.close(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + loading = false; + } + + public void save() + { + try + { + PrintStream writer = new PrintStream(propertyFile); + + for(Entry entry : propertyMap.entrySet()) + { + writer.println(entry.getKey()+"="+entry.getValue()); + } + + writer.close(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + } + + public void clear() + { + propertyMap.clear(); + } + + public boolean hasProperty(String key) + { + return propertyMap.containsKey(key); + } + + public void removeProperty(String key) + { + if(propertyMap.remove(key) != null && saveOnChange && !loading) + save(); + } + + public void setProperty(String key, int value) + { + setProperty(key, Integer.toString(value)); + } + + public void setProperty(String key, boolean value) + { + setProperty(key, Boolean.toString(value)); + } + + public void setProperty(String key, String value) + { + propertyMap.put(key, value); + if(saveOnChange && !loading) + save(); + } + + public int getProperty(String property, int defaultvalue) + { + try { + return Integer.parseInt(getProperty(property, Integer.toString(defaultvalue))); + } catch(NumberFormatException nfe) + {return defaultvalue;} + } + + public boolean getProperty(String property, boolean defaultvalue) + { + try { + return Boolean.parseBoolean(getProperty(property, Boolean.toString(defaultvalue))); + } catch(NumberFormatException nfe) + {return defaultvalue;} + } + + public String getProperty(String property, String defaultvalue) + { + String value = propertyMap.get(property); + if(value == null) + { + setProperty(property, defaultvalue); + return defaultvalue; + } + return value; + } + + public String getProperty(String property) + { + return propertyMap.get(property); + } +} diff --git a/codechicken/lib/data/MCDataInput.java b/codechicken/lib/data/MCDataInput.java new file mode 100644 index 0000000..5474a11 --- /dev/null +++ b/codechicken/lib/data/MCDataInput.java @@ -0,0 +1,26 @@ +package codechicken.lib.data; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.vec.BlockCoord; + +public interface MCDataInput +{ + public long readLong(); + public int readInt(); + public short readShort(); + public int readUnsignedShort(); + public byte readByte(); + public int readUnsignedByte(); + public double readDouble(); + public float readFloat(); + public boolean readBoolean(); + public char readChar(); + public byte[] readByteArray(int length); + public String readString(); + public BlockCoord readCoord(); + public NBTTagCompound readNBTTagCompound(); + public ItemStack readItemStack(); + public FluidStack readFluidStack(); +} diff --git a/codechicken/lib/data/MCDataInputStream.java b/codechicken/lib/data/MCDataInputStream.java new file mode 100644 index 0000000..18267be --- /dev/null +++ b/codechicken/lib/data/MCDataInputStream.java @@ -0,0 +1,19 @@ +package codechicken.lib.data; + +import java.io.InputStream; + +public class MCDataInputStream extends InputStream +{ + private MCDataInput in; + + public MCDataInputStream(MCDataInput in) + { + this.in = in; + } + + @Override + public int read() + { + return in.readByte()&0xFF; + } +} diff --git a/codechicken/lib/data/MCDataOutput.java b/codechicken/lib/data/MCDataOutput.java new file mode 100644 index 0000000..40d694e --- /dev/null +++ b/codechicken/lib/data/MCDataOutput.java @@ -0,0 +1,25 @@ +package codechicken.lib.data; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.vec.BlockCoord; + +public interface MCDataOutput +{ + public MCDataOutput writeLong(long l); + public MCDataOutput writeInt(int i); + public MCDataOutput writeShort(int s); + public MCDataOutput writeByte(int b); + public MCDataOutput writeDouble(double d); + public MCDataOutput writeFloat(float f); + public MCDataOutput writeBoolean(boolean b); + public MCDataOutput writeChar(char c); + public MCDataOutput writeByteArray(byte[] array); + public MCDataOutput writeString(String s); + public MCDataOutput writeCoord(int x, int y, int z); + public MCDataOutput writeCoord(BlockCoord coord); + public MCDataOutput writeNBTTagCompound(NBTTagCompound tag); + public MCDataOutput writeItemStack(ItemStack stack); + public MCDataOutput writeFluidStack(FluidStack liquid); +} diff --git a/codechicken/lib/data/MCDataOutputStream.java b/codechicken/lib/data/MCDataOutputStream.java new file mode 100644 index 0000000..bf929a5 --- /dev/null +++ b/codechicken/lib/data/MCDataOutputStream.java @@ -0,0 +1,19 @@ +package codechicken.lib.data; + +import java.io.OutputStream; + +public class MCDataOutputStream extends OutputStream +{ + private MCDataOutput out; + + public MCDataOutputStream(MCDataOutput out) + { + this.out = out; + } + + @Override + public void write(int b) + { + out.writeByte(b); + } +} diff --git a/codechicken/lib/data/MCOutputStreamWrapper.java b/codechicken/lib/data/MCOutputStreamWrapper.java new file mode 100644 index 0000000..71e5163 --- /dev/null +++ b/codechicken/lib/data/MCOutputStreamWrapper.java @@ -0,0 +1,232 @@ +package codechicken.lib.data; + +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.vec.BlockCoord; + +public class MCOutputStreamWrapper implements MCDataOutput +{ + public DataOutputStream dataout; + + public MCOutputStreamWrapper(DataOutputStream out) + { + dataout = out; + } + + public MCOutputStreamWrapper writeBoolean(boolean b) + { + try + { + dataout.writeBoolean(b); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeByte(int b) + { + try + { + dataout.writeByte(b); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeShort(int s) + { + try + { + dataout.writeShort(s); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeInt(int i) + { + try + { + dataout.writeInt(i); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeFloat(float f) + { + try + { + dataout.writeFloat(f); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeDouble(double d) + { + try + { + dataout.writeDouble(d); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeLong(long l) + { + try + { + dataout.writeLong(l); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + @Override + public MCOutputStreamWrapper writeChar(char c) + { + try + { + dataout.writeChar(c); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeByteArray(byte[] barray) + { + try + { + dataout.write(barray); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeCoord(int x, int y, int z) + { + writeInt(x); + writeInt(y); + writeInt(z); + return this; + } + + public MCOutputStreamWrapper writeCoord(BlockCoord coord) + { + writeInt(coord.x); + writeInt(coord.y); + writeInt(coord.z); + return this; + } + + public MCOutputStreamWrapper writeString(String s) + { + try + { + if(s.length() > 65535) + throw new IOException("String length: "+s.length()+"too long."); + dataout.writeShort(s.length()); + dataout.writeChars(s); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeItemStack(ItemStack stack) + { + writeItemStack(stack, false); + return this; + } + + public MCOutputStreamWrapper writeItemStack(ItemStack stack, boolean large) + { + if (stack == null) + { + writeShort(-1); + } + else + { + writeShort(stack.itemID); + if(large) + writeInt(stack.stackSize); + else + writeByte(stack.stackSize); + writeShort(stack.getItemDamage()); + writeNBTTagCompound(stack.stackTagCompound); + } + return this; + } + + public MCOutputStreamWrapper writeNBTTagCompound(NBTTagCompound compound) + { + try + { + if (compound == null) + { + writeShort(-1); + } + else + { + byte[] bytes = CompressedStreamTools.compress(compound); + writeShort((short)bytes.length); + writeByteArray(bytes); + } + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public MCOutputStreamWrapper writeFluidStack(FluidStack fluid) + { + if (fluid == null) + { + writeShort(-1); + } + else + { + writeShort(fluid.fluidID); + writeInt(fluid.amount); + writeNBTTagCompound(fluid.tag); + } + return this; + } +} diff --git a/codechicken/lib/data/NBTDataWrapper.java b/codechicken/lib/data/NBTDataWrapper.java new file mode 100644 index 0000000..1b5b189 --- /dev/null +++ b/codechicken/lib/data/NBTDataWrapper.java @@ -0,0 +1,246 @@ +package codechicken.lib.data; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagByteArray; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagDouble; +import net.minecraft.nbt.NBTTagFloat; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.NBTTagShort; +import net.minecraft.nbt.NBTTagString; +import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.vec.BlockCoord; + +public class NBTDataWrapper implements MCDataInput, MCDataOutput +{ + private NBTTagList readList; + private int readTag = 0; + private NBTTagList writeList; + + public NBTDataWrapper(NBTTagList input) + { + readList = input; + } + + public NBTDataWrapper() + { + writeList = new NBTTagList(); + } + + public NBTTagList toTag() + { + return writeList; + } + + @Override + public NBTDataWrapper writeLong(long l) + { + writeList.appendTag(new NBTTagLong(null, l)); + return this; + } + + @Override + public NBTDataWrapper writeInt(int i) + { + writeList.appendTag(new NBTTagInt(null, i)); + return this; + } + + @Override + public NBTDataWrapper writeShort(int s) + { + writeList.appendTag(new NBTTagShort(null, (short) s)); + return this; + } + + @Override + public NBTDataWrapper writeByte(int b) + { + writeList.appendTag(new NBTTagByte(null, (byte) b)); + return this; + } + + @Override + public NBTDataWrapper writeDouble(double d) + { + writeList.appendTag(new NBTTagDouble(null, d)); + return this; + } + + @Override + public NBTDataWrapper writeFloat(float f) + { + writeList.appendTag(new NBTTagFloat(null, f)); + return this; + } + + @Override + public NBTDataWrapper writeBoolean(boolean b) + { + writeList.appendTag(new NBTTagByte(null, (byte) (b ? 1 : 0))); + return this; + } + + @Override + public NBTDataWrapper writeChar(char c) + { + writeList.appendTag(new NBTTagShort(null, (short)c)); + return this; + } + + @Override + public NBTDataWrapper writeByteArray(byte[] array) + { + writeList.appendTag(new NBTTagByteArray(null, array)); + return this; + } + + @Override + public NBTDataWrapper writeString(String s) + { + writeList.appendTag(new NBTTagString(null, s)); + return this; + } + + @Override + public NBTDataWrapper writeCoord(int x, int y, int z) + { + writeInt(x); + writeInt(y); + writeInt(z); + return this; + } + + @Override + public NBTDataWrapper writeCoord(BlockCoord coord) + { + writeCoord(coord.x, coord.y, coord.z); + return this; + } + + @Override + public NBTDataWrapper writeNBTTagCompound(NBTTagCompound tag) + { + writeList.appendTag(tag); + return this; + } + + @Override + public NBTDataWrapper writeItemStack(ItemStack stack) + { + writeList.appendTag(stack.writeToNBT(new NBTTagCompound())); + return this; + } + + @Override + public NBTDataWrapper writeFluidStack(FluidStack liquid) + { + writeList.appendTag(liquid.writeToNBT(new NBTTagCompound())); + return this; + } + + @Override + public long readLong() + { + return ((NBTTagLong)readTag()).data; + } + + @Override + public int readInt() + { + return ((NBTTagInt)readTag()).data; + } + + @Override + public short readShort() + { + return ((NBTTagShort)readTag()).data; + } + + @Override + public int readUnsignedShort() + { + return ((NBTTagShort)readTag()).data & 0xFFFF; + } + + @Override + public byte readByte() + { + return ((NBTTagByte)readTag()).data; + } + + @Override + public int readUnsignedByte() + { + return ((NBTTagByte)readTag()).data & 0xFF; + } + + @Override + public double readDouble() + { + return ((NBTTagDouble)readTag()).data; + } + + @Override + public float readFloat() + { + return ((NBTTagFloat)readTag()).data; + } + + @Override + public boolean readBoolean() + { + return ((NBTTagByte)readTag()).data != 0; + } + + @Override + public char readChar() + { + return (char)((NBTTagShort)readTag()).data; + } + + @Override + public byte[] readByteArray(int length) + { + return ((NBTTagByteArray)readTag()).byteArray; + } + + @Override + public String readString() + { + return ((NBTTagString)readTag()).data; + } + + @Override + public BlockCoord readCoord() + { + return new BlockCoord(readInt(), readInt(), readInt()); + } + + @Override + public NBTTagCompound readNBTTagCompound() + { + return (NBTTagCompound)readTag(); + } + + @Override + public ItemStack readItemStack() + { + return ItemStack.loadItemStackFromNBT(readNBTTagCompound()); + } + + @Override + public FluidStack readFluidStack() + { + return FluidStack.loadFluidStackFromNBT(readNBTTagCompound()); + } + + private NBTBase readTag() + { + return readList.tagAt(readTag++); + } +} diff --git a/codechicken/lib/lighting/CCRBModel.java b/codechicken/lib/lighting/CCRBModel.java new file mode 100644 index 0000000..a3074b0 --- /dev/null +++ b/codechicken/lib/lighting/CCRBModel.java @@ -0,0 +1,31 @@ +package codechicken.lib.lighting; + +import codechicken.lib.render.CCModel; +import codechicken.lib.render.Vertex5; + +public class CCRBModel extends CCModel +{ + public LC[] lightCoefficents; + + /** + * Lighting sides and coefficients are computed for each vertex of the model. All faces must be axis planar and all verts are assumed to be in the range (0,0,0) to (1,1,1) + */ + public CCRBModel(CCModel m) + { + super(m.vertexMode); + verts = new Vertex5[m.verts.length]; + copy(m, 0, this, 0, m.verts.length); + if(normals == null) + computeNormals(); + if(colours == null) + setColour(-1); + computeLighting(); + } + + private void computeLighting() + { + lightCoefficents = new LC[verts.length]; + for(int k = 0; k < verts.length; k++) + lightCoefficents[k] = LC.compute(verts[k].vec, normals[k]); + } +} diff --git a/codechicken/lib/lighting/LC.java b/codechicken/lib/lighting/LC.java new file mode 100644 index 0000000..baa3ab7 --- /dev/null +++ b/codechicken/lib/lighting/LC.java @@ -0,0 +1,59 @@ +package codechicken.lib.lighting; + +import codechicken.lib.render.CCModel; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Vector3; + +public class LC +{ + public LC(int s, float e, float f, float g, float h) + { + side = s; + fa = e; + fb = f; + fc = g; + fd = h; + } + + public int side; + public float fa; + public float fb; + public float fc; + public float fd; + + public static LC compute(Vector3 vec, Vector3 normal) + { + int side = CCModel.findSide(normal); + if(side < 0) + return new LC(12, 1, 0, 0, 0); + return compute(vec, side); + } + + public static LC compute(Vector3 vec, int side) + { + boolean offset = false; + switch(side) + { + case 0: offset = vec.y <= 0; break; + case 1: offset = vec.y >= 1; break; + case 2: offset = vec.z <= 0; break; + case 3: offset = vec.z >= 1; break; + case 4: offset = vec.x <= 0; break; + case 5: offset = vec.x >= 1; break; + } + if(!offset) + side+=6; + return computeO(vec, side); + } + + public static LC computeO(Vector3 vec, int side) + { + Vector3 v1 = Rotation.axes[((side&0xE)+3)%6]; + Vector3 v2 = Rotation.axes[((side&0xE)+5)%6]; + float d1 = (float) vec.scalarProject(v1); + float d2 = 1-d1; + float d3 = (float) vec.scalarProject(v2); + float d4 = 1-d3; + return new LC(side, d2*d4, d2*d3, d1*d4, d1*d3); + } +} \ No newline at end of file diff --git a/codechicken/lib/lighting/LazyLightMatrix.java b/codechicken/lib/lighting/LazyLightMatrix.java new file mode 100644 index 0000000..3c957cd --- /dev/null +++ b/codechicken/lib/lighting/LazyLightMatrix.java @@ -0,0 +1,28 @@ +package codechicken.lib.lighting; + +import net.minecraft.world.IBlockAccess; +import codechicken.lib.vec.BlockCoord; + +public class LazyLightMatrix +{ + private BlockCoord pos = new BlockCoord(); + private IBlockAccess access; + private boolean computed = false; + private LightMatrix lightMatrix = new LightMatrix(); + + public LightMatrix lightMatrix() + { + if(computed) + return lightMatrix; + computed = true; + lightMatrix.computeAt(access, pos.x, pos.y, pos.z); + return lightMatrix; + } + + public void setPos(IBlockAccess access, int x, int y, int z) + { + computed = false; + this.access = access; + pos.set(x, y, z); + } +} \ No newline at end of file diff --git a/codechicken/lib/lighting/LightMatrix.java b/codechicken/lib/lighting/LightMatrix.java new file mode 100644 index 0000000..882ea0b --- /dev/null +++ b/codechicken/lib/lighting/LightMatrix.java @@ -0,0 +1,209 @@ +package codechicken.lib.lighting; + +import codechicken.lib.render.CCModel; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.IVertexModifier; +import codechicken.lib.render.UV; +import codechicken.lib.vec.BlockCoord; +import codechicken.lib.vec.Vector3; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.world.IBlockAccess; + +/** + * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> (x+1, y+1, z+1) + */ +public class LightMatrix implements IVertexModifier +{ + public int computed = 0; + public float[][] ao = new float[13][4]; + public int[][] brightness = new int[13][4]; + public BlockCoord pos = new BlockCoord(); + + private float[] aSamples = new float[27]; + private int[] bSamples = new int[27]; + private Vector3 v_temp = new Vector3(); + + /** + * The 9 positions in the sample array for each side, sides >= 6 are centered on sample 13 (the block itself) + */ + public static final int[][] ssamplem = new int[][]{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8}, + {18,19,20,21,22,23,24,25,26}, + { 0, 9,18, 1,10,19, 2,11,20}, + { 6,15,24, 7,16,25, 8,17,26}, + { 0, 3, 6, 9,12,15,18,21,24}, + { 2, 5, 8,11,14,17,20,23,26}, + { 9,10,11,12,13,14,15,16,17}, + { 9,10,11,12,13,14,15,16,17}, + { 3,12,21, 4,13,22, 5,14,23}, + { 3,12,21, 4,13,22, 5,14,23}, + { 1, 4, 7,10,13,16,19,22,25}, + { 1, 4, 7,10,13,16,19,22,25}, + {13,13,13,13,13,13,13,13,13}}; + public static final int[][] qsamplem = new int[][]{//the positions in the side sample array for each corner + {0,1,3,4}, + {5,1,2,4}, + {6,7,3,4}, + {5,7,8,4}}; + public static final float[] sideao = new float[]{ + 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, + 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, + 1F}; + + /*static + { + int[][] os = new int[][]{ + {0,-1,0}, + {0, 1,0}, + {0,0,-1}, + {0,0, 1}, + {-1,0,0}, + { 1,0,0}}; + + for(int s = 0; s < 12; s++) + { + int[] d0 = s < 6 ? new int[]{os[s][0]+1, os[s][1]+1, os[s][2]+1} : new int[]{1, 1, 1}; + int[] d1 = os[((s&0xE)+3)%6]; + int[] d2 = os[((s&0xE)+5)%6]; + for(int a = -1; a <= 1; a++) + for(int b = -1; b <= 1; b++) + ssamplem[s][(a+1)*3+b+1] = (d0[1]+d1[1]*a+d2[1]*b)*9+(d0[2]+d1[2]*a+d2[2]*b)*3+(d0[0]+d1[0]*a+d2[0]*b); + } + System.out.println(Arrays.deepToString(ssamplem)); + }*/ + + public void computeAt(IBlockAccess a, int x, int y, int z) + { + pos.set(x, y, z); + computed = 0; + //inc x, inc z, inc y + sample( 0, aSamples, bSamples, a, x-1, y-1, z-1); + sample( 1, aSamples, bSamples, a, x , y-1, z-1); + sample( 2, aSamples, bSamples, a, x+1, y-1, z-1); + sample( 3, aSamples, bSamples, a, x-1, y-1, z ); + sample( 4, aSamples, bSamples, a, x , y-1, z ); + sample( 5, aSamples, bSamples, a, x+1, y-1, z ); + sample( 6, aSamples, bSamples, a, x-1, y-1, z+1); + sample( 7, aSamples, bSamples, a, x , y-1, z+1); + sample( 8, aSamples, bSamples, a, x+1, y-1, z+1); + sample( 9, aSamples, bSamples, a, x-1, y , z-1); + sample(10, aSamples, bSamples, a, x , y , z-1); + sample(11, aSamples, bSamples, a, x+1, y , z-1); + sample(12, aSamples, bSamples, a, x-1, y , z ); + sample(13, aSamples, bSamples, a, x , y , z ); + sample(14, aSamples, bSamples, a, x+1, y , z ); + sample(15, aSamples, bSamples, a, x-1, y , z+1); + sample(16, aSamples, bSamples, a, x , y , z+1); + sample(17, aSamples, bSamples, a, x+1, y , z+1); + sample(18, aSamples, bSamples, a, x-1, y+1, z-1); + sample(19, aSamples, bSamples, a, x , y+1, z-1); + sample(20, aSamples, bSamples, a, x+1, y+1, z-1); + sample(21, aSamples, bSamples, a, x-1, y+1, z ); + sample(22, aSamples, bSamples, a, x , y+1, z ); + sample(23, aSamples, bSamples, a, x+1, y+1, z ); + sample(24, aSamples, bSamples, a, x-1, y+1, z+1); + sample(25, aSamples, bSamples, a, x , y+1, z+1); + sample(26, aSamples, bSamples, a, x+1, y+1, z+1); + } + + public int[] brightness(int side) + { + sideSample(side); + return brightness[side]; + } + + public float[] ao(int side) + { + sideSample(side); + return ao[side]; + } + + public void sideSample(int side) + { + if((computed&1<>2 & 0xFF00FF; + } + + public void setColour(Tessellator tess, LC lc, int c) + { + float[] a = ao(lc.side); + float f = (a[0]*lc.fa + a[1]*lc.fb + a[2]*lc.fc + a[3]*lc.fd); + CCRenderState.vertexColour((int)((c>>>24)*f), (int)((c>>16&0xFF)*f), (int)((c>>8&0xFF)*f), (c&0xFF)); + } + + public void setBrightness(Tessellator tess, LC lc) + { + int[] b = brightness(lc.side); + tess.setBrightness((int)(b[0]*lc.fa + b[1]*lc.fb + b[2]*lc.fc+b[3]*lc.fd) & 0xFF00FF); + } + + @Override + public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) + { + LC lc; + if(m instanceof CCRBModel) + lc = ((CCRBModel)m).lightCoefficents[i]; + else + lc = LC.compute(v_temp.set(vec).add(-pos.x, -pos.y, -pos.z), normal); + + setColour(tess, lc, (m == null || m.colours == null) ? -1 : m.colours[i]); + setBrightness(tess, lc); + } + + @Override + public boolean needsNormals() + { + return true; + } +} \ No newline at end of file diff --git a/codechicken/lib/lighting/LightModel.java b/codechicken/lib/lighting/LightModel.java new file mode 100644 index 0000000..831298d --- /dev/null +++ b/codechicken/lib/lighting/LightModel.java @@ -0,0 +1,112 @@ +package codechicken.lib.lighting; + +import net.minecraft.client.renderer.Tessellator; +import codechicken.lib.render.CCModel; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.IVertexModifier; +import codechicken.lib.render.UV; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Vector3; + +public class LightModel implements IVertexModifier +{ + public static class Light + { + public Vector3 ambient = new Vector3(); + public Vector3 diffuse = new Vector3(); + public Vector3 position; + + public Light(Vector3 pos) + { + position = pos.copy().normalize(); + } + + public Light setDiffuse(Vector3 vec) + { + diffuse.set(vec); + return this; + } + + public Light setAmbient(Vector3 vec) + { + ambient.set(vec); + return this; + } + } + + public static LightModel standardLightModel; + static + { + standardLightModel = new LightModel() + .setAmbient(new Vector3(0.4, 0.4, 0.4)) + .addLight(new Light(new Vector3(0.2, 1, -0.7)) + .setDiffuse(new Vector3(0.6, 0.6, 0.6))) + .addLight(new Light(new Vector3(-0.2, 1, 0.7)) + .setDiffuse(new Vector3(0.6, 0.6, 0.6))); + } + + private Vector3 ambient = new Vector3(); + private Light[] lights = new Light[8]; + private int lightCount; + + public LightModel addLight(Light light) + { + lights[lightCount++] = light; + return this; + } + + public LightModel setAmbient(Vector3 vec) + { + ambient.set(vec); + return this; + } + + /** + * @param colour The pre-lighting vertex colour. RGBA format + * @param normal The normal at the vertex + * @return The lighting applied colour + */ + public int apply(int colour, Vector3 normal) + { + Vector3 n_colour = ambient.copy(); + for(int l = 0; l < lightCount; l++) + { + Light light = lights[l]; + double n_l = light.position.dotProduct(normal); + double f = n_l > 0 ? 1 : 0; + n_colour.x += light.ambient.x + f*light.diffuse.x*n_l; + n_colour.y += light.ambient.y + f*light.diffuse.y*n_l; + n_colour.z += light.ambient.z + f*light.diffuse.z*n_l; + } + + if(n_colour.x > 1) + n_colour.x = 1; + if(n_colour.y > 1) + n_colour.y = 1; + if(n_colour.z > 1) + n_colour.z = 1; + + n_colour.multiply((colour >>> 24)/255D, (colour >> 16 & 0xFF)/255D, (colour >> 8 & 0xFF)/255D); + return (int)(n_colour.x*255)<<24 | (int)(n_colour.y*255)<<16 | (int)(n_colour.z*255)<<8 | colour&0xFF; + } + + @Override + public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) + { + CCRenderState.setColour(apply((m == null || m.colours == null) ? -1 : m.colours[i], normal)); + } + + @Override + public boolean needsNormals() + { + return true; + } + + public PlanarLightModel reducePlanar() + { + int[] colours = new int[6]; + for(int i = 0; i < 6; i++) + colours[i] = apply(-1, Rotation.axes[i]); + return new PlanarLightModel(colours); + } +} diff --git a/codechicken/lib/lighting/PlanarLightModel.java b/codechicken/lib/lighting/PlanarLightModel.java new file mode 100644 index 0000000..cd81b1c --- /dev/null +++ b/codechicken/lib/lighting/PlanarLightModel.java @@ -0,0 +1,40 @@ +package codechicken.lib.lighting; + +import net.minecraft.client.renderer.Tessellator; +import codechicken.lib.colour.Colour; +import codechicken.lib.colour.ColourRGBA; +import codechicken.lib.render.CCModel; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.IVertexModifier; +import codechicken.lib.render.UV; +import codechicken.lib.vec.Vector3; + +/** + * Faster precomputed version of LightModel that only works for axis planar sides + */ +public class PlanarLightModel implements IVertexModifier +{ + public ColourRGBA[] colours; + + public PlanarLightModel(int[] colours) + { + this.colours = new ColourRGBA[6]; + for(int i = 0; i < 6; i++) + this.colours[i] = new ColourRGBA(colours[i]); + } + + @Override + public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) + { + ColourRGBA light = colours[CCModel.findSide(normal)]; + int colour = (m == null || m.colours == null) ? -1 : m.colours[i]; + Colour res = new ColourRGBA(colour).multiply(light); + CCRenderState.vertexColour(res.r&0xFF, res.g&0xFF, res.b&0xFF, res.a&0xFF) ; + } + + @Override + public boolean needsNormals() + { + return true; + } +} diff --git a/codechicken/lib/math/MathHelper.java b/codechicken/lib/math/MathHelper.java new file mode 100644 index 0000000..37ed8bf --- /dev/null +++ b/codechicken/lib/math/MathHelper.java @@ -0,0 +1,168 @@ +package codechicken.lib.math; + +public class MathHelper +{ + public static final double phi = 1.618033988749894; + public static final double pi = Math.PI; + public static final double todeg = 57.29577951308232; + public static final double torad = 0.017453292519943; + public static final double sqrt2 = 1.414213562373095; + + public static double[] SIN_TABLE = new double[65536]; + static + { + for (int i = 0; i < 65536; ++i) + SIN_TABLE[i] = Math.sin(i / 65536D * 2 * Math.PI); + + SIN_TABLE[0] = 0; + SIN_TABLE[16384] = 1; + SIN_TABLE[32768] = 0; + SIN_TABLE[49152] = 1; + } + + public static double sin(double d) + { + return SIN_TABLE[(int)((float)d * 10430.378F) & 65535]; + } + + public static double cos(double d) + { + return SIN_TABLE[(int)((float)d * 10430.378F + 16384.0F) & 65535]; + } + + /** + * @param a The value + * @param b The value to approach + * @param max The maximum step + * @return the closed value to b no less than max from a + */ + public static float approachLinear(float a, float b, float max) + { + return (a > b) ? + (a - b < max ? b : a-max) : + (b - a < max ? b : a+max); + } + + /** + * @param a The value + * @param b The value to approach + * @param max The maximum step + * @return the closed value to b no less than max from a + */ + public static double approachLinear(double a, double b, double max) + { + return (a > b) ? + (a - b < max ? b : a-max) : + (b - a < max ? b : a+max); + } + + /** + * @param a The first value + * @param b The second value + * @param d The interpolation factor, between 0 and 1 + * @return a+(b-a)*d + */ + public static float interpolate(float a, float b, float d) + { + return a+(b-a)*d; + } + + /** + * @param a The first value + * @param b The second value + * @param d The interpolation factor, between 0 and 1 + * @return a+(b-a)*d + */ + public static double interpolate(double a, double b, double d) + { + return a+(b-a)*d; + } + + /** + * @param a The value + * @param b The value to approach + * @param ratio The ratio to reduce the difference by + * @return a+(b-a)*ratio + */ + public static double approachExp(double a, double b, double ratio) + { + return a+(b-a)*ratio; + } + + /** + * @param a The value + * @param b The value to approach + * @param ratio The ratio to reduce the difference by + * @param cap The maximum amount to advance by + * @return a+(b-a)*ratio + */ + public static double approachExp(double a, double b, double ratio, double cap) + { + double d = (b-a)*ratio; + if(Math.abs(d) > cap) + d = Math.signum(d)*cap; + return a+d; + } + + /** + * @param a The value + * @param b The value to approach + * @param ratio The ratio to reduce the difference by + * @param c The value to retreat from + * @param kick The difference when a == c + * @return + */ + public static double retreatExp(double a, double b, double c, double ratio, double kick) + { + double d = (Math.abs(c-a)+kick)*ratio; + if(d > Math.abs(b-a)) + return b; + return a+Math.signum(b-a)*d; + } + + /** + * + * @param value The value + * @param min The min value + * @param max The max value + * @return The clipped value between min and max + */ + public static double clip(double value, double min, double max) + { + if(value > max) + value = max; + if(value < min) + value = min; + return value; + } + + /** + * @return a <= x <= b + */ + public static boolean between(double a, double x, double b) + { + return a <= x && x <= b; + } + + public static int approachExpI(int a, int b, double ratio) + { + int r = (int)Math.round(approachExp(a, b, ratio)); + return r == a ? b : r; + } + + public static int retreatExpI(int a, int b, int c, double ratio, int kick) + { + int r = (int)Math.round(retreatExp(a, b, c, ratio, kick)); + return r == a ? b : r; + } + + public static int floor_double(double d) + { + return net.minecraft.util.MathHelper.floor_double(d); + } + + public static int roundAway(double d) + { + return (int) (d < 0 ? Math.floor(d) : Math.ceil(d)); + } +} diff --git a/codechicken/lib/packet/ICustomPacketTile.java b/codechicken/lib/packet/ICustomPacketTile.java new file mode 100644 index 0000000..d6832db --- /dev/null +++ b/codechicken/lib/packet/ICustomPacketTile.java @@ -0,0 +1,6 @@ +package codechicken.lib.packet; + +public interface ICustomPacketTile +{ + public void handleDescriptionPacket(PacketCustom packet); +} diff --git a/codechicken/lib/packet/MetaPacket.java b/codechicken/lib/packet/MetaPacket.java new file mode 100644 index 0000000..cff1474 --- /dev/null +++ b/codechicken/lib/packet/MetaPacket.java @@ -0,0 +1,55 @@ +package codechicken.lib.packet; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import net.minecraft.network.packet.NetHandler; +import net.minecraft.network.packet.Packet; + +public class MetaPacket extends Packet +{ + public ArrayList packets = new ArrayList(); + + public MetaPacket(Packet... packets) + { + for(Packet p : packets) + this.packets.add(p); + } + + public MetaPacket(Collection packets) + { + this.packets.addAll(packets); + } + + @Override + public void readPacketData(DataInput datain) + { + throw new IllegalStateException("Meta packets can't be read"); + } + + @Override + public void writePacketData(DataOutput dataout) throws IOException + { + for(Packet p : packets) + p.writePacketData(dataout); + } + + @Override + public void processPacket(NetHandler nethandler) + { + for(Packet p : packets)//Memory connection + p.processPacket(nethandler); + } + + @Override + public int getPacketSize() + { + int size = 0; + for(Packet p : packets) + size+=p.getPacketSize(); + return size; + } +} diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java new file mode 100644 index 0000000..9ea252f --- /dev/null +++ b/codechicken/lib/packet/PacketCustom.java @@ -0,0 +1,1041 @@ +package codechicken.lib.packet; + +import java.io.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + +import codechicken.lib.data.MCDataInput; +import codechicken.lib.data.MCDataOutput; +import codechicken.lib.vec.BlockCoord; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import cpw.mods.fml.common.network.FMLNetworkHandler; +import cpw.mods.fml.common.network.IPacketHandler; +import cpw.mods.fml.common.network.ITinyPacketHandler; +import cpw.mods.fml.common.network.NetworkModHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.network.Player; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.NetClientHandler; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.INetworkManager; +import net.minecraft.network.NetServerHandler; +import net.minecraft.network.packet.NetHandler; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.Packet131MapData; +import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.PlayerInstance; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.fluids.FluidStack; + +public final class PacketCustom implements MCDataInput, MCDataOutput +{ + public static interface ICustomPacketHandler + { + } + + public interface IClientPacketHandler extends ICustomPacketHandler + { + public void handlePacket(PacketCustom packetCustom, NetClientHandler nethandler, Minecraft mc); + } + + public interface IServerPacketHandler extends ICustomPacketHandler + { + public void handlePacket(PacketCustom packetCustom, NetServerHandler nethandler, EntityPlayerMP sender); + } + + public static class PacketAssembler + { + public class AssemblyEntry + { + public AssemblyEntry(Object channel, int type, int length) + { + this.channel = channel; + this.type = type; + data = new byte[length]; + } + + public void append(byte[] b, int off, int len) + { + System.arraycopy(b, off, data, pos, len); + pos+=len; + } + + public PacketCustom finished() + { + if(pos < data.length) + return null; + + return new PacketCustom(channel, type, data); + } + + Object channel; + int type; + int pos; + byte[] data; + } + + public HashMap assemblerMap = new HashMap(); + + public PacketCustom assemble(IPacketCarrier carrier, Packet packet) + { + int type = carrier.readType(packet); + if(type != 0x80) + return new PacketCustom(carrier.readChannel(packet), carrier.readType(packet), carrier.readData(packet)); + + byte[] data = carrier.readData(packet); + int asmID = readInt(data, 0); + AssemblyEntry e = assemblerMap.get(asmID); + if(e == null) + { + e = new AssemblyEntry(carrier.readChannel(packet), data[4]&0xFF, readInt(data, 5)); + assemblerMap.put(asmID, e); + return null; + } + + e.append(data, 4, data.length-4); + PacketCustom ret = e.finished(); + if(ret != null) + assemblerMap.remove(asmID); + return ret; + } + } + + private static abstract class CustomPacketHandler implements IPacketHandler + { + HashMap handlermap = new HashMap(); + + public CustomPacketHandler(String channel) + { + NetworkRegistry.instance().registerChannel(this, channel, getSide()); + } + + @Override + public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) + { + PacketCustom packetCustom = assembler.assemble(carrier250, packet); + if(packetCustom == null) + return; + + ICustomPacketHandler handler = handlermap.get(packetCustom.getType()); + if(handler != null) + handle(handler, packetCustom, player); + } + + public void registerRange(int firstID, int lastID, ICustomPacketHandler handler) + { + for(int i = firstID; i <= lastID; i++) + handlermap.put(i, handler); + } + + public abstract Side getSide(); + public abstract void handle(ICustomPacketHandler handler, PacketCustom packet, Player player); + } + + private static class ClientPacketHandler extends CustomPacketHandler + { + public ClientPacketHandler(String channel) + { + super(channel); + } + + @Override + public Side getSide() + { + return Side.CLIENT; + } + + @Override + public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) + { + ((IClientPacketHandler)handler).handlePacket(packet, Minecraft.getMinecraft().getNetHandler(), Minecraft.getMinecraft()); + } + } + + private static class ServerPacketHandler extends CustomPacketHandler + { + public ServerPacketHandler(String channel) + { + super(channel); + } + + @Override + public Side getSide() + { + return Side.SERVER; + } + + @Override + public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) + { + ((IServerPacketHandler)handler).handlePacket(packet, ((EntityPlayerMP)player).playerNetServerHandler, (EntityPlayerMP)player); + } + } + + private static class ServerTinyPacketHandler + { + IServerPacketHandler serverHandler; + + public ServerTinyPacketHandler(IServerPacketHandler handler) + { + serverHandler = handler; + } + + public void handle(PacketCustom packetCustom, NetHandler handler) + { + serverHandler.handlePacket(packetCustom, (NetServerHandler)handler, ((NetServerHandler)handler).playerEntity); + } + } + + private static class ClientTinyPacketHandler + { + IClientPacketHandler clientHandler; + + public ClientTinyPacketHandler(IClientPacketHandler handler) + { + clientHandler = handler; + } + + public void handle(PacketCustom packetCustom, NetHandler handler) + { + clientHandler.handlePacket(packetCustom, (NetClientHandler)handler, Minecraft.getMinecraft()); + } + } + + public static final class CustomTinyPacketHandler implements ITinyPacketHandler + { + private ClientTinyPacketHandler clientDelegate; + private ServerTinyPacketHandler serverDelegate; + + @Override + public void handle(NetHandler handler, Packet131MapData packet) + { + PacketCustom packetCustom = assembler.assemble(carrier131, packet); + if(packetCustom == null) + return; + + if(handler instanceof NetServerHandler) + serverDelegate.handle(packetCustom, handler); + else + clientDelegate.handle(packetCustom, handler); + } + + private void registerSidedHandler(ICustomPacketHandler handler) + { + if(handler instanceof IClientPacketHandler) + { + if(clientDelegate != null) + throw new IllegalStateException("Client handler already registered"); + + clientDelegate = new ClientTinyPacketHandler((IClientPacketHandler) handler); + } + else if(handler instanceof IServerPacketHandler) + { + if(serverDelegate != null) + throw new IllegalStateException("Server handler already registered"); + + serverDelegate = new ServerTinyPacketHandler((IServerPacketHandler) handler); + } + else + { + throw new IllegalStateException("Handler is not a client or server handler"); + } + } + } + + public static interface IPacketCarrier + { + public int readType(Packet packet); + public byte[] readData(Packet packet); + public Object readChannel(Packet packet); + public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data); + public boolean shortCapped(); + } + + public static class Packet250Carrier implements IPacketCarrier + { + @Override + public int readType(Packet packet) + { + return ((Packet250CustomPayload)packet).data[0]&0xFF; + } + + @Override + public byte[] readData(Packet packet) + { + byte[] data = ((Packet250CustomPayload)packet).data; + return Arrays.copyOfRange(data, 1, data.length); + } + + public Object readChannel(Packet packet) + { + return ((Packet250CustomPayload)packet).channel; + } + + @Override + public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data) + { + byte[] pdata = new byte[data.length+1]; + pdata[0] = (byte) type; + System.arraycopy(data, 0, pdata, 1, data.length); + + Packet250CustomPayload payload = new Packet250CustomPayload(); + payload.channel = (String) channel; + payload.isChunkDataPacket = chunkDataPacket; + payload.data = pdata; + payload.length = payload.data.length; + return payload; + } + + public boolean shortCapped() + { + return true; + } + } + + public static class Packet131Carrier implements IPacketCarrier + { + @Override + public int readType(Packet packet) + { + return ((Packet131MapData)packet).uniqueID&0xFF; + } + + @Override + public byte[] readData(Packet packet) + { + return ((Packet131MapData)packet).itemData; + } + + public Object readChannel(Packet packet) + { + return ((Packet131MapData)packet).itemID; + } + + @Override + public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data) + { + NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(channel); + Packet131MapData payload = new Packet131MapData((short) nmh.getNetworkId(), (short) type, data); + payload.isChunkDataPacket = chunkDataPacket; + return payload; + } + + @Override + public boolean shortCapped() + { + return true; + } + } + + public static PacketAssembler assembler = new PacketAssembler(); + public static IPacketCarrier carrier250 = new Packet250Carrier(); + public static IPacketCarrier carrier131 = new Packet131Carrier(); + + public static IPacketCarrier carrierForChannel(Object channel) + { + if(channel instanceof String) + return carrier250; + if(FMLNetworkHandler.instance().findNetworkModHandler(channel) != null) + return carrier131; + + return null; + } + + private static int assemblyID = 0; + + public static void writeInt(byte[] b, int pos, int i) + { + b[pos++] = (byte) (i>>>24); + b[pos++] = (byte) (i>>16); + b[pos++] = (byte) (i>>8); + b[pos++] = (byte) (i); + } + + public static int readInt(byte[] b, int pos) + { + return (b[pos++]&0xFF)<<24| + (b[pos++]&0xFF)<<16| + (b[pos++]&0xFF)<<8| + b[pos++]&0xFF; + } + + private PacketCustom(Object channel, int type, byte[] data) + { + this.channel = channel; + this.type = type; + if(type > 0x80) + data = decompress(data); + datain = new DataInputStream(new ByteArrayInputStream(data)); + } + + public PacketCustom(Object channel, int type) + { + if(type <= 0 || type >= 0x80) + throw new IllegalArgumentException("Packet type: "+type+" is not within required 0 < t < 0x80"); + + this.channel = channel; + this.type = type; + isChunkDataPacket = false; + + dataarrayout = new ByteArrayOutputStream(); + dataout = new DataOutputStream(dataarrayout); + } + + public boolean incoming() + { + return dataout == null; + } + + public int getType() + { + return type&0x7F; + } + + public PacketCustom setChunkDataPacket() + { + isChunkDataPacket = true; + return this; + } + + private byte[] decompress(byte[] cdata) + { + if((type&0x80) == 0) + return cdata; + + Inflater inflater = new Inflater(); + try + { + byte[] ddata = new byte[readInt(cdata, 0)]; + inflater.setInput(cdata, 4, cdata.length-4); + inflater.inflate(ddata); + return ddata; + } + catch(Exception e) + { + throw new RuntimeException(e); + } + finally + { + inflater.end(); + } + } + + public PacketCustom compressed() + { + if(incoming()) + throw new IllegalStateException("Tried to compress an incoming packet"); + if((type&0x80) != 0) + throw new IllegalStateException("Packet already compressed"); + type|=0x80; + return this; + } + + private byte[] compress(byte[] data) + { + Deflater deflater = new Deflater(); + try + { + deflater.setInput(data, 0, data.length); + deflater.finish(); + byte[] cdata = new byte[data.length+4]; + int clen = deflater.deflate(cdata, 4, data.length); + if(clen == data.length || !deflater.finished())//not worth compressing, gets larger + { + type &= 0x7F; + return data; + } + + writeInt(cdata, 0, data.length); + return cdata; + } + catch(Exception e) + { + throw new RuntimeException(e); + } + finally + { + deflater.end(); + } + } + + public Packet toPacket() + { + if(incoming()) + throw new IllegalStateException("Tried to write an incoming packet"); + + try + { + dataout.close(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + + byte[] data = dataarrayout.toByteArray(); + if(data.length > 32000 || (type&0x80) != 0) + data = compress(data); + + IPacketCarrier carrier = carrierForChannel(channel); + if(data.length > 32000 && carrier.shortCapped()) + { + MetaPacket payload = new MetaPacket(); + int asmID = assemblyID++; + + byte[] hdata = new byte[9]; + writeInt(hdata, 0, asmID); + hdata[4] = (byte) type; + writeInt(hdata, 5, data.length); + payload.packets.add(carrier.write(channel, isChunkDataPacket, 0x80, hdata)); + + for(int i = 0; i < data.length; i+=32000) + { + int size = Math.min(data.length-i, 32000); + byte[] sdata = new byte[size+4]; + writeInt(sdata, 0, asmID); + System.arraycopy(data, i, sdata, 4, size); + payload.packets.add(carrier.write(channel, isChunkDataPacket, 0x80, sdata)); + } + + return payload; + } + + return carrier.write(channel, isChunkDataPacket, type, data); + } + + public PacketCustom writeBoolean(boolean b) + { + try + { + dataout.writeBoolean(b); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeByte(int b) + { + try + { + dataout.writeByte(b); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeShort(int s) + { + try + { + dataout.writeShort(s); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeInt(int i) + { + try + { + dataout.writeInt(i); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeFloat(float f) + { + try + { + dataout.writeFloat(f); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeDouble(double d) + { + try + { + dataout.writeDouble(d); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeLong(long l) + { + try + { + dataout.writeLong(l); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + @Override + public PacketCustom writeChar(char c) + { + try + { + dataout.writeChar(c); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeByteArray(byte[] barray) + { + try + { + dataout.write(barray); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeCoord(int x, int y, int z) + { + writeInt(x); + writeInt(y); + writeInt(z); + return this; + } + + public PacketCustom writeCoord(BlockCoord coord) + { + writeInt(coord.x); + writeInt(coord.y); + writeInt(coord.z); + return this; + } + + public PacketCustom writeString(String s) + { + try + { + if(s.length() > 65535) + throw new IOException("String length: "+s.length()+"too long."); + dataout.writeShort(s.length()); + dataout.writeChars(s); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeItemStack(ItemStack stack) + { + writeItemStack(stack, false); + return this; + } + + public PacketCustom writeItemStack(ItemStack stack, boolean large) + { + if (stack == null) + { + writeShort(-1); + } + else + { + writeShort(stack.itemID); + if(large) + writeInt(stack.stackSize); + else + writeByte(stack.stackSize); + writeShort(stack.getItemDamage()); + writeNBTTagCompound(stack.stackTagCompound); + } + return this; + } + + public PacketCustom writeNBTTagCompound(NBTTagCompound compound) + { + try + { + if (compound == null) + { + writeShort(-1); + } + else + { + byte[] bytes = CompressedStreamTools.compress(compound); + writeShort((short)bytes.length); + writeByteArray(bytes); + } + } + catch(IOException e) + { + throw new RuntimeException(e); + } + return this; + } + + public PacketCustom writeFluidStack(FluidStack fluid) + { + if (fluid == null) + { + writeShort(-1); + } + else + { + writeShort(fluid.fluidID); + writeInt(fluid.amount); + writeNBTTagCompound(fluid.tag); + } + return this; + } + + public boolean readBoolean() + { + try + { + return datain.readBoolean(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public int readUnsignedByte() + { + return readByte() & 0xFF; + } + + public int readUnsignedShort() + { + return readShort() & 0xFFFF; + } + + public byte readByte() + { + try + { + return datain.readByte(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public short readShort() + { + try + { + return datain.readShort(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public int readInt() + { + try + { + return datain.readInt(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public float readFloat() + { + try + { + return datain.readFloat(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public double readDouble() + { + try + { + return datain.readDouble(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public long readLong() + { + try + { + return datain.readLong(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public char readChar() + { + try + { + return datain.readChar(); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public BlockCoord readCoord() + { + return new BlockCoord(readInt(), readInt(), readInt()); + } + + public byte[] readByteArray(int length) + { + try + { + byte[] barray = new byte[length]; + datain.readFully(barray, 0, length); + return barray; + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public String readString() + { + try + { + int length = datain.readUnsignedShort(); + char[] chars = new char[length]; + for(int i = 0; i < length; i++) + { + chars[i] = readChar(); + } + return new String(chars); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + + } + + public ItemStack readItemStack() + { + return readItemStack(false); + } + + public ItemStack readItemStack(boolean large) + { + ItemStack item = null; + short itemID = readShort(); + + if (itemID >= 0) + { + int stackSize = large ? readInt() : readByte(); + short damage = readShort(); + item = new ItemStack(itemID, stackSize, damage); + item.stackTagCompound = readNBTTagCompound(); + } + + return item; + } + + public NBTTagCompound readNBTTagCompound() + { + try + { + short len = readShort(); + + if (len < 0) + return null; + + byte[] bytes = readByteArray(len); + return CompressedStreamTools.decompress(bytes); + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + public FluidStack readFluidStack() + { + FluidStack fluid = null; + short fluidID = readShort(); + + if (fluidID >= 0) + fluid = new FluidStack(fluidID, readInt(), readNBTTagCompound()); + + return fluid; + } + + private Object channel; + private int type; + private boolean isChunkDataPacket; + + private ByteArrayOutputStream dataarrayout; + private DataOutputStream dataout; + + private DataInputStream datain; + + private static HashMap clienthandlermap = new HashMap(); + private static HashMap serverhandlermap = new HashMap(); + + public static void assignHandler(String channel, int firstID, int lastID, ICustomPacketHandler IHandler) + { + Side side = IHandler instanceof IClientPacketHandler ? Side.CLIENT : Side.SERVER; + HashMap handlerMap = side.isClient() ? clienthandlermap : serverhandlermap; + CustomPacketHandler handler = handlerMap.get(channel); + + if(handler == null) + { + if(side.isClient()) + handler = new ClientPacketHandler(channel); + else + handler = new ServerPacketHandler(channel); + + handlerMap.put(channel, handler); + } + handler.registerRange(firstID, lastID, IHandler); + } + + public static void assignHandler(Object mod, ICustomPacketHandler handler) + { + NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mod); + if(nmh == null || nmh.getTinyPacketHandler() == null || !(nmh.getTinyPacketHandler() instanceof CustomTinyPacketHandler)) + throw new IllegalStateException("Invalid network tiny packet handler for mod: "+mod); + + ((CustomTinyPacketHandler)nmh.getTinyPacketHandler()).registerSidedHandler(handler); + } + + public void sendToPlayer(EntityPlayer player) + { + sendToPlayer(toPacket(), player); + } + + public static void sendToPlayer(Packet packet, EntityPlayer player) + { + if(player == null) + sendToClients(packet); + else + ((EntityPlayerMP)player).playerNetServerHandler.sendPacketToPlayer(packet); + } + + public void sendToClients() + { + sendToClients(toPacket()); + } + + public static void sendToClients(Packet packet) + { + MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayers(packet); + } + + public void sendPacketToAllAround(double x, double y, double z, double range, int dim) + { + sendToAllAround(toPacket(), x, y, z, range, dim); + } + + public static void sendToAllAround(Packet packet, double x, double y, double z, double range, int dim) + { + MinecraftServer.getServer().getConfigurationManager().sendToAllNear(x, y, z, range, dim, packet); + } + + public void sendToDimension(int dim) + { + sendToDimension(toPacket(), dim); + } + + public static void sendToDimension(Packet packet, int dim) + { + MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayersInDimension(packet, dim); + } + + public void sendToChunk(World world, int chunkX, int chunkZ) + { + sendToChunk(toPacket(), world, chunkX, chunkZ); + } + + public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) + { + PlayerInstance p = ((WorldServer)world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); + if(p != null) + p.sendToAllPlayersWatchingChunk(packet); + } + + public void sendToOps() + { + sendToOps(toPacket()); + } + + public static void sendToOps(Packet packet) + { + for(EntityPlayerMP player : (List)MinecraftServer.getServer().getConfigurationManager().playerEntityList) + if(MinecraftServer.getServer().getConfigurationManager().areCommandsAllowed(player.username)) + sendToPlayer(packet, player); + } + + @SideOnly(Side.CLIENT) + public void sendToServer() + { + sendToServer(toPacket()); + } + + @SideOnly(Side.CLIENT) + public static void sendToServer(Packet packet) + { + Minecraft.getMinecraft().getNetHandler().addToSendQueue(packet); + } +} diff --git a/codechicken/lib/raytracer/ExtendedMOP.java b/codechicken/lib/raytracer/ExtendedMOP.java new file mode 100644 index 0000000..5d81e43 --- /dev/null +++ b/codechicken/lib/raytracer/ExtendedMOP.java @@ -0,0 +1,50 @@ +package codechicken.lib.raytracer; + +import net.minecraft.entity.Entity; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +public class ExtendedMOP extends MovingObjectPosition +{ + public Object data; + + public ExtendedMOP(Entity entity, Object data) + { + super(entity); + setData(data); + } + + public ExtendedMOP(int x, int y, int z, int side, Vec3 hit, Object data) + { + super(x, y, z, side, hit); + setData(data); + } + + public ExtendedMOP(MovingObjectPosition mop, Object data) + { + super(0, 0, 0, 0, mop.hitVec); + typeOfHit = mop.typeOfHit; + blockX = mop.blockX; + blockY = mop.blockY; + blockZ = mop.blockZ; + sideHit = mop.sideHit; + subHit = mop.subHit; + setData(data); + } + + public void setData(Object data) + { + if(data instanceof Integer) + subHit = ((Integer) data).intValue(); + this.data = data; + } + + @SuppressWarnings("unchecked") + public static T getData(MovingObjectPosition mop) + { + if(mop instanceof ExtendedMOP) + return (T)((ExtendedMOP)mop).data; + + return (T)Integer.valueOf(mop.subHit); + } +} diff --git a/codechicken/lib/raytracer/IndexedCuboid6.java b/codechicken/lib/raytracer/IndexedCuboid6.java new file mode 100644 index 0000000..a585ac9 --- /dev/null +++ b/codechicken/lib/raytracer/IndexedCuboid6.java @@ -0,0 +1,14 @@ +package codechicken.lib.raytracer; + +import codechicken.lib.vec.Cuboid6; + +public class IndexedCuboid6 extends Cuboid6 +{ + public Object data; + + public IndexedCuboid6(Object data, Cuboid6 cuboid) + { + super(cuboid); + this.data = data; + } +} \ No newline at end of file diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java new file mode 100644 index 0000000..1526ebb --- /dev/null +++ b/codechicken/lib/raytracer/RayTracer.java @@ -0,0 +1,193 @@ +package codechicken.lib.raytracer; + +import java.util.List; + +import codechicken.lib.math.MathHelper; +import codechicken.lib.vec.BlockCoord; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.EnumMovingObjectType; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class RayTracer +{ + private Vector3 vec = new Vector3(); + private Vector3 vec2 = new Vector3(); + + private Vector3 s_vec = new Vector3(); + private double s_dist; + private int s_side; + private IndexedCuboid6 c_cuboid; + + public static RayTracer instance = new RayTracer(); + + private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) + { + vec.set(start); + Vector3 hit = null; + switch(side) + { + case 0: + hit = vec.XZintercept(end, cuboid.min.y); + break; + case 1: + hit = vec.XZintercept(end, cuboid.max.y); + break; + case 2: + hit = vec.XYintercept(end, cuboid.min.z); + break; + case 3: + hit = vec.XYintercept(end, cuboid.max.z); + break; + case 4: + hit = vec.YZintercept(end, cuboid.min.x); + break; + case 5: + hit = vec.YZintercept(end, cuboid.max.x); + break; + } + if(hit == null) + return; + + switch(side) + { + case 0: + case 1: + if(!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; + break; + case 2: + case 3: + if(!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) || !MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y)) return; + break; + case 4: + case 5: + if(!MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y) || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; + break; + } + + double dist = vec2.set(hit).subtract(start).magSquared(); + if(dist < s_dist) + { + s_side = side; + s_dist = dist; + s_vec.set(vec); + } + } + + public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid) + { + s_dist = Double.MAX_VALUE; + s_side = -1; + + for(int i = 0; i < 6; i++) + traceSide(i, start, end, cuboid); + + if(s_side < 0) + return null; + + MovingObjectPosition mop = new MovingObjectPosition(0, 0, 0, s_side, s_vec.toVec3D()); + mop.typeOfHit = null; + return mop; + } + + public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid, BlockCoord pos) + { + MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); + if(mop != null) + { + mop.typeOfHit = EnumMovingObjectType.TILE; + mop.blockX = pos.x; + mop.blockY = pos.y; + mop.blockZ = pos.z; + } + return mop; + } + + public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid, Entity e) + { + MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); + if(mop != null) + { + mop.typeOfHit = EnumMovingObjectType.ENTITY; + mop.entityHit = e; + } + return mop; + } + + public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids) + { + double c_dist = Double.MAX_VALUE; + MovingObjectPosition c_hit = null; + + for(IndexedCuboid6 cuboid : cuboids) + { + MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); + if(mop != null && s_dist < c_dist) + { + mop = new ExtendedMOP(mop, cuboid.data); + c_dist = s_dist; + c_hit = mop; + c_cuboid = cuboid; + } + } + + return c_hit; + } + + public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids, BlockCoord pos, Block block) + { + MovingObjectPosition mop = rayTraceCuboids(start, end, cuboids); + if(mop != null) + { + mop.typeOfHit = EnumMovingObjectType.TILE; + mop.blockX = pos.x; + mop.blockY = pos.y; + mop.blockZ = pos.z; + if(block != null) + c_cuboid.add(new Vector3(-pos.x, -pos.y, -pos.z)).setBlockBounds(block); + } + return mop; + } + + public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) + { + Vec3 headVec = Vec3.createVectorHelper(player.posX, (player.posY + 1.62) - player.yOffset, player.posZ); + Vec3 lookVec = player.getLook(1.0F); + double reach = world.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player); + Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); + return Block.blocksList[world.getBlockId(x, y, z)].collisionRayTrace(world, x, y, z, headVec, endVec); + } + + private static double getBlockReachDistance_server(EntityPlayerMP player) + { + return player.theItemInWorldManager.getBlockReachDistance(); + } + + @SideOnly(Side.CLIENT) + private static double getBlockReachDistance_client() + { + return Minecraft.getMinecraft().playerController.getBlockReachDistance(); + } + + public static MovingObjectPosition reTrace(World world, EntityPlayer player) + { + return reTrace(world, player, world.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player)); + } + + public static MovingObjectPosition reTrace(World world, EntityPlayer player, double reach) + { + Vec3 headVec = Vec3.createVectorHelper(player.posX, (player.posY + 1.62) - player.yOffset, player.posZ); + Vec3 lookVec = player.getLook(1); + Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); + return world.rayTraceBlocks_do_do(headVec, endVec, true, false); + } +} diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java new file mode 100644 index 0000000..e688251 --- /dev/null +++ b/codechicken/lib/render/CCModel.java @@ -0,0 +1,968 @@ +package codechicken.lib.render; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; +import codechicken.lib.lighting.CCRBModel; +import codechicken.lib.lighting.LightModel; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.RedundantTransformation; +import codechicken.lib.vec.Transformation; +import codechicken.lib.vec.TransformationList; +import codechicken.lib.vec.Translation; +import codechicken.lib.vec.Vector3; + +import static codechicken.lib.vec.Rotation.*; + +public class CCModel +{ + private static class PositionNormalEntry + { + public Vector3 pos; + public LinkedList normals = new LinkedList(); + + public PositionNormalEntry(Vector3 position) + { + pos = position; + } + + public boolean positionEqual(Vector3 v) + { + return pos.x == v.x && pos.y == v.y && pos.z == v.z; + } + + public PositionNormalEntry addNormal(Vector3 normal) + { + normals.add(normal); + return this; + } + } + + public final int vertexMode; + public final int vp; + public Vertex5[] verts; + public Vector3[] normals; + public int[] colours; + + protected CCModel(int vertexMode) + { + if(vertexMode != 7 && vertexMode != 4) + throw new IllegalArgumentException("Models must be GL_QUADS or GL_TRIANGLES"); + + this.vertexMode = vertexMode; + vp = vertexMode == 7 ? 4 : 3; + } + + /** + * Each pixel corresponds to one unit of position when generating the model + * @param i Vertex index to start generating at + * @param x1 The minX bound of the box + * @param y1 The minY bound of the box + * @param z1 The minZ bound of the box + * @param w The width of the box + * @param h The height of the box + * @param d The depth of the box + * @param tx The distance of the top left corner of the texture map from the left in pixels + * @param ty The distance of the top left corner of the texture map from the top in pixels + * @param tw The width of the texture in pixels + * @param th The height of the texture in pixels + * @param f The scale of the model, pixels per block, normally 16 + * @return The generated model + */ + public CCModel generateBox(int i, double x1, double y1, double z1, double w, double h, double d, double tx, double ty, double tw, double th, double f) + { + double u1, v1, u2, v2; + double x2 = x1+w; + double y2 = y1+h; + double z2 = z1+d; + x1 /= f; x2 /= f; y1 /= f; y2 /= f; z1 /= f; z2 /= f; + + //bottom face + u1 = (tx + d + w) / tw; v1 = (ty + d) / th; + u2 = (tx + d*2 + w) / tw; v2 = ty / th; + verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + verts[i++] = new Vertex5(x1, y1, z1, u1, v1); + verts[i++] = new Vertex5(x2, y1, z1, u2, v1); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + + //top face + u1 = (tx + d) / tw; v1 = (ty + d) / th; + u2 = (tx + d + w) / tw; v2 = ty / th; + verts[i++] = new Vertex5(x2, y2, z2, u2, v2); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x1, y2, z2, u1, v2); + + //front face + u1 = (tx + d + w) / tw; v1 = (ty + d) / th; + u2 = (tx + d) / tw; v2 = (ty + d + h) / th; + verts[i++] = new Vertex5(x1, y2, z1, u2, v1); + verts[i++] = new Vertex5(x2, y2, z1, u1, v1); + verts[i++] = new Vertex5(x2, y1, z1, u1, v2); + verts[i++] = new Vertex5(x1, y1, z1, u2, v2); + + //back face + u1 = (tx + d*2 + w*2) / tw; v1 = (ty + d) / th; + u2 = (tx + d*2 + w) / tw; v2 = (ty + d + h) / th; + verts[i++] = new Vertex5(x1, y2, z2, u1, v1); + verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1); + + //left face + u1 = (tx + d) / tw; v1 = (ty + d) / th; + u2 = (tx) / tw; v2 = (ty + d + h) / th; + verts[i++] = new Vertex5(x1, y2, z2, u2, v1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x1, y1, z1, u1, v2); + verts[i++] = new Vertex5(x1, y1, z2, u2, v2); + + //right face + u1 = (tx + d*2 + w) / tw; v1 = (ty + d) / th; + u2 = (tx + d + w) / tw; v2 = (ty + d + h) / th; + verts[i++] = new Vertex5(x2, y1, z2, u1, v2); + verts[i++] = new Vertex5(x2, y1, z1, u2, v2); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1); + verts[i++] = new Vertex5(x2, y2, z2, u1, v1); + + return this; + } + + /** + * Generates a box, uv mapped to be the same as a minecraft block with the same bounds + * @param i The vertex index to start generating at + * @param bounds The bounds of the block, 0 to 1 + * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. + */ + public CCModel generateBlock(int i, Cuboid6 bounds) + { + return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z); + } + + /** + * Generates a box, uv mapped to be the same as a minecraft block with the same bounds + * @param i The vertex index to start generating at + * @param x1 minX + * @param y1 minY + * @param z1 minZ + * @param x2 maxX + * @param y2 maxY + * @param z2 maxZ + * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. + */ + public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) + { + double u1, v1, u2, v2; + + //bottom face + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + verts[i++] = new Vertex5(x1, y1, z1, u1, v1); + verts[i++] = new Vertex5(x2, y1, z1, u2, v1); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + + //top face + u1 = x1+2; v1 = z1; + u2 = x2+2; v2 = z2; + verts[i++] = new Vertex5(x2, y2, z2, u2, v2); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x1, y2, z2, u1, v2); + + //east face + u1 = x1+4; v1 = 1-y2; + u2 = x2+4; v2 = 1-y1; + verts[i++] = new Vertex5(x1, y1, z1, u1, v2); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1); + verts[i++] = new Vertex5(x2, y1, z1, u2, v2); + + //west face + u1 = x1+6; v1 = 1-y2; + u2 = x2+6; v2 = 1-y1; + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1); + verts[i++] = new Vertex5(x1, y2, z2, u1, v1); + verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + + //north face + u1 = z1+8; v1 = 1-y2; + u2 = z2+8; v2 = 1-y1; + verts[i++] = new Vertex5(x1, y1, z2, u2, v2); + verts[i++] = new Vertex5(x1, y2, z2, u2, v1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x1, y1, z1, u1, v2); + + //south face + u1 = z1+10; v1 = 1-y2; + u2 = z2+10; v2 = 1-y1; + verts[i++] = new Vertex5(x2, y1, z1, u1, v2); + verts[i++] = new Vertex5(x2, y2, z1, u1, v1); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + + return this; + } + + public CCModel computeNormals() + { + return computeNormals(0, verts.length); + } + + /** + * Computes the normals of all faces in the model. + * Uses the cross product of the vectors along 2 sides of the face + * @param start The first vertex to generate normals for + * @param length The number of vertices to generate normals for. Note this must be a multiple of 3 for triangles or 4 for quads + * @return The model + */ + public CCModel computeNormals(int start, int length) + { + if(length%vp != 0 || start%vp != 0) + throw new IllegalArgumentException("Cannot generate normals across polygons"); + + if(normals == null) + normals = new Vector3[verts.length]; + + for(int k = 0; k < length; k+=vp) + { + int i = k + start; + Vector3 diff1 = verts[i+1].vec.copy().subtract(verts[i].vec); + Vector3 diff2 = verts[i+vp-1].vec.copy().subtract(verts[i].vec); + normals[i] = diff1.crossProduct(diff2).normalize(); + for(int d = 1; d < vp; d++) + normals[i+d] = normals[i].copy(); + } + + return this; + } + + /** + * Computes lighting using the normals and the colour 0xFFFFFF. + * Per vert colouring will be added when needed. + * Make sure you have generated your normals on the model first. + * If you rotate your model after this, the lighting will no longer be valid + * @param light The light model to calculate + * @return The model + */ + public CCModel computeLighting(LightModel light) + { + if(colours == null) + setColour(-1); + for(int k = 0; k < verts.length; k++) + colours[k] = light.apply(colours[k], normals[k]); + return this; + } + + public CCModel setColour(int c) + { + if(colours == null) + colours = new int[verts.length]; + for(int k = 0; k < verts.length; k++) + colours[k] = c; + return this; + } + + /** + * Warning, only use this if you NEED to be identical to MC's light model, it's hideous. + */ + public CCRBModel withMCLighting() + { + return new CCRBModel(this); + } + + /** + * Averages all normals at the same position to produce a smooth lighting effect. + * @return The model + */ + public CCModel smoothNormals() + { + ArrayList map = new ArrayList(); + nextvert: for(int k = 0; k < verts.length; k++) + { + Vector3 vec = verts[k].vec; + for(PositionNormalEntry e : map) + if(e.positionEqual(vec)) + { + e.addNormal(normals[k]); + continue nextvert; + } + + map.add(new PositionNormalEntry(vec).addNormal(normals[k])); + } + + for(PositionNormalEntry e : map) + { + if(e.normals.size() <= 1) + continue; + + Vector3 new_n = new Vector3(); + for(Vector3 n : e.normals) + new_n.add(n); + + new_n.normalize(); + for(Vector3 n : e.normals) + n.set(new_n); + } + + return this; + } + + public CCModel apply(Transformation t) + { + for(int k = 0; k < verts.length; k++) + t.apply(verts[k].vec); + + if(normals != null) + for(int k = 0; k < normals.length; k++) + t.applyN(normals[k]); + + return this; + } + + public void render() + { + render(0, verts.length, null, null, null); + } + + public void render(double x, double y, double z, double u, double v) + { + render(new Translation(new Vector3(x, y, z)), new UVTranslation(u, v)); + } + + public void render(double x, double y, double z, IUVTransformation u) + { + render(new Translation(new Vector3(x, y, z)), u); + } + + public void render(Transformation t, double u, double v) + { + render(t, new UVTranslation(u, v)); + } + + public void render(Transformation t, IUVTransformation u) + { + render(t, u, ColourModifier.instance); + } + + public void render(Transformation t, IUVTransformation u, IVertexModifier m) + { + render(0, verts.length, t, u, m); + } + + /** + * Renders vertices start through start+length-1 of the model + * @param start The first vertex to render + * @param length The number of vertices to render + * @param t The transformation to apply to the mat + * @param u The u texture offset + * @param v The v texture offset + */ + public void render(int start, int length, Transformation t, IUVTransformation u, IVertexModifier m) + { + boolean drawNormal = CCRenderState.useNormals() && normals != null; + boolean computeNormal = drawNormal || m != null && m.needsNormals(); + Vector3 normal = new Vector3(); + Vertex5 vert; + Vector3 vec = new Vector3(); + UV uv = new UV(); + Tessellator tess = Tessellator.instance; + for(int k = 0; k < length; k++) + { + int i = start+k; + if(computeNormal) + { + if(t != null) + t.applyN(normal.set(normals[i])); + else + normal = normals[i]; + + if(drawNormal) + tess.setNormal((float)normal.x, (float)normal.y, (float)normal.z); + } + + vert = verts[i]; + if(t != null) + t.apply(vec.set(vert.vec)); + else + vec = vert.vec; + + if(u != null) + u.transform(uv.set(vert.uv)); + else + uv = vert.uv; + + if(m != null) + m.applyModifiers(this, tess, vec, uv, normal, i); + + tess.addVertexWithUV(vec.x, vec.y, vec.z, uv.u, uv.v); + } + } + + public static CCModel quadModel(int numVerts) + { + return newModel(7, numVerts); + } + + public static CCModel triModel(int numVerts) + { + return newModel(4, numVerts); + } + + public static CCModel newModel(int vertexMode, int numVerts) + { + CCModel model = newModel(vertexMode); + model.verts = new Vertex5[numVerts]; + return model; + } + + public static CCModel newModel(int vertexMode) + { + return new CCModel(vertexMode); + } + + public static double[] parseDoubles(String s, String token) + { + String[] as = s.split(token); + double[] values = new double[as.length]; + for(int i = 0; i < as.length; i++) + values[i] = Double.parseDouble(as[i]); + return values; + } + + public static void illegalAssert(boolean b, String err) + { + if(!b) throw new IllegalArgumentException(err); + } + + public static void assertMatch(Matcher m, String s) + { + m.reset(s); + illegalAssert(m.matches(), "Malformed line: "+s); + } + + private static final Pattern vertPattern = Pattern.compile("v(?: ([\\d\\.+-]+))+"); + private static final Pattern uvwPattern = Pattern.compile("vt(?: ([\\d\\.+-]+))+"); + private static final Pattern normalPattern = Pattern.compile("vn(?: ([\\d\\.+-]+))+"); + private static final Pattern polyPattern = Pattern.compile("f(?: ((?:\\d*)(?:/\\d*)?(?:/\\d*)?))+"); + public static final Matcher vertMatcher = vertPattern.matcher(""); + public static final Matcher uvwMatcher = uvwPattern.matcher(""); + public static final Matcher normalMatcher = normalPattern.matcher(""); + public static final Matcher polyMatcher = polyPattern.matcher(""); + + /** + * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file + * @param input An input stream to a obj file + * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) + * @param coordSystem The cooridnate system transformation to apply + * @return A map of group names to models + * @throws IOException + */ + public static Map parseObjModels(InputStream input, int vertexMode, Transformation coordSystem) throws IOException + { + if(coordSystem == null) + coordSystem = new RedundantTransformation(); + int vp = vertexMode == 7 ? 4 : 3; + + HashMap modelMap = new HashMap(); + ArrayList verts = new ArrayList(); + ArrayList uvs = new ArrayList(); + ArrayList normals = new ArrayList(); + ArrayList polys = new ArrayList(); + String modelName = "unnamed"; + + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + + String line; + while((line = reader.readLine()) != null) + { + line = line.replaceAll("\\s+", " ").trim(); + if(line.startsWith("#") || line.length() == 0) + continue; + + if(line.startsWith("v ")) + { + assertMatch(vertMatcher, line); + double[] values = parseDoubles(line.substring(2), " "); + illegalAssert(values.length >= 3, "Vertices must have x, y and z components"); + Vector3 vert = new Vector3(values[0], values[1], values[2]); + coordSystem.apply(vert); + verts.add(vert); + continue; + } + if(line.startsWith("vt ")) + { + assertMatch(uvwMatcher, line); + double[] values = parseDoubles(line.substring(3), " "); + illegalAssert(values.length >= 2, "Tex Coords must have u, and v components"); + uvs.add(new Vector3(values[0], 1-values[1], 0)); + continue; + } + if(line.startsWith("vn ")) + { + assertMatch(normalMatcher, line); + double[] values = parseDoubles(line.substring(3), " "); + illegalAssert(values.length >= 3, "Normals must have x, y and z components"); + Vector3 norm = new Vector3(values[0], values[1], values[2]).normalize(); + coordSystem.applyN(norm); + normals.add(norm); + continue; + } + if(line.startsWith("f ")) + { + assertMatch(polyMatcher, line); + String[] av = line.substring(2).split(" "); + illegalAssert(av.length >= 3, "Polygons must have at least 3 vertices"); + int[][] polyVerts = new int[av.length][3]; + for(int i = 0; i < av.length; i++) + { + String[] as = av[i].split("/"); + for(int p = 0; p < as.length; p++) + if(as[p].length() > 0) + polyVerts[i][p] = Integer.parseInt(as[p]); + } + if(vp == 3) + triangulate(polys, polyVerts); + else + quadulate(polys, polyVerts); + } + if(line.startsWith("g ")) + { + if(!polys.isEmpty()) + { + modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); + polys.clear(); + } + modelName = line.substring(2); + } + } + + if(!polys.isEmpty()) + modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); + + return modelMap; + } + + public static void triangulate(List polys, int[][] polyVerts) + { + for(int i = 2; i < polyVerts.length; i++) + { + polys.add(polyVerts[0]); + polys.add(polyVerts[i]); + polys.add(polyVerts[i-1]); + } + } + + public static void quadulate(List polys, int[][] polyVerts) + { + if(polyVerts.length == 4) + { + polys.add(polyVerts[0]); + polys.add(polyVerts[3]); + polys.add(polyVerts[2]); + polys.add(polyVerts[1]); + } + else + { + for(int i = 2; i < polyVerts.length; i++) + { + polys.add(polyVerts[0]); + polys.add(polyVerts[i]); + polys.add(polyVerts[i-1]); + polys.add(polyVerts[i-1]); + } + } + } + + /** + * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file + * @param s The name of the obj resource + * @return A map of group names to models + */ + public static Map parseObjModels(ResourceLocation res) + { + return parseObjModels(res, 4, null); + } + /** + * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file + * @param res The resource for the obj file + * @param coordSystem The cooridnate system transformation to apply + * @return A map of group names to models + */ + public static Map parseObjModels(ResourceLocation res, Transformation coordSystem) + { + try + { + return parseObjModels( + Minecraft.getMinecraft().func_110442_L().func_110536_a(res).func_110527_b(), + 4, coordSystem); + } + catch(IOException e) + { + throw new RuntimeException("failed to load model: "+res, e); + } + } + + /** + * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file + * @param s The name of the obj resource + * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) + * @param coordSystem The cooridnate system transformation to apply + * @return A map of group names to models + */ + public static Map parseObjModels(ResourceLocation res, int vertexMode, Transformation coordSystem) + { + try + { + return parseObjModels( + Minecraft.getMinecraft().func_110442_L().func_110536_a(res).func_110527_b(), + vertexMode, coordSystem); + } + catch(Exception e) + { + throw new RuntimeException("failed to load model: "+res, e); + } + } + + public static CCModel createModel(List verts, List uvs, List normals, int vertexMode, List polys) + { + int vp = vertexMode == 7 ? 4 : 3; + if(polys.size() < vp || polys.size()%vp != 0) + throw new IllegalArgumentException("Invalid number of vertices for model: "+polys.size()); + + boolean hasNormals = polys.get(0)[2] > 0; + CCModel model = CCModel.newModel(vertexMode, polys.size()); + if(hasNormals) + model.normals = new Vector3[polys.size()]; + + for(int i = 0; i < polys.size(); i++) + { + int[] ai = polys.get(i); + Vector3 vert = verts.get(ai[0]-1).copy(); + Vector3 uv = ai[1] <= 0 ? new Vector3() : uvs.get(ai[1]-1).copy(); + if(ai[2] > 0 != hasNormals) + throw new IllegalArgumentException("Normals are an all or nothing deal here."); + + model.verts[i] = new Vertex5(vert, uv.x, uv.y); + if(hasNormals) + model.normals[i] = normals.get(ai[2]-1).copy(); + } + + return model; + } + + /** + * Brings the UV coordinates of each face closer to the center UV by d. + * Useful for fixing texture seams + */ + public CCModel shrinkUVs(double d) + { + for(int k = 0; k < verts.length; k+=vp) + { + UV uv = new UV(); + for(int i = 0; i < vp; i++) + { + uv.add(verts[k+i].uv); + } + uv.mul(1D/vp); + for(int i = 0; i < vp; i++) + { + Vertex5 vert = verts[k+i]; + vert.uv.u += vert.uv.u < uv.u ? d : -d; + vert.uv.v += vert.uv.v < uv.v ? d : -d; + } + } + return this; + } + + /** + * @param side1 The side of this model + * @param side2 The side of the new model + * @param point The point to rotate around + * @return A copy of this model rotated to the appropriate side + */ + public CCModel sidedCopy(int side1, int side2, Vector3 point) + { + CCModel model = newModel(vertexMode, verts.length); + copy(this, 0, model, 0, model.verts.length); + return model.apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point)); + } + + /** + * Copies length vertices and normals + */ + public static void copy(CCModel src, int srcpos, CCModel dest, int destpos, int length) + { + for(int k = 0; k < length; k++) + dest.verts[destpos+k] = src.verts[srcpos+k].copy(); + + if(src.normals != null) + { + if(dest.normals == null) + dest.normals = new Vector3[dest.verts.length]; + + for(int k = 0; k < length; k++) + dest.normals[destpos+k] = src.normals[srcpos+k].copy(); + } + + if(src.colours != null) + { + if(dest.colours == null) + dest.colours = new int[dest.verts.length]; + System.arraycopy(src.colours, srcpos, dest.colours, destpos, length); + } + } + + /** + * Generate models rotated to the other 5 sides of the block + * @param models An array of 6 models + * @param side The side of this model + * @param point The rotation point + */ + public static void generateSidedModels(CCModel[] models, int side, Vector3 point) + { + for(int s = 0; s < 6; s++) + { + if(s == side) + continue; + + models[s] = models[side].sidedCopy(side, s, point); + } + } + + /** + * Generate models rotated to the other 3 horizontal of the block + * @param models An array of 4 models + * @param side The side of this model + * @param point The rotation point + */ + public static void generateSidedModelsH(CCModel[] models, int side, Vector3 point) + { + for(int s = 2; s < 6; s++) + { + if(s == side) + continue; + + models[s] = models[side].sidedCopy(side, s, point); + } + } + + /** + * Generates copies of faces with clockwise vertices + * @return The model + */ + public CCModel generateBackface(int srcpos, int destpos, int length) + { + if(srcpos+length > destpos) + throw new IllegalArgumentException("Overlapping src and dest arrays"); + if(srcpos%vp != 0 || destpos%vp != 0 || length%vp != 0) + throw new IllegalArgumentException("Vertices do not align with polygons"); + + int[][] o = new int[][]{{0, 0}, {1, vp-1}, {2, vp-2}, {3, vp-3}}; + for(int i = 0; i < length; i++) + { + int b = (i/vp)*vp; + int d = i%vp; + int di = destpos+b+o[d][1]; + int si = srcpos+b+o[d][0]; + verts[di] = new Vertex5(verts[si]); + if(normals != null && normals[si] != null) + normals[di] = normals[si].copy().negate(); + } + return this; + } + + /** + * Generates sided copies of vertices into this model. + * Assumes that your model has been generated at vertex side*(numVerts/6) + */ + public CCModel generateSidedParts(int side, Vector3 point) + { + if(verts.length%(6*vp) != 0) + throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); + int length = verts.length/6; + + for(int s = 0; s < 6; s++) + { + if(s == side) + continue; + + generateSidedPart(side, s, point, length*side, length*s, length); + } + + return this; + } + + /** + * Generates sided copies of vertices into this model. + * Assumes that your model has been generated at vertex side*(numVerts/4) + */ + public CCModel generateSidedPartsH(int side, Vector3 point) + { + if(verts.length%(4*vp) != 0) + throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); + int length = verts.length/4; + + for(int s = 2; s < 6; s++) + { + if(s == side) + continue; + + generateSidedPart(side, s, point, length*(side-2), length*(s-2), length); + } + + return this; + } + + /** + * Generates a sided copy of verts into this model + */ + public CCModel generateSidedPart(int side1, int side2, Vector3 point, int srcpos, int destpos, int length) + { + return generateRotatedPart(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]), point, srcpos, destpos, length); + } + + /** + * Generates a rotated copy of verts into this model + */ + public CCModel generateRotatedPart(Transformation t, Vector3 point, int srcpos, int destpos, int length) + { + for(int k = 0; k < length; k++) + { + verts[destpos+k] = verts[srcpos+k].copy(); + verts[destpos+k].vec + .subtract(point) + .apply(t) + .add(point); + } + + if(normals != null) + for(int k = 0; k < length; k++) + normals[destpos+k] = normals[srcpos+k].copy().apply(t); + + return this; + } + + public static CCModel combine(Collection models) + { + if(models.isEmpty()) + return null; + + int numVerts = 0; + int vertexMode = -1; + for(CCModel model : models) + { + if(vertexMode == -1) + vertexMode = model.vertexMode; + if(vertexMode != model.vertexMode) + throw new IllegalArgumentException("Cannot combine models with different vertex modes"); + + numVerts+=model.verts.length; + } + + CCModel c_model = newModel(vertexMode, numVerts); + int i = 0; + for(CCModel model : models) + { + copy(model, 0, c_model, i, model.verts.length); + i+=model.verts.length; + } + + return c_model; + } + + public CCModel twoFacedCopy() + { + CCModel model = newModel(vertexMode, verts.length*2); + copy(this, 0, model, 0, verts.length); + model.generateBackface(0, verts.length, verts.length); + return model; + } + + public CCModel copy() + { + CCModel model = newModel(vertexMode, verts.length); + copy(this, 0, model, 0, verts.length); + return model; + } + + /** + * @return The average of all vertices, for bones. + */ + public Vector3 collapse() + { + Vector3 v = new Vector3(); + for(Vertex5 vert : verts) + v.add(vert.vec); + v.multiply(1/(double)verts.length); + return v; + } + + public CCModel zOffset(Cuboid6 offsets) + { + for(int k = 0; k < verts.length; k++) + { + Vertex5 vert = verts[k]; + Vector3 normal = normals[k]; + switch(findSide(normal)) + { + case 0: + vert.vec.y += offsets.min.y; + break; + case 1: + vert.vec.y += offsets.max.y; + break; + case 2: + vert.vec.z += offsets.min.z; + break; + case 3: + vert.vec.z += offsets.max.z; + break; + case 4: + vert.vec.x += offsets.min.x; + break; + case 5: + vert.vec.x += offsets.max.x; + break; + } + } + return this; + } + + public static int findSide(Vector3 normal) + { + if(normal.y <=-0.99) return 0; + if(normal.y >= 0.99) return 1; + if(normal.z <=-0.99) return 2; + if(normal.z >= 0.99) return 3; + if(normal.x <=-0.99) return 4; + if(normal.x >= 0.99) return 5; + return -1; + } + + /** + * @return A Cuboid6 containing all the verts in this model + */ + public Cuboid6 bounds() + { + Vector3 vec1 = verts[0].vec; + Cuboid6 c = new Cuboid6(vec1.copy(), vec1.copy()); + for(int i = 1; i < verts.length; i++) + c.enclose(verts[i].vec); + return c; + } +} diff --git a/codechicken/lib/render/CCModelLibrary.java b/codechicken/lib/render/CCModelLibrary.java new file mode 100644 index 0000000..bb246c1 --- /dev/null +++ b/codechicken/lib/render/CCModelLibrary.java @@ -0,0 +1,93 @@ +package codechicken.lib.render; + +import codechicken.lib.vec.Matrix4; +import codechicken.lib.vec.Quat; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Scale; +import codechicken.lib.vec.Vector3; + +import static codechicken.lib.math.MathHelper.phi; + +public class CCModelLibrary +{ + public static CCModel icosahedron4; + public static CCModel icosahedron7; + + private static int i; + + static + { + generateIcosahedron(); + } + + private static void generateIcosahedron() + { + Vector3[] verts = new Vector3[12]; + + verts[0] = new Vector3(-1, phi, 0); + verts[1] = new Vector3( 1, phi, 0); + verts[2] = new Vector3( 1,-phi, 0); + verts[3] = new Vector3(-1,-phi, 0); + + verts[4] = new Vector3(0,-1, phi); + verts[5] = new Vector3(0, 1, phi); + verts[6] = new Vector3(0, 1,-phi); + verts[7] = new Vector3(0,-1,-phi); + + verts[8] = new Vector3( phi, 0,-1); + verts[9] = new Vector3( phi, 0, 1); + verts[10] = new Vector3(-phi, 0, 1); + verts[11] = new Vector3(-phi, 0,-1); + + Quat quat = Quat.aroundAxis(0, 0, 1, Math.atan(1/phi)); + for(Vector3 vec : verts) + quat.rotate(vec); + + icosahedron4 = CCModel.newModel(4, 60); + icosahedron7 = CCModel.newModel(7, 80); + + i = 0; + //top + addIcosahedronTriangle(verts[1], 0.5, 0, verts[0], 0, 0.25, verts[5], 1, 0.25); + addIcosahedronTriangle(verts[1], 0.5, 0, verts[5], 0, 0.25, verts[9], 1, 0.25); + addIcosahedronTriangle(verts[1], 0.5, 0, verts[9], 0, 0.25, verts[8], 1, 0.25); + addIcosahedronTriangle(verts[1], 0.5, 0, verts[8], 0, 0.25, verts[6], 1, 0.25); + addIcosahedronTriangle(verts[1], 0.5, 0, verts[6], 0, 0.25, verts[0], 1, 0.25); + //centre 1vert top + addIcosahedronTriangle(verts[0], 0.5, 0.25, verts[11],0, 0.75, verts[10],1, 0.75); + addIcosahedronTriangle(verts[5], 0.5, 0.25, verts[10],0, 0.75, verts[4], 1, 0.75); + addIcosahedronTriangle(verts[9], 0.5, 0.25, verts[4], 0, 0.75, verts[2], 1, 0.75); + addIcosahedronTriangle(verts[8], 0.5, 0.25, verts[2], 0, 0.75, verts[7], 1, 0.75); + addIcosahedronTriangle(verts[6], 0.5, 0.25, verts[7], 0, 0.75, verts[11],1, 0.75); + //centre 1vert bottom + addIcosahedronTriangle(verts[2], 0.5, 0.75, verts[8], 0, 0.25, verts[9], 1, 0.25); + addIcosahedronTriangle(verts[7], 0.5, 0.75, verts[6], 0, 0.25, verts[8], 1, 0.25); + addIcosahedronTriangle(verts[11],0.5, 0.75, verts[0], 0, 0.25, verts[6], 1, 0.25); + addIcosahedronTriangle(verts[10],0.5, 0.75, verts[5], 0, 0.25, verts[0], 1, 0.25); + addIcosahedronTriangle(verts[4], 0.5, 0.75, verts[9], 0, 0.25, verts[5], 1, 0.25); + //bottom + addIcosahedronTriangle(verts[3], 0.5, 1, verts[2], 0, 0.75, verts[4], 1, 0.75); + addIcosahedronTriangle(verts[3], 0.5, 1, verts[7], 0, 0.75, verts[2], 1, 0.75); + addIcosahedronTriangle(verts[3], 0.5, 1, verts[11],0, 0.75, verts[7], 1, 0.75); + addIcosahedronTriangle(verts[3], 0.5, 1, verts[10],0, 0.75, verts[11],1, 0.75); + addIcosahedronTriangle(verts[3], 0.5, 1, verts[4], 0, 0.75, verts[10],1, 0.75); + + icosahedron4.computeNormals().smoothNormals(); + icosahedron7.computeNormals().smoothNormals(); + } + + private static void addIcosahedronTriangle(Vector3 vec1, double u1, double v1, + Vector3 vec2, double u2, double v2, + Vector3 vec3, double u3, double v3) + { + icosahedron4.verts[i*3] = icosahedron7.verts[i*4] = new Vertex5(vec1, u1, v1); + icosahedron4.verts[i*3+1] = icosahedron7.verts[i*4+1] = new Vertex5(vec2, u2, v2); + icosahedron4.verts[i*3+2] = icosahedron7.verts[i*4+2] = icosahedron7.verts[i*4+3] = new Vertex5(vec3, u3, v3); + i++; + } + + public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) + { + return new Matrix4().translate(position).apply(new Scale(scale)).apply(rotation); + } +} diff --git a/codechicken/lib/render/CCRenderState.java b/codechicken/lib/render/CCRenderState.java new file mode 100644 index 0000000..85d99ad --- /dev/null +++ b/codechicken/lib/render/CCRenderState.java @@ -0,0 +1,140 @@ +package codechicken.lib.render; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.IBlockAccess; + +public class CCRenderState +{ + private static boolean useNormals; + private static boolean hasBrightness; + private static int brightness; + private static boolean useModelColours; + private static int colour; + private static boolean hasColour; + private static int alpha; + private static boolean alphaOverride; + + public static void useNormals(boolean b) + { + useNormals = b; + } + + public static boolean useNormals() + { + return useNormals; + } + + public static void useModelColours(boolean b) + { + useModelColours = b; + } + + public static boolean useModelColours() + { + return useModelColours; + } + + public static void setAlpha(int a) + { + alpha = a; + alphaOverride = true; + } + + public static void clearAlphaOverride() + { + alphaOverride = false; + } + + public static void vertexColour(int c) + { + if(alphaOverride) + setColour(c&0xFFFFFF00|alpha); + else + setColour(c); + } + + public static void vertexColour(int r, int g, int b, int a) + { + if(alphaOverride) + Tessellator.instance.setColorRGBA(r, g, b, alpha); + else + Tessellator.instance.setColorRGBA(r, g, b, a); + } + + public static void setBrightness(IBlockAccess world, int x, int y, int z) + { + Block block = Block.blocksList[world.getBlockId(x, y, z)]; + setBrightness(block == null ? world.getLightBrightnessForSkyBlocks(x, y, z, 0) : block.getMixedBrightnessForBlock(world, x, y, z)); + setColour(0xFFFFFFFF); + } + + public static void setBrightness(int b) + { + hasBrightness = true; + Tessellator.instance.setBrightness(brightness = b); + } + + public static void setColourOpaque(int c) + { + setColour(c << 8 | 0xFF); + } + + //RGBA + public static void setColour(int c) + { + hasColour = true; + colour = c; + Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF); + } + + public static void changeTexture(String texture) + { + changeTexture(new ResourceLocation(texture)); + } + + public static void changeTexture(ResourceLocation texture) + { + Minecraft.getMinecraft().renderEngine.func_110577_a(texture); + } + + public static void apply() + { + if(hasBrightness) + Tessellator.instance.setBrightness(brightness); + if(hasColour) + Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF); + } + + public static void reset() + { + hasBrightness = false; + useModelColours = false; + hasColour = false; + alphaOverride = false; + } + + public static void startDrawing(int i) + { + Tessellator.instance.startDrawing(i); + apply(); + } + + public static void draw() + { + Tessellator.instance.draw(); + } + + public static void pullLightmap() + { + setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX); + } + + public static void applyBrightnessTexCoords() + { + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness&0xFFFF, brightness>>>16); + } +} diff --git a/codechicken/lib/render/ColourModifier.java b/codechicken/lib/render/ColourModifier.java new file mode 100644 index 0000000..b1808b6 --- /dev/null +++ b/codechicken/lib/render/ColourModifier.java @@ -0,0 +1,22 @@ +package codechicken.lib.render; + +import net.minecraft.client.renderer.Tessellator; +import codechicken.lib.vec.Vector3; + +public class ColourModifier implements IVertexModifier +{ + public static final ColourModifier instance = new ColourModifier(); + + @Override + public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) + { + if(CCRenderState.useModelColours() && m != null && m.colours != null) + CCRenderState.vertexColour(m.colours[i]); + } + + @Override + public boolean needsNormals() + { + return false; + } +} diff --git a/codechicken/lib/render/EntityDigIconFX.java b/codechicken/lib/render/EntityDigIconFX.java new file mode 100644 index 0000000..97f854e --- /dev/null +++ b/codechicken/lib/render/EntityDigIconFX.java @@ -0,0 +1,106 @@ +package codechicken.lib.render; + +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; +import net.minecraft.client.particle.EffectRenderer; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class EntityDigIconFX extends EntityFX +{ + public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, Icon icon) + { + super(world, x, y, z, dx, dy, dz); + particleIcon = icon; + particleGravity = 1; + particleRed = particleGreen = particleBlue = 0.6F; + particleScale /= 2.0F; + } + + @Override + public int getFXLayer() + { + return 1; + } + + /** + * copy pasted from EntityDiggingFX + */ + @Override + public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7) + { + float f6 = (particleTextureIndexX + particleTextureJitterX / 4.0F) / 16.0F; + float f7 = f6 + 0.015609375F; + float f8 = (particleTextureIndexY + particleTextureJitterY / 4.0F) / 16.0F; + float f9 = f8 + 0.015609375F; + float f10 = 0.1F * particleScale; + + if (particleIcon != null) + { + f6 = particleIcon.getInterpolatedU(particleTextureJitterX / 4.0F * 16.0F); + f7 = particleIcon.getInterpolatedU((particleTextureJitterX + 1.0F) / 4.0F * 16.0F); + f8 = particleIcon.getInterpolatedV(particleTextureJitterY / 4.0F * 16.0F); + f9 = particleIcon.getInterpolatedV((particleTextureJitterY + 1.0F) / 4.0F * 16.0F); + } + + float f11 = (float)(prevPosX + (posX - prevPosX) * par2 - interpPosX); + float f12 = (float)(prevPosY + (posY - prevPosY) * par2 - interpPosY); + float f13 = (float)(prevPosZ + (posZ - prevPosZ) * par2 - interpPosZ); + float f14 = 1.0F; + par1Tessellator.setColorOpaque_F(f14 * particleRed, f14 * particleGreen, f14 * particleBlue); + par1Tessellator.addVertexWithUV(f11 - par3 * f10 - par6 * f10, f12 - par4 * f10, f13 - par5 * f10 - par7 * f10, f6, f9); + par1Tessellator.addVertexWithUV(f11 - par3 * f10 + par6 * f10, f12 + par4 * f10, f13 - par5 * f10 + par7 * f10, f6, f8); + par1Tessellator.addVertexWithUV(f11 + par3 * f10 + par6 * f10, f12 + par4 * f10, f13 + par5 * f10 + par7 * f10, f7, f8); + par1Tessellator.addVertexWithUV(f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10, f7, f9); + } + + public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, Icon icon, EffectRenderer effectRenderer) + { + float border = 0.1F; + Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2*border); + diff.x*=world.rand.nextDouble(); + diff.y*=world.rand.nextDouble(); + diff.z*=world.rand.nextDouble(); + Vector3 pos = diff.add(bounds.min).add(border); + + if (side == 0) + diff.y = bounds.min.y - border; + if (side == 1) + diff.y = bounds.max.y + border; + if (side == 2) + diff.z = bounds.min.z - border; + if (side == 3) + diff.z = bounds.max.z + border; + if (side == 4) + diff.x = bounds.min.x - border; + if (side == 5) + diff.x = bounds.max.x + border; + + effectRenderer.addEffect( + new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon) + .multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F)); + } + + public static void addBlockDestroyEffects(World world, Cuboid6 bounds, Icon[] icons, EffectRenderer effectRenderer) + { + Vector3 diff = bounds.max.copy().subtract(bounds.min); + Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); + Vector3 density = diff.copy().multiply(4); + density.x = Math.ceil(density.x); + density.y = Math.ceil(density.y); + density.z = Math.ceil(density.z); + + for (int i = 0; i < density.x; ++i) + for (int j = 0; j < density.y; ++j) + for (int k = 0; k < density.z; ++k) + { + double x = bounds.min.x+(i+0.5)*diff.x/density.x; + double y = bounds.min.y+(j+0.5)*diff.y/density.y; + double z = bounds.min.z+(k+0.5)*diff.z/density.z; + effectRenderer.addEffect( + new EntityDigIconFX(world, x, y, z, x-center.x, y-center.y, z-center.z, icons[world.rand.nextInt(icons.length)])); + } + } +} diff --git a/codechicken/lib/render/FontUtils.java b/codechicken/lib/render/FontUtils.java new file mode 100644 index 0000000..97ac4a5 --- /dev/null +++ b/codechicken/lib/render/FontUtils.java @@ -0,0 +1,69 @@ +package codechicken.lib.render; + +import org.lwjgl.opengl.GL11; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.item.ItemStack; + +public class FontUtils +{ + public static FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + + public static void drawCenteredString(String s, int xCenter, int y, int colour) + { + fontRenderer.drawString(s, xCenter-fontRenderer.getStringWidth(s)/2, y, colour); + } + + public static void drawRightString(String s, int xRight, int y, int colour) + { + fontRenderer.drawString(s, xRight-fontRenderer.getStringWidth(s), y, colour); + } + + public static final String[] prefixes = new String[]{"K", "M", "G"}; + public static void drawItemQuantity(int x, int y, ItemStack item, String quantity, int mode) + { + if(item == null || (quantity == null && item.stackSize <= 1)) + return; + + if(quantity == null) + { + switch(mode) + { + case 2: + int q = item.stackSize; + String postfix = ""; + for(int p = 0; p < 3 && q > 1000; p++) + { + q/=1000; + postfix = prefixes[p]; + } + quantity = Integer.toString(q)+postfix; + case 1: + quantity = ""; + if(item.stackSize/64 > 0) + quantity+=item.stackSize/64 + "s"; + if(item.stackSize%64 > 0) + quantity+=item.stackSize%64; + break; + default: + quantity = Integer.toString(item.stackSize); + break; + } + } + + double scale = quantity.length() > 2 ? 0.5 : 1; + double sheight = 8*scale; + double swidth = fontRenderer.getStringWidth(quantity)*scale; + + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glPushMatrix(); + GL11.glTranslated(x+16-swidth, y+16-sheight, 0); + GL11.glScaled(scale, scale, 1); + fontRenderer.drawStringWithShadow(quantity, 0, 0, 0xFFFFFF); + GL11.glPopMatrix(); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_DEPTH_TEST); + } +} diff --git a/codechicken/lib/render/IFaceRenderer.java b/codechicken/lib/render/IFaceRenderer.java new file mode 100644 index 0000000..d2ed2b4 --- /dev/null +++ b/codechicken/lib/render/IFaceRenderer.java @@ -0,0 +1,6 @@ +package codechicken.lib.render; + +public interface IFaceRenderer +{ + public void renderFace(Vertex5[] face, int side); +} diff --git a/codechicken/lib/render/IUVTransformation.java b/codechicken/lib/render/IUVTransformation.java new file mode 100644 index 0000000..386d583 --- /dev/null +++ b/codechicken/lib/render/IUVTransformation.java @@ -0,0 +1,6 @@ +package codechicken.lib.render; + +public interface IUVTransformation +{ + public void transform(UV texcoord); +} diff --git a/codechicken/lib/render/IVertexModifier.java b/codechicken/lib/render/IVertexModifier.java new file mode 100644 index 0000000..34cc286 --- /dev/null +++ b/codechicken/lib/render/IVertexModifier.java @@ -0,0 +1,11 @@ +package codechicken.lib.render; + +import net.minecraft.client.renderer.Tessellator; +import codechicken.lib.vec.Vector3; + +public interface IVertexModifier +{ + public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i); + + public boolean needsNormals(); +} diff --git a/codechicken/lib/render/IconTransformation.java b/codechicken/lib/render/IconTransformation.java new file mode 100644 index 0000000..3a189c5 --- /dev/null +++ b/codechicken/lib/render/IconTransformation.java @@ -0,0 +1,20 @@ +package codechicken.lib.render; + +import net.minecraft.util.Icon; + +public class IconTransformation implements IUVTransformation +{ + public Icon icon; + + public IconTransformation(Icon icon) + { + this.icon = icon; + } + + @Override + public void transform(UV texcoord) + { + texcoord.u = icon.getInterpolatedU(texcoord.u%2*16); + texcoord.v = icon.getInterpolatedV(texcoord.v%2*16); + } +} diff --git a/codechicken/lib/render/ManagedTextureFX.java b/codechicken/lib/render/ManagedTextureFX.java new file mode 100644 index 0000000..ed1166d --- /dev/null +++ b/codechicken/lib/render/ManagedTextureFX.java @@ -0,0 +1,31 @@ +package codechicken.lib.render; + +public class ManagedTextureFX extends TextureFX +{ + public boolean changed; + + public ManagedTextureFX(int size, String name) + { + super(size, name); + imageData = new int[size*size]; + } + + @Override + public void setup() + { + } + + public void setData(int[] data) + { + System.arraycopy(data, 0, imageData, 0, imageData.length); + changed = true; + } + + @Override + public boolean changed() + { + boolean r = changed; + changed = false; + return r; + } +} diff --git a/codechicken/lib/render/MultiIconTransformation.java b/codechicken/lib/render/MultiIconTransformation.java new file mode 100644 index 0000000..e9ed9a2 --- /dev/null +++ b/codechicken/lib/render/MultiIconTransformation.java @@ -0,0 +1,41 @@ +package codechicken.lib.render; + +import net.minecraft.util.Icon; + +/** + * Icon index is specified as (int)u>>1 + */ +public class MultiIconTransformation implements IUVTransformation +{ + public Icon[] icons; + + public MultiIconTransformation(Icon[] icons) + { + this.icons = icons; + } + + @Override + public void transform(UV texcoord) + { + int i = (int)texcoord.u>>1; + Icon icon = icons[i%icons.length]; + texcoord.u = icon.getInterpolatedU(texcoord.u%2*16); + texcoord.v = icon.getInterpolatedV(texcoord.v%2*16); + } + + public static CCModel setIconIndex(CCModel m, int index) + { + return setIconIndex(m, 0, m.verts.length, index); + } + + public static CCModel setIconIndex(CCModel m, int start, int length, int index) + { + for(int k = start; k < length; k++) + { + UV uv = m.verts[k].uv; + uv.u = uv.u%2+index*2; + uv.v %= 2; + } + return m; + } +} diff --git a/codechicken/lib/render/PlaceholderTexture.java b/codechicken/lib/render/PlaceholderTexture.java new file mode 100644 index 0000000..34538a6 --- /dev/null +++ b/codechicken/lib/render/PlaceholderTexture.java @@ -0,0 +1,19 @@ +package codechicken.lib.render; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.ResourceManager; +import net.minecraft.util.ResourceLocation; + +public class PlaceholderTexture extends TextureAtlasSprite +{ + protected PlaceholderTexture(String par1) + { + super(par1); + } + + @Override + public boolean load(ResourceManager manager, ResourceLocation location) + { + return false; + } +} diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java new file mode 100644 index 0000000..da37e99 --- /dev/null +++ b/codechicken/lib/render/RenderUtils.java @@ -0,0 +1,435 @@ +package codechicken.lib.render; + +import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; +import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; + +import org.lwjgl.opengl.GL11; + +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Transformation; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Vector3; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Icon; +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraftforge.client.IItemRenderer; +import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; + +public class RenderUtils +{ + static Vector3[] vectors = new Vector3[8]; + static RenderItem uniformRenderItem = new RenderItem() + { + public boolean shouldBob() + { + return false; + } + }; + static EntityItem entityItem; + + static + { + for(int i = 0; i < vectors.length; i++) + vectors[i] = new Vector3(); + + uniformRenderItem.setRenderManager(RenderManager.instance); + + entityItem = new EntityItem(null); + entityItem.hoverStart = 0; + } + + public static void renderLiquidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) + { + double u1 = icon.getMinU(); + double du = icon.getMaxU()-icon.getMinU(); + double v2 = icon.getMaxV(); + double dv = icon.getMaxV()-icon.getMinV(); + + Vector3 wide = vectors[0].set(point4).subtract(point1); + Vector3 high = vectors[1].set(point1).subtract(point2); + Tessellator t = Tessellator.instance; + + double wlen = wide.mag(); + double hlen = high.mag(); + + double x = 0; + while(x < wlen) + { + double rx = wlen - x; + if(rx > res) + rx = res; + + double y = 0; + while(y < hlen) + { + double ry = hlen-y; + if(ry > res) + ry = res; + + Vector3 dx1 = vectors[2].set(wide).multiply(x/wlen); + Vector3 dx2 = vectors[3].set(wide).multiply((x+rx)/wlen); + Vector3 dy1 = vectors[4].set(high).multiply(y/hlen); + Vector3 dy2 = vectors[5].set(high).multiply((y+ry)/hlen); + + t.addVertexWithUV(point2.x+dx1.x+dy2.x, point2.y+dx1.y+dy2.y, point2.z+dx1.z+dy2.z, u1, v2-ry/res*dv); + t.addVertexWithUV(point2.x+dx1.x+dy1.x, point2.y+dx1.y+dy1.y, point2.z+dx1.z+dy1.z, u1, v2); + t.addVertexWithUV(point2.x+dx2.x+dy1.x, point2.y+dx2.y+dy1.y, point2.z+dx2.z+dy1.z, u1+rx/res*du, v2); + t.addVertexWithUV(point2.x+dx2.x+dy2.x, point2.y+dx2.y+dy2.y, point2.z+dx2.z+dy2.z, u1+rx/res*du, v2-ry/res*dv); + + y+=ry; + } + + x+=rx; + } + } + + public static void translateToWorldCoords(Entity entity, float frame) + { + double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame; + double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame; + double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame; + + GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ); + } + + public static void drawOutlinedBoundingBox(AxisAlignedBB par1AxisAlignedBB) + { + Tessellator var2 = Tessellator.instance; + var2.startDrawing(3); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); + var2.draw(); + var2.startDrawing(3); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); + var2.draw(); + var2.startDrawing(1); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); + var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); + var2.draw(); + } + + public static void renderLiquidCuboid(Cuboid6 bound, Icon tex, double res) + { + renderLiquidQuad(//bottom + new Vector3(bound.min.x, bound.min.y, bound.min.z), + new Vector3(bound.max.x, bound.min.y, bound.min.z), + new Vector3(bound.max.x, bound.min.y, bound.max.z), + new Vector3(bound.min.x, bound.min.y, bound.max.z), + tex, res); + renderLiquidQuad(//top + new Vector3(bound.min.x, bound.max.y, bound.min.z), + new Vector3(bound.min.x, bound.max.y, bound.max.z), + new Vector3(bound.max.x, bound.max.y, bound.max.z), + new Vector3(bound.max.x, bound.max.y, bound.min.z), + tex, res); + renderLiquidQuad(//-x + new Vector3(bound.min.x, bound.max.y, bound.min.z), + new Vector3(bound.min.x, bound.min.y, bound.min.z), + new Vector3(bound.min.x, bound.min.y, bound.max.z), + new Vector3(bound.min.x, bound.max.y, bound.max.z), + tex, res); + renderLiquidQuad(//+x + new Vector3(bound.max.x, bound.max.y, bound.max.z), + new Vector3(bound.max.x, bound.min.y, bound.max.z), + new Vector3(bound.max.x, bound.min.y, bound.min.z), + new Vector3(bound.max.x, bound.max.y, bound.min.z), + tex, res); + renderLiquidQuad(//-z + new Vector3(bound.max.x, bound.max.y, bound.min.z), + new Vector3(bound.max.x, bound.min.y, bound.min.z), + new Vector3(bound.min.x, bound.min.y, bound.min.z), + new Vector3(bound.min.x, bound.max.y, bound.min.z), + tex, res); + renderLiquidQuad(//+z + new Vector3(bound.min.x, bound.max.y, bound.max.z), + new Vector3(bound.min.x, bound.min.y, bound.max.z), + new Vector3(bound.max.x, bound.min.y, bound.max.z), + new Vector3(bound.max.x, bound.max.y, bound.max.z), + tex, res); + } + + public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1, double ty2) + { + double[] points = new double[]{x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009}; + + Tessellator tessellator = Tessellator.instance; + switch(side) + { + case 0: + tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty1); + tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty1); + tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2); + tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2); + break; + case 1: + tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1); + tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1); + tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty2); + tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty2); + break; + case 2: + tessellator.addVertexWithUV(points[0], points[3], points[4], tx2, ty1); + tessellator.addVertexWithUV(points[1], points[3], points[4], tx1, ty1); + tessellator.addVertexWithUV(points[1], points[2], points[4], tx1, ty2); + tessellator.addVertexWithUV(points[0], points[2], points[4], tx2, ty2); + break; + case 3: + tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty1); + tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty1); + tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2); + tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2); + break; + case 4: + tessellator.addVertexWithUV(points[0], points[3], points[5], tx2, ty1); + tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1); + tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty2); + tessellator.addVertexWithUV(points[0], points[2], points[5], tx2, ty2); + break; + case 5: + tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1); + tessellator.addVertexWithUV(points[1], points[3], points[5], tx1, ty1); + tessellator.addVertexWithUV(points[1], points[2], points[5], tx1, ty2); + tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty2); + break; + } + } + + public static boolean shouldRenderLiquid(FluidStack stack) + { + return stack.amount > 0 && stack.getFluid() != null; + } + + /** + * @param stack The fluid stack to render + * @return The icon of the fluid + */ + public static Icon prepareFluidRender(FluidStack stack, int alpha) + { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + Fluid fluid = stack.getFluid(); + CCRenderState.setColour(fluid.getColor(stack)<<8|alpha); + TextureUtils.bindAtlas(fluid.getSpriteNumber()); + return fluid.getIcon(stack); + } + + /** + * Re-enables lighting and disables blending. + */ + public static void postFluidRender() + { + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_BLEND); + } + + /** + * Renders a fluid within a bounding box. + * If the fluid is a liquid it will render as a normal tank with height equal to density/bound.height. + * If the fluid is a gas, it will render the full box with an alpha equal to density. + * Warning, bound will be mutated if the fluid is a liquid + * @param stack The fluid to render. + * @param bound The box within which the fluid is contained. + * @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids this determines the height. + * @param res The resolution to render at. + */ + public static void renderLiquidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) + { + if(!shouldRenderLiquid(stack)) + return; + + int alpha = 255; + if(stack.getFluid().isGaseous()) + alpha = (int) (density*255); + else + bound.max.y = bound.min.y+(bound.max.y-bound.min.y)*density; + + Icon tex = prepareFluidRender(stack, alpha); + CCRenderState.startDrawing(7); + renderLiquidCuboid(bound, tex, res); + CCRenderState.draw(); + postFluidRender(); + } + + public static void renderItemUniform(ItemStack item) + { + IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, ENTITY); + boolean is3D = customRenderer != null && customRenderer.shouldUseRenderHelper(ENTITY, item, BLOCK_3D); + + boolean larger = false; + if (item.getItem() instanceof ItemBlock && RenderBlocks.renderItemIn3d(Block.blocksList[item.itemID].getRenderType())) + { + int renderType = Block.blocksList[item.itemID].getRenderType(); + larger = !(renderType == 1 || renderType == 19 || renderType == 12 || renderType == 2); + } + else if(is3D) + { + larger = true; + } + + double d = 2; + double d1 = 1/d; + if(larger) + GL11.glScaled(d, d, d); + + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + + entityItem.setEntityItemStack(item); + uniformRenderItem.doRenderItem(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, 0); + + if(larger) + GL11.glScaled(d1, d1, d1); + } + + private static Vertex5[] face = new Vertex5[]{new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; + public static void renderBlock(Cuboid6 c, int sideMask, IFaceRenderer r) + { + double x1 = c.min.x; + double x2 = c.max.x; + double y1 = c.min.y; + double y2 = c.max.y; + double z1 = c.min.z; + double z2 = c.max.z; + double u1 = 0; + double u2 = 0; + double v1 = 0; + double v2 = 0; + + if((sideMask&1) == 0) + { + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + face[0].set(x1, y1, z2, u1, v2); + face[1].set(x1, y1, z1, u1, v1); + face[2].set(x2, y1, z1, u2, v1); + face[3].set(x2, y1, z2, u2, v2); + r.renderFace(face, c.min.y > 0 ? 6 : 0); + } + + if((sideMask&2) == 0) + { + u1 = x1+2; v1 = z1; + u2 = x2+2; v2 = z2; + face[0].set(x2, y2, z2, u2, v2); + face[1].set(x2, y2, z1, u2, v1); + face[2].set(x1, y2, z1, u1, v1); + face[3].set(x1, y2, z2, u1, v2); + r.renderFace(face, c.max.y < 1 ? 7 : 1); + } + + if((sideMask&4) == 0) + { + u1 = 1-x1+4; v1 = 1-y2; + u2 = 1-x2+4; v2 = 1-y1; + face[0].set(x1, y1, z1, u1, v2); + face[1].set(x1, y2, z1, u1, v1); + face[2].set(x2, y2, z1, u2, v1); + face[3].set(x2, y1, z1, u2, v2); + r.renderFace(face, c.min.z > 0 ? 8 : 2); + } + + if((sideMask&8) == 0) + { + u1 = x1+6; v1 = 1-y2; + u2 = x2+6; v2 = 1-y1; + face[0].set(x2, y1, z2, u2, v2); + face[1].set(x2, y2, z2, u2, v1); + face[2].set(x1, y2, z2, u1, v1); + face[3].set(x1, y1, z2, u1, v2); + r.renderFace(face, c.max.z < 1 ? 9 : 3); + } + + if((sideMask&0x10) == 0) + { + u1 = z1+8; v1 = 1-y2; + u2 = z2+8; v2 = 1-y1; + face[0].set(x1, y1, z2, u2, v2); + face[1].set(x1, y2, z2, u2, v1); + face[2].set(x1, y2, z1, u1, v1); + face[3].set(x1, y1, z1, u1, v2); + r.renderFace(face, c.min.x > 0 ? 10 : 4); + } + + if((sideMask&0x20) == 0) + { + u1 = 1-z1+10; v1 = 1-y2; + u2 = 1-z2+10; v2 = 1-y1; + face[0].set(x2, y1, z1, u1, v2); + face[1].set(x2, y2, z1, u1, v1); + face[2].set(x2, y2, z2, u2, v1); + face[3].set(x2, y1, z2, u2, v2); + r.renderFace(face, c.max.x < 1 ? 11 : 5); + } + } + + public static void renderBlock(Cuboid6 bounds, int sideMask, final Transformation t, final IUVTransformation u, final IVertexModifier m) + { + renderBlock(bounds, sideMask, new IFaceRenderer(){ + boolean drawNormal = CCRenderState.useNormals(); + boolean computeNormal = drawNormal || m != null && m.needsNormals(); + Vector3 normal = new Vector3(); + Vertex5 vert; + Vector3 vec = new Vector3(); + UV uv = new UV(); + + @Override + public void renderFace(Vertex5[] face, int side) + { + Tessellator tess = Tessellator.instance; + for(int i = 0; i < face.length; i++) + { + if(computeNormal) + { + if(t != null) + t.applyN(normal.set(Rotation.axes[side%6])); + else + normal = Rotation.axes[side%6]; + + if(drawNormal) + tess.setNormal((float)normal.x, (float)normal.y, (float)normal.z); + } + + vert = face[i]; + if(t != null) + t.apply(vec.set(vert.vec)); + else + vec = vert.vec; + + if(u != null) + u.transform(uv.set(vert.uv)); + else + uv = vert.uv; + + if(m != null) + m.applyModifiers(null, tess, vec, uv, normal, i); + + tess.addVertexWithUV(vec.x, vec.y, vec.z, uv.u, uv.v); + } + } + }); + } +} diff --git a/codechicken/lib/render/ShaderProgram.java b/codechicken/lib/render/ShaderProgram.java new file mode 100644 index 0000000..df8dd16 --- /dev/null +++ b/codechicken/lib/render/ShaderProgram.java @@ -0,0 +1,137 @@ +package codechicken.lib.render; + +import static org.lwjgl.opengl.ARBShaderObjects.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.lwjgl.opengl.ARBShaderObjects; +import org.lwjgl.opengl.ARBVertexShader; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Matrix4f; + +public class ShaderProgram +{ + int programID; + + public ShaderProgram() + { + programID = glCreateProgramObjectARB(); + if(programID == 0) + throw new RuntimeException("Unable to allocate shader program object."); + } + + public void attach(int shaderType, String resource) + { + InputStream stream = ShaderProgram.class.getResourceAsStream(resource); + if(stream == null) + throw new RuntimeException("Unable to locate resource: "+resource); + + attach(shaderType, stream); + } + + public void use() + { + glUseProgramObjectARB(programID); + } + + public static void restore() + { + glUseProgramObjectARB(0); + } + + public void link() + { + glLinkProgramARB(programID); + if(glGetObjectParameteriARB(programID, GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) + throw new RuntimeException("Error linking program: "+getInfoLog(programID)); + + glValidateProgramARB(programID); + if(glGetObjectParameteriARB(programID, GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) + throw new RuntimeException("Error validating program: "+getInfoLog(programID)); + + use(); + onLink(); + restore(); + } + + public void attach(int shaderType, InputStream stream) + { + if(stream == null) + throw new RuntimeException("Invalid shader inputstream"); + + int shaderID = 0; + try + { + shaderID = glCreateShaderObjectARB(shaderType); + if(shaderID == 0) + throw new RuntimeException("Unable to allocate shader object."); + + try + { + glShaderSourceARB(shaderID, asString(stream)); + } + catch(IOException e) + { + throw new RuntimeException("Error reading inputstream.", e); + } + + glCompileShaderARB(shaderID); + if(glGetObjectParameteriARB(shaderID, GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) + throw new RuntimeException("Error compiling shader: "+getInfoLog(shaderID)); + + glAttachObjectARB(programID, shaderID); + } + catch(RuntimeException e) + { + glDeleteObjectARB(shaderID); + throw e; + } + } + + public static String asString(InputStream stream) throws IOException + { + StringBuilder sb = new StringBuilder(); + BufferedReader bin = new BufferedReader(new InputStreamReader(stream)); + String line; + while((line = bin.readLine()) != null) + sb.append(line).append('\n'); + stream.close(); + return sb.toString(); + } + + private static String getInfoLog(int shaderID) + { + return glGetInfoLogARB(shaderID, glGetObjectParameteriARB(shaderID, GL_OBJECT_INFO_LOG_LENGTH_ARB)); + } + + public int getUniformLoc(String name) + { + return ARBShaderObjects.glGetUniformLocationARB(programID, name); + } + + public int getAttribLoc(String name) + { + return ARBVertexShader.glGetAttribLocationARB(programID, name); + } + + public void uniformTexture(String name, int textureIndex) + { + ARBShaderObjects.glUniform1iARB(getUniformLoc(name), textureIndex); + } + + public void onLink() + { + + } + + public void glVertexAttributeMat4(int loc, Matrix4f matrix) + { + ARBVertexShader.glVertexAttrib4fARB(loc , matrix.m00, matrix.m01, matrix.m02, matrix.m03); + ARBVertexShader.glVertexAttrib4fARB(loc+1, matrix.m10, matrix.m11, matrix.m12, matrix.m13); + ARBVertexShader.glVertexAttrib4fARB(loc+2, matrix.m20, matrix.m21, matrix.m22, matrix.m23); + ARBVertexShader.glVertexAttrib4fARB(loc+3, matrix.m30, matrix.m31, matrix.m32, matrix.m33); + } +} diff --git a/codechicken/lib/render/SpriteSheetManager.java b/codechicken/lib/render/SpriteSheetManager.java new file mode 100644 index 0000000..be8d327 --- /dev/null +++ b/codechicken/lib/render/SpriteSheetManager.java @@ -0,0 +1,143 @@ +package codechicken.lib.render; + +import java.util.ArrayList; +import java.util.HashMap; + +import codechicken.lib.render.TextureUtils.IIconRegister; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.Icon; +import net.minecraft.util.ResourceLocation; + +public class SpriteSheetManager +{ + @SideOnly(Side.CLIENT) + public static class SpriteSheet implements IIconRegister + { + private int tilesX; + private int tilesY; + private ArrayList newSprites = new ArrayList(); + private TextureSpecial[] sprites; + private ResourceLocation resource; + private TextureDataHolder texture; + private int spriteWidth; + private int spriteHeight; + + public int atlasIndex; + + private SpriteSheet(int tilesX, int tilesY, ResourceLocation textureFile) + { + this.tilesX = tilesX; + this.tilesY = tilesY; + this.resource = textureFile; + sprites = new TextureSpecial[tilesX*tilesY]; + } + + public void requestIndicies(int... indicies) + { + for(int i : indicies) + setupSprite(i); + } + + public void registerIcons(IconRegister register) + { + TextureMap textureMap = (TextureMap)register; + + if(TextureUtils.refreshTexture(textureMap, resource.func_110623_a())) + { + reloadTexture(); + for(int i = 0; i < sprites.length; i++) + if(sprites[i] != null) + textureMap.setTextureEntry(sprites[i].getIconName(), sprites[i]); + } + else + { + for(int i : newSprites) + textureMap.setTextureEntry(sprites[i].getIconName(), sprites[i]); + } + newSprites.clear(); + } + + public TextureSpecial setupSprite(int i) + { + if(sprites[i] == null) + { + String name = resource+"_"+i; + sprites[i] = new TextureSpecial(name).baseFromSheet(this, i); + newSprites.add(i); + } + return sprites[i]; + } + + private void reloadTexture() + { + texture = TextureUtils.loadTexture(resource); + spriteWidth = texture.width/tilesX; + spriteHeight = texture.height/tilesY; + } + + public Icon getSprite(int index) + { + Icon i = sprites[index]; + if(i == null) + throw new IllegalArgumentException("Sprite at index: "+index+" from texture file "+resource+" was not preloaded."); + return i; + } + + public TextureDataHolder createSprite(int spriteIndex) + { + int sx = spriteIndex%tilesX; + int sy = spriteIndex/tilesX; + TextureDataHolder sprite = new TextureDataHolder(spriteWidth, spriteHeight); + TextureUtils.copySubImg(texture.data, texture.width, sx*spriteWidth, sy*spriteHeight, + spriteWidth, spriteHeight, + sprite.data, spriteWidth, 0, 0); + return sprite; + } + + public int spriteWidth() + { + return spriteWidth; + } + + public int spriteHeight() + { + return spriteHeight; + } + + public TextureSpecial func_110577_aFX(int i, TextureFX textureFX) + { + return setupSprite(i).addTextureFX(textureFX); + } + + public SpriteSheet selfRegister(int atlas) + { + TextureUtils.addIconRegistrar(this); + return this; + } + + @Override + public int atlasIndex() + { + return atlasIndex; + } + } + + private static HashMap spriteSheets = new HashMap(); + + public static SpriteSheet getSheet(ResourceLocation resource) + { + return getSheet(16, 16, resource); + } + + public static SpriteSheet getSheet(int tilesX, int tilesY, ResourceLocation resource) + { + SpriteSheet sheet = spriteSheets.get(resource.toString()); + if(sheet == null) + spriteSheets.put(resource.toString(), sheet = new SpriteSheet(tilesX, tilesY, resource)); + return sheet; + } +} diff --git a/codechicken/lib/render/TextureDataHolder.java b/codechicken/lib/render/TextureDataHolder.java new file mode 100644 index 0000000..e945c08 --- /dev/null +++ b/codechicken/lib/render/TextureDataHolder.java @@ -0,0 +1,38 @@ +package codechicken.lib.render; + +import java.awt.image.BufferedImage; + +public class TextureDataHolder +{ + public int width; + public int height; + public int[] data; + + public TextureDataHolder(int width, int height) + { + this.width = width; + this.height = height; + data = new int[width*height]; + } + + public TextureDataHolder(int[] data, int width) + { + this.data = data; + this.width = width; + height = data.length/width; + } + + public TextureDataHolder(BufferedImage img) + { + this(img.getWidth(), img.getHeight()); + img.getRGB(0, 0, width, height, data, 0, width); + } + + public TextureDataHolder copyData() + { + int[] copy = new int[data.length]; + System.arraycopy(data, 0, copy, 0, data.length); + data = copy; + return this; + } +} diff --git a/codechicken/lib/render/TextureFX.java b/codechicken/lib/render/TextureFX.java new file mode 100644 index 0000000..b79bfe1 --- /dev/null +++ b/codechicken/lib/render/TextureFX.java @@ -0,0 +1,67 @@ +package codechicken.lib.render; + +import codechicken.lib.render.SpriteSheetManager.SpriteSheet; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; + +@SideOnly(Side.CLIENT) +public class TextureFX +{ + public int[] imageData; + public int tileSizeBase = 16; + public int tileSizeSquare = 256; + public int tileSizeMask = 15; + public int tileSizeSquareMask = 255; + + public boolean anaglyphEnabled; + public TextureSpecial texture; + + public TextureFX(int spriteIndex, SpriteSheet sheet) + { + texture = sheet.func_110577_aFX(spriteIndex, this); + } + + public TextureFX(int size, String name) + { + texture = new TextureSpecial(name).blank(size).selfRegister().addTextureFX(this); + } + + public TextureFX setAtlas(int index) + { + texture.atlasIndex = index; + return this; + } + + public void setup() + { + imageData = new int[tileSizeSquare]; + } + + public void onTextureDimensionsUpdate(int width, int height) + { + if(width != height) + throw new IllegalArgumentException("Non-Square textureFX not supported ("+width+":"+height+")"); + + tileSizeBase = width; + tileSizeSquare = tileSizeBase * tileSizeBase; + tileSizeMask = tileSizeBase - 1; + tileSizeSquareMask = tileSizeSquare - 1; + setup(); + } + + public void update() + { + anaglyphEnabled = Minecraft.getMinecraft().gameSettings.anaglyph; + onTick(); + } + + public void onTick() + { + } + + public boolean changed() + { + return true; + } +} diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java new file mode 100644 index 0000000..a1ae887 --- /dev/null +++ b/codechicken/lib/render/TextureSpecial.java @@ -0,0 +1,150 @@ +package codechicken.lib.render; + +import java.util.ArrayList; +import codechicken.lib.render.SpriteSheetManager.SpriteSheet; +import codechicken.lib.render.TextureUtils.IIconRegister; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.texture.TextureUtil; +import net.minecraft.client.resources.ResourceManager; +import net.minecraft.util.ResourceLocation; + +@SideOnly(Side.CLIENT) +public class TextureSpecial extends TextureAtlasSprite implements IIconRegister +{ + //sprite sheet fields + private int spriteIndex; + private SpriteSheet spriteSheet; + + //textureFX fields + private TextureFX textureFX; + + private int blankSize = -1; + + private ArrayList baseTextures; + + private boolean selfRegister; + public int atlasIndex; + + protected TextureSpecial(String par1) + { + super(par1); + } + + public TextureSpecial addTexture(TextureDataHolder t) + { + if(baseTextures == null) + baseTextures = new ArrayList(); + baseTextures.add(t); + return this; + } + + public TextureSpecial baseFromSheet(SpriteSheet spriteSheet, int spriteIndex) + { + this.spriteSheet = spriteSheet; + this.spriteIndex = spriteIndex; + return this; + } + + public TextureSpecial addTextureFX(TextureFX fx) + { + textureFX = fx; + return this; + } + + @Override + public void func_110971_a(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) + { + super.func_110971_a(sheetWidth, sheetHeight, originX, originY, rotated); + if(textureFX != null) + textureFX.onTextureDimensionsUpdate(field_130223_c, field_130224_d); + } + + @Override + public void updateAnimation() + { + if(textureFX != null) + { + textureFX.update(); + if(textureFX.changed()) + TextureUtil.func_110998_a(textureFX.imageData, field_130223_c, field_130224_d, field_110975_c, field_110974_d, false, false); + } + } + + @Override + public boolean load(ResourceManager manager, ResourceLocation location) + { + if(baseTextures != null) + { + for(TextureDataHolder tex : baseTextures) + { + field_110976_a.add(tex.data); + field_130223_c = tex.width; + field_130224_d = tex.height; + } + } + + if(spriteSheet != null) + { + TextureDataHolder tex = spriteSheet.createSprite(spriteIndex); + field_130223_c = tex.width; + field_130224_d = tex.height; + field_110976_a.add(tex.data); + } + + if(blankSize > 0) + { + field_130223_c = field_130224_d = blankSize; + field_110976_a.add(new int[blankSize*blankSize]); + } + + if(field_110976_a.isEmpty()) + throw new RuntimeException("No base frame for texture: "+getIconName()); + + return true; + } + + @Override + public boolean func_130098_m() + { + return textureFX != null || super.func_130098_m(); + } + + @Override + public int func_110970_k() + { + if(textureFX != null) + return 1; + + return super.func_110970_k(); + } + + public TextureSpecial blank(int size) + { + blankSize = size; + return this; + } + + public TextureSpecial selfRegister() + { + selfRegister = true; + TextureUtils.addIconRegistrar(this); + return this; + } + + @Override + public void registerIcons(IconRegister register) + { + if(selfRegister) + ((TextureMap)register).setTextureEntry(getIconName(), this); + } + + @Override + public int atlasIndex() + { + return atlasIndex; + } +} diff --git a/codechicken/lib/render/TextureUtils.java b/codechicken/lib/render/TextureUtils.java new file mode 100644 index 0000000..1cbf069 --- /dev/null +++ b/codechicken/lib/render/TextureUtils.java @@ -0,0 +1,179 @@ +package codechicken.lib.render; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +import javax.imageio.ImageIO; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import codechicken.lib.colour.Colour; +import codechicken.lib.colour.ColourARGB; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.Icon; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; + +public class TextureUtils +{ + public static interface IIconRegister + { + public void registerIcons(IconRegister register); + public int atlasIndex(); + } + + static + { + MinecraftForge.EVENT_BUS.register(new TextureUtils()); + } + + private static ArrayList iconRegistrars = new ArrayList(); + + public static void addIconRegistrar(IIconRegister registrar) + { + iconRegistrars.add(registrar); + } + + @ForgeSubscribe + public void textureLoad(TextureStitchEvent.Pre event) + { + for(IIconRegister reg : iconRegistrars) + if(reg.atlasIndex() == event.map.textureType) + reg.registerIcons(event.map); + } + + /** + * @return an array of ARGB pixel data + */ + public static int[] loadTextureData(ResourceLocation resource) + { + return loadTexture(resource).data; + } + + public static Colour[] loadTextureColours(ResourceLocation resource) + { + int[] idata = loadTextureData(resource); + Colour[] data = new Colour[idata.length]; + for(int i = 0; i < data.length; i++) + data[i] = new ColourARGB(idata[i]); + return data; + } + + public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException + { + return Minecraft.getMinecraft().func_110442_L().func_110536_a(textureFile).func_110527_b(); + } + + public static BufferedImage loadBufferedImage(ResourceLocation textureFile) + { + try + { + return loadBufferedImage(getTextureResource(textureFile)); + } + catch(Exception e) + { + System.err.println("Failed to load texture file: "+textureFile); + e.printStackTrace(); + } + return null; + } + + public static BufferedImage loadBufferedImage(InputStream in) throws IOException + { + BufferedImage img = ImageIO.read(in); + in.close(); + return img; + } + + public static TextureManager engine() + { + return Minecraft.getMinecraft().renderEngine; + } + + public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) + { + for(int y = 0; y < height; y++) + for(int x = 0; x < width; x++) + { + int fp = (y+fromY)*fromWidth+x+fromX; + int tp = (y+toX)*toWidth+x+toX; + + toTex[tp] = fromTex[fp]; + } + } + + public static void bindAtlas(int atlasIndex) + { + engine().func_110577_a(atlasIndex == 0 ? TextureMap.field_110575_b : TextureMap.field_110576_c); + } + + public static Icon getBlankIcon(int size, IconRegister iconRegister) + { + TextureMap textureMap = (TextureMap)iconRegister; + String s = "blank_"+size; + if(textureMap.getTextureExtry(s) == null) + { + TextureSpecial icon = new TextureSpecial(s).blank(size); + textureMap.setTextureEntry(s, icon); + } + return iconRegister.registerIcon(s); + } + + public static TextureSpecial getTextureSpecial(IconRegister iconRegister, String name) + { + TextureMap textureMap = (TextureMap) iconRegister; + Icon entry = textureMap.getTextureExtry(name); + if(entry != null) + throw new IllegalStateException("Texture: "+name+" is already registered"); + + TextureSpecial icon = new TextureSpecial(name); + textureMap.setTextureEntry(name, icon); + return icon; + } + + public static void prepareTexture(int target, int texture, int min_mag_filter, int wrap) + { + GL11.glBindTexture(target, texture); + GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, min_mag_filter); + GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, min_mag_filter); + switch(target) + { + case GL12.GL_TEXTURE_3D: + GL11.glTexParameteri(target, GL12.GL_TEXTURE_WRAP_R, wrap); + case GL11.GL_TEXTURE_2D: + GL11.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_T, wrap); + case GL11.GL_TEXTURE_1D: + GL11.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_S, wrap); + } + } + + public static TextureDataHolder loadTexture(ResourceLocation resource) + { + BufferedImage img = loadBufferedImage(resource); + if(img == null) + throw new RuntimeException("Texture not found: "+resource); + return new TextureDataHolder(img); + } + + /** + * Uses an empty placeholder texture to tell if the map has been reloaded since the last call to refresh texture and the texture with name needs to be reacquired to be valid + */ + public static boolean refreshTexture(TextureMap map, String name) + { + if(map.getTextureExtry(name) == null) + { + map.setTextureEntry(name, new PlaceholderTexture(name)); + return true; + } + return false; + } +} diff --git a/codechicken/lib/render/UV.java b/codechicken/lib/render/UV.java new file mode 100644 index 0000000..6233302 --- /dev/null +++ b/codechicken/lib/render/UV.java @@ -0,0 +1,71 @@ +package codechicken.lib.render; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UV +{ + public double u; + public double v; + + public UV() + { + } + + public UV(double u, double v) + { + this.u = u; + this.v = v; + } + + public UV(UV uv) + { + this(uv.u, uv.v); + } + + public UV set(double u, double v) + { + this.u = u; + this.v = v; + return this; + } + + public UV set(UV uv) + { + u = uv.u; + v = uv.v; + return this; + } + + public UV copy() + { + return new UV(this); + } + + public UV add(UV uv) + { + u+=uv.u; + v+=uv.v; + return this; + } + + public UV mul(double d) + { + u*=d; + v*=d; + return this; + } + + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UV("+new BigDecimal(u, cont)+", "+new BigDecimal(v, cont)+")"; + } + + public UV apply(IUVTransformation transform) + { + transform.transform(this); + return this; + } +} \ No newline at end of file diff --git a/codechicken/lib/render/UVScale.java b/codechicken/lib/render/UVScale.java new file mode 100644 index 0000000..4c948c4 --- /dev/null +++ b/codechicken/lib/render/UVScale.java @@ -0,0 +1,20 @@ +package codechicken.lib.render; + +public class UVScale implements IUVTransformation +{ + double su; + double sv; + + public UVScale(double scaleu, double scalev) + { + su = scaleu; + sv = scalev; + } + + @Override + public void transform(UV uv) + { + uv.u*=su; + uv.v*=sv; + } +} diff --git a/codechicken/lib/render/UVTranslation.java b/codechicken/lib/render/UVTranslation.java new file mode 100644 index 0000000..ffd2565 --- /dev/null +++ b/codechicken/lib/render/UVTranslation.java @@ -0,0 +1,20 @@ +package codechicken.lib.render; + +public class UVTranslation implements IUVTransformation +{ + public double du; + public double dv; + + public UVTranslation(double u, double v) + { + du = u; + dv = v; + } + + @Override + public void transform(UV texcoord) + { + texcoord.u+=du; + texcoord.v+=dv; + } +} diff --git a/codechicken/lib/render/Vertex5.java b/codechicken/lib/render/Vertex5.java new file mode 100644 index 0000000..1edfe5b --- /dev/null +++ b/codechicken/lib/render/Vertex5.java @@ -0,0 +1,57 @@ +package codechicken.lib.render; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import codechicken.lib.vec.Vector3; + +public class Vertex5 +{ + public Vector3 vec; + public UV uv; + + public Vertex5() + { + this(new Vector3(), new UV()); + } + + public Vertex5(Vector3 vert, UV uv) + { + this.vec = vert; + this.uv = uv; + } + + public Vertex5(Vector3 vert, double u, double v) + { + this(vert, new UV(u, v)); + } + + public Vertex5(double x, double y, double z, double u, double v) + { + this(new Vector3(x, y, z), new UV(u, v)); + } + + public Vertex5 set(double x, double y, double z, double u, double v) + { + vec.set(x, y, z); + uv.set(u, v); + return this; + } + + public Vertex5(Vertex5 vertex5) + { + this(vertex5.vec.copy(), vertex5.uv.copy()); + } + + public Vertex5 copy() + { + return new Vertex5(this); + } + + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Vertex: ("+new BigDecimal(vec.x, cont)+", "+new BigDecimal(vec.y, cont)+", "+new BigDecimal(vec.z, cont)+") ("+new BigDecimal(uv.u, cont)+", "+new BigDecimal(uv.v, cont)+")"; + } +} diff --git a/codechicken/lib/vec/AxisCycle.java b/codechicken/lib/vec/AxisCycle.java new file mode 100644 index 0000000..5a0a526 --- /dev/null +++ b/codechicken/lib/vec/AxisCycle.java @@ -0,0 +1,21 @@ +package codechicken.lib.vec; + +public class AxisCycle +{ + public static Transformation[] cycles = new Transformation[]{ + new RedundantTransformation(), + new VariableTransformation(new Matrix4(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d0 = vec.x; double d1 = vec.y; double d2 = vec.z; + vec.x = d2; vec.y = d0; vec.z = d1; + } @Override public Transformation inverse(){ + return cycles[2]; + }}, + new VariableTransformation(new Matrix4(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d0 = vec.x; double d1 = vec.y; double d2 = vec.z; + vec.x = d1; vec.y = d2; vec.z = d0; + } @Override public Transformation inverse(){ + return cycles[1]; + }}}; +} diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java new file mode 100644 index 0000000..7c713d2 --- /dev/null +++ b/codechicken/lib/vec/BlockCoord.java @@ -0,0 +1,180 @@ +package codechicken.lib.vec; + +import net.minecraft.tileentity.TileEntity; +import codechicken.lib.math.MathHelper; + +public class BlockCoord implements Comparable +{ + public int x; + public int y; + public int z; + + public BlockCoord(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public BlockCoord(Vector3 v) + { + this(MathHelper.floor_double(v.x), MathHelper.floor_double(v.y), MathHelper.floor_double(v.z)); + } + + public BlockCoord(TileEntity tile) + { + this(tile.xCoord, tile.yCoord, tile.zCoord); + } + + public BlockCoord(int[] ia) + { + this(ia[0], ia[1], ia[2]); + } + + public BlockCoord() + { + } + + @Override + public boolean equals(Object obj) + { + if(!(obj instanceof BlockCoord)) + return false; + BlockCoord o2 = (BlockCoord)obj; + return x == o2.x && y == o2.y && z == o2.z; + } + + @Override + public int hashCode() + { + return (x^z)*31 + y; + } + + public int compareTo(BlockCoord o) + { + if(x != o.x)return x < o.x ? 1 : -1; + if(y != o.y)return y < o.y ? 1 : -1; + if(z != o.z)return z < o.z ? 1 : -1; + return 0; + } + + public Vector3 toVector3Centered() + { + return new Vector3(x+0.5, y+0.5, z+0.5); + } + + public BlockCoord multiply(int i) + { + x*=i; + y*=i; + z*=i; + return this; + } + + public double mag_() + { + return Math.sqrt(x*x+y*y+z*z); + } + + public int mag2() + { + return x*x+y*y+z*z; + } + + public boolean isZero() + { + return x == 0 && y == 0 && z == 0; + } + + public boolean isAxial() + { + return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); + } + + public BlockCoord add(BlockCoord coord2) + { + x+=coord2.x; + y+=coord2.y; + z+=coord2.z; + return this; + } + + public BlockCoord add(int i, int j, int k) + { + x+=i; + y+=j; + z+=k; + return this; + } + + public BlockCoord sub(BlockCoord coord2) + { + x-=coord2.x; + y-=coord2.y; + z-=coord2.z; + return this; + } + + public BlockCoord sub(int i, int j, int k) + { + x-=i; + y-=j; + z-=k; + return this; + } + + public BlockCoord offset(int side) + { + return offset(side, 1); + } + + public BlockCoord offset(int side, int amount) + { + BlockCoord offset = sideOffsets[side]; + x+=offset.x*amount; + y+=offset.y*amount; + z+=offset.z*amount; + return this; + } + + public BlockCoord inset(int side) + { + return inset(side, 1); + } + + public BlockCoord inset(int side, int amount) + { + return offset(side, -amount); + } + + public static final BlockCoord[] sideOffsets = new BlockCoord[]{ + new BlockCoord( 0,-1, 0), + new BlockCoord( 0, 1, 0), + new BlockCoord( 0, 0,-1), + new BlockCoord( 0, 0, 1), + new BlockCoord(-1, 0, 0), + new BlockCoord( 1, 0, 0)}; + + public int[] intArray() + { + return new int[]{x, y, z}; + } + + public BlockCoord copy() + { + return new BlockCoord(x, y, z); + } + + public BlockCoord set(int i, int j, int k) + { + x = i; + y = j; + z = k; + return this; + } + + public BlockCoord set(BlockCoord coord) + { + return set(coord.x, coord.y, coord.z); + } +} diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java new file mode 100644 index 0000000..c31d83e --- /dev/null +++ b/codechicken/lib/vec/Cuboid6.java @@ -0,0 +1,136 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import net.minecraft.block.Block; +import net.minecraft.util.AxisAlignedBB; + +public class Cuboid6 +{ + public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); + + public Vector3 min; + public Vector3 max; + + public Cuboid6(Vector3 min, Vector3 max) + { + this.min = min; + this.max = max; + } + + public Cuboid6(AxisAlignedBB aabb) + { + min = new Vector3(aabb.minX, aabb.minY, aabb.minZ); + max = new Vector3(aabb.maxX, aabb.maxY, aabb.maxZ); + } + + public Cuboid6(Cuboid6 cuboid) + { + min = cuboid.min.copy(); + max = cuboid.max.copy(); + } + + public Cuboid6(double minx, double miny, double minz, double maxx, double maxy, double maxz) + { + min = new Vector3(minx, miny, minz); + max = new Vector3(maxx, maxy, maxz); + } + + public AxisAlignedBB toAABB() + { + return AxisAlignedBB.getBoundingBox(min.x, min.y, min.z, max.x, max.y, max.z); + } + + public Cuboid6 copy() + { + return new Cuboid6(this); + } + + public Cuboid6 add(Vector3 vec) + { + min.add(vec); + max.add(vec); + return this; + } + + public Cuboid6 sub(Vector3 vec) + { + min.subtract(vec); + max.subtract(vec); + return this; + } + + public void setBlockBounds(Block block) + { + block.setBlockBounds((float)min.x, (float)min.y, (float)min.z, (float)max.x, (float)max.y, (float)max.z); + } + + public boolean intersects(Cuboid6 b) + { + return max.x-1E-5 > b.min.x && + b.max.x-1E-5 > min.x && + max.y-1E-5 > b.min.y && + b.max.y-1E-5 > min.y && + max.z-1E-5 > b.min.z && + b.max.z-1E-5 > min.z; + } + + public Cuboid6 offset(Cuboid6 o) + { + min.add(o.min); + max.add(o.max); + return this; + } + + public Vector3 center() + { + return min.copy().add(max).multiply(0.5); + } + + public static boolean intersects(Cuboid6 a, Cuboid6 b) + { + return a != null && b != null && a.intersects(b); + } + + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Cuboid: ("+new BigDecimal(min.x, cont)+", "+new BigDecimal(min.y, cont)+", "+new BigDecimal(min.z, cont)+") -> ("+ + new BigDecimal(max.x, cont)+", "+new BigDecimal(max.y, cont)+", "+new BigDecimal(max.z, cont)+")"; + } + + public Cuboid6 enclose(Vector3 vec) + { + if(min.x > vec.x) min.x = vec.x; + if(min.y > vec.y) min.y = vec.y; + if(min.z > vec.z) min.z = vec.z; + if(max.x < vec.x) max.x = vec.x; + if(max.y < vec.y) max.y = vec.y; + if(max.z < vec.z) max.z = vec.z; + return this; + } + + public Cuboid6 enclose(Cuboid6 c) + { + if(min.x > c.min.x) min.x = c.min.x; + if(min.y > c.min.y) min.y = c.min.y; + if(min.z > c.min.z) min.z = c.min.z; + if(max.x < c.max.x) max.x = c.max.x; + if(max.y < c.max.y) max.y = c.max.y; + if(max.z < c.max.z) max.z = c.max.z; + return this; + } + + public Cuboid6 transform(Transformation t) + { + t.apply(min); + t.apply(max); + double temp; + if(min.x > max.x) {temp = min.x; min.x = max.x; max.x = temp;} + if(min.y > max.y) {temp = min.y; min.y = max.y; max.y = temp;} + if(min.z > max.z) {temp = min.z; min.z = max.z; max.z = temp;} + return this; + } +} diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java new file mode 100644 index 0000000..dbe21c7 --- /dev/null +++ b/codechicken/lib/vec/CuboidCoord.java @@ -0,0 +1,113 @@ +package codechicken.lib.vec; + +import net.minecraft.util.AxisAlignedBB; + +public class CuboidCoord +{ + public BlockCoord min; + public BlockCoord max; + + public CuboidCoord(BlockCoord min, BlockCoord max) + { + this.min = min; + this.max = max; + } + + public CuboidCoord(BlockCoord coord) + { + this(coord, coord.copy()); + } + + public CuboidCoord(int[] ia) + { + this(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); + } + + public CuboidCoord(int x1, int y1, int z1, int x2, int y2, int z2) + { + this(new BlockCoord(x1, y1, z1), new BlockCoord(x2, y2, z2)); + } + + public void expand(int side, int amount) + { + if(side%2 == 0)//negative side + min = min.offset(side, amount); + else + max = max.offset(side, amount); + } + + public void shrink(int side, int amount) + { + if(side%2 == 0)//negative side + min = min.inset(side, amount); + else + max = max.inset(side, amount); + } + + public int size(int s) + { + switch(s) + { + case 0: + case 1: + return max.y - min.y+1; + case 2: + case 3: + return max.z - min.z+1; + case 4: + case 5: + return max.x - min.x+1; + default: + return 0; + } + } + + public int getVolume() + { + return (max.x-min.x+1)*(max.y-min.y+1)*(max.z-min.z+1); + } + + public Vector3 getCenterVec() + { + return new Vector3(min.x+(max.x-min.x+1)/2D, min.y+(max.y-min.y+1)/2D, min.z+(max.z-min.z+1)/2D); + } + + public BlockCoord getCenter(BlockCoord store) + { + store.set(min.x+(max.x-min.x)/2, min.y+(max.y-min.y)/2, min.z+(max.z-min.z)/2); + return store; + } + + public boolean contains(BlockCoord coord) + { + return contains(coord.x, coord.y, coord.z); + } + + public boolean contains(int x, int y, int z) + { + return x >= min.x && x <= max.x + && y >= min.y && y <= max.y + && z >= min.z && z <= max.z; + } + + public int[] intArray() + { + return new int[]{min.x, min.y, min.z, max.x, max.y, max.z}; + } + + public CuboidCoord copy() + { + return new CuboidCoord(min.copy(), max.copy()); + } + + public AxisAlignedBB toAABB() + { + return AxisAlignedBB.getBoundingBox(min.x, min.y, min.z, max.x+1, max.y+1, max.z+1); + } + + public void set(BlockCoord min, BlockCoord max) + { + this.min = min; + this.max = max; + } +} diff --git a/codechicken/lib/vec/IrreversibleTransformationException.java b/codechicken/lib/vec/IrreversibleTransformationException.java new file mode 100644 index 0000000..c7d5c4d --- /dev/null +++ b/codechicken/lib/vec/IrreversibleTransformationException.java @@ -0,0 +1,18 @@ +package codechicken.lib.vec; + +@SuppressWarnings("serial") +public class IrreversibleTransformationException extends RuntimeException +{ + public Transformation t; + + public IrreversibleTransformationException(Transformation t) + { + this.t = t; + } + + @Override + public String getMessage() + { + return "The following transformation is irreversible:\n"+t; + } +} diff --git a/codechicken/lib/vec/Line3.java b/codechicken/lib/vec/Line3.java new file mode 100644 index 0000000..90b428c --- /dev/null +++ b/codechicken/lib/vec/Line3.java @@ -0,0 +1,47 @@ +package codechicken.lib.vec; + + +public class Line3 +{ + public static final double tol = 0.0001D; + + public Vector3 pt1; + public Vector3 pt2; + + public Line3(Vector3 pt1, Vector3 pt2) + { + this.pt1 = pt1; + this.pt2 = pt2; + } + + public Line3() + { + this(new Vector3(), new Vector3()); + } + + public static boolean intersection2D(Line3 line1, Line3 line2, Vector3 store) + { + // calculate differences + double xD1 = line1.pt2.x - line1.pt1.x; + double zD1 = line1.pt2.z - line1.pt1.z; + double xD2 = line2.pt2.x - line2.pt1.x; + double zD2 = line2.pt2.z - line2.pt1.z; + + double xD3 = line1.pt1.x - line2.pt1.x; + double zD3 = line1.pt1.z - line2.pt1.z; + + double div = zD2 * xD1 - xD2 * zD1; + if(div == 0)//lines are parallel + return false; + double ua = (xD2 * zD3 - zD2 * xD3) / div; + store.set(line1.pt1.x + ua * xD1, 0, line1.pt1.z + ua * zD1); + + if(store.x >= Math.min(line1.pt1.x, line1.pt2.x)-tol && store.x >= Math.min(line2.pt1.x, line2.pt2.x)-tol + && store.z >= Math.min(line1.pt1.z, line1.pt2.z)-tol && store.z >= Math.min(line2.pt1.z, line2.pt2.z)-tol + && store.x <= Math.max(line1.pt1.x, line1.pt2.x)+tol && store.x <= Math.max(line2.pt1.x, line2.pt2.x)+tol + && store.z <= Math.max(line1.pt1.z, line1.pt2.z)+tol && store.z <= Math.max(line2.pt1.z, line2.pt2.z)+tol) + return true; + + return false; + } +} diff --git a/codechicken/lib/vec/Matrix4.java b/codechicken/lib/vec/Matrix4.java new file mode 100644 index 0000000..10afb16 --- /dev/null +++ b/codechicken/lib/vec/Matrix4.java @@ -0,0 +1,353 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.DoubleBuffer; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class Matrix4 extends Transformation +{ + private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); + + //m + public double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; + + public Matrix4() + { + m00 = m11 = m22 = m33 = 1; + } + + public Matrix4(double d00, double d01, double d02, double d03, + double d10, double d11, double d12, double d13, + double d20, double d21, double d22, double d23, + double d30, double d31, double d32, double d33) + { + m00 = d00; + m01 = d01; + m02 = d02; + m03 = d03; + m10 = d10; + m11 = d11; + m12 = d12; + m13 = d13; + m20 = d20; + m21 = d21; + m22 = d22; + m23 = d23; + m30 = d30; + m31 = d31; + m32 = d32; + m33 = d33; + } + + public Matrix4(Matrix4 mat) + { + set(mat); + } + + public Matrix4 setIdentity() + { + m00 = m11 = m22 = m33 = 1; + m01 = m02 = m03 = m10 = m12 = m13 = m20 = m21 = m23 = m30 = m31 = m32 = 0; + + return this; + } + + public Matrix4 translate(Vector3 vec) + { + m03 += m00 * vec.x + m01 * vec.y + m02 * vec.z; + m13 += m10 * vec.x + m11 * vec.y + m12 * vec.z; + m23 += m20 * vec.x + m21 * vec.y + m22 * vec.z; + m33 += m30 * vec.x + m31 * vec.y + m32 * vec.z; + + return this; + } + + public Matrix4 scale(Vector3 vec) + { + m00 *= vec.x; + m10 *= vec.x; + m20 *= vec.x; + m30 *= vec.x; + m01 *= vec.y; + m11 *= vec.y; + m21 *= vec.y; + m31 *= vec.y; + m02 *= vec.z; + m12 *= vec.z; + m22 *= vec.z; + m32 *= vec.z; + + return this; + } + + public Matrix4 rotate(double angle, Vector3 axis) + { + double c = Math.cos(angle); + double s = Math.sin(angle); + double mc = 1.0f - c; + double xy = axis.x*axis.y; + double yz = axis.y*axis.z; + double xz = axis.x*axis.z; + double xs = axis.x*s; + double ys = axis.y*s; + double zs = axis.z*s; + + double f00 = axis.x*axis.x*mc+c; + double f10 = xy*mc+zs; + double f20 = xz*mc-ys; + + double f01 = xy*mc-zs; + double f11 = axis.y*axis.y*mc+c; + double f21 = yz*mc+xs; + + double f02 = xz*mc+ys; + double f12 = yz*mc-xs; + double f22 = axis.z*axis.z*mc+c; + + double t00 = m00 * f00 + m01 * f10 + m02 * f20; + double t10 = m10 * f00 + m11 * f10 + m12 * f20; + double t20 = m20 * f00 + m21 * f10 + m22 * f20; + double t30 = m30 * f00 + m31 * f10 + m32 * f20; + double t01 = m00 * f01 + m01 * f11 + m02 * f21; + double t11 = m10 * f01 + m11 * f11 + m12 * f21; + double t21 = m20 * f01 + m21 * f11 + m22 * f21; + double t31 = m30 * f01 + m31 * f11 + m32 * f21; + m02 = m00 * f02 + m01 * f12 + m02 * f22; + m12 = m10 * f02 + m11 * f12 + m12 * f22; + m22 = m20 * f02 + m21 * f12 + m22 * f22; + m32 = m30 * f02 + m31 * f12 + m32 * f22; + m00 = t00; + m10 = t10; + m20 = t20; + m30 = t30; + m01 = t01; + m11 = t11; + m21 = t21; + m31 = t31; + + return this; + } + + public Matrix4 rotate(Rotation rotation) + { + rotation.apply(this); + return this; + } + + public Matrix4 leftMultiply(Matrix4 mat) + { + double n00 = m00 * mat.m00 + m10 * mat.m01 + m20 * mat.m02 + m30 * mat.m03; + double n01 = m01 * mat.m00 + m11 * mat.m01 + m21 * mat.m02 + m31 * mat.m03; + double n02 = m02 * mat.m00 + m12 * mat.m01 + m22 * mat.m02 + m32 * mat.m03; + double n03 = m03 * mat.m00 + m13 * mat.m01 + m23 * mat.m02 + m33 * mat.m03; + double n10 = m00 * mat.m10 + m10 * mat.m11 + m20 * mat.m12 + m30 * mat.m13; + double n11 = m01 * mat.m10 + m11 * mat.m11 + m21 * mat.m12 + m31 * mat.m13; + double n12 = m02 * mat.m10 + m12 * mat.m11 + m22 * mat.m12 + m32 * mat.m13; + double n13 = m03 * mat.m10 + m13 * mat.m11 + m23 * mat.m12 + m33 * mat.m13; + double n20 = m00 * mat.m20 + m10 * mat.m21 + m20 * mat.m22 + m30 * mat.m23; + double n21 = m01 * mat.m20 + m11 * mat.m21 + m21 * mat.m22 + m31 * mat.m23; + double n22 = m02 * mat.m20 + m12 * mat.m21 + m22 * mat.m22 + m32 * mat.m23; + double n23 = m03 * mat.m20 + m13 * mat.m21 + m23 * mat.m22 + m33 * mat.m23; + double n30 = m00 * mat.m30 + m10 * mat.m31 + m20 * mat.m32 + m30 * mat.m33; + double n31 = m01 * mat.m30 + m11 * mat.m31 + m21 * mat.m32 + m31 * mat.m33; + double n32 = m02 * mat.m30 + m12 * mat.m31 + m22 * mat.m32 + m32 * mat.m33; + double n33 = m03 * mat.m30 + m13 * mat.m31 + m23 * mat.m32 + m33 * mat.m33; + + m00 = n00; + m01 = n01; + m02 = n02; + m03 = n03; + m10 = n10; + m11 = n11; + m12 = n12; + m13 = n13; + m20 = n20; + m21 = n21; + m22 = n22; + m23 = n23; + m30 = n30; + m31 = n31; + m32 = n32; + m33 = n33; + + return this; + } + + public Matrix4 multiply(Matrix4 mat) + { + double n00 = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20 + m03 * mat.m30; + double n01 = m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21 + m03 * mat.m31; + double n02 = m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22 + m03 * mat.m32; + double n03 = m00 * mat.m03 + m01 * mat.m13 + m02 * mat.m23 + m03 * mat.m33; + double n10 = m10 * mat.m00 + m11 * mat.m10 + m12 * mat.m20 + m13 * mat.m30; + double n11 = m10 * mat.m01 + m11 * mat.m11 + m12 * mat.m21 + m13 * mat.m31; + double n12 = m10 * mat.m02 + m11 * mat.m12 + m12 * mat.m22 + m13 * mat.m32; + double n13 = m10 * mat.m03 + m11 * mat.m13 + m12 * mat.m23 + m13 * mat.m33; + double n20 = m20 * mat.m00 + m21 * mat.m10 + m22 * mat.m20 + m23 * mat.m30; + double n21 = m20 * mat.m01 + m21 * mat.m11 + m22 * mat.m21 + m23 * mat.m31; + double n22 = m20 * mat.m02 + m21 * mat.m12 + m22 * mat.m22 + m23 * mat.m32; + double n23 = m20 * mat.m03 + m21 * mat.m13 + m22 * mat.m23 + m23 * mat.m33; + double n30 = m30 * mat.m00 + m31 * mat.m10 + m32 * mat.m20 + m33 * mat.m30; + double n31 = m30 * mat.m01 + m31 * mat.m11 + m32 * mat.m21 + m33 * mat.m31; + double n32 = m30 * mat.m02 + m31 * mat.m12 + m32 * mat.m22 + m33 * mat.m32; + double n33 = m30 * mat.m03 + m31 * mat.m13 + m32 * mat.m23 + m33 * mat.m33; + + m00 = n00; + m01 = n01; + m02 = n02; + m03 = n03; + m10 = n10; + m11 = n11; + m12 = n12; + m13 = n13; + m20 = n20; + m21 = n21; + m22 = n22; + m23 = n23; + m30 = n30; + m31 = n31; + m32 = n32; + m33 = n33; + + return this; + } + + public Matrix4 transpose() + { + double n00 = m00; + double n10 = m01; + double n20 = m02; + double n30 = m03; + double n01 = m10; + double n11 = m11; + double n21 = m12; + double n31 = m13; + double n02 = m20; + double n12 = m21; + double n22 = m22; + double n32 = m23; + double n03 = m30; + double n13 = m31; + double n23 = m32; + double n33 = m33; + + m00 = n00; + m01 = n01; + m02 = n02; + m03 = n03; + m10 = n10; + m11 = n11; + m12 = n12; + m13 = n13; + m20 = n20; + m21 = n21; + m22 = n22; + m23 = n23; + m30 = n30; + m31 = n31; + m32 = n32; + m33 = n33; + + return this; + } + + public Matrix4 copy() + { + return new Matrix4(this); + } + + public Matrix4 set(Matrix4 mat) + { + m00 = mat.m00; + m01 = mat.m01; + m02 = mat.m02; + m03 = mat.m03; + m10 = mat.m10; + m11 = mat.m11; + m12 = mat.m12; + m13 = mat.m13; + m20 = mat.m20; + m21 = mat.m21; + m22 = mat.m22; + m23 = mat.m23; + m30 = mat.m30; + m31 = mat.m31; + m32 = mat.m32; + m33 = mat.m33; + + return this; + } + + @Override + public void apply(Matrix4 mat) + { + mat.multiply(this); + } + + private void mult3x3(Vector3 vec) + { + double x = m00 * vec.x + m01 * vec.y + m02 * vec.z; + double y = m10 * vec.x + m11 * vec.y + m12 * vec.z; + double z = m20 * vec.x + m21 * vec.y + m22 * vec.z; + + vec.x = x; + vec.y = y; + vec.z = z; + } + + @Override + public void apply(Vector3 vec) + { + mult3x3(vec); + vec.add(m03, m13, m23); + } + + @Override + public void applyN(Vector3 vec) + { + mult3x3(vec); + vec.normalize(); + } + + @Override + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "["+new BigDecimal(m00, cont)+","+new BigDecimal(m01, cont)+","+new BigDecimal(m02, cont)+","+new BigDecimal(m03, cont)+"]\n"+ + "["+new BigDecimal(m10, cont)+","+new BigDecimal(m11, cont)+","+new BigDecimal(m12, cont)+","+new BigDecimal(m13, cont)+"]\n"+ + "["+new BigDecimal(m20, cont)+","+new BigDecimal(m21, cont)+","+new BigDecimal(m22, cont)+","+new BigDecimal(m23, cont)+"]\n"+ + "["+new BigDecimal(m30, cont)+","+new BigDecimal(m31, cont)+","+new BigDecimal(m32, cont)+","+new BigDecimal(m33, cont)+"]"; + } + + public Matrix4 apply(Transformation t) + { + t.apply(this); + return this; + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + glBuf.put(m00).put(m10).put(m20).put(m30) + .put(m01).put(m11).put(m21).put(m31) + .put(m02).put(m12).put(m22).put(m32) + .put(m03).put(m13).put(m23).put(m33); + glBuf.flip(); + GL11.glMultMatrix(glBuf); + } + + @Override + public Transformation inverse() + { + throw new IrreversibleTransformationException(this);//Don't waste your cpu with matrix inverses + } +} diff --git a/codechicken/lib/vec/Quat.java b/codechicken/lib/vec/Quat.java new file mode 100644 index 0000000..e639552 --- /dev/null +++ b/codechicken/lib/vec/Quat.java @@ -0,0 +1,156 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import codechicken.lib.math.MathHelper; + +public class Quat +{ + public double x; + public double y; + public double z; + public double s; + public static final double SQRT2 = Math.sqrt(2D); + + public Quat() + { + s = 1; + x = 0; + y = 0; + z = 0; + } + + public Quat(Quat quat) + { + x = quat.x; + y = quat.y; + z = quat.z; + s = quat.s; + } + + public Quat(double d, double d1, double d2, double d3) + { + x = d1; + y = d2; + z = d3; + s = d; + } + + public Quat set(Quat quat) + { + x = quat.x; + y = quat.y; + z = quat.z; + s = quat.s; + + return this; + } + + public Quat set(double d, double d1, double d2, double d3) + { + x = d1; + y = d2; + z = d3; + s = d; + + return this; + } + + public static Quat aroundAxis(double ax, double ay, double az, double angle) + { + return new Quat().setAroundAxis(ax, ay, az, angle); + } + + public static Quat aroundAxis(Vector3 axis, double angle) + { + return aroundAxis(axis.x, axis.y, axis.z, angle); + } + + public Quat setAroundAxis(double ax, double ay, double az, double angle) + { + angle *= 0.5; + double d4 = MathHelper.sin(angle); + return set(MathHelper.cos(angle), ax * d4, ay * d4, az * d4); + } + + public Quat setAroundAxis(Vector3 axis, double angle) + { + return setAroundAxis(axis.x, axis.y, axis.z, angle); + } + + public Quat multiply(Quat quat) + { + double d = s * quat.s - x * quat.x - y * quat.y - z * quat.z; + double d1 = s * quat.x + x * quat.s - y * quat.z + z * quat.y; + double d2 = s * quat.y + x * quat.z + y * quat.s - z * quat.x; + double d3 = s * quat.z - x * quat.y + y * quat.x + z * quat.s; + s = d; + x = d1; + y = d2; + z = d3; + + return this; + } + + public Quat rightMultiply(Quat quat) + { + double d = s * quat.s - x * quat.x - y * quat.y - z * quat.z; + double d1 = s * quat.x + x * quat.s + y * quat.z - z * quat.y; + double d2 = s * quat.y - x * quat.z + y * quat.s + z * quat.x; + double d3 = s * quat.z + x * quat.y - y * quat.x + z * quat.s; + s = d; + x = d1; + y = d2; + z = d3; + + return this; + } + + public double mag() + { + return Math.sqrt(x * x + y * y + z * z + s * s); + } + + public Quat normalize() + { + double d = mag(); + if(d != 0) + { + d = 1 / d; + x *= d; + y *= d; + z *= d; + s *= d; + } + + return this; + } + + public Quat copy() + { + return new Quat(this); + } + + public void rotate(Vector3 vec) + { + double d = -x * vec.x - y * vec.y - z * vec.z; + double d1 = s * vec.x + y * vec.z - z * vec.y; + double d2 = s * vec.y - x * vec.z + z * vec.x; + double d3 = s * vec.z + x * vec.y - y * vec.x; + vec.x = d1 * s - d * x - d2 * z + d3 * y; + vec.y = d2 * s - d * y + d1 * z - d3 * x; + vec.z = d3 * s - d * z - d1 * y + d2 * x; + } + + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Quat("+new BigDecimal(s, cont)+", "+new BigDecimal(x, cont)+", "+new BigDecimal(y, cont)+", "+new BigDecimal(z, cont)+")"; + } + + public Rotation rotation() + { + return new Rotation(this); + } +} diff --git a/codechicken/lib/vec/Rectangle4i.java b/codechicken/lib/vec/Rectangle4i.java new file mode 100644 index 0000000..3574e58 --- /dev/null +++ b/codechicken/lib/vec/Rectangle4i.java @@ -0,0 +1,42 @@ +package codechicken.lib.vec; + +public class Rectangle4i +{ + public int x; + public int y; + public int w; + public int h; + + public Rectangle4i() + { + } + + public Rectangle4i(int x, int y, int w, int h) + { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } + + public Rectangle4i offset(int dx, int dy) + { + x+=dx; + y+=dy; + return this; + } + + public Rectangle4i with(int px, int py) + { + if(x > px) x = px; + if(y > py) y = py; + if(x + w <= px) w = px-x+1; + if(y + h <= py) h = py-y+1; + return this; + } + + public boolean contains(int px, int py) + { + return x <= px && px < x+w && y <= py && py < y+h; + } +} diff --git a/codechicken/lib/vec/RedundantTransformation.java b/codechicken/lib/vec/RedundantTransformation.java new file mode 100644 index 0000000..a803675 --- /dev/null +++ b/codechicken/lib/vec/RedundantTransformation.java @@ -0,0 +1,38 @@ +package codechicken.lib.vec; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class RedundantTransformation extends Transformation +{ + @Override + public void apply(Vector3 vec){} + + @Override + public void apply(Matrix4 mat){} + + @Override + public void applyN(Vector3 normal){} + + @Override + public Transformation at(Vector3 point) + { + return this; + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply(){} + + @Override + public Transformation inverse() + { + return this; + } + + @Override + public String toString() + { + return "Nothing()"; + } +} diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java new file mode 100644 index 0000000..6b9ed15 --- /dev/null +++ b/codechicken/lib/vec/Rotation.java @@ -0,0 +1,238 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import net.minecraft.entity.player.EntityPlayer; + +import org.lwjgl.opengl.GL11; + +import codechicken.lib.math.MathHelper; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class Rotation extends Transformation +{ + /** + * Clockwise pi/2 about y looking down + */ + public static Transformation[] quarterRotations = new Transformation[]{ + new RedundantTransformation(), + new VariableTransformation(new Matrix4(0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d1 = vec.x; double d2 = vec.z; + vec.x = -d2; vec.z = d1; + } @Override public Transformation inverse(){ + return quarterRotations[3]; + }}, + new VariableTransformation(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + vec.x = -vec.x; vec.z = -vec.z; + } @Override public Transformation inverse(){ + return this; + }}, + new VariableTransformation(new Matrix4(0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d1 = vec.x; double d2 = vec.z; + vec.x = d2; vec.z = -d1; + } @Override public Transformation inverse(){ + return quarterRotations[1]; + }} + }; + + public static Transformation[] sideRotations = new Transformation[]{ + new RedundantTransformation(), + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0,-1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + vec.y = -vec.y; vec.z = -vec.z; + } @Override public Transformation inverse(){ + return this; + }}, + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d1 = vec.y; double d2 = vec.z; + vec.y = -d2; vec.z = d1; + } @Override public Transformation inverse(){ + return sideRotations[3]; + }}, + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d1 = vec.y; double d2 = vec.z; + vec.y = d2; vec.z = -d1; + } @Override public Transformation inverse(){ + return sideRotations[2]; + }}, + new VariableTransformation(new Matrix4(0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d0 = vec.x; double d1 = vec.y; + vec.x = d1; vec.y = -d0; + } @Override public Transformation inverse(){ + return sideRotations[5]; + }}, + new VariableTransformation(new Matrix4(0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)){ + @Override public void apply(Vector3 vec){ + double d0 = vec.x; double d1 = vec.y; + vec.x = -d1; vec.y = d0; + } @Override public Transformation inverse(){ + return sideRotations[4]; + }} + }; + + public static Vector3[] axes = new Vector3[]{ + new Vector3( 0,-1, 0), + new Vector3( 0, 1, 0), + new Vector3( 0, 0,-1), + new Vector3( 0, 0, 1), + new Vector3(-1, 0, 0), + new Vector3( 1, 0, 0)}; + + public static int[] sideRotMap = new int[]{ + 3,4,2,5, + 3,5,2,4, + 1,5,0,4, + 1,4,0,5, + 1,2,0,3, + 1,3,0,2}; + + public static int[] rotSideMap = new int[]{ + -1,-1, 2, 0, 1, 3, + -1,-1, 2, 0, 3, 1, + 2, 0,-1,-1, 3, 1, + 2, 0,-1,-1, 1, 3, + 2, 0, 1, 3,-1,-1, + 2, 0, 3, 1,-1,-1}; + + /** + * Rotate pi/2 * this offset for [side] about y axis before rotating to the side for the rotation indicies to line up + */ + public static int[] sideRotOffsets = new int[]{0, 2, 2, 0, 1, 3}; + + public static int rotateSide(int s, int r) + { + return sideRotMap[s<<2|r]; + } + + /** + * Reverse of rotateSide + */ + public static int rotationTo(int s1, int s2) + { + if((s1&6) == (s2&6)) + throw new IllegalArgumentException("Faces "+s1+" and "+s2+" are opposites"); + return rotSideMap[s1*6+s2]; + } + + /** + * @param player The placing player, used for obtaining the look vector + * @param side The side of the block being placed on + * @return The rotation for the face == side^1 + */ + public static int getSidedRotation(EntityPlayer player, int side) + { + Vector3 look = new Vector3(player.getLook(1)); + double max = 0; + int maxr = 0; + for(int r = 0; r < 4; r++) + { + Vector3 axis = Rotation.axes[rotateSide(side^1, r)]; + double d = look.scalarProject(axis); + if(max > d) + { + max = d; + maxr = r; + } + } + return maxr; + } + + /** + * @return The rotation quat for side 0 and rotation 0 to side s with rotation r + */ + public static Transformation sideOrientation(int s, int r) + { + return quarterRotations[(r+sideRotOffsets[s])%4].with(sideRotations[s]); + } + + public double angle; + public Vector3 axis; + + private Quat quat; + + public Rotation(double angle, Vector3 axis) + { + this.angle = angle; + this.axis = axis; + } + + public Rotation(double angle, double x, double y, double z) + { + this(angle, new Vector3(x, y, z)); + } + + public Rotation(Quat quat) + { + this.quat = quat; + + angle = Math.acos(quat.s)*2; + if(angle == 0) + { + axis = new Vector3(0, 1, 0); + } + else + { + double sa = Math.sin(angle*0.5); + axis = new Vector3(quat.x/sa, quat.y/sa, quat.z/sa); + } + } + + @Override + public void apply(Vector3 vec) + { + if(quat == null) + quat = Quat.aroundAxis(axis, angle); + + vec.rotate(quat); + } + + @Override + public void applyN(Vector3 normal) + { + apply(normal); + } + + @Override + public void apply(Matrix4 mat) + { + mat.rotate(angle, axis); + } + + public Quat toQuat() + { + if(quat == null) + quat = Quat.aroundAxis(axis, angle); + return quat; + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + GL11.glRotatef((float)(angle*MathHelper.todeg), (float)axis.x, (float)axis.y, (float)axis.z); + } + + @Override + public Transformation inverse() + { + return new Rotation(-angle, axis); + } + + @Override + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Rotation("+new BigDecimal(angle, cont)+", "+new BigDecimal(axis.x, cont)+", "+ + new BigDecimal(axis.y, cont)+", "+new BigDecimal(axis.z, cont)+")"; + } +} diff --git a/codechicken/lib/vec/Scale.java b/codechicken/lib/vec/Scale.java new file mode 100644 index 0000000..55c8dcd --- /dev/null +++ b/codechicken/lib/vec/Scale.java @@ -0,0 +1,67 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class Scale extends Transformation +{ + private Vector3 factor; + + public Scale(Vector3 factor) + { + this.factor = factor; + } + + public Scale(double factor) + { + this(new Vector3(factor, factor, factor)); + } + + public Scale(double x, double y, double z) + { + this(new Vector3(x, y, z)); + } + + @Override + public void apply(Vector3 vec) + { + vec.multiply(factor); + } + + @Override + public void applyN(Vector3 normal) + { + } + + @Override + public void apply(Matrix4 mat) + { + mat.scale(factor); + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + GL11.glScaled(factor.x, factor.y, factor.z); + } + + @Override + public Transformation inverse() + { + return new Scale(1/factor.x, 1/factor.y, 1/factor.z); + } + + @Override + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Scale("+new BigDecimal(factor.x, cont)+", "+new BigDecimal(factor.y, cont)+", "+new BigDecimal(factor.z, cont)+")"; + } +} diff --git a/codechicken/lib/vec/SwapYZ.java b/codechicken/lib/vec/SwapYZ.java new file mode 100644 index 0000000..d4524d4 --- /dev/null +++ b/codechicken/lib/vec/SwapYZ.java @@ -0,0 +1,27 @@ +package codechicken.lib.vec; + +public class SwapYZ extends VariableTransformation +{ + public SwapYZ() + { + super(new Matrix4( + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, 1, 0, 0, + 0, 0, 0, 1)); + } + + @Override + public void apply(Vector3 vec) + { + double vz = vec.z; + vec.z = vec.y; + vec.y = vz; + } + + @Override + public Transformation inverse() + { + return this; + } +} diff --git a/codechicken/lib/vec/Transformation.java b/codechicken/lib/vec/Transformation.java new file mode 100644 index 0000000..512720d --- /dev/null +++ b/codechicken/lib/vec/Transformation.java @@ -0,0 +1,51 @@ +package codechicken.lib.vec; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +/** + * Interface for any 3D vector transformation + */ +public abstract class Transformation +{ + /** + * Applies this transformation to a position vector + * @param vec The vector to transform + */ + public abstract void apply(Vector3 vec); + + /** + * Applies this transformation to a normal (doesn't translate) + * @param normal The normal to transform + */ + public abstract void applyN(Vector3 normal); + + /** + * Applies this transformation to a matrix as a multiplication on the right hand side. + * @param mat The matrix to combine this transformation with + */ + public abstract void apply(Matrix4 mat); + + /** + * @param point The point in OBJECT space to apply this transformation around + * @return Wraps this transformation in a translation to point and then back from point + */ + public Transformation at(Vector3 point) + { + return new TranslatedTransformation(this, point); + } + + /** + * Creates a transformation list composed of this transformation followed by t + * If this is a TransformationList, the transformation will be appended and this returned + */ + public TransformationList with(Transformation t) + { + return new TransformationList(this, t); + } + + @SideOnly(Side.CLIENT) + public abstract void glApply(); + + public abstract Transformation inverse(); +} diff --git a/codechicken/lib/vec/TransformationList.java b/codechicken/lib/vec/TransformationList.java new file mode 100644 index 0000000..2b7520f --- /dev/null +++ b/codechicken/lib/vec/TransformationList.java @@ -0,0 +1,101 @@ +package codechicken.lib.vec; + +import java.util.ArrayList; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class TransformationList extends Transformation +{ + private ArrayList transformations = new ArrayList(); + private Matrix4 mat; + + public TransformationList(Transformation... transforms) + { + for(Transformation t : transforms) + with(t); + } + + public Matrix4 compile() + { + if(mat == null) + { + mat = new Matrix4(); + for(int i = transformations.size()-1; i >= 0; i--) + transformations.get(i).apply(mat); + } + return mat; + } + + /** + * Returns a global space matrix as opposed to an object space matrix (reverse application order) + * @return + */ + public Matrix4 reverseCompile() + { + Matrix4 mat = new Matrix4(); + for(Transformation t : transformations) + t.apply(mat); + return mat; + } + + @Override + public void apply(Vector3 vec) + { + if(mat != null) + mat.apply(vec); + else + for(Transformation t : transformations) + t.apply(vec); + } + + @Override + public void applyN(Vector3 normal) + { + if(mat != null) + mat.applyN(normal); + else + for(Transformation t : transformations) + t.applyN(normal); + } + + @Override + public void apply(Matrix4 mat) + { + mat.multiply(compile()); + } + + @Override + public TransformationList with(Transformation t) + { + mat = null;//matrix invalid + transformations.add(t); + return this; + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + for(int i = transformations.size()-1; i >= 0; i--) + transformations.get(i).glApply(); + } + + @Override + public Transformation inverse() + { + TransformationList rev = new TransformationList(); + for(int i = transformations.size()-1; i >= 0; i--) + rev.with(transformations.get(i).inverse()); + return rev; + } + + @Override + public String toString() + { + String s = ""; + for(Transformation t : transformations) + s+="\n"+t.toString(); + return s.trim(); + } +} diff --git a/codechicken/lib/vec/TranslatedTransformation.java b/codechicken/lib/vec/TranslatedTransformation.java new file mode 100644 index 0000000..babab60 --- /dev/null +++ b/codechicken/lib/vec/TranslatedTransformation.java @@ -0,0 +1,60 @@ +package codechicken.lib.vec; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class TranslatedTransformation extends Transformation +{ + public Vector3 point; + public Transformation wrapped; + + public TranslatedTransformation(Transformation t, Vector3 vec) + { + point = vec; + wrapped = t; + } + + @Override + public void apply(Vector3 vec) + { + vec.subtract(point).apply(wrapped).add(point); + } + + @Override + public void applyN(Vector3 normal) + { + wrapped.applyN(normal); + } + + @Override + public void apply(Matrix4 mat) + { + mat.translate(point).apply(wrapped) + .translate(new Vector3(-point.x, -point.y, -point.z)); + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + GL11.glTranslated(point.x, point.y, point.z); + wrapped.glApply(); + GL11.glTranslated(-point.x, -point.y, -point.z); + } + + @Override + public Transformation inverse() + { + return new TranslatedTransformation(wrapped.inverse(), point); + } + + @Override + public String toString() + { + return point.translation()+"\n"+ + wrapped.toString()+"\n"+ + new Translation(-point.x, -point.y, -point.z); + } +} diff --git a/codechicken/lib/vec/Translation.java b/codechicken/lib/vec/Translation.java new file mode 100644 index 0000000..cceea44 --- /dev/null +++ b/codechicken/lib/vec/Translation.java @@ -0,0 +1,68 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class Translation extends Transformation +{ + private Vector3 vec; + + public Translation(Vector3 vec) + { + this.vec = vec; + } + + public Translation(double x, double y, double z) + { + this(new Vector3(x, y, z)); + } + + @Override + public void apply(Vector3 vec) + { + vec.add(this.vec); + } + + @Override + public void applyN(Vector3 normal) + { + } + + @Override + public void apply(Matrix4 mat) + { + mat.translate(vec); + } + + @Override + public Transformation at(Vector3 point) + { + return this; + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + GL11.glTranslated(vec.x, vec.y, vec.z); + } + + @Override + public Transformation inverse() + { + return new Translation(-vec.x, -vec.y, -vec.z); + } + + @Override + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Translation("+new BigDecimal(vec.x, cont)+", "+new BigDecimal(vec.y, cont)+", "+new BigDecimal(vec.z, cont)+")"; + } +} diff --git a/codechicken/lib/vec/VariableTransformation.java b/codechicken/lib/vec/VariableTransformation.java new file mode 100644 index 0000000..9e8ec89 --- /dev/null +++ b/codechicken/lib/vec/VariableTransformation.java @@ -0,0 +1,33 @@ +package codechicken.lib.vec; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public abstract class VariableTransformation extends Transformation +{ + public Matrix4 mat; + + public VariableTransformation(Matrix4 mat) + { + this.mat = mat; + } + + @Override + public void applyN(Vector3 normal) + { + apply(normal); + } + + @Override + public void apply(Matrix4 mat) + { + mat.multiply(this.mat); + } + + @Override + @SideOnly(Side.CLIENT) + public void glApply() + { + mat.glApply(); + } +} \ No newline at end of file diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java new file mode 100644 index 0000000..675e9ad --- /dev/null +++ b/codechicken/lib/vec/Vector3.java @@ -0,0 +1,423 @@ +package codechicken.lib.vec; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import org.lwjgl.util.vector.Vector3f; +import org.lwjgl.util.vector.Vector4f; + +import codechicken.lib.math.MathHelper; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import net.minecraft.entity.Entity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Vec3; + +public class Vector3 +{ + public static Vector3 zero = new Vector3(); + public static Vector3 one = new Vector3(1, 1, 1); + public static Vector3 center = new Vector3(0.5, 0.5, 0.5); + + public double x; + public double y; + public double z; + + public Vector3() + { + } + + public Vector3(double d, double d1, double d2) + { + x = d; + y = d1; + z = d2; + } + + public Vector3(Vector3 vec) + { + x = vec.x; + y = vec.y; + z = vec.z; + } + + public Vector3(Vec3 vec) + { + x = vec.xCoord; + y = vec.yCoord; + z = vec.zCoord; + } + + public Vector3 copy() + { + return new Vector3(this); + } + + public static Vector3 fromEntity(Entity e) + { + return new Vector3(e.posX, e.posY, e.posZ); + } + + public static Vector3 fromEntityCenter(Entity e) + { + return new Vector3(e.posX, e.posY - e.yOffset + e.height/2, e.posZ); + } + + public static Vector3 fromTileEntity(TileEntity e) + { + return new Vector3(e.xCoord, e.yCoord, e.zCoord); + } + + public static Vector3 fromTileEntityCenter(TileEntity e) + { + return new Vector3(e.xCoord + 0.5, e.yCoord + 0.5, e.zCoord + 0.5); + } + + @Deprecated + public static Vector3 fromVec3D(Vec3 vec) + { + return new Vector3(vec); + } + + public Vector3 set(double d, double d1, double d2) + { + x = d; + y = d1; + z = d2; + return this; + } + + public Vector3 set(Vector3 vec) + { + x = vec.x; + y = vec.y; + z = vec.z; + return this; + } + + public double dotProduct(Vector3 vec) + { + double d = vec.x * x + vec.y * y + vec.z * z; + + if(d > 1 && d < 1.00001) + d = 1; + else if(d < -1 && d > -1.00001) + d = -1; + return d; + } + + public double dotProduct(double d, double d1, double d2) + { + return d * x + d1 * y + d2 * z; + } + + public Vector3 crossProduct(Vector3 vec) + { + double d = y * vec.z - z * vec.y; + double d1 = z * vec.x - x * vec.z; + double d2 = x * vec.y - y * vec.x; + x = d; + y = d1; + z = d2; + return this; + } + + public Vector3 add(double d, double d1, double d2) + { + x += d; + y += d1; + z += d2; + return this; + } + + public Vector3 add(Vector3 vec) + { + x += vec.x; + y += vec.y; + z += vec.z; + return this; + } + + public Vector3 add(double d) + { + return add(d, d, d); + } + + public Vector3 sub(Vector3 vec) + { + return subtract(vec); + } + + public Vector3 subtract(Vector3 vec) + { + x -= vec.x; + y -= vec.y; + z -= vec.z; + return this; + } + + public Vector3 negate(Vector3 vec) + { + x = -x; + y = -y; + z = -z; + return this; + } + + public Vector3 multiply(double d) + { + x *= d; + y *= d; + z *= d; + return this; + } + + public Vector3 multiply(Vector3 f) + { + x *= f.x; + y *= f.y; + z *= f.z; + return this; + } + + public Vector3 multiply(double fx, double fy, double fz) + { + x *= fx; + y *= fy; + z *= fz; + return this; + } + + public double mag() + { + return Math.sqrt(x * x + y * y + z * z); + } + + public double magSquared() + { + return x * x + y * y + z * z; + } + + public Vector3 normalize() + { + double d = mag(); + if(d != 0) + { + multiply(1 / d); + } + return this; + } + + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "Vector3("+new BigDecimal(x, cont)+", "+new BigDecimal(y, cont)+", "+new BigDecimal(z, cont)+")"; + } + + public Vector3 perpendicular() + { + if(z == 0) + return zCrossProduct(); + return xCrossProduct(); + } + + public Vector3 xCrossProduct() + { + double d = z; + double d1 = -y; + x = 0; + y = d; + z = d1; + return this; + } + + public Vector3 zCrossProduct() + { + double d = y; + double d1 = -x; + x = d; + y = d1; + z = 0; + return this; + } + + public Vector3 yCrossProduct() + { + double d = -z; + double d1 = x; + x = d; + y = 0; + z = d1; + return this; + } + + public Vector3 rotate(double angle, Vector3 axis){ + Quat.aroundAxis(axis.copy().normalize(), angle).rotate(this); + return this; + } + + public Vector3 rotate(Quat rotator) + { + rotator.rotate(this); + return this; + } + + public Vec3 toVec3D() + { + return Vec3.createVectorHelper(x, y, z); + } + + public double angle(Vector3 vec) + { + return Math.acos(copy().normalize().dotProduct(vec.copy().normalize())); + } + + public boolean isZero() + { + return x == 0 && y == 0 && z == 0; + } + + public boolean isAxial() + { + return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); + } + + @SideOnly(Side.CLIENT) + public Vector3f vector3f() + { + return new Vector3f((float)x, (float)y, (float)z); + } + + @SideOnly(Side.CLIENT) + public Vector4f vector4f() + { + return new Vector4f((float)x, (float)y, (float)z, 1); + } + + public Vector3 YZintercept(Vector3 end, double px) + { + double dx = end.x - x; + double dy = end.y - y; + double dz = end.z - z; + + if (dx == 0) + return null; + + double d = (px - x) / dx; + if(MathHelper.between(-1E-5, d, 1E-5)) + return this; + + if(!MathHelper.between(0, d, 1)) + return null; + + x = px; + y += d*dy; + z += d*dz; + return this; + } + + public Vector3 XZintercept(Vector3 end, double py) + { + double dx = end.x - x; + double dy = end.y - y; + double dz = end.z - z; + + if (dy == 0) + return null; + + double d = (py - y) / dy; + if(MathHelper.between(-1E-5, d, 1E-5)) + return this; + + if(!MathHelper.between(0, d, 1)) + return null; + + x += d*dx; + y = py; + z += d*dz; + return this; + } + + public Vector3 XYintercept(Vector3 end, double pz) + { + double dx = end.x - x; + double dy = end.y - y; + double dz = end.z - z; + + if (dz == 0) + return null; + + double d = (pz - z) / dz; + if(MathHelper.between(-1E-5, d, 1E-5)) + return this; + + if(!MathHelper.between(0, d, 1)) + return null; + + x += d*dx; + y += d*dy; + z = pz; + return this; + } + + public Vector3 negate() + { + x = -x; + y = -y; + z = -z; + return this; + } + + public Translation translation() + { + return new Translation(this); + } + + public double scalarProject(Vector3 b) + { + double l = b.mag(); + return l == 0 ? 0 : dotProduct(b)/l; + } + + public Vector3 project(Vector3 b) + { + double l = b.magSquared(); + if(l == 0) + { + set(0, 0, 0); + return this; + } + double m = dotProduct(b)/l; + set(b).multiply(m); + return this; + } + + @Override + public boolean equals(Object o) + { + if(!(o instanceof Vector3)) + return false; + Vector3 v = (Vector3)o; + return x == v.x && y == v.y && z == v.z; + } + + /** + * Equals method with tolerance + * @return true if this is equal to v within +-1E-5 + */ + public boolean equalsT(Vector3 v) + { + return MathHelper.between(x-1E-5, v.x, x+1E-5) && + MathHelper.between(y-1E-5, v.y, y+1E-5) && + MathHelper.between(z-1E-5, v.z, z+1E-5); + } + + public Vector3 apply(Transformation t) + { + t.apply(this); + return this; + } +} diff --git a/codechicken/lib/world/ChunkExtension.java b/codechicken/lib/world/ChunkExtension.java new file mode 100644 index 0000000..1315e3a --- /dev/null +++ b/codechicken/lib/world/ChunkExtension.java @@ -0,0 +1,85 @@ +package codechicken.lib.world; + +import java.util.HashSet; + +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.packet.Packet; + +public abstract class ChunkExtension +{ + public final Chunk chunk; + public final ChunkCoordIntPair coord; + public final WorldExtension world; + public HashSet watchedPlayers; + + public ChunkExtension(Chunk chunk, WorldExtension world) + { + this.chunk = chunk; + coord = chunk.getChunkCoordIntPair(); + this.world = world; + watchedPlayers = new HashSet(); + } + + public void loadData(NBTTagCompound tag) + { + } + + public void saveData(NBTTagCompound tag) + { + } + + public void load() + { + } + + public void unload() + { + } + + public final void sendPacketToPlayers(Packet packet) + { + for(EntityPlayerMP player : watchedPlayers) + player.playerNetServerHandler.sendPacketToPlayer(packet); + } + + public final void watchPlayer(EntityPlayerMP player) + { + watchedPlayers.add(player); + onWatchPlayer(player); + } + + public void onWatchPlayer(EntityPlayerMP player) + { + } + + public final void unwatchPlayer(EntityPlayerMP player) + { + watchedPlayers.remove(player); + onUnWatchPlayer(player); + } + + public void onUnWatchPlayer(EntityPlayerMP player) + { + } + + public void sendUpdatePackets() + { + } + + @Override + public int hashCode() + { + return coord.chunkXPos ^ coord.chunkZPos; + } + + @Override + public boolean equals(Object o) + { + return (o instanceof ChunkExtension && ((ChunkExtension)o).coord.equals(coord)) || + (o instanceof ChunkCoordIntPair && coord.equals(o)) || + (o instanceof Long && (Long)o == (((long)coord.chunkXPos)<<32 | coord.chunkZPos)); + } +} diff --git a/codechicken/lib/world/WorldExtension.java b/codechicken/lib/world/WorldExtension.java new file mode 100644 index 0000000..3df2593 --- /dev/null +++ b/codechicken/lib/world/WorldExtension.java @@ -0,0 +1,99 @@ +package codechicken.lib.world; + +import java.util.HashMap; + +import net.minecraft.world.chunk.Chunk; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +public abstract class WorldExtension +{ + public final World world; + public HashMap chunkMap = new HashMap(); + + public WorldExtension(World world) + { + this.world = world; + } + + public void load() + { + } + + public void unload() + { + } + + public void save() + { + } + + public void preTick() + { + } + + public void postTick() + { + } + + protected final void addChunk(ChunkExtension extension) + { + chunkMap.put(extension.chunk, extension); + } + + protected final void loadChunk(Chunk chunk) + { + chunkMap.get(chunk).load(); + } + + protected final void unloadChunk(Chunk chunk) + { + chunkMap.get(chunk).unload(); + } + + protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) + { + chunkMap.get(chunk).loadData(tag); + } + + protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) + { + chunkMap.get(chunk).saveData(tag); + } + + protected final void remChunk(Chunk chunk) + { + chunkMap.remove(chunk); + } + + protected final void watchChunk(Chunk chunk, EntityPlayerMP player) + { + chunkMap.get(chunk).watchPlayer(player); + } + + protected final void unwatchChunk(Chunk chunk, EntityPlayerMP player) + { + ChunkExtension extension = chunkMap.get(chunk); + if(extension != null) + extension.unwatchPlayer(player); + } + + protected final void sendChunkUpdates(Chunk chunk) + { + chunkMap.get(chunk).sendUpdatePackets(); + } + + public boolean containsChunk(Chunk chunk) + { + return chunkMap.containsKey(chunk); + } + + public ChunkExtension getChunkExtension(int chunkXPos, int chunkZPos) + { + if(!world.blockExists(chunkXPos<<4, 128, chunkZPos<<4)) + return null; + + return chunkMap.get(world.getChunkFromChunkCoords(chunkXPos, chunkZPos)); + } +} diff --git a/codechicken/lib/world/WorldExtensionInstantiator.java b/codechicken/lib/world/WorldExtensionInstantiator.java new file mode 100644 index 0000000..754b441 --- /dev/null +++ b/codechicken/lib/world/WorldExtensionInstantiator.java @@ -0,0 +1,17 @@ +package codechicken.lib.world; + +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.World; + +public abstract class WorldExtensionInstantiator +{ + public int instantiatorID; + + public abstract WorldExtension createWorldExtension(World world); + public abstract ChunkExtension createChunkExtension(Chunk chunk, WorldExtension world); + + public WorldExtension getExtension(World world) + { + return WorldExtensionManager.getWorldExtension(world, instantiatorID); + } +} diff --git a/codechicken/lib/world/WorldExtensionManager.java b/codechicken/lib/world/WorldExtensionManager.java new file mode 100644 index 0000000..4f41627 --- /dev/null +++ b/codechicken/lib/world/WorldExtensionManager.java @@ -0,0 +1,256 @@ +package codechicken.lib.world; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ITickHandler; +import cpw.mods.fml.common.TickType; +import cpw.mods.fml.common.registry.TickRegistry; +import cpw.mods.fml.relauncher.Side; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.EmptyChunk; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.event.world.ChunkWatchEvent.UnWatch; +import net.minecraftforge.event.world.ChunkWatchEvent.Watch; + +public class WorldExtensionManager +{ + public static class WorldExtensionEventHandler + { + @ForgeSubscribe + public void onChunkDataLoad(ChunkDataEvent.Load event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + + createChunkExtension(event.world, event.getChunk()); + + for(WorldExtension extension : worldMap.get(event.world)) + extension.loadChunkData(event.getChunk(), event.getData()); + } + + @ForgeSubscribe + public void onChunkDataSave(ChunkDataEvent.Save event) + { + for(WorldExtension extension : worldMap.get(event.world)) + extension.saveChunkData(event.getChunk(), event.getData()); + + if(!event.getChunk().isChunkLoaded) + removeChunk(event.world, event.getChunk()); + } + + @ForgeSubscribe + public void onChunkLoad(ChunkEvent.Load event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + + createChunkExtension(event.world, event.getChunk()); + + for(WorldExtension extension : worldMap.get(event.world)) + extension.loadChunk(event.getChunk()); + } + + @ForgeSubscribe + public void onChunkUnLoad(ChunkEvent.Unload event) + { + if(event.getChunk() instanceof EmptyChunk) + return; + + for(WorldExtension extension : worldMap.get(event.world)) + extension.unloadChunk(event.getChunk()); + + if(event.world.isRemote) + removeChunk(event.world, event.getChunk()); + } + + @ForgeSubscribe + public void onWorldSave(WorldEvent.Save event) + { + for(WorldExtension extension : worldMap.get(event.world)) + extension.save(); + } + + @ForgeSubscribe + public void onWorldLoad(WorldEvent.Load event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + } + + @ForgeSubscribe + public void onWorldUnLoad(WorldEvent.Unload event) + { + WorldExtensionManager.onWorldUnload(event.world); + } + + @ForgeSubscribe + public void onChunkWatch(Watch event) + { + Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); + for(WorldExtension extension : worldMap.get(event.player.worldObj)) + extension.watchChunk(chunk, event.player); + } + + @ForgeSubscribe + public void onChunkUnWatch(UnWatch event) + { + Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); + for(WorldExtension extension : worldMap.get(event.player.worldObj)) + extension.unwatchChunk(chunk, event.player); + } + } + + public static class WorldExtensionClientTickHandler implements ITickHandler + { + @Override + public void tickStart(EnumSet type, Object... tickData) + { + if(type.contains(TickType.CLIENT)) + { + World world = Minecraft.getMinecraft().theWorld; + if(worldMap.containsKey(world)) + preTick(world); + } + } + + @Override + public void tickEnd(EnumSet type, Object... tickData) + { + if(type.contains(TickType.CLIENT)) + { + World world = Minecraft.getMinecraft().theWorld; + if(worldMap.containsKey(world)) + postTick(world); + } + } + + @Override + public EnumSet ticks() + { + return EnumSet.of(TickType.CLIENT); + } + + @Override + public String getLabel() + { + return "WorldExtenstions"; + } + } + + public static class WorldExtensionServerTickHandler implements ITickHandler + { + @Override + public void tickStart(EnumSet type, Object... tickData) + { + if(type.contains(TickType.WORLD)) + { + preTick((World)tickData[0]); + } + } + + @Override + public void tickEnd(EnumSet type, Object... tickData) + { + if(type.contains(TickType.WORLD)) + { + postTick((World)tickData[0]); + } + } + + @Override + public EnumSet ticks() + { + return EnumSet.of(TickType.WORLD, TickType.CLIENT); + } + + @Override + public String getLabel() + { + return "WorldExtenstions"; + } + } + + private static boolean initialised; + private static ArrayList extensionIntialisers = new ArrayList(); + + public static void registerWorldExtension(WorldExtensionInstantiator init) + { + if(!initialised) + init(); + + init.instantiatorID = extensionIntialisers.size(); + extensionIntialisers.add(init); + } + + private static void init() + { + initialised = true; + MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); + TickRegistry.registerTickHandler(new WorldExtensionServerTickHandler(), Side.SERVER); + if(FMLCommonHandler.instance().getSide().isClient()) + { + TickRegistry.registerTickHandler(new WorldExtensionClientTickHandler(), Side.CLIENT); + } + } + + private static HashMap worldMap = new HashMap(); + + private static void onWorldLoad(World world) + { + WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()]; + for(int i = 0; i < extensions.length; i++) + extensions[i] = extensionIntialisers.get(i).createWorldExtension(world); + + worldMap.put(world, extensions); + + for(WorldExtension extension : extensions) + extension.load(); + } + + public static void onWorldUnload(World world) + { + for(WorldExtension extension : worldMap.remove(world)) + extension.unload(); + } + + private static void createChunkExtension(World world, Chunk chunk) + { + WorldExtension[] extensions = worldMap.get(world); + for(int i = 0; i < extensionIntialisers.size(); i++) + if(!extensions[i].containsChunk(chunk)) + extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); + } + + private static void removeChunk(World world, Chunk chunk) + { + for(WorldExtension extension : worldMap.get(world)) + extension.remChunk(chunk); + } + + private static void preTick(World world) + { + for(WorldExtension extension : worldMap.get(world)) + extension.preTick(); + } + + private static void postTick(World world) + { + for(WorldExtension extension : worldMap.get(world)) + extension.postTick(); + } + + public static WorldExtension getWorldExtension(World world, int instantiatorID) + { + return worldMap.get(world)[instantiatorID]; + } +} From 3c5a61e01137d2704e2a117d2680f12741ecae79 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 17 Jul 2013 18:18:57 +1000 Subject: [PATCH 003/219] Fixed a few mapping bugs Added version files --- codechicken/lib/asm/ClassHeirachyManager.java | 9 +++++++-- codechicken/lib/asm/ObfMapping.java | 2 +- mcversion.txt | 1 + version.txt | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 mcversion.txt create mode 100644 version.txt diff --git a/codechicken/lib/asm/ClassHeirachyManager.java b/codechicken/lib/asm/ClassHeirachyManager.java index e3c890d..6a2d6b7 100644 --- a/codechicken/lib/asm/ClassHeirachyManager.java +++ b/codechicken/lib/asm/ClassHeirachyManager.java @@ -18,6 +18,11 @@ public class ClassHeirachyManager implements IClassTransformer public static HashMap> superclasses = new HashMap>(); private static LaunchClassLoader cl = (LaunchClassLoader)ClassHeirachyManager.class.getClassLoader(); + static + { + cl.addTransformerExclusion("codechicken.lib.asm"); + } + /** * Returns true if clazz extends, either directly or indirectly, superclass. * @param clazz The class in question @@ -93,7 +98,7 @@ public byte[] transform(String name, String tname, byte[] bytes) { if (bytes == null) return null; if(!knownClasses.contains(name)) - { + { ClassNode node = ASMHelper.createClassNode(bytes); knownClasses.add(name); @@ -111,7 +116,7 @@ private static void addSuperclass(String name, String superclass) if(supers == null) superclasses.put(name, supers = new ArrayList()); supers.add(superclass); - supers.add(new ObfMapping(superclass).toRuntime().javaClass()); + supers.add(new ObfMapping(superclass.replace('.', '/')).toRuntime().javaClass()); } public static String getSuperClass(String c) diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index 8ebe831..e2c02ad 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -46,7 +46,7 @@ public class ObfMapping public ObfMapping(String owner) { - this(owner, null, null); + this(owner, "", ""); } public ObfMapping(String owner, String name, String desc) diff --git a/mcversion.txt b/mcversion.txt new file mode 100644 index 0000000..308b6fa --- /dev/null +++ b/mcversion.txt @@ -0,0 +1 @@ +1.6.2 \ No newline at end of file diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..afaf360 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +1.0.0 \ No newline at end of file From 9341031e7fe1c1eb0bdc13a50546a6b12ba88e29 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 19 Jul 2013 01:00:09 +1000 Subject: [PATCH 004/219] Added LangUtil for localisations --- codechicken/lib/asm/ObfMapping.java | 26 +++++-- codechicken/lib/lang/LangUtil.java | 111 ++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 codechicken/lib/lang/LangUtil.java diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index e2c02ad..7af323f 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -69,7 +69,7 @@ public ObfMapping(ObfMapping descmap, String subclass) public static ObfMapping fromDesc(String s) { - int lastDot = s.lastIndexOf('.'); + int lastDot = s.lastIndexOf('.'); if(lastDot < 0) return new ObfMapping(s, "", ""); int sep = s.indexOf('(');//methods @@ -85,7 +85,7 @@ public static ObfMapping fromDesc(String s) if(sep < 0) return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), ""); - return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot+1, sep), s.substring(sep_end)); + return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot+1, sep), s.substring(sep_end)); } public ObfMapping subclass(String subclass) @@ -176,7 +176,17 @@ public String toString() return "["+s_owner+"]"; if(s_desc.length() == 0) return "["+s_owner+"."+s_name+"]"; - return "["+s_owner+"."+s_name+s_desc+"]"; + return "["+(isMethod() ? methodDesc() : fieldDesc())+"]"; + } + + public String methodDesc() + { + return s_owner+"."+s_name+s_desc; + } + + public String fieldDesc() + { + return s_owner+"."+s_name+":"+s_desc; } public boolean isClass() @@ -203,12 +213,14 @@ else if(isField()) s_owner = mapper.mapType(s_owner); - if(!isClass()) + if(isMethod()) + s_desc = mapper.mapMethodDesc(s_desc); + else if(!isClass()) s_desc = mapper.mapDesc(s_desc); return this; } - + public ObfMapping toRuntime() { if(!runtime) @@ -217,9 +229,9 @@ public ObfMapping toRuntime() runtime = true; return this; } - + public ObfMapping copy() { - return new ObfMapping(s_owner, s_name, s_desc); + return new ObfMapping(s_owner, s_name, s_desc); } } diff --git a/codechicken/lib/lang/LangUtil.java b/codechicken/lib/lang/LangUtil.java new file mode 100644 index 0000000..608c7f9 --- /dev/null +++ b/codechicken/lib/lang/LangUtil.java @@ -0,0 +1,111 @@ +package codechicken.lib.lang; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.SortedSet; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.Language; +import net.minecraft.client.resources.Resource; +import net.minecraft.client.resources.ResourceManager; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import cpw.mods.fml.common.registry.LanguageRegistry; + +/** + * Easy localisation access. + */ +public class LangUtil +{ + public static LangUtil instance = new LangUtil(null); + + public String prefix; + + public LangUtil(String prefix) + { + this.prefix = prefix; + } + + public static String translateG(String s, Object... format) + { + return instance.translate(s, format); + } + + public String translate(String s, Object... format) + { + if(prefix != null && !s.startsWith(prefix+".")) + s = prefix+"."+s; + String ret = LanguageRegistry.instance().getStringLocalization(s); + if(ret.length() == 0) + ret = LanguageRegistry.instance().getStringLocalization(s, "en_US"); + if(ret.length() == 0) + ret = StatCollector.translateToLocal(s); + if(ret.length() == 0) + return s; + if(format.length > 0) + ret = String.format(ret, format); + return ret; + } + + public void addLangFile(InputStream resource, String lang) throws IOException + { + LanguageRegistry reg = LanguageRegistry.instance(); + BufferedReader reader = new BufferedReader(new InputStreamReader(resource, "UTF-8")); + while(true) + { + String read = reader.readLine(); + if(read == null) + break; + + int equalIndex = read.indexOf('='); + if(equalIndex == -1) + continue; + String key = read.substring(0, equalIndex); + String value = read.substring(equalIndex+1); + if(prefix != null) + key = prefix+"."+key; + reg.addStringLocalization(key, lang, value); + } + } + + public static LangUtil loadLangDir(String domain) + { + return new LangUtil(domain).addLangDir(new ResourceLocation(domain, "lang")); + } + + public LangUtil addLangDir(ResourceLocation dir) + { + ResourceManager resManager = Minecraft.getMinecraft().func_110442_L(); + for(Language lang : (SortedSet)Minecraft.getMinecraft().func_135016_M().func_135040_d()) + { + String langID = lang.func_135034_a(); + Resource langRes; + try + { + langRes = resManager.func_110536_a(new ResourceLocation(dir.func_110624_b(), dir.func_110623_a()+'/'+langID+".lang")); + } + catch(Exception e) + { + continue; + } + try + { + addLangFile(langRes.func_110527_b(), langID); + } + catch(IOException e) + { + System.err.println("Failed to load lang resource. domain="+prefix+", resource="+langRes); + e.printStackTrace(); + } + } + + return this; + } + + public static void loadBaseLangDir(ResourceLocation dir) + { + instance.addLangDir(dir); + } +} From a2d30512709eaea0cf59fbdf687ce1bcb4be9059 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 19 Jul 2013 03:11:36 +1000 Subject: [PATCH 005/219] Fix for fields maps without descriptors. --- codechicken/lib/asm/ObfMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index 7af323f..846e8cf 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -215,7 +215,7 @@ else if(isField()) if(isMethod()) s_desc = mapper.mapMethodDesc(s_desc); - else if(!isClass()) + else if(s_desc.length() > 0) s_desc = mapper.mapDesc(s_desc); return this; From 8518ed3bb03e677d5f900ec49154833178abd0bd Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Sun, 21 Jul 2013 22:44:12 +1000 Subject: [PATCH 006/219] A little cleanup, added glColour to CCRenderState --- codechicken/lib/render/CCRenderState.java | 6 ++++++ codechicken/lib/render/RenderUtils.java | 2 +- codechicken/lib/world/WorldExtensionManager.java | 10 +++------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/codechicken/lib/render/CCRenderState.java b/codechicken/lib/render/CCRenderState.java index 85d99ad..d8a92b0 100644 --- a/codechicken/lib/render/CCRenderState.java +++ b/codechicken/lib/render/CCRenderState.java @@ -1,5 +1,6 @@ package codechicken.lib.render; +import codechicken.lib.colour.ColourRGBA; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; @@ -137,4 +138,9 @@ public static void applyBrightnessTexCoords() { OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness&0xFFFF, brightness>>>16); } + + public static void glColour() + { + new ColourRGBA(colour).glColour(); + } } diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index da37e99..0ccc668 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -296,7 +296,7 @@ else if(is3D) if(larger) GL11.glScaled(d, d, d); - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glColor4f(1, 1, 1, 1); entityItem.setEntityItemStack(item); uniformRenderItem.doRenderItem(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, 0); diff --git a/codechicken/lib/world/WorldExtensionManager.java b/codechicken/lib/world/WorldExtensionManager.java index 4f41627..95d5651 100644 --- a/codechicken/lib/world/WorldExtensionManager.java +++ b/codechicken/lib/world/WorldExtensionManager.java @@ -90,7 +90,9 @@ public void onWorldLoad(WorldEvent.Load event) @ForgeSubscribe public void onWorldUnLoad(WorldEvent.Unload event) { - WorldExtensionManager.onWorldUnload(event.world); + if(worldMap.containsKey(event.world))//because force closing unloads a world twice + for(WorldExtension extension : worldMap.remove(event.world)) + extension.unload(); } @ForgeSubscribe @@ -217,12 +219,6 @@ private static void onWorldLoad(World world) extension.load(); } - public static void onWorldUnload(World world) - { - for(WorldExtension extension : worldMap.remove(world)) - extension.unload(); - } - private static void createChunkExtension(World world, Chunk chunk) { WorldExtension[] extensions = worldMap.get(world); From fed626df0b7646c64da710763f3b9605e0e206c7 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Mon, 22 Jul 2013 15:12:29 +1000 Subject: [PATCH 007/219] Added safeguard to WorldExtensionManager.saveWorld for when someone force closes the client. Made config files save themselves on tag remove Removed ' ' -> '_' mapping in config file keys --- codechicken/lib/config/ConfigTag.java | 5 ++--- codechicken/lib/config/ConfigTagParent.java | 8 ++++++-- codechicken/lib/world/WorldExtensionManager.java | 5 +++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/codechicken/lib/config/ConfigTag.java b/codechicken/lib/config/ConfigTag.java index 82987d3..98472a4 100644 --- a/codechicken/lib/config/ConfigTag.java +++ b/codechicken/lib/config/ConfigTag.java @@ -200,10 +200,9 @@ public void save(PrintWriter writer, int tabs, String bracequalifier, boolean fi { String vname; if(qualifiedname.contains(".") && bracequalifier.length() > 0) - vname = qualifiedname.substring(bracequalifier.length() + 1).replace(' ', '_'); + vname = qualifiedname.substring(bracequalifier.length() + 1); else vname = qualifiedname; - vname.replace(' ', '_'); if(newline && !first) ConfigFile.writeLine(writer, "", tabs); @@ -220,7 +219,7 @@ public void save(PrintWriter writer, int tabs, String bracequalifier, boolean fi if(value == null) ConfigFile.writeLine(writer, vname, tabs); ConfigFile.writeLine(writer, "{", tabs); - saveTagTree(writer, tabs+1, qualifiedname.replace(' ', '_')); + saveTagTree(writer, tabs+1, qualifiedname); ConfigFile.writeLine(writer, "}", tabs); } else diff --git a/codechicken/lib/config/ConfigTagParent.java b/codechicken/lib/config/ConfigTagParent.java index f3ab8d7..0db27f9 100644 --- a/codechicken/lib/config/ConfigTagParent.java +++ b/codechicken/lib/config/ConfigTagParent.java @@ -117,7 +117,6 @@ public ConfigTag getNewTag(String tagname) public ConfigTag getTag(String tagname, boolean create) { - tagname = tagname.replace('_', ' '); int dotpos = tagname.indexOf("."); String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos); ConfigTag basetag = childtags.get(basetagname); @@ -149,7 +148,12 @@ public boolean removeTag(String tagname) int dotpos = tagname.lastIndexOf("."); String lastpart = dotpos == -1 ? tagname : tagname.substring(dotpos+1, tagname.length()); if(tag.parent != null) - return tag.parent.childtags.remove(lastpart) != null; + { + boolean ret = tag.parent.childtags.remove(lastpart) != null; + if(ret) + saveConfig(); + return ret; + } return false; } diff --git a/codechicken/lib/world/WorldExtensionManager.java b/codechicken/lib/world/WorldExtensionManager.java index 95d5651..536a190 100644 --- a/codechicken/lib/world/WorldExtensionManager.java +++ b/codechicken/lib/world/WorldExtensionManager.java @@ -76,8 +76,9 @@ public void onChunkUnLoad(ChunkEvent.Unload event) @ForgeSubscribe public void onWorldSave(WorldEvent.Save event) { - for(WorldExtension extension : worldMap.get(event.world)) - extension.save(); + if(worldMap.containsKey(event.world)) + for(WorldExtension extension : worldMap.get(event.world)) + extension.save(); } @ForgeSubscribe From a003f2638dd0eb84ce340f71c3b7c72ba2fad2b6 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Mon, 22 Jul 2013 19:10:53 +1000 Subject: [PATCH 008/219] Refactored readUnsigned to readU --- codechicken/lib/data/MCDataInput.java | 4 ++-- codechicken/lib/data/NBTDataWrapper.java | 4 ++-- codechicken/lib/packet/PacketCustom.java | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/codechicken/lib/data/MCDataInput.java b/codechicken/lib/data/MCDataInput.java index 5474a11..d1169bd 100644 --- a/codechicken/lib/data/MCDataInput.java +++ b/codechicken/lib/data/MCDataInput.java @@ -10,9 +10,9 @@ public interface MCDataInput public long readLong(); public int readInt(); public short readShort(); - public int readUnsignedShort(); + public int readUShort(); public byte readByte(); - public int readUnsignedByte(); + public int readUByte(); public double readDouble(); public float readFloat(); public boolean readBoolean(); diff --git a/codechicken/lib/data/NBTDataWrapper.java b/codechicken/lib/data/NBTDataWrapper.java index 1b5b189..19cf013 100644 --- a/codechicken/lib/data/NBTDataWrapper.java +++ b/codechicken/lib/data/NBTDataWrapper.java @@ -162,7 +162,7 @@ public short readShort() } @Override - public int readUnsignedShort() + public int readUShort() { return ((NBTTagShort)readTag()).data & 0xFFFF; } @@ -174,7 +174,7 @@ public byte readByte() } @Override - public int readUnsignedByte() + public int readUByte() { return ((NBTTagByte)readTag()).data & 0xFF; } diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index 9ea252f..73e6235 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -739,12 +739,12 @@ public boolean readBoolean() } } - public int readUnsignedByte() + public int readUByte() { return readByte() & 0xFF; } - public int readUnsignedShort() + public int readUShort() { return readShort() & 0xFFFF; } @@ -859,9 +859,8 @@ public String readString() int length = datain.readUnsignedShort(); char[] chars = new char[length]; for(int i = 0; i < length; i++) - { chars[i] = readChar(); - } + return new String(chars); } catch(IOException e) From 36e6c64b66a25b422c82ad88d3111fb914af1015 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 23 Jul 2013 16:04:41 +1000 Subject: [PATCH 009/219] Fixed class heirachy evaluation getting confused with obfuscation. --- codechicken/lib/asm/CC_ClassWriter.java | 10 +++- codechicken/lib/asm/ClassHeirachyManager.java | 55 ++++++++++++------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/codechicken/lib/asm/CC_ClassWriter.java b/codechicken/lib/asm/CC_ClassWriter.java index 22fb36c..1969dfe 100644 --- a/codechicken/lib/asm/CC_ClassWriter.java +++ b/codechicken/lib/asm/CC_ClassWriter.java @@ -5,9 +5,17 @@ public class CC_ClassWriter extends ClassWriter { + private final boolean runtime; + public CC_ClassWriter(int flags) + { + this(flags, false); + } + + public CC_ClassWriter(int flags, boolean runtime) { super(flags); + this.runtime = runtime; } @Override @@ -21,7 +29,7 @@ protected String getCommonSuperClass(String type1, String type2) return type2; do { - c = ClassHeirachyManager.getSuperClass(c); + c = ClassHeirachyManager.getSuperClass(c, runtime); } while(!ClassHeirachyManager.classExtends(d, c)); return c.replace('.', '/'); diff --git a/codechicken/lib/asm/ClassHeirachyManager.java b/codechicken/lib/asm/ClassHeirachyManager.java index 6a2d6b7..e5bf3d6 100644 --- a/codechicken/lib/asm/ClassHeirachyManager.java +++ b/codechicken/lib/asm/ClassHeirachyManager.java @@ -5,6 +5,7 @@ import java.util.HashSet; import org.objectweb.asm.tree.ClassNode; +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.LaunchClassLoader; @@ -23,19 +24,28 @@ public class ClassHeirachyManager implements IClassTransformer cl.addTransformerExclusion("codechicken.lib.asm"); } + public static String toKey(String name) + { + if(ObfMapping.obfuscated) + name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/','.'); + return name; + } + /** * Returns true if clazz extends, either directly or indirectly, superclass. - * @param clazz The class in question + * @param name The class in question * @param superclass The class being extended - * @param bytes The bytes for the clazz. Only needed if not already defined. + * @param bytes The bytes for the class. Only needed if not already defined. * @return */ - public static boolean classExtends(String clazz, String superclass, byte[] bytes) + public static boolean classExtends(String name, String superclass, byte[] bytes) { - if(!knownClasses.contains(clazz)) - new ClassHeirachyManager().transform(clazz, clazz, bytes); + name = toKey(name); + + if(!knownClasses.contains(name)) + new ClassHeirachyManager().transform(name, name, bytes); - return classExtends(clazz, superclass); + return classExtends(name, superclass); } public static boolean classExtends(String clazz, String superclass) @@ -58,33 +68,35 @@ public static boolean classExtends(String clazz, String superclass) return false; } - private static void declareClass(String clazz) + private static void declareClass(String name) { + name = toKey(name); + try { - if(!knownClasses.contains(clazz)) + if(!knownClasses.contains(name)) { try { - byte[] bytes = cl.getClassBytes(clazz); + byte[] bytes = cl.getClassBytes(name); if(bytes != null) - new ClassHeirachyManager().transform(clazz, clazz, bytes); + new ClassHeirachyManager().transform(name, name, bytes); } catch(Exception e) { } - if(!knownClasses.contains(clazz)) + if(!knownClasses.contains(name)) { - Class aclass = Class.forName(clazz); + Class aclass = Class.forName(name); - knownClasses.add(clazz); + knownClasses.add(name); if(aclass.isInterface()) - addSuperclass(clazz, "java.lang.Object"); + addSuperclass(name, "java.lang.Object"); else - addSuperclass(clazz, aclass.getSuperclass().getName()); + addSuperclass(name, aclass.getSuperclass().getName()); for(Class iclass : aclass.getInterfaces()) - addSuperclass(clazz, iclass.getName()); + addSuperclass(name, iclass.getName()); } } } @@ -119,11 +131,14 @@ private static void addSuperclass(String name, String superclass) supers.add(new ObfMapping(superclass.replace('.', '/')).toRuntime().javaClass()); } - public static String getSuperClass(String c) + public static String getSuperClass(String name, boolean runtime) { - declareClass(c); - if(!knownClasses.contains(c)) + name = toKey(name); + declareClass(name); + + if(!knownClasses.contains(name)) return "java.lang.Object"; - return superclasses.get(c).get(0); + + return superclasses.get(name).get(runtime ? 1 : 0); } } From d6f14e9ab1ca2163dc481bcdf6ec18ae9ca172a0 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Mon, 29 Jul 2013 22:53:29 +1000 Subject: [PATCH 010/219] Optimised ClassHeirachyManager --- codechicken/lib/asm/ClassHeirachyManager.java | 189 +++++++++++------- 1 file changed, 118 insertions(+), 71 deletions(-) diff --git a/codechicken/lib/asm/ClassHeirachyManager.java b/codechicken/lib/asm/ClassHeirachyManager.java index e5bf3d6..d04cb52 100644 --- a/codechicken/lib/asm/ClassHeirachyManager.java +++ b/codechicken/lib/asm/ClassHeirachyManager.java @@ -15,8 +15,36 @@ */ public class ClassHeirachyManager implements IClassTransformer { - public static HashSet knownClasses = new HashSet(); - public static HashMap> superclasses = new HashMap>(); + public static class SuperCache + { + String superclass; + public HashSet parents = new HashSet(); + private boolean flattened; + + public void add(String parent) + { + parents.add(parent); + } + + public void flatten() + { + if(flattened) + return; + + for(String s : new ArrayList(parents)) + { + SuperCache c = declareClass(s); + if(c != null) + { + c.flatten(); + parents.addAll(c.parents); + } + } + flattened = true; + } + } + + public static HashMap superclasses = new HashMap(); private static LaunchClassLoader cl = (LaunchClassLoader)ClassHeirachyManager.class.getClassLoader(); static @@ -27,7 +55,14 @@ public class ClassHeirachyManager implements IClassTransformer public static String toKey(String name) { if(ObfMapping.obfuscated) - name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/','.'); + name = FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.'); + return name; + } + + public static String unKey(String name) + { + if(ObfMapping.obfuscated) + name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); return name; } @@ -38,107 +73,119 @@ public static String toKey(String name) * @param bytes The bytes for the class. Only needed if not already defined. * @return */ - public static boolean classExtends(String name, String superclass, byte[] bytes) + public static boolean classExtends(String name, String superclass) { name = toKey(name); + superclass = toKey(superclass); - if(!knownClasses.contains(name)) - new ClassHeirachyManager().transform(name, name, bytes); - - return classExtends(name, superclass); - } - - public static boolean classExtends(String clazz, String superclass) - { - if(clazz.equals(superclass)) + if(name.equals(superclass)) return true; - if(clazz.equals("java.lang.Object")) + SuperCache cache = declareClass(name); + if(cache == null)//just can't handle this return false; - declareClass(clazz); - - if(!superclasses.containsKey(clazz))//just can't handle this - return false; - - for(String s : superclasses.get(clazz)) - if(classExtends(s, superclass)) - return true; - - return false; + cache.flatten(); + return cache.parents.contains(superclass); } - private static void declareClass(String name) + private static SuperCache declareClass(String name) { name = toKey(name); + SuperCache cache = superclasses.get(name); + + if(cache != null) + return cache; try { - if(!knownClasses.contains(name)) - { - try - { - byte[] bytes = cl.getClassBytes(name); - if(bytes != null) - new ClassHeirachyManager().transform(name, name, bytes); - } - catch(Exception e) - { - } - - if(!knownClasses.contains(name)) - { - Class aclass = Class.forName(name); - - knownClasses.add(name); - if(aclass.isInterface()) - addSuperclass(name, "java.lang.Object"); - else - addSuperclass(name, aclass.getSuperclass().getName()); - for(Class iclass : aclass.getInterfaces()) - addSuperclass(name, iclass.getName()); - } - } + byte[] bytes = cl.getClassBytes(unKey(name)); + if(bytes != null) + cache = declareASM(bytes); + } + catch(Exception e) + { + } + + if(cache != null) + return cache; + + + try + { + cache = declareReflection(name); } catch(ClassNotFoundException e) { } + + return cache; + } + + private static SuperCache declareReflection(String name) throws ClassNotFoundException + { + Class aclass = Class.forName(name); + + SuperCache cache = getOrCreateCache(name); + if(aclass.isInterface()) + cache.superclass = "java.lang.Object"; + else if(name.equals("java.lang.Object")) + return cache; + else + cache.superclass = toKey(aclass.getSuperclass().getName()); + + cache.add(cache.superclass); + for(Class iclass : aclass.getInterfaces()) + cache.add(toKey(iclass.getName())); + + return cache; + } + + private static SuperCache declareASM(byte[] bytes) + { + ClassNode node = ASMHelper.createClassNode(bytes); + String name = toKey(node.name); + + SuperCache cache = getOrCreateCache(name); + cache.superclass = toKey(node.superName.replace('/', '.')); + cache.add(cache.superclass); + for(String iclass : node.interfaces) + cache.add(toKey(iclass.replace('/', '.'))); + + return cache; } @Override public byte[] transform(String name, String tname, byte[] bytes) { - if (bytes == null) return null; - if(!knownClasses.contains(name)) - { - ClassNode node = ASMHelper.createClassNode(bytes); - - knownClasses.add(name); - addSuperclass(name, node.superName.replace('/', '.')); - for(String iclass : node.interfaces) - addSuperclass(name, iclass.replace('/', '.')); - } + if (bytes == null) + return null; + + if(!superclasses.containsKey(tname)) + declareASM(bytes); return bytes; } - - private static void addSuperclass(String name, String superclass) + + public static SuperCache getOrCreateCache(String name) { - ArrayList supers = superclasses.get(name); - if(supers == null) - superclasses.put(name, supers = new ArrayList()); - supers.add(superclass); - supers.add(new ObfMapping(superclass.replace('.', '/')).toRuntime().javaClass()); + SuperCache cache = superclasses.get(name); + if(cache == null) + superclasses.put(name, cache = new SuperCache()); + return cache; } public static String getSuperClass(String name, boolean runtime) { name = toKey(name); - declareClass(name); - - if(!knownClasses.contains(name)) + SuperCache cache = declareClass(name); + if(cache == null) return "java.lang.Object"; - return superclasses.get(name).get(runtime ? 1 : 0); + cache.flatten(); + String s = cache.superclass; + if(!runtime) + s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s); + return s; } } From 16704eb60181c293f484602fd5951eb20e10f257 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 30 Jul 2013 16:17:40 +1000 Subject: [PATCH 011/219] changed drawOutlinedBoundingBox to drawCuboidOutline accepting Cuboid6 Added expand function to Cuboid6 Renamed transform to apply on Cuboid6 --- codechicken/lib/render/RenderUtils.java | 44 ++++++++++++++----------- codechicken/lib/vec/Cuboid6.java | 18 ++++++++++ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 0ccc668..a73afb3 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -102,32 +102,38 @@ public static void translateToWorldCoords(Entity entity, float frame) GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ); } - public static void drawOutlinedBoundingBox(AxisAlignedBB par1AxisAlignedBB) + @Deprecated + public static void drawOutlinedBoundingBox(AxisAlignedBB aabb) + { + drawCuboidOutline(new Cuboid6(aabb)); + } + + public static void drawCuboidOutline(Cuboid6 c) { Tessellator var2 = Tessellator.instance; var2.startDrawing(3); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); + var2.addVertex(c.min.x, c.min.y, c.min.z); + var2.addVertex(c.max.x, c.min.y, c.min.z); + var2.addVertex(c.max.x, c.min.y, c.max.z); + var2.addVertex(c.min.x, c.min.y, c.max.z); + var2.addVertex(c.min.x, c.min.y, c.min.z); var2.draw(); var2.startDrawing(3); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); + var2.addVertex(c.min.x, c.max.y, c.min.z); + var2.addVertex(c.max.x, c.max.y, c.min.z); + var2.addVertex(c.max.x, c.max.y, c.max.z); + var2.addVertex(c.min.x, c.max.y, c.max.z); + var2.addVertex(c.min.x, c.max.y, c.min.z); var2.draw(); var2.startDrawing(1); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.minZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.maxX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.minY, par1AxisAlignedBB.maxZ); - var2.addVertex(par1AxisAlignedBB.minX, par1AxisAlignedBB.maxY, par1AxisAlignedBB.maxZ); + var2.addVertex(c.min.x, c.min.y, c.min.z); + var2.addVertex(c.min.x, c.max.y, c.min.z); + var2.addVertex(c.max.x, c.min.y, c.min.z); + var2.addVertex(c.max.x, c.max.y, c.min.z); + var2.addVertex(c.max.x, c.min.y, c.max.z); + var2.addVertex(c.max.x, c.max.y, c.max.z); + var2.addVertex(c.min.x, c.min.y, c.max.z); + var2.addVertex(c.min.x, c.max.y, c.max.z); var2.draw(); } diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index c31d83e..237504f 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -61,6 +61,18 @@ public Cuboid6 sub(Vector3 vec) max.subtract(vec); return this; } + + public Cuboid6 expand(double d) + { + return expand(new Vector3(d, d, d)); + } + + public Cuboid6 expand(Vector3 vec) + { + min.sub(vec); + max.add(vec); + return this; + } public void setBlockBounds(Block block) { @@ -123,7 +135,13 @@ public Cuboid6 enclose(Cuboid6 c) return this; } + @Deprecated public Cuboid6 transform(Transformation t) + { + return apply(t); + } + + public Cuboid6 apply(Transformation t) { t.apply(min); t.apply(max); From 57bcf384d17e7fbbacaf26594249a3d4c5603940 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 31 Jul 2013 11:10:44 +1000 Subject: [PATCH 012/219] Fixed uv mappings for some sides in CCModel.generateBlock --- codechicken/lib/render/CCModel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index e688251..076f4ed 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -184,8 +184,8 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x1, y2, z2, u1, v2); //east face - u1 = x1+4; v1 = 1-y2; - u2 = x2+4; v2 = 1-y1; + u1 = 1-x1+4; v1 = 1-y2; + u2 = 1-x2+4; v2 = 1-y1; verts[i++] = new Vertex5(x1, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x2, y2, z1, u2, v1); @@ -208,8 +208,8 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x1, y1, z1, u1, v2); //south face - u1 = z1+10; v1 = 1-y2; - u2 = z2+10; v2 = 1-y1; + u1 = 1-z1+10; v1 = 1-y2; + u2 = 1-z2+10; v2 = 1-y1; verts[i++] = new Vertex5(x2, y1, z1, u1, v2); verts[i++] = new Vertex5(x2, y2, z1, u1, v1); verts[i++] = new Vertex5(x2, y2, z2, u2, v1); From a1433ba4d4cbd326ce243468d54e509b99dec90c Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 31 Jul 2013 13:28:35 +1000 Subject: [PATCH 013/219] Added set function to Colour --- codechicken/lib/colour/Colour.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index c1fc27c..1fa4ff7 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -136,4 +136,12 @@ public int rgba() { return (r & 0xFF) << 24 | (g & 0xFF) << 16 | (b & 0xFF) << 8 | (a & 0xFF); } + + public Colour set(Colour colour) + { + r = colour.r; + g = colour.g; + b = colour.b; + a = colour.a; + } } From 15d0edcafb64365e25f21784ad6cfb99f824053d Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 31 Jul 2013 13:30:01 +1000 Subject: [PATCH 014/219] Amend typo --- codechicken/lib/colour/Colour.java | 1 + 1 file changed, 1 insertion(+) diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index 1fa4ff7..83a95c0 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -143,5 +143,6 @@ public Colour set(Colour colour) g = colour.g; b = colour.b; a = colour.a; + return this; } } From b16ad2115b02c6b787de10bde4670e61f4fd666c Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 2 Aug 2013 01:21:08 +1000 Subject: [PATCH 015/219] Added RenderUtils.renderLiquidGauge --- codechicken/lib/render/RenderUtils.java | 69 +++++++++++++++++++++---- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index a73afb3..6021334 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -6,6 +6,7 @@ import org.lwjgl.opengl.GL11; import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Rectangle4i; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; @@ -47,8 +48,14 @@ public boolean shouldBob() entityItem = new EntityItem(null); entityItem.hoverStart = 0; } - + + @Deprecated public static void renderLiquidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) + { + renderFluidQuad(point1, point2, point3, point4, icon, res); + } + + public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) { double u1 = icon.getMinU(); double du = icon.getMaxU()-icon.getMinU(); @@ -137,39 +144,45 @@ public static void drawCuboidOutline(Cuboid6 c) var2.draw(); } + @Deprecated public static void renderLiquidCuboid(Cuboid6 bound, Icon tex, double res) { - renderLiquidQuad(//bottom + renderFluidCuboid(bound, tex, res); + } + + public static void renderFluidCuboid(Cuboid6 bound, Icon tex, double res) + { + renderFluidQuad(//bottom new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), tex, res); - renderLiquidQuad(//top + renderFluidQuad(//top new Vector3(bound.min.x, bound.max.y, bound.min.z), new Vector3(bound.min.x, bound.max.y, bound.max.z), new Vector3(bound.max.x, bound.max.y, bound.max.z), new Vector3(bound.max.x, bound.max.y, bound.min.z), tex, res); - renderLiquidQuad(//-x + renderFluidQuad(//-x new Vector3(bound.min.x, bound.max.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), new Vector3(bound.min.x, bound.max.y, bound.max.z), tex, res); - renderLiquidQuad(//+x + renderFluidQuad(//+x new Vector3(bound.max.x, bound.max.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.max.y, bound.min.z), tex, res); - renderLiquidQuad(//-z + renderFluidQuad(//-z new Vector3(bound.max.x, bound.max.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.min.x, bound.max.y, bound.min.z), tex, res); - renderLiquidQuad(//+z + renderFluidQuad(//+z new Vector3(bound.min.x, bound.max.y, bound.max.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), @@ -222,8 +235,14 @@ public static void renderBlockOverlaySide(int x, int y, int z, int side, double break; } } - + + @Deprecated public static boolean shouldRenderLiquid(FluidStack stack) + { + return shouldRenderFluid(stack); + } + + public static boolean shouldRenderFluid(FluidStack stack) { return stack.amount > 0 && stack.getFluid() != null; } @@ -252,6 +271,12 @@ public static void postFluidRender() GL11.glEnable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_BLEND); } + + @Deprecated + public static void renderLiquidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) + { + renderFluidCuboid(stack, bound, density, res); + } /** * Renders a fluid within a bounding box. @@ -263,7 +288,7 @@ public static void postFluidRender() * @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids this determines the height. * @param res The resolution to render at. */ - public static void renderLiquidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) + public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { if(!shouldRenderLiquid(stack)) return; @@ -281,6 +306,32 @@ public static void renderLiquidCuboid(FluidStack stack, Cuboid6 bound, double de postFluidRender(); } + public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) + { + if(!shouldRenderLiquid(stack)) + return; + + int alpha = 255; + if(stack.getFluid().isGaseous()) + alpha = (int) (density*255); + else + { + int height = (int) (rect.h*density); + rect.y +=rect.h-height; + rect.h = height; + } + + Icon tex = prepareFluidRender(stack, alpha); + CCRenderState.startDrawing(7); + renderLiquidQuad( + new Vector3(rect.x, rect.y, 0), + new Vector3(rect.x, rect.y+rect.h, 0), + new Vector3(rect.x+rect.w, rect.y+rect.h, 0), + new Vector3(rect.x+rect.w, rect.y, 0), tex, res); + CCRenderState.draw(); + postFluidRender(); + } + public static void renderItemUniform(ItemStack item) { IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, ENTITY); From 5184abc23cb740e800a9afe7df59b10c54b37f43 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 2 Aug 2013 02:04:19 +1000 Subject: [PATCH 016/219] Made alpha a power function of density for gases to produce better visuals for low densities. --- codechicken/lib/render/RenderUtils.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 6021334..581ccc3 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -277,6 +277,11 @@ public static void renderLiquidCuboid(FluidStack stack, Cuboid6 bound, double de { renderFluidCuboid(stack, bound, density, res); } + + public static double fluidDensityToAlpha(double density) + { + return Math.pow(density, 0.4); + } /** * Renders a fluid within a bounding box. @@ -295,7 +300,7 @@ public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double den int alpha = 255; if(stack.getFluid().isGaseous()) - alpha = (int) (density*255); + alpha = (int) (fluidDensityToAlpha(density)*255); else bound.max.y = bound.min.y+(bound.max.y-bound.min.y)*density; @@ -313,7 +318,7 @@ public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double d int alpha = 255; if(stack.getFluid().isGaseous()) - alpha = (int) (density*255); + alpha = (int) (fluidDensityToAlpha(density)*255); else { int height = (int) (rect.h*density); From 56776c8149a193eb6636eb4e3efb0d34c439732a Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 2 Aug 2013 12:02:01 +1000 Subject: [PATCH 017/219] Fix NPE in RayTracer when tracing a null block. --- codechicken/lib/raytracer/RayTracer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 1526ebb..5337d95 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -160,11 +160,15 @@ public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List Date: Mon, 5 Aug 2013 08:23:26 +1000 Subject: [PATCH 018/219] Acquire NetClientHandler for packets sent before the Player and World are established. --- codechicken/lib/packet/PacketCustom.java | 54 +++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index 73e6235..49a2b9d 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -14,6 +14,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.common.network.FMLNetworkHandler; +import cpw.mods.fml.common.network.IConnectionHandler; import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.ITinyPacketHandler; import cpw.mods.fml.common.network.NetworkModHandler; @@ -28,10 +29,12 @@ import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.INetworkManager; +import net.minecraft.network.NetLoginHandler; import net.minecraft.network.NetServerHandler; import net.minecraft.network.packet.NetHandler; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.Packet131MapData; +import net.minecraft.network.packet.Packet1Login; import net.minecraft.network.packet.Packet250CustomPayload; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.PlayerInstance; @@ -148,6 +151,7 @@ private static class ClientPacketHandler extends CustomPacketHandler public ClientPacketHandler(String channel) { super(channel); + NetClientHandlerHelper.register(); } @Override @@ -159,7 +163,7 @@ public Side getSide() @Override public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) { - ((IClientPacketHandler)handler).handlePacket(packet, Minecraft.getMinecraft().getNetHandler(), Minecraft.getMinecraft()); + ((IClientPacketHandler)handler).handlePacket(packet, NetClientHandlerHelper.handler, Minecraft.getMinecraft()); } } @@ -254,6 +258,54 @@ else if(handler instanceof IServerPacketHandler) } } + private static class NetClientHandlerHelper implements IConnectionHandler + { + private static boolean registered = false; + public static NetClientHandler handler; + + public static void register() + { + if(registered) + return; + + NetworkRegistry.instance().registerConnectionHandler(new NetClientHandlerHelper()); + registered = true; + } + + @Override + public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) + { + handler = (NetClientHandler) netClientHandler; + } + + @Override + public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) + { + handler = (NetClientHandler) netClientHandler; + } + + @Override + public void connectionClosed(INetworkManager manager) + { + } + + @Override + public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) + { + return null; + } + + @Override + public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) + { + } + + @Override + public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) + { + } + } + public static interface IPacketCarrier { public int readType(Packet packet); From 4bd5aab59a95446489022f751a9d314312f190a5 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Thu, 8 Aug 2013 19:16:06 +1000 Subject: [PATCH 019/219] Fixed packet compression and splitting on TCP connections. --- codechicken/lib/packet/MetaPacket.java | 39 ++++++++++++++++++++++-- codechicken/lib/packet/PacketCustom.java | 7 +++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/codechicken/lib/packet/MetaPacket.java b/codechicken/lib/packet/MetaPacket.java index cff1474..c29a7ee 100644 --- a/codechicken/lib/packet/MetaPacket.java +++ b/codechicken/lib/packet/MetaPacket.java @@ -3,18 +3,45 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; +import java.util.Map; + +import codechicken.lib.asm.ObfMapping; import net.minecraft.network.packet.NetHandler; import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.Packet250CustomPayload; -public class MetaPacket extends Packet +/** + * A class that facilitates sending of multiple packets one after the other. + * It first sends an empty 250 packet and then it's payloads. + */ +public class MetaPacket extends Packet250CustomPayload { + static + { + try + { + String fieldName = new ObfMapping("net/minecraft/network/packet/Packet", "packetClassToIdMap", "Ljava/util/Map;").toRuntime().s_name; + Field field = Packet.class.getDeclaredField(fieldName); + field.setAccessible(true); + Map, Integer> packetClassToIdMap = (Map, Integer>) field.get(null); + packetClassToIdMap.put(MetaPacket.class, 250); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + } + public ArrayList packets = new ArrayList(); public MetaPacket(Packet... packets) { + super("", null); + for(Packet p : packets) this.packets.add(p); } @@ -33,8 +60,14 @@ public void readPacketData(DataInput datain) @Override public void writePacketData(DataOutput dataout) throws IOException { + //send a dummy 250 + super.writePacketData(dataout); + for(Packet p : packets) - p.writePacketData(dataout); + Packet.writePacket(p, dataout); + + //adjust sent size for Packet.writePacket + Packet.sentSize-=getPacketSize()-super.getPacketSize(); } @Override @@ -49,7 +82,7 @@ public int getPacketSize() { int size = 0; for(Packet p : packets) - size+=p.getPacketSize(); + size+=p.getPacketSize()+1; return size; } } diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index 49a2b9d..17a8265 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -501,15 +501,18 @@ private byte[] compress(byte[] data) { deflater.setInput(data, 0, data.length); deflater.finish(); - byte[] cdata = new byte[data.length+4]; - int clen = deflater.deflate(cdata, 4, data.length); + byte[] cbuf = new byte[data.length]; + int clen = deflater.deflate(cbuf, 0, data.length); if(clen == data.length || !deflater.finished())//not worth compressing, gets larger { type &= 0x7F; return data; } + byte[] cdata = new byte[clen+4]; writeInt(cdata, 0, data.length); + System.arraycopy(cbuf, 0, cdata, 4, clen); + type|=0x80; return cdata; } catch(Exception e) From 575ec570500e2100a016ea47a1bee355de7dd36a Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Mon, 12 Aug 2013 13:30:54 +1000 Subject: [PATCH 020/219] Added apply methods to some common Vector containers Added ColourMultiplier vertex modifier. --- codechicken/lib/render/CCModel.java | 10 +++++- codechicken/lib/render/ColourMultiplier.java | 34 ++++++++++++++++++++ codechicken/lib/render/UVScale.java | 5 +++ codechicken/lib/render/Vertex5.java | 13 ++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 codechicken/lib/render/ColourMultiplier.java diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 076f4ed..a65fa96 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -325,7 +325,7 @@ public CCModel smoothNormals() public CCModel apply(Transformation t) { for(int k = 0; k < verts.length; k++) - t.apply(verts[k].vec); + verts[k].apply(t); if(normals != null) for(int k = 0; k < normals.length; k++) @@ -333,6 +333,14 @@ public CCModel apply(Transformation t) return this; } + + public CCModel apply(IUVTransformation uvt) + { + for(int k = 0; k < verts.length; k++) + verts[k].apply(uvt); + + return this; + } public void render() { diff --git a/codechicken/lib/render/ColourMultiplier.java b/codechicken/lib/render/ColourMultiplier.java new file mode 100644 index 0000000..d672ff3 --- /dev/null +++ b/codechicken/lib/render/ColourMultiplier.java @@ -0,0 +1,34 @@ +package codechicken.lib.render; + +import net.minecraft.client.renderer.Tessellator; +import codechicken.lib.colour.Colour; +import codechicken.lib.colour.ColourRGBA; +import codechicken.lib.vec.Vector3; + +public class ColourMultiplier implements IVertexModifier +{ + public Colour colour; + + public ColourMultiplier(Colour colour) + { + this.colour = colour; + } + + public ColourMultiplier(int colour) + { + this(new ColourRGBA(colour)); + } + + @Override + public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) + { + if(CCRenderState.useModelColours() && m != null && m.colours != null) + CCRenderState.vertexColour(new ColourRGBA(m.colours[i]).multiply(colour).rgba()); + } + + @Override + public boolean needsNormals() + { + return false; + } +} diff --git a/codechicken/lib/render/UVScale.java b/codechicken/lib/render/UVScale.java index 4c948c4..3abdce0 100644 --- a/codechicken/lib/render/UVScale.java +++ b/codechicken/lib/render/UVScale.java @@ -11,6 +11,11 @@ public UVScale(double scaleu, double scalev) sv = scalev; } + public UVScale(double d) + { + this(d, d); + } + @Override public void transform(UV uv) { diff --git a/codechicken/lib/render/Vertex5.java b/codechicken/lib/render/Vertex5.java index 1edfe5b..4c6780b 100644 --- a/codechicken/lib/render/Vertex5.java +++ b/codechicken/lib/render/Vertex5.java @@ -4,6 +4,7 @@ import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; public class Vertex5 @@ -54,4 +55,16 @@ public String toString() MathContext cont = new MathContext(4, RoundingMode.HALF_UP); return "Vertex: ("+new BigDecimal(vec.x, cont)+", "+new BigDecimal(vec.y, cont)+", "+new BigDecimal(vec.z, cont)+") ("+new BigDecimal(uv.u, cont)+", "+new BigDecimal(uv.v, cont)+")"; } + + public Vertex5 apply(Transformation t) + { + vec.apply(t); + return this; + } + + public Vertex5 apply(IUVTransformation t) + { + uv.apply(t); + return this; + } } From 3d4e11255280b3b16160f0d23b57b9f579136817 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Thu, 15 Aug 2013 22:02:58 +1000 Subject: [PATCH 021/219] Refactored generateRotatedPart to apply --- codechicken/lib/render/CCModel.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index a65fa96..4b44b88 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -841,26 +841,25 @@ public CCModel generateSidedPartsH(int side, Vector3 point) */ public CCModel generateSidedPart(int side1, int side2, Vector3 point, int srcpos, int destpos, int length) { - return generateRotatedPart(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]), point, srcpos, destpos, length); + return apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point), srcpos, destpos, length); } /** * Generates a rotated copy of verts into this model */ - public CCModel generateRotatedPart(Transformation t, Vector3 point, int srcpos, int destpos, int length) + public CCModel apply(Transformation t, int srcpos, int destpos, int length) { for(int k = 0; k < length; k++) { verts[destpos+k] = verts[srcpos+k].copy(); - verts[destpos+k].vec - .subtract(point) - .apply(t) - .add(point); + verts[destpos+k].vec.apply(t); } if(normals != null) - for(int k = 0; k < length; k++) - normals[destpos+k] = normals[srcpos+k].copy().apply(t); + for(int k = 0; k < length; k++) { + normals[destpos+k] = normals[srcpos+k].copy(); + t.applyN(normals[destpos+k]); + } return this; } From 2636721becdd45be7373f73ac6bea2228ac57f82 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 21 Aug 2013 23:32:16 +1000 Subject: [PATCH 022/219] Added mask to CCModel.generateBlock Fixed misleading variable name in MultiIconTransformation.setIconIndex --- codechicken/lib/render/CCModel.java | 108 ++++++++++-------- .../lib/render/MultiIconTransformation.java | 4 +- 2 files changed, 62 insertions(+), 50 deletions(-) diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 4b44b88..7e16e71 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -152,6 +152,11 @@ public CCModel generateBlock(int i, Cuboid6 bounds) return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z); } + public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) + { + return generateBlock(i, x1, y1, z1, x2, y2, z2, 0); + } + /** * Generates a box, uv mapped to be the same as a minecraft block with the same bounds * @param i The vertex index to start generating at @@ -161,59 +166,66 @@ public CCModel generateBlock(int i, Cuboid6 bounds) * @param x2 maxX * @param y2 maxY * @param z2 maxZ + * @param mask A bitmask of sides NOT to generate. I high bit at index s means side s will not be generated * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. */ - public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) + public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2, int mask) { double u1, v1, u2, v2; - //bottom face - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; - verts[i++] = new Vertex5(x1, y1, z2, u1, v2); - verts[i++] = new Vertex5(x1, y1, z1, u1, v1); - verts[i++] = new Vertex5(x2, y1, z1, u2, v1); - verts[i++] = new Vertex5(x2, y1, z2, u2, v2); - - //top face - u1 = x1+2; v1 = z1; - u2 = x2+2; v2 = z2; - verts[i++] = new Vertex5(x2, y2, z2, u2, v2); - verts[i++] = new Vertex5(x2, y2, z1, u2, v1); - verts[i++] = new Vertex5(x1, y2, z1, u1, v1); - verts[i++] = new Vertex5(x1, y2, z2, u1, v2); - - //east face - u1 = 1-x1+4; v1 = 1-y2; - u2 = 1-x2+4; v2 = 1-y1; - verts[i++] = new Vertex5(x1, y1, z1, u1, v2); - verts[i++] = new Vertex5(x1, y2, z1, u1, v1); - verts[i++] = new Vertex5(x2, y2, z1, u2, v1); - verts[i++] = new Vertex5(x2, y1, z1, u2, v2); - - //west face - u1 = x1+6; v1 = 1-y2; - u2 = x2+6; v2 = 1-y1; - verts[i++] = new Vertex5(x2, y1, z2, u2, v2); - verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - verts[i++] = new Vertex5(x1, y2, z2, u1, v1); - verts[i++] = new Vertex5(x1, y1, z2, u1, v2); - - //north face - u1 = z1+8; v1 = 1-y2; - u2 = z2+8; v2 = 1-y1; - verts[i++] = new Vertex5(x1, y1, z2, u2, v2); - verts[i++] = new Vertex5(x1, y2, z2, u2, v1); - verts[i++] = new Vertex5(x1, y2, z1, u1, v1); - verts[i++] = new Vertex5(x1, y1, z1, u1, v2); - - //south face - u1 = 1-z1+10; v1 = 1-y2; - u2 = 1-z2+10; v2 = 1-y1; - verts[i++] = new Vertex5(x2, y1, z1, u1, v2); - verts[i++] = new Vertex5(x2, y2, z1, u1, v1); - verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + if((mask&1) == 0) {//bottom face + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + verts[i++] = new Vertex5(x1, y1, z1, u1, v1); + verts[i++] = new Vertex5(x2, y1, z1, u2, v1); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + } + + if((mask&2) == 0) {//top face + u1 = x1+2; v1 = z1; + u2 = x2+2; v2 = z2; + verts[i++] = new Vertex5(x2, y2, z2, u2, v2); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x1, y2, z2, u1, v2); + } + + if((mask&4) == 0) {//east face + u1 = 1-x1+4; v1 = 1-y2; + u2 = 1-x2+4; v2 = 1-y1; + verts[i++] = new Vertex5(x1, y1, z1, u1, v2); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1); + verts[i++] = new Vertex5(x2, y1, z1, u2, v2); + } + + if((mask&8) == 0) {//west face + u1 = x1+6; v1 = 1-y2; + u2 = x2+6; v2 = 1-y1; + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1); + verts[i++] = new Vertex5(x1, y2, z2, u1, v1); + verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + } + + if((mask&0x10) == 0) {//north face + u1 = z1+8; v1 = 1-y2; + u2 = z2+8; v2 = 1-y1; + verts[i++] = new Vertex5(x1, y1, z2, u2, v2); + verts[i++] = new Vertex5(x1, y2, z2, u2, v1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1); + verts[i++] = new Vertex5(x1, y1, z1, u1, v2); + } + + if((mask&0x20) == 0) {//south face + u1 = 1-z1+10; v1 = 1-y2; + u2 = 1-z2+10; v2 = 1-y1; + verts[i++] = new Vertex5(x2, y1, z1, u1, v2); + verts[i++] = new Vertex5(x2, y2, z1, u1, v1); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + } return this; } diff --git a/codechicken/lib/render/MultiIconTransformation.java b/codechicken/lib/render/MultiIconTransformation.java index e9ed9a2..34352fc 100644 --- a/codechicken/lib/render/MultiIconTransformation.java +++ b/codechicken/lib/render/MultiIconTransformation.java @@ -28,9 +28,9 @@ public static CCModel setIconIndex(CCModel m, int index) return setIconIndex(m, 0, m.verts.length, index); } - public static CCModel setIconIndex(CCModel m, int start, int length, int index) + public static CCModel setIconIndex(CCModel m, int start, int end, int index) { - for(int k = start; k < length; k++) + for(int k = start; k < end; k++) { UV uv = m.verts[k].uv; uv.u = uv.u%2+index*2; From a580ca90a9434aa16e6e8c14552907c2cf405341 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 23 Aug 2013 17:30:37 +1000 Subject: [PATCH 023/219] Add standard planar light model --- codechicken/lib/lighting/PlanarLightModel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codechicken/lib/lighting/PlanarLightModel.java b/codechicken/lib/lighting/PlanarLightModel.java index cd81b1c..f6f5b51 100644 --- a/codechicken/lib/lighting/PlanarLightModel.java +++ b/codechicken/lib/lighting/PlanarLightModel.java @@ -14,6 +14,8 @@ */ public class PlanarLightModel implements IVertexModifier { + public static PlanarLightModel standardLightModel = LightModel.standardLightModel.reducePlanar(); + public ColourRGBA[] colours; public PlanarLightModel(int[] colours) From 9601c27e9d1117ae5caaf082022c43bf5059acfa Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 23 Aug 2013 17:49:00 +1000 Subject: [PATCH 024/219] Add some TransformationList compacting. --- codechicken/lib/vec/TransformationList.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/vec/TransformationList.java b/codechicken/lib/vec/TransformationList.java index 2b7520f..c76e726 100644 --- a/codechicken/lib/vec/TransformationList.java +++ b/codechicken/lib/vec/TransformationList.java @@ -69,7 +69,20 @@ public void apply(Matrix4 mat) public TransformationList with(Transformation t) { mat = null;//matrix invalid - transformations.add(t); + if(t instanceof TransformationList) + transformations.addAll(((TransformationList)t).transformations); + else + transformations.add(t); + return this; + } + + public TransformationList prepend(Transformation t) + { + mat = null;//matrix invalid + if(t instanceof TransformationList) + transformations.addAll(0, ((TransformationList)t).transformations); + else + transformations.add(0, t); return this; } From 094184522758e376d1588c19148648e0eef8b44e Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 27 Aug 2013 15:27:10 +1000 Subject: [PATCH 025/219] Simplify MultiIconTransformation constructor with vaargs --- codechicken/lib/render/MultiIconTransformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codechicken/lib/render/MultiIconTransformation.java b/codechicken/lib/render/MultiIconTransformation.java index 34352fc..ea6e4e3 100644 --- a/codechicken/lib/render/MultiIconTransformation.java +++ b/codechicken/lib/render/MultiIconTransformation.java @@ -9,7 +9,7 @@ public class MultiIconTransformation implements IUVTransformation { public Icon[] icons; - public MultiIconTransformation(Icon[] icons) + public MultiIconTransformation(Icon... icons) { this.icons = icons; } From 5ef9f6174d55ae3668b735430b13669b0c2b836c Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Thu, 29 Aug 2013 11:10:33 +1000 Subject: [PATCH 026/219] Add transformation compacting. --- codechicken/lib/raytracer/RayTracer.java | 42 +++++++++++-- codechicken/lib/vec/Rotation.java | 16 +++++ codechicken/lib/vec/Scale.java | 13 ++++ codechicken/lib/vec/Transformation.java | 10 +++- codechicken/lib/vec/TransformationList.java | 48 ++++++++++++++- .../lib/vec/TranslatedTransformation.java | 60 ------------------- codechicken/lib/vec/Translation.java | 10 ++++ 7 files changed, 133 insertions(+), 66 deletions(-) delete mode 100644 codechicken/lib/vec/TranslatedTransformation.java diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 5337d95..7273d77 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -28,8 +28,19 @@ public class RayTracer private int s_side; private IndexedCuboid6 c_cuboid; + @Deprecated//not threadsafe public static RayTracer instance = new RayTracer(); + private static ThreadLocal t_inst = new ThreadLocal(); + + public static RayTracer instance() + { + RayTracer inst = t_inst.get(); + if(inst == null) + t_inst.set(inst = new RayTracer()); + return inst; + } + private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) { vec.set(start); @@ -133,7 +144,7 @@ public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids, BlockCoord pos, Block block, List hitList) + { + for(IndexedCuboid6 cuboid : cuboids) + { + MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); + if(mop != null) + { + ExtendedMOP emop = new ExtendedMOP(mop, cuboid.data, s_dist); + emop.typeOfHit = EnumMovingObjectType.TILE; + emop.blockX = pos.x; + emop.blockY = pos.y; + emop.blockZ = pos.z; + hitList.add(emop); + } + } + } + public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) { Block block = Block.blocksList[world.getBlockId(x, y, z)]; if(block == null) return null; - - Vec3 headVec = Vec3.createVectorHelper(player.posX, (player.posY + 1.62) - player.yOffset, player.posZ); + + Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1.0F); double reach = world.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player); Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); @@ -189,9 +217,15 @@ public static MovingObjectPosition reTrace(World world, EntityPlayer player) public static MovingObjectPosition reTrace(World world, EntityPlayer player, double reach) { - Vec3 headVec = Vec3.createVectorHelper(player.posX, (player.posY + 1.62) - player.yOffset, player.posZ); + Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1); Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); return world.rayTraceBlocks_do_do(headVec, endVec, true, false); } + + public static Vec3 getCorrectedHeadVec(EntityPlayer player) + { + double d = player.worldObj.isRemote ? 0 : (player instanceof EntityPlayerMP && player.isSneaking() ? 1.54 : 1.62); + return Vec3.createVectorHelper(player.posX, player.posY + d, player.posZ); + } } diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java index 6b9ed15..66503a6 100644 --- a/codechicken/lib/vec/Rotation.java +++ b/codechicken/lib/vec/Rotation.java @@ -227,6 +227,22 @@ public Transformation inverse() { return new Rotation(-angle, axis); } + + @Override + public Transformation merge(Transformation next) { + if(next instanceof Rotation) { + Rotation r = (Rotation)next; + if(r.axis.equalsT(axis)) { + double d = angle+r.angle; + if(d == 0) + return new RedundantTransformation(); + + return new Rotation(angle, axis); + } + } + + return null; + } @Override public String toString() diff --git a/codechicken/lib/vec/Scale.java b/codechicken/lib/vec/Scale.java index 55c8dcd..889af8c 100644 --- a/codechicken/lib/vec/Scale.java +++ b/codechicken/lib/vec/Scale.java @@ -58,6 +58,19 @@ public Transformation inverse() return new Scale(1/factor.x, 1/factor.y, 1/factor.z); } + @Override + public Transformation merge(Transformation next) { + if(next instanceof Scale) { + Vector3 vec = factor.copy().multiply(((Scale) next).factor); + if(vec.equalsT(Vector3.one)) + return new RedundantTransformation(); + + return new Scale(vec); + } + + return null; + } + @Override public String toString() { diff --git a/codechicken/lib/vec/Transformation.java b/codechicken/lib/vec/Transformation.java index 512720d..9dcde27 100644 --- a/codechicken/lib/vec/Transformation.java +++ b/codechicken/lib/vec/Transformation.java @@ -32,7 +32,7 @@ public abstract class Transformation */ public Transformation at(Vector3 point) { - return new TranslatedTransformation(this, point); + return new TransformationList(new Translation(-point.x, -point.y, -point.z), this, point.translation()); } /** @@ -44,6 +44,14 @@ public TransformationList with(Transformation t) return new TransformationList(this, t); } + /** + * Returns a simplified transformation that performs this, followed by next. If such a transformation does not exist, returns null + */ + public Transformation merge(Transformation next) + { + return null; + } + @SideOnly(Side.CLIENT) public abstract void glApply(); diff --git a/codechicken/lib/vec/TransformationList.java b/codechicken/lib/vec/TransformationList.java index c76e726..3f150a7 100644 --- a/codechicken/lib/vec/TransformationList.java +++ b/codechicken/lib/vec/TransformationList.java @@ -1,6 +1,7 @@ package codechicken.lib.vec; import java.util.ArrayList; +import java.util.Iterator; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -13,7 +14,12 @@ public class TransformationList extends Transformation public TransformationList(Transformation... transforms) { for(Transformation t : transforms) - with(t); + if(t instanceof TransformationList) + transformations.addAll(((TransformationList)t).transformations); + else + transformations.add(t); + + compact(); } public Matrix4 compile() @@ -68,24 +74,64 @@ public void apply(Matrix4 mat) @Override public TransformationList with(Transformation t) { + if(t instanceof RedundantTransformation) + return this; + mat = null;//matrix invalid if(t instanceof TransformationList) transformations.addAll(((TransformationList)t).transformations); else transformations.add(t); + + compact(); return this; } public TransformationList prepend(Transformation t) { + if(t instanceof RedundantTransformation) + return this; + mat = null;//matrix invalid if(t instanceof TransformationList) transformations.addAll(0, ((TransformationList)t).transformations); else transformations.add(0, t); + + compact(); return this; } + private void compact() { + if(transformations.isEmpty()) + return; + + ArrayList newList = new ArrayList(transformations.size()); + Iterator iterator = transformations.iterator(); + Transformation prev = iterator.next(); + while(iterator.hasNext()) { + Transformation t = iterator.next(); + Transformation m = prev == null ? null : prev.merge(t); + if(m instanceof RedundantTransformation) { + prev = null; + } + else if(m != null) { + prev = m; + } + else { + newList.add(prev); + prev = t; + } + } + if(prev != null) + newList.add(prev); + + if(newList.size() < transformations.size()) { + transformations = newList; + mat = null; + } + } + @Override @SideOnly(Side.CLIENT) public void glApply() diff --git a/codechicken/lib/vec/TranslatedTransformation.java b/codechicken/lib/vec/TranslatedTransformation.java deleted file mode 100644 index babab60..0000000 --- a/codechicken/lib/vec/TranslatedTransformation.java +++ /dev/null @@ -1,60 +0,0 @@ -package codechicken.lib.vec; - -import org.lwjgl.opengl.GL11; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -public class TranslatedTransformation extends Transformation -{ - public Vector3 point; - public Transformation wrapped; - - public TranslatedTransformation(Transformation t, Vector3 vec) - { - point = vec; - wrapped = t; - } - - @Override - public void apply(Vector3 vec) - { - vec.subtract(point).apply(wrapped).add(point); - } - - @Override - public void applyN(Vector3 normal) - { - wrapped.applyN(normal); - } - - @Override - public void apply(Matrix4 mat) - { - mat.translate(point).apply(wrapped) - .translate(new Vector3(-point.x, -point.y, -point.z)); - } - - @Override - @SideOnly(Side.CLIENT) - public void glApply() - { - GL11.glTranslated(point.x, point.y, point.z); - wrapped.glApply(); - GL11.glTranslated(-point.x, -point.y, -point.z); - } - - @Override - public Transformation inverse() - { - return new TranslatedTransformation(wrapped.inverse(), point); - } - - @Override - public String toString() - { - return point.translation()+"\n"+ - wrapped.toString()+"\n"+ - new Translation(-point.x, -point.y, -point.z); - } -} diff --git a/codechicken/lib/vec/Translation.java b/codechicken/lib/vec/Translation.java index cceea44..9dde79e 100644 --- a/codechicken/lib/vec/Translation.java +++ b/codechicken/lib/vec/Translation.java @@ -59,6 +59,16 @@ public Transformation inverse() return new Translation(-vec.x, -vec.y, -vec.z); } + @Override + public Transformation merge(Transformation next) { + if(next instanceof Translation) { + Vector3 vec2 = vec.copy().add(((Translation) next).vec); + return vec2.isZero() ? new RedundantTransformation() : new Translation(vec2); + } + + return null; + } + @Override public String toString() { From c545683025fc6021cfee8b8f15bd84d146110825 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 4 Sep 2013 12:51:37 +1000 Subject: [PATCH 027/219] Added a few functions to BlockCoord Made RedundantTransformation more redundant --- codechicken/lib/vec/BlockCoord.java | 20 +++++++++++++++++++ .../lib/vec/RedundantTransformation.java | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java index 7c713d2..63952cc 100644 --- a/codechicken/lib/vec/BlockCoord.java +++ b/codechicken/lib/vec/BlockCoord.java @@ -177,4 +177,24 @@ public BlockCoord set(BlockCoord coord) { return set(coord.x, coord.y, coord.z); } + + public int toSide() + { + if(!isAxial()) return -1; + if(y < 0) return 0; + if(y > 0) return 1; + if(z < 0) return 2; + if(z > 0) return 3; + if(x < 0) return 4; + if(x > 0) return 5; + + return -1; + } + + public int absSum() + { + return (x < 0 ? -x : x) + + (y < 0 ? -y : y) + + (z < 0 ? -z : z); + } } diff --git a/codechicken/lib/vec/RedundantTransformation.java b/codechicken/lib/vec/RedundantTransformation.java index a803675..08842f6 100644 --- a/codechicken/lib/vec/RedundantTransformation.java +++ b/codechicken/lib/vec/RedundantTransformation.java @@ -30,6 +30,11 @@ public Transformation inverse() return this; } + @Override + public Transformation merge(Transformation next) { + return next; + } + @Override public String toString() { From c67c73164730872f1eaacf48fcf591e1a2037fbd Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 4 Sep 2013 13:05:24 +1000 Subject: [PATCH 028/219] Extend MOP for RayTracer depth sorting. --- codechicken/lib/raytracer/ExtendedMOP.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/codechicken/lib/raytracer/ExtendedMOP.java b/codechicken/lib/raytracer/ExtendedMOP.java index 5d81e43..029e19e 100644 --- a/codechicken/lib/raytracer/ExtendedMOP.java +++ b/codechicken/lib/raytracer/ExtendedMOP.java @@ -4,9 +4,10 @@ import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; -public class ExtendedMOP extends MovingObjectPosition +public class ExtendedMOP extends MovingObjectPosition implements Comparable { public Object data; + public double dist; public ExtendedMOP(Entity entity, Object data) { @@ -20,7 +21,7 @@ public ExtendedMOP(int x, int y, int z, int side, Vec3 hit, Object data) setData(data); } - public ExtendedMOP(MovingObjectPosition mop, Object data) + public ExtendedMOP(MovingObjectPosition mop, Object data, double dist) { super(0, 0, 0, 0, mop.hitVec); typeOfHit = mop.typeOfHit; @@ -30,6 +31,7 @@ public ExtendedMOP(MovingObjectPosition mop, Object data) sideHit = mop.sideHit; subHit = mop.subHit; setData(data); + this.dist = dist; } public void setData(Object data) @@ -47,4 +49,10 @@ public static T getData(MovingObjectPosition mop) return (T)Integer.valueOf(mop.subHit); } + + @Override + public int compareTo(ExtendedMOP o) + { + return dist == o.dist ? 0 : dist < o.dist ? -1 : 1; + } } From 5c5384f79ce3d2f6e79bba4f43a2057556fd7e76 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 4 Sep 2013 13:56:47 +1000 Subject: [PATCH 029/219] Update Forge Mappings. --- codechicken/lib/lang/LangUtil.java | 13 +++---- codechicken/lib/packet/PacketCustom.java | 2 +- codechicken/lib/render/CCModel.java | 4 +-- codechicken/lib/render/CCRenderState.java | 2 +- .../lib/render/SpriteSheetManager.java | 4 +-- codechicken/lib/render/TextureFX.java | 2 +- codechicken/lib/render/TextureSpecial.java | 34 +++++++++---------- codechicken/lib/render/TextureUtils.java | 4 +-- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/codechicken/lib/lang/LangUtil.java b/codechicken/lib/lang/LangUtil.java index 608c7f9..4c75980 100644 --- a/codechicken/lib/lang/LangUtil.java +++ b/codechicken/lib/lang/LangUtil.java @@ -77,14 +77,14 @@ public static LangUtil loadLangDir(String domain) public LangUtil addLangDir(ResourceLocation dir) { - ResourceManager resManager = Minecraft.getMinecraft().func_110442_L(); - for(Language lang : (SortedSet)Minecraft.getMinecraft().func_135016_M().func_135040_d()) + ResourceManager resManager = Minecraft.getMinecraft().getResourceManager(); + for(Language lang : (SortedSet)Minecraft.getMinecraft().getLanguageManager().getLanguages()) { - String langID = lang.func_135034_a(); + String langID = lang.getLanguageCode(); Resource langRes; try { - langRes = resManager.func_110536_a(new ResourceLocation(dir.func_110624_b(), dir.func_110623_a()+'/'+langID+".lang")); + langRes = resManager.getResource(new ResourceLocation(dir.getResourceDomain(), dir.getResourcePath()+'/'+langID+".lang")); } catch(Exception e) { @@ -92,7 +92,7 @@ public LangUtil addLangDir(ResourceLocation dir) } try { - addLangFile(langRes.func_110527_b(), langID); + addLangFile(langRes.getInputStream(), langID); } catch(IOException e) { @@ -103,7 +103,8 @@ public LangUtil addLangDir(ResourceLocation dir) return this; } - + + @Deprecated public static void loadBaseLangDir(ResourceLocation dir) { instance.addLangDir(dir); diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index 17a8265..e21f5ac 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -1077,7 +1077,7 @@ public void sendToOps() public static void sendToOps(Packet packet) { for(EntityPlayerMP player : (List)MinecraftServer.getServer().getConfigurationManager().playerEntityList) - if(MinecraftServer.getServer().getConfigurationManager().areCommandsAllowed(player.username)) + if(MinecraftServer.getServer().getConfigurationManager().isPlayerOpped(player.username)) sendToPlayer(packet, player); } diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 7e16e71..5fd692f 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -628,7 +628,7 @@ public static Map parseObjModels(ResourceLocation res, Transfor try { return parseObjModels( - Minecraft.getMinecraft().func_110442_L().func_110536_a(res).func_110527_b(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), 4, coordSystem); } catch(IOException e) @@ -649,7 +649,7 @@ public static Map parseObjModels(ResourceLocation res, int vert try { return parseObjModels( - Minecraft.getMinecraft().func_110442_L().func_110536_a(res).func_110527_b(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), vertexMode, coordSystem); } catch(Exception e) diff --git a/codechicken/lib/render/CCRenderState.java b/codechicken/lib/render/CCRenderState.java index d8a92b0..87f2c31 100644 --- a/codechicken/lib/render/CCRenderState.java +++ b/codechicken/lib/render/CCRenderState.java @@ -99,7 +99,7 @@ public static void changeTexture(String texture) public static void changeTexture(ResourceLocation texture) { - Minecraft.getMinecraft().renderEngine.func_110577_a(texture); + Minecraft.getMinecraft().renderEngine.bindTexture(texture); } public static void apply() diff --git a/codechicken/lib/render/SpriteSheetManager.java b/codechicken/lib/render/SpriteSheetManager.java index be8d327..0d8c28f 100644 --- a/codechicken/lib/render/SpriteSheetManager.java +++ b/codechicken/lib/render/SpriteSheetManager.java @@ -46,7 +46,7 @@ public void registerIcons(IconRegister register) { TextureMap textureMap = (TextureMap)register; - if(TextureUtils.refreshTexture(textureMap, resource.func_110623_a())) + if(TextureUtils.refreshTexture(textureMap, resource.getResourcePath())) { reloadTexture(); for(int i = 0; i < sprites.length; i++) @@ -108,7 +108,7 @@ public int spriteHeight() return spriteHeight; } - public TextureSpecial func_110577_aFX(int i, TextureFX textureFX) + public TextureSpecial bindTextureFX(int i, TextureFX textureFX) { return setupSprite(i).addTextureFX(textureFX); } diff --git a/codechicken/lib/render/TextureFX.java b/codechicken/lib/render/TextureFX.java index b79bfe1..3685226 100644 --- a/codechicken/lib/render/TextureFX.java +++ b/codechicken/lib/render/TextureFX.java @@ -19,7 +19,7 @@ public class TextureFX public TextureFX(int spriteIndex, SpriteSheet sheet) { - texture = sheet.func_110577_aFX(spriteIndex, this); + texture = sheet.bindTextureFX(spriteIndex, this); } public TextureFX(int size, String name) diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java index a1ae887..d5adcdb 100644 --- a/codechicken/lib/render/TextureSpecial.java +++ b/codechicken/lib/render/TextureSpecial.java @@ -56,11 +56,11 @@ public TextureSpecial addTextureFX(TextureFX fx) } @Override - public void func_110971_a(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) + public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) { - super.func_110971_a(sheetWidth, sheetHeight, originX, originY, rotated); + super.initSprite(sheetWidth, sheetHeight, originX, originY, rotated); if(textureFX != null) - textureFX.onTextureDimensionsUpdate(field_130223_c, field_130224_d); + textureFX.onTextureDimensionsUpdate(width, height); } @Override @@ -70,7 +70,7 @@ public void updateAnimation() { textureFX.update(); if(textureFX.changed()) - TextureUtil.func_110998_a(textureFX.imageData, field_130223_c, field_130224_d, field_110975_c, field_110974_d, false, false); + TextureUtil.uploadTextureSub(textureFX.imageData, width, height, originX, originY, false, false); } } @@ -81,45 +81,45 @@ public boolean load(ResourceManager manager, ResourceLocation location) { for(TextureDataHolder tex : baseTextures) { - field_110976_a.add(tex.data); - field_130223_c = tex.width; - field_130224_d = tex.height; + framesTextureData.add(tex.data); + width = tex.width; + height = tex.height; } } if(spriteSheet != null) { TextureDataHolder tex = spriteSheet.createSprite(spriteIndex); - field_130223_c = tex.width; - field_130224_d = tex.height; - field_110976_a.add(tex.data); + width = tex.width; + height = tex.height; + framesTextureData.add(tex.data); } if(blankSize > 0) { - field_130223_c = field_130224_d = blankSize; - field_110976_a.add(new int[blankSize*blankSize]); + width = height = blankSize; + framesTextureData.add(new int[blankSize*blankSize]); } - if(field_110976_a.isEmpty()) + if(framesTextureData.isEmpty()) throw new RuntimeException("No base frame for texture: "+getIconName()); return true; } @Override - public boolean func_130098_m() + public boolean hasAnimationMetadata() { - return textureFX != null || super.func_130098_m(); + return textureFX != null || super.hasAnimationMetadata(); } @Override - public int func_110970_k() + public int getFrameCount() { if(textureFX != null) return 1; - return super.func_110970_k(); + return super.getFrameCount(); } public TextureSpecial blank(int size) diff --git a/codechicken/lib/render/TextureUtils.java b/codechicken/lib/render/TextureUtils.java index 1cbf069..4a01a1f 100644 --- a/codechicken/lib/render/TextureUtils.java +++ b/codechicken/lib/render/TextureUtils.java @@ -70,7 +70,7 @@ public static Colour[] loadTextureColours(ResourceLocation resource) public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException { - return Minecraft.getMinecraft().func_110442_L().func_110536_a(textureFile).func_110527_b(); + return Minecraft.getMinecraft().getResourceManager().getResource(textureFile).getInputStream(); } public static BufferedImage loadBufferedImage(ResourceLocation textureFile) @@ -113,7 +113,7 @@ public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY public static void bindAtlas(int atlasIndex) { - engine().func_110577_a(atlasIndex == 0 ? TextureMap.field_110575_b : TextureMap.field_110576_c); + engine().bindTexture(atlasIndex == 0 ? TextureMap.locationBlocksTexture : TextureMap.locationItemsTexture); } public static Icon getBlankIcon(int size, IconRegister iconRegister) From ea515682c1672f4291abae430bee674baaf2bd6e Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Thu, 5 Sep 2013 17:41:31 +1000 Subject: [PATCH 030/219] Improved transformation compacting. --- .../lib/vec/RedundantTransformation.java | 5 +++ codechicken/lib/vec/Rotation.java | 16 +++++---- codechicken/lib/vec/Scale.java | 14 ++++---- codechicken/lib/vec/Transformation.java | 8 +++++ codechicken/lib/vec/TransformationList.java | 36 ++++++++++--------- codechicken/lib/vec/Translation.java | 11 +++--- 6 files changed, 56 insertions(+), 34 deletions(-) diff --git a/codechicken/lib/vec/RedundantTransformation.java b/codechicken/lib/vec/RedundantTransformation.java index 08842f6..be2e87e 100644 --- a/codechicken/lib/vec/RedundantTransformation.java +++ b/codechicken/lib/vec/RedundantTransformation.java @@ -35,6 +35,11 @@ public Transformation merge(Transformation next) { return next; } + @Override + public boolean isRedundant() { + return true; + } + @Override public String toString() { diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java index 66503a6..86a6c81 100644 --- a/codechicken/lib/vec/Rotation.java +++ b/codechicken/lib/vec/Rotation.java @@ -232,18 +232,20 @@ public Transformation inverse() public Transformation merge(Transformation next) { if(next instanceof Rotation) { Rotation r = (Rotation)next; - if(r.axis.equalsT(axis)) { - double d = angle+r.angle; - if(d == 0) - return new RedundantTransformation(); - - return new Rotation(angle, axis); - } + if(r.axis.equalsT(axis)) + return new Rotation(angle+r.angle, axis); + + return new Rotation(toQuat().copy().multiply(r.toQuat())); } return null; } + @Override + public boolean isRedundant() { + return MathHelper.between(-1E-5, angle, 1E-5); + } + @Override public String toString() { diff --git a/codechicken/lib/vec/Scale.java b/codechicken/lib/vec/Scale.java index 889af8c..ca36bf5 100644 --- a/codechicken/lib/vec/Scale.java +++ b/codechicken/lib/vec/Scale.java @@ -60,17 +60,17 @@ public Transformation inverse() @Override public Transformation merge(Transformation next) { - if(next instanceof Scale) { - Vector3 vec = factor.copy().multiply(((Scale) next).factor); - if(vec.equalsT(Vector3.one)) - return new RedundantTransformation(); - - return new Scale(vec); - } + if(next instanceof Scale) + return new Scale(factor.copy().multiply(((Scale) next).factor)); return null; } + @Override + public boolean isRedundant() { + return factor.equalsT(Vector3.one); + } + @Override public String toString() { diff --git a/codechicken/lib/vec/Transformation.java b/codechicken/lib/vec/Transformation.java index 9dcde27..469761f 100644 --- a/codechicken/lib/vec/Transformation.java +++ b/codechicken/lib/vec/Transformation.java @@ -52,6 +52,14 @@ public Transformation merge(Transformation next) return null; } + /** + * Returns true if this transformation is redundant, eg. Scale(1, 1, 1), Translation(0, 0, 0) or Rotation(0, a, b, c) + */ + public boolean isRedundant() + { + return false; + } + @SideOnly(Side.CLIENT) public abstract void glApply(); diff --git a/codechicken/lib/vec/TransformationList.java b/codechicken/lib/vec/TransformationList.java index 3f150a7..92bbcf7 100644 --- a/codechicken/lib/vec/TransformationList.java +++ b/codechicken/lib/vec/TransformationList.java @@ -74,7 +74,7 @@ public void apply(Matrix4 mat) @Override public TransformationList with(Transformation t) { - if(t instanceof RedundantTransformation) + if(t.isRedundant()) return this; mat = null;//matrix invalid @@ -89,7 +89,7 @@ public TransformationList with(Transformation t) public TransformationList prepend(Transformation t) { - if(t instanceof RedundantTransformation) + if(t.isRedundant()) return this; mat = null;//matrix invalid @@ -103,25 +103,24 @@ public TransformationList prepend(Transformation t) } private void compact() { - if(transformations.isEmpty()) - return; - ArrayList newList = new ArrayList(transformations.size()); Iterator iterator = transformations.iterator(); - Transformation prev = iterator.next(); + Transformation prev = null; while(iterator.hasNext()) { Transformation t = iterator.next(); - Transformation m = prev == null ? null : prev.merge(t); - if(m instanceof RedundantTransformation) { - prev = null; - } - else if(m != null) { - prev = m; - } - else { - newList.add(prev); - prev = t; + if(t.isRedundant()) + continue; + + if(prev != null) { + Transformation m = prev.merge(t); + if(m == null) + newList.add(prev); + else if(m.isRedundant()) + t = null; + else + t = m; } + prev = t; } if(prev != null) newList.add(prev); @@ -131,6 +130,11 @@ else if(m != null) { mat = null; } } + + @Override + public boolean isRedundant() { + return transformations.size() == 0; + } @Override @SideOnly(Side.CLIENT) diff --git a/codechicken/lib/vec/Translation.java b/codechicken/lib/vec/Translation.java index 9dde79e..ad2776e 100644 --- a/codechicken/lib/vec/Translation.java +++ b/codechicken/lib/vec/Translation.java @@ -61,14 +61,17 @@ public Transformation inverse() @Override public Transformation merge(Transformation next) { - if(next instanceof Translation) { - Vector3 vec2 = vec.copy().add(((Translation) next).vec); - return vec2.isZero() ? new RedundantTransformation() : new Translation(vec2); - } + if(next instanceof Translation) + return new Translation(vec.copy().add(((Translation) next).vec)); return null; } + @Override + public boolean isRedundant() { + return vec.equalsT(Vector3.zero); + } + @Override public String toString() { From 6a29a2428f87dcc44d997e531ec6ea2c70df7e00 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Mon, 9 Sep 2013 08:29:10 +1000 Subject: [PATCH 031/219] Added easier backface generation. --- codechicken/lib/render/CCModel.java | 26 ++++++++++++++--------- codechicken/lib/render/CCRenderState.java | 1 + 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 5fd692f..8687cc9 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -5,6 +5,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; @@ -781,17 +782,21 @@ public static void generateSidedModelsH(CCModel[] models, int side, Vector3 poin } } + public CCModel backfacedCopy() + { + return generateBackface(this, 0, copy(), 0, verts.length); + } + /** * Generates copies of faces with clockwise vertices * @return The model */ - public CCModel generateBackface(int srcpos, int destpos, int length) + public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int destpos, int length) { - if(srcpos+length > destpos) - throw new IllegalArgumentException("Overlapping src and dest arrays"); + int vp = src.vp; if(srcpos%vp != 0 || destpos%vp != 0 || length%vp != 0) throw new IllegalArgumentException("Vertices do not align with polygons"); - + int[][] o = new int[][]{{0, 0}, {1, vp-1}, {2, vp-2}, {3, vp-3}}; for(int i = 0; i < length; i++) { @@ -799,11 +804,13 @@ public CCModel generateBackface(int srcpos, int destpos, int length) int d = i%vp; int di = destpos+b+o[d][1]; int si = srcpos+b+o[d][0]; - verts[di] = new Vertex5(verts[si]); - if(normals != null && normals[si] != null) - normals[di] = normals[si].copy().negate(); + dst.verts[di] = src.verts[si].copy(); + if(src.normals != null && src.normals[si] != null) + dst.normals[di] = src.normals[si].copy().negate(); + if(src.colours != null) + dst.colours[di] = src.colours[si]; } - return this; + return dst; } /** @@ -908,8 +915,7 @@ public CCModel twoFacedCopy() { CCModel model = newModel(vertexMode, verts.length*2); copy(this, 0, model, 0, verts.length); - model.generateBackface(0, verts.length, verts.length); - return model; + return generateBackface(model, 0, model, verts.length, verts.length); } public CCModel copy() diff --git a/codechicken/lib/render/CCRenderState.java b/codechicken/lib/render/CCRenderState.java index 87f2c31..3ef7262 100644 --- a/codechicken/lib/render/CCRenderState.java +++ b/codechicken/lib/render/CCRenderState.java @@ -116,6 +116,7 @@ public static void reset() useModelColours = false; hasColour = false; alphaOverride = false; + useNormals = false; } public static void startDrawing(int i) From f5bbe9d2dab65877d2b46fc541a0347240565d8d Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 10 Sep 2013 18:22:44 +1000 Subject: [PATCH 032/219] Optimised render transformations. Added documentation to ExtendedMOP.dist Added expand function to CCModel. --- codechicken/lib/raytracer/ExtendedMOP.java | 3 +++ codechicken/lib/render/CCModel.java | 11 +++++++++++ codechicken/lib/vec/TransformationList.java | 11 +++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/codechicken/lib/raytracer/ExtendedMOP.java b/codechicken/lib/raytracer/ExtendedMOP.java index 029e19e..ddff053 100644 --- a/codechicken/lib/raytracer/ExtendedMOP.java +++ b/codechicken/lib/raytracer/ExtendedMOP.java @@ -7,6 +7,9 @@ public class ExtendedMOP extends MovingObjectPosition implements Comparable { public Object data; + /** + * The square distance from the start of the raytrace. + */ public double dist; public ExtendedMOP(Entity entity, Object data) diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 8687cc9..57c4905 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -355,6 +355,17 @@ public CCModel apply(IUVTransformation uvt) return this; } + public CCModel expand(int extraVerts) + { + int newLen = verts.length+extraVerts; + verts = Arrays.copyOf(verts, newLen); + if(normals != null) + normals = Arrays.copyOf(normals, newLen); + if(colours != null) + colours = Arrays.copyOf(colours, newLen); + return this; + } + public void render() { render(0, verts.length, null, null, null); diff --git a/codechicken/lib/vec/TransformationList.java b/codechicken/lib/vec/TransformationList.java index 92bbcf7..4b383ea 100644 --- a/codechicken/lib/vec/TransformationList.java +++ b/codechicken/lib/vec/TransformationList.java @@ -51,8 +51,8 @@ public void apply(Vector3 vec) if(mat != null) mat.apply(vec); else - for(Transformation t : transformations) - t.apply(vec); + for(int i = 0; i < transformations.size(); i++) + transformations.get(i).apply(vec); } @Override @@ -61,8 +61,8 @@ public void applyN(Vector3 normal) if(mat != null) mat.applyN(normal); else - for(Transformation t : transformations) - t.applyN(normal); + for(int i = 0; i < transformations.size(); i++) + transformations.get(i).applyN(normal); } @Override @@ -129,6 +129,9 @@ else if(m.isRedundant()) transformations = newList; mat = null; } + + if(transformations.size() > 3 && mat == null) + compile(); } @Override From d889cf9cbc3f32f8e4b7a7d0e54eef028f210b17 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 18 Sep 2013 23:17:26 +1000 Subject: [PATCH 033/219] Added some SideOnly annotations to LangUtil --- codechicken/lib/lang/LangUtil.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/lang/LangUtil.java b/codechicken/lib/lang/LangUtil.java index 4c75980..70749ce 100644 --- a/codechicken/lib/lang/LangUtil.java +++ b/codechicken/lib/lang/LangUtil.java @@ -13,6 +13,8 @@ import net.minecraft.util.StatCollector; import cpw.mods.fml.common.registry.LanguageRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; /** * Easy localisation access. @@ -69,12 +71,14 @@ public void addLangFile(InputStream resource, String lang) throws IOException reg.addStringLocalization(key, lang, value); } } - + + @SideOnly(Side.CLIENT) public static LangUtil loadLangDir(String domain) { return new LangUtil(domain).addLangDir(new ResourceLocation(domain, "lang")); } + @SideOnly(Side.CLIENT) public LangUtil addLangDir(ResourceLocation dir) { ResourceManager resManager = Minecraft.getMinecraft().getResourceManager(); @@ -105,6 +109,7 @@ public LangUtil addLangDir(ResourceLocation dir) } @Deprecated + @SideOnly(Side.CLIENT) public static void loadBaseLangDir(ResourceLocation dir) { instance.addLangDir(dir); From cdb52bf72ae9f15441f2ba18f551263a347ff136 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Thu, 19 Sep 2013 12:24:27 +1000 Subject: [PATCH 034/219] Update to 1.6.3 --- mcversion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcversion.txt b/mcversion.txt index 308b6fa..f5d2a58 100644 --- a/mcversion.txt +++ b/mcversion.txt @@ -1 +1 @@ -1.6.2 \ No newline at end of file +1.6.3 \ No newline at end of file From bd3234b033ffcf9cf15255dbf251b2404aecf5e7 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Fri, 20 Sep 2013 17:17:39 +1000 Subject: [PATCH 035/219] Added missing overload for CCModel.generateBlock --- codechicken/lib/render/CCModel.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 57c4905..6b0620f 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -150,7 +150,12 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou */ public CCModel generateBlock(int i, Cuboid6 bounds) { - return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z); + return generateBlock(i, bounds, 0); + } + + public CCModel generateBlock(int i, Cuboid6 bounds, int mask) + { + return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z, mask); } public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) From 1b71ee5e3dea1a51c0bebecd1cca8a242c2d47ff Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Sun, 22 Sep 2013 13:02:08 +1000 Subject: [PATCH 036/219] 1.6.4 Update --- mcversion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcversion.txt b/mcversion.txt index f5d2a58..6463e95 100644 --- a/mcversion.txt +++ b/mcversion.txt @@ -1 +1 @@ -1.6.3 \ No newline at end of file +1.6.4 \ No newline at end of file From b1057544a775f691e388bd145a740f8ee2e2e78b Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Sun, 22 Sep 2013 14:23:08 +1000 Subject: [PATCH 037/219] Remove all deprecated content --- codechicken/lib/colour/Colour.java | 9 +----- codechicken/lib/lang/LangUtil.java | 7 ----- codechicken/lib/raytracer/RayTracer.java | 3 -- codechicken/lib/render/RenderUtils.java | 38 +++--------------------- codechicken/lib/vec/Cuboid6.java | 6 ---- codechicken/lib/vec/Vector3.java | 6 ---- 6 files changed, 5 insertions(+), 64 deletions(-) diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index 83a95c0..8960c07 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -41,14 +41,7 @@ public void glColour(int a) { GL11.glColor4ub(r, g, b, (byte) a); } - - @SideOnly(Side.CLIENT) - @Deprecated - public void glColour(byte a) - { - GL11.glColor4ub(r, g, b, a); - } - + public abstract int pack(); @Override diff --git a/codechicken/lib/lang/LangUtil.java b/codechicken/lib/lang/LangUtil.java index 70749ce..767887b 100644 --- a/codechicken/lib/lang/LangUtil.java +++ b/codechicken/lib/lang/LangUtil.java @@ -107,11 +107,4 @@ public LangUtil addLangDir(ResourceLocation dir) return this; } - - @Deprecated - @SideOnly(Side.CLIENT) - public static void loadBaseLangDir(ResourceLocation dir) - { - instance.addLangDir(dir); - } } diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 7273d77..4161d84 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -28,9 +28,6 @@ public class RayTracer private int s_side; private IndexedCuboid6 c_cuboid; - @Deprecated//not threadsafe - public static RayTracer instance = new RayTracer(); - private static ThreadLocal t_inst = new ThreadLocal(); public static RayTracer instance() diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 581ccc3..a867002 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -49,12 +49,6 @@ public boolean shouldBob() entityItem.hoverStart = 0; } - @Deprecated - public static void renderLiquidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) - { - renderFluidQuad(point1, point2, point3, point4, icon, res); - } - public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) { double u1 = icon.getMinU(); @@ -109,12 +103,6 @@ public static void translateToWorldCoords(Entity entity, float frame) GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ); } - @Deprecated - public static void drawOutlinedBoundingBox(AxisAlignedBB aabb) - { - drawCuboidOutline(new Cuboid6(aabb)); - } - public static void drawCuboidOutline(Cuboid6 c) { Tessellator var2 = Tessellator.instance; @@ -144,12 +132,6 @@ public static void drawCuboidOutline(Cuboid6 c) var2.draw(); } - @Deprecated - public static void renderLiquidCuboid(Cuboid6 bound, Icon tex, double res) - { - renderFluidCuboid(bound, tex, res); - } - public static void renderFluidCuboid(Cuboid6 bound, Icon tex, double res) { renderFluidQuad(//bottom @@ -235,12 +217,6 @@ public static void renderBlockOverlaySide(int x, int y, int z, int side, double break; } } - - @Deprecated - public static boolean shouldRenderLiquid(FluidStack stack) - { - return shouldRenderFluid(stack); - } public static boolean shouldRenderFluid(FluidStack stack) { @@ -272,12 +248,6 @@ public static void postFluidRender() GL11.glDisable(GL11.GL_BLEND); } - @Deprecated - public static void renderLiquidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) - { - renderFluidCuboid(stack, bound, density, res); - } - public static double fluidDensityToAlpha(double density) { return Math.pow(density, 0.4); @@ -295,7 +265,7 @@ public static double fluidDensityToAlpha(double density) */ public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { - if(!shouldRenderLiquid(stack)) + if(!shouldRenderFluid(stack)) return; int alpha = 255; @@ -306,14 +276,14 @@ public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double den Icon tex = prepareFluidRender(stack, alpha); CCRenderState.startDrawing(7); - renderLiquidCuboid(bound, tex, res); + renderFluidCuboid(bound, tex, res); CCRenderState.draw(); postFluidRender(); } public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) { - if(!shouldRenderLiquid(stack)) + if(!shouldRenderFluid(stack)) return; int alpha = 255; @@ -328,7 +298,7 @@ public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double d Icon tex = prepareFluidRender(stack, alpha); CCRenderState.startDrawing(7); - renderLiquidQuad( + renderFluidQuad( new Vector3(rect.x, rect.y, 0), new Vector3(rect.x, rect.y+rect.h, 0), new Vector3(rect.x+rect.w, rect.y+rect.h, 0), diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index 237504f..9233cf7 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -135,12 +135,6 @@ public Cuboid6 enclose(Cuboid6 c) return this; } - @Deprecated - public Cuboid6 transform(Transformation t) - { - return apply(t); - } - public Cuboid6 apply(Transformation t) { t.apply(min); diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java index 675e9ad..8a2c502 100644 --- a/codechicken/lib/vec/Vector3.java +++ b/codechicken/lib/vec/Vector3.java @@ -76,12 +76,6 @@ public static Vector3 fromTileEntityCenter(TileEntity e) return new Vector3(e.xCoord + 0.5, e.yCoord + 0.5, e.zCoord + 0.5); } - @Deprecated - public static Vector3 fromVec3D(Vec3 vec) - { - return new Vector3(vec); - } - public Vector3 set(double d, double d1, double d2) { x = d; From ab0713c129be8c59422fb4173b512757fdfed9ce Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 1 Oct 2013 11:54:47 +1000 Subject: [PATCH 038/219] Added side function to Cuboid6 --- codechicken/lib/vec/Cuboid6.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index 9233cf7..7c98df4 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -145,4 +145,17 @@ public Cuboid6 apply(Transformation t) if(min.z > max.z) {temp = min.z; min.z = max.z; max.z = temp;} return this; } + + public double side(int s) + { + switch(s) { + case 0: return min.y; + case 1: return max.y; + case 2: return min.z; + case 3: return max.z; + case 4: return min.x; + case 5: return max.x; + } + throw new IndexOutOfBoundsException("Switch Falloff"); + } } From 3b762d300fc2a29628603d7a7d816a2924c61191 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Tue, 1 Oct 2013 11:58:04 +1000 Subject: [PATCH 039/219] Added setSide function to Cuboid6 --- codechicken/lib/vec/Cuboid6.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index 7c98df4..d44d331 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -146,7 +146,7 @@ public Cuboid6 apply(Transformation t) return this; } - public double side(int s) + public double getSide(int s) { switch(s) { case 0: return min.y; @@ -158,4 +158,18 @@ public double side(int s) } throw new IndexOutOfBoundsException("Switch Falloff"); } + + public Cuboid6 setSide(int s, double d) + { + switch(s) { + case 0: min.y = d; break; + case 1: max.y = d; break; + case 2: min.z = d; break; + case 3: max.z = d; break; + case 4: min.x = d; break; + case 5: max.x = d; break; + default: throw new IndexOutOfBoundsException("Switch Falloff"); + } + return this; + } } From 112c0abc088b6870682161cfbe0a4e4b42ee3fd2 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Wed, 2 Oct 2013 12:21:43 +1000 Subject: [PATCH 040/219] Wrapped fluid rendering with safeIcon method. --- codechicken/lib/render/RenderUtils.java | 2 +- codechicken/lib/render/TextureUtils.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index a867002..3fed169 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -236,7 +236,7 @@ public static Icon prepareFluidRender(FluidStack stack, int alpha) Fluid fluid = stack.getFluid(); CCRenderState.setColour(fluid.getColor(stack)<<8|alpha); TextureUtils.bindAtlas(fluid.getSpriteNumber()); - return fluid.getIcon(stack); + return TextureUtils.safeIcon(fluid.getIcon(stack)); } /** diff --git a/codechicken/lib/render/TextureUtils.java b/codechicken/lib/render/TextureUtils.java index 4a01a1f..ce52719 100644 --- a/codechicken/lib/render/TextureUtils.java +++ b/codechicken/lib/render/TextureUtils.java @@ -176,4 +176,12 @@ public static boolean refreshTexture(TextureMap map, String name) } return false; } + + public static Icon safeIcon(Icon icon) + { + if(icon == null) + icon = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); + + return icon; + } } From ddadd1f831892c213ba6b7fdf520b56972423603 Mon Sep 17 00:00:00 2001 From: Soaryn Date: Sat, 12 Oct 2013 19:18:08 -0400 Subject: [PATCH 041/219] Adds getter and setter for Dig FX particleScale A copy method may be better for this, in the end this will allow for "layered" textures to work properly when breaking a block --- codechicken/lib/render/EntityDigIconFX.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/codechicken/lib/render/EntityDigIconFX.java b/codechicken/lib/render/EntityDigIconFX.java index 97f854e..185b2ba 100644 --- a/codechicken/lib/render/EntityDigIconFX.java +++ b/codechicken/lib/render/EntityDigIconFX.java @@ -25,6 +25,14 @@ public int getFXLayer() return 1; } + public void setScale(float scale) { + particleScale = scale; + } + + public float getScale() { + return particleScale; + } + /** * copy pasted from EntityDiggingFX */ From a7637ca787c9aca01b6de4caed9b8dc95e0609d5 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 30 Oct 2013 11:51:17 +1000 Subject: [PATCH 042/219] Changed RayTracer.getCorrectedHeadVec to use a sneaking offset relative to getEyeHeight() in SMP. Should fix compatibility with eye-height changing mods. --- codechicken/lib/raytracer/RayTracer.java | 29 +++++++++++++++++++++--- codechicken/lib/render/RenderUtils.java | 1 - 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 4161d84..2be94e6 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -191,7 +191,7 @@ public static MovingObjectPosition retraceBlock(World world, EntityPlayer player Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1.0F); - double reach = world.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player); + double reach = getBlockReachDistance(player); Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); return block.collisionRayTrace(world, x, y, z, headVec, endVec); } @@ -222,7 +222,30 @@ public static MovingObjectPosition reTrace(World world, EntityPlayer player, dou public static Vec3 getCorrectedHeadVec(EntityPlayer player) { - double d = player.worldObj.isRemote ? 0 : (player instanceof EntityPlayerMP && player.isSneaking() ? 1.54 : 1.62); - return Vec3.createVectorHelper(player.posX, player.posY + d, player.posZ); + Vec3 v = Vec3.createVectorHelper(player.posX, player.posY, player.posZ); + if(!player.worldObj.isRemote) { + v.yCoord+=player.getEyeHeight(); + if(player instanceof EntityPlayerMP && player.isSneaking()) + v.yCoord-=0.08; + } + return v; + } + + public static Vec3 getStartVec(EntityPlayer player) + { + return getCorrectedHeadVec(player); + } + + public static double getBlockReachDistance(EntityPlayer player) + { + return player.worldObj.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player); + } + + public static Vec3 getEndVec(EntityPlayer player) + { + Vec3 headVec = getCorrectedHeadVec(player); + Vec3 lookVec = player.getLook(1.0F); + double reach = getBlockReachDistance(player); + return headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); } } diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 3fed169..0eafa56 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -10,7 +10,6 @@ import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.Icon; import net.minecraft.block.Block; import net.minecraft.entity.Entity; From dd297d6e42fd5040a275de129285c5ffcf54fd00 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 30 Oct 2013 12:23:03 +1000 Subject: [PATCH 043/219] Fix RayTracer with non EntityPlayerMP instances on server worlds. --- codechicken/lib/raytracer/RayTracer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 2be94e6..9d534aa 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -209,7 +209,7 @@ private static double getBlockReachDistance_client() public static MovingObjectPosition reTrace(World world, EntityPlayer player) { - return reTrace(world, player, world.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player)); + return reTrace(world, player, getBlockReachDistance(player)); } public static MovingObjectPosition reTrace(World world, EntityPlayer player, double reach) @@ -238,7 +238,8 @@ public static Vec3 getStartVec(EntityPlayer player) public static double getBlockReachDistance(EntityPlayer player) { - return player.worldObj.isRemote ? getBlockReachDistance_client() : getBlockReachDistance_server((EntityPlayerMP) player); + return player.worldObj.isRemote ? getBlockReachDistance_client() : + player instanceof EntityPlayerMP ? getBlockReachDistance_server((EntityPlayerMP) player) : 5D; } public static Vec3 getEndVec(EntityPlayer player) From 6233c2f6ca58a6abe0f250f5e791abadd65cab72 Mon Sep 17 00:00:00 2001 From: Soaryn Date: Thu, 31 Oct 2013 17:13:18 -0400 Subject: [PATCH 044/219] Accessors for particleMaxAge Allows access to the maxAge for "copied" layers to behave for the same duration. --- codechicken/lib/render/EntityDigIconFX.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/codechicken/lib/render/EntityDigIconFX.java b/codechicken/lib/render/EntityDigIconFX.java index 185b2ba..5a8c064 100644 --- a/codechicken/lib/render/EntityDigIconFX.java +++ b/codechicken/lib/render/EntityDigIconFX.java @@ -33,6 +33,14 @@ public float getScale() { return particleScale; } + public void setMaxAge(int age){ + particleMaxAge = age; + } + + public int getMaxAge(){ + return particleMaxAge; + } + /** * copy pasted from EntityDiggingFX */ From 699221214cf931732fde594429959cb02c10e46e Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 21 Nov 2013 12:48:47 +1000 Subject: [PATCH 045/219] Made a small change to RayTracer to potentially add support for eye-height changing mods. --- codechicken/lib/raytracer/RayTracer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 9d534aa..44bb183 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -223,7 +223,9 @@ public static MovingObjectPosition reTrace(World world, EntityPlayer player, dou public static Vec3 getCorrectedHeadVec(EntityPlayer player) { Vec3 v = Vec3.createVectorHelper(player.posX, player.posY, player.posZ); - if(!player.worldObj.isRemote) { + if(player.worldObj.isRemote) { + v.yCoord+=player.getEyeHeight()-player.getDefaultEyeHeight();//compatibility with eye height changing mods + } else { v.yCoord+=player.getEyeHeight(); if(player instanceof EntityPlayerMP && player.isSneaking()) v.yCoord-=0.08; From 8a777b265e2e8c458d8e45dc51931bf5849e77cf Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 11 Dec 2013 17:34:04 +1000 Subject: [PATCH 046/219] Add intersects method to Rectangle4i Added compare methods to MathHelper --- codechicken/lib/math/MathHelper.java | 10 ++++++++++ codechicken/lib/vec/Rectangle4i.java | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/codechicken/lib/math/MathHelper.java b/codechicken/lib/math/MathHelper.java index 37ed8bf..2da16b0 100644 --- a/codechicken/lib/math/MathHelper.java +++ b/codechicken/lib/math/MathHelper.java @@ -165,4 +165,14 @@ public static int roundAway(double d) { return (int) (d < 0 ? Math.floor(d) : Math.ceil(d)); } + + public static int compare(int a, int b) + { + return a == b ? 0 : a < b ? -1 : 1; + } + + public static int compare(double a, double b) + { + return a == b ? 0 : a < b ? -1 : 1; + } } diff --git a/codechicken/lib/vec/Rectangle4i.java b/codechicken/lib/vec/Rectangle4i.java index 3574e58..0792a97 100644 --- a/codechicken/lib/vec/Rectangle4i.java +++ b/codechicken/lib/vec/Rectangle4i.java @@ -39,4 +39,10 @@ public boolean contains(int px, int py) { return x <= px && px < x+w && y <= py && py < y+h; } + + public boolean intersects(Rectangle4i r) + { + return x <= r.x+r.w && r.x <= x+w && + y <= r.y+r.h && r.y <= y+h; + } } From 9e6ac47eba3cac892ff3cfd87aac54d611abf3f3 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 17 Dec 2013 14:50:02 +1000 Subject: [PATCH 047/219] Added scala operator overloading to Vector3 and Transformation --- codechicken/lib/vec/Transformation.java | 5 +++ codechicken/lib/vec/Vector3.java | 54 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/codechicken/lib/vec/Transformation.java b/codechicken/lib/vec/Transformation.java index 469761f..5e0e12d 100644 --- a/codechicken/lib/vec/Transformation.java +++ b/codechicken/lib/vec/Transformation.java @@ -64,4 +64,9 @@ public boolean isRedundant() public abstract void glApply(); public abstract Transformation inverse(); + + public TransformationList $plus$plus(Transformation t) + { + return with(t); + } } diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java index 8a2c502..3a76e61 100644 --- a/codechicken/lib/vec/Vector3.java +++ b/codechicken/lib/vec/Vector3.java @@ -4,6 +4,7 @@ import java.math.MathContext; import java.math.RoundingMode; +import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; import org.lwjgl.util.vector.Vector4f; @@ -51,6 +52,13 @@ public Vector3(Vec3 vec) z = vec.zCoord; } + public Vector3(BlockCoord coord) + { + x = coord.x; + y = coord.y; + z = coord.z; + } + public Vector3 copy() { return new Vector3(this); @@ -290,6 +298,12 @@ public Vector4f vector4f() { return new Vector4f((float)x, (float)y, (float)z, 1); } + + @SideOnly(Side.CLIENT) + public void glVertex() + { + GL11.glVertex3d(x, y, z); + } public Vector3 YZintercept(Vector3 end, double px) { @@ -414,4 +428,44 @@ public Vector3 apply(Transformation t) t.apply(this); return this; } + + public Vector3 $tilde() + { + return normalize(); + } + + public Vector3 unary_$tilde() + { + return normalize(); + } + + public Vector3 $plus(Vector3 v) + { + return add(v); + } + + public Vector3 $minus(Vector3 v) + { + return subtract(v); + } + + public Vector3 $times(double d) + { + return multiply(d); + } + + public Vector3 $div(double d) + { + return multiply(1/d); + } + + public Vector3 $times(Vector3 v) + { + return crossProduct(v); + } + + public double $dot$times(Vector3 v) + { + return dotProduct(v); + } } From 16d43f287dbbca670e53f2b2161440ab9b385d49 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 18 Dec 2013 12:25:04 +1000 Subject: [PATCH 048/219] Added a few more set methods to (Block/Cuboid)Coord --- codechicken/lib/vec/BlockCoord.java | 7 ++++++- codechicken/lib/vec/CuboidCoord.java | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java index 63952cc..e47dce1 100644 --- a/codechicken/lib/vec/BlockCoord.java +++ b/codechicken/lib/vec/BlockCoord.java @@ -71,7 +71,7 @@ public BlockCoord multiply(int i) return this; } - public double mag_() + public double mag() { return Math.sqrt(x*x+y*y+z*z); } @@ -177,6 +177,11 @@ public BlockCoord set(BlockCoord coord) { return set(coord.x, coord.y, coord.z); } + + public BlockCoord set(int[] ia) + { + return set(ia[0], ia[1], ia[2]); + } public int toSide() { diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java index dbe21c7..90b69ba 100644 --- a/codechicken/lib/vec/CuboidCoord.java +++ b/codechicken/lib/vec/CuboidCoord.java @@ -107,7 +107,25 @@ public AxisAlignedBB toAABB() public void set(BlockCoord min, BlockCoord max) { - this.min = min; - this.max = max; + this.min.set(min); + this.max.set(max); + } + + public CuboidCoord set(int x1, int y1, int z1, int x2, int y2, int z2) + { + min.set(x1, y1, z1); + max.set(x2, y2, z2); + return this; + } + + public CuboidCoord set(BlockCoord coord) { + min.set(coord); + max.set(coord); + return this; + } + + public CuboidCoord set(int[] ia) + { + return set(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); } } From 6a8a4534966df5ff220def376bc2a05dd7536c27 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 18 Dec 2013 12:25:28 +1000 Subject: [PATCH 049/219] Added general inventory management classes --- codechicken/lib/inventory/InventoryCopy.java | 123 ++++++++ codechicken/lib/inventory/InventoryNBT.java | 107 +++++++ codechicken/lib/inventory/InventoryRange.java | 71 +++++ .../lib/inventory/InventorySimple.java | 130 ++++++++ codechicken/lib/inventory/InventoryUtils.java | 295 ++++++++++++++++++ 5 files changed, 726 insertions(+) create mode 100644 codechicken/lib/inventory/InventoryCopy.java create mode 100644 codechicken/lib/inventory/InventoryNBT.java create mode 100644 codechicken/lib/inventory/InventoryRange.java create mode 100644 codechicken/lib/inventory/InventorySimple.java create mode 100644 codechicken/lib/inventory/InventoryUtils.java diff --git a/codechicken/lib/inventory/InventoryCopy.java b/codechicken/lib/inventory/InventoryCopy.java new file mode 100644 index 0000000..c36ba0a --- /dev/null +++ b/codechicken/lib/inventory/InventoryCopy.java @@ -0,0 +1,123 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class InventoryCopy implements IInventory +{ + public boolean[] accessible; + public ItemStack[] items; + public IInventory inv; + + public InventoryCopy(IInventory inv) + { + items = new ItemStack[inv.getSizeInventory()]; + accessible = new boolean[inv.getSizeInventory()]; + this.inv = inv; + update(); + } + + public void update() + { + for(int i = 0; i < items.length; i++) + { + ItemStack stack = inv.getStackInSlot(i); + if(stack != null) + items[i] = stack.copy(); + } + } + + public InventoryCopy open(InventoryRange access) + { + int lslot = access.lastSlot(); + if(lslot > accessible.length) + { + boolean[] l_accessable = new boolean[lslot]; + ItemStack[] l_items = new ItemStack[lslot]; + System.arraycopy(accessible, 0, l_accessable, 0, accessible.length); + System.arraycopy(items, 0, l_items, 0, items.length); + accessible = l_accessable; + items = l_items; + } + + for(int slot : access.slots) + accessible[slot] = true; + return this; + } + + @Override + public int getSizeInventory() + { + return items.length; + } + + @Override + public ItemStack getStackInSlot(int slot) + { + return items[slot]; + } + + public ItemStack decrStackSize(int slot, int amount) + { + return InventoryUtils.decrStackSize(this, slot, amount); + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return InventoryUtils.getStackInSlotOnClosing(this, slot); + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) + { + items[slot] = stack; + onInventoryChanged(); + } + + @Override + public String getInvName() + { + return "copy"; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) + { + return true; + } + + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + + @Override + public void onInventoryChanged() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return inv.isItemValidForSlot(i, itemstack); + } + + @Override + public boolean isInvNameLocalized() + { + return true; + } +} diff --git a/codechicken/lib/inventory/InventoryNBT.java b/codechicken/lib/inventory/InventoryNBT.java new file mode 100644 index 0000000..e3da78a --- /dev/null +++ b/codechicken/lib/inventory/InventoryNBT.java @@ -0,0 +1,107 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +public class InventoryNBT implements IInventory +{ + protected ItemStack[] items; + protected NBTTagCompound tag; + + public InventoryNBT(int size, NBTTagCompound tag) + { + this.tag = tag; + items = new ItemStack[size]; + readNBT(); + } + + private void writeNBT() + { + tag.setTag("items", InventoryUtils.writeItemStacksToTag(items, getInventoryStackLimit())); + } + + private void readNBT() + { + if(tag.hasKey("items")) + InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items")); + } + + @Override + public int getSizeInventory() + { + return items.length; + } + + @Override + public ItemStack getStackInSlot(int slot) + { + return items[slot]; + } + + @Override + public ItemStack decrStackSize(int slot, int amount) + { + return InventoryUtils.decrStackSize(this, slot, amount); + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return InventoryUtils.getStackInSlotOnClosing(this, slot); + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) + { + items[slot] = stack; + onInventoryChanged(); + } + + @Override + public String getInvName() + { + return "NBT"; + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public void onInventoryChanged() + { + writeNBT(); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return true; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + + @Override + public boolean isInvNameLocalized() + { + return true; + } +} diff --git a/codechicken/lib/inventory/InventoryRange.java b/codechicken/lib/inventory/InventoryRange.java new file mode 100644 index 0000000..6efc0bd --- /dev/null +++ b/codechicken/lib/inventory/InventoryRange.java @@ -0,0 +1,71 @@ +package codechicken.lib.inventory; + +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; + +public class InventoryRange +{ + public IInventory inv; + public int side; + public ISidedInventory sidedInv; + public int[] slots; + + public InventoryRange(IInventory inv, int side) + { + this.inv = inv; + this.side = side; + if(inv instanceof ISidedInventory) + { + sidedInv = (ISidedInventory)inv; + slots = sidedInv.getAccessibleSlotsFromSide(side); + } + else + { + slots = new int[inv.getSizeInventory()]; + for(int i = 0; i < slots.length; i++) + slots[i] = i; + } + } + + public InventoryRange(IInventory inv) + { + this(inv, 0); + } + + public InventoryRange(IInventory inv, int fslot, int lslot) + { + this.inv = inv; + slots = new int[lslot-fslot]; + for(int i = 0; i < slots.length; i++) + slots[i] = fslot+i; + } + + public InventoryRange(IInventory inv, InventoryRange access) + { + this.inv = inv; + this.slots = access.slots; + this.side = access.side; + if(inv instanceof ISidedInventory) + sidedInv = (ISidedInventory) inv; + } + + public boolean canInsertItem(int slot, ItemStack item) + { + return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canInsertItem(slot, item, side); + } + + public boolean canExtractItem(int slot, ItemStack item) + { + return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canExtractItem(slot, item, side); + } + + public int lastSlot() + { + int last = 0; + for(int slot : slots) + if(slot > last) + last = slot; + return last; + } +} diff --git a/codechicken/lib/inventory/InventorySimple.java b/codechicken/lib/inventory/InventorySimple.java new file mode 100644 index 0000000..90a24a1 --- /dev/null +++ b/codechicken/lib/inventory/InventorySimple.java @@ -0,0 +1,130 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class InventorySimple implements IInventory +{ + public ItemStack[] items; + public int limit; + public String name; + + public InventorySimple(ItemStack[] items, int limit, String name) + { + this.items = items; + this.limit = limit; + this.name = name; + } + + public InventorySimple(ItemStack[] items, String name) + { + this(items, 64, name); + } + + public InventorySimple(ItemStack[] items, int limit) + { + this(items, limit, "inv"); + } + + public InventorySimple(ItemStack[] items) + { + this(items, 64, "inv"); + } + + public InventorySimple(int size, int limit, String name) + { + this(new ItemStack[size], limit, name); + } + + public InventorySimple(int size, int limit) + { + this(size, limit, "inv"); + } + + public InventorySimple(int size, String name) + { + this(size, 64, name); + } + + public InventorySimple(int size) + { + this(size, 64, "inv"); + } + + @Override + public int getSizeInventory() + { + return items.length; + } + + @Override + public ItemStack getStackInSlot(int slot) + { + return items[slot]; + } + + @Override + public ItemStack decrStackSize(int slot, int amount) + { + return InventoryUtils.decrStackSize(this, slot, amount); + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) + { + return InventoryUtils.getStackInSlotOnClosing(this, slot); + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) + { + items[slot] = stack; + onInventoryChanged(); + } + + @Override + public String getInvName() + { + return name; + } + + @Override + public int getInventoryStackLimit() + { + return limit; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) + { + return true; + } + + @Override + public void openChest() + { + } + + @Override + public void closeChest() + { + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) + { + return true; + } + + @Override + public boolean isInvNameLocalized() + { + return true; + } + + @Override + public void onInventoryChanged() + { + } +} diff --git a/codechicken/lib/inventory/InventoryUtils.java b/codechicken/lib/inventory/InventoryUtils.java new file mode 100644 index 0000000..64bb560 --- /dev/null +++ b/codechicken/lib/inventory/InventoryUtils.java @@ -0,0 +1,295 @@ +package codechicken.lib.inventory; + +import com.google.common.base.Objects; + +import codechicken.lib.vec.Vector3; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryLargeChest; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagShort; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; + +public class InventoryUtils +{ + public static ItemStack decrStackSize(IInventory inv, int slot, int size) + { + ItemStack item = inv.getStackInSlot(slot); + + if(item != null) + { + if(item.stackSize <= size) + { + ItemStack itemstack = item; + inv.setInventorySlotContents(slot, null); + inv.onInventoryChanged(); + return itemstack; + } + ItemStack itemstack1 = item.splitStack(size); + if(item.stackSize == 0) + { + inv.setInventorySlotContents(slot, null); + } + inv.onInventoryChanged(); + return itemstack1; + } + return null; + } + + public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) + { + ItemStack stack = inv.getStackInSlot(slot); + inv.setInventorySlotContents(slot, null); + return stack; + } + + /** + * + * @param base + * @param addition + * @return The quantity of items from addition that can be added to base + */ + public static int incrStackSize(ItemStack base, ItemStack addition) + { + if (canStack(base, addition)) + return incrStackSize(base, addition.stackSize); + + return 0; + } + + /** + * + * @param base + * @param addition + * @return The quantity of items from addition that can be added to base + */ + public static int incrStackSize(ItemStack base, int addition) + { + int totalSize = base.stackSize + addition; + + if (totalSize <= base.getMaxStackSize()) + return addition; + else if (base.stackSize < base.getMaxStackSize()) + return base.getMaxStackSize() - base.stackSize; + + return 0; + } + + public static NBTTagList writeItemStacksToTag(ItemStack[] items) + { + return writeItemStacksToTag(items, 64); + } + + public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) + { + NBTTagList tagList = new NBTTagList(); + for(int i = 0; i < items.length; i++) + { + if (items[i] != null) + { + NBTTagCompound tag = new NBTTagCompound(); + tag.setShort("Slot", (short) i); + items[i].writeToNBT(tag); + + if(maxQuantity > Short.MAX_VALUE) + tag.setInteger("Quantity", items[i].stackSize); + else if(maxQuantity > Byte.MAX_VALUE) + tag.setShort("Quantity", (short) items[i].stackSize); + + tagList.appendTag(tag); + } + } + return tagList; + } + + public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) + { + for(int i = 0; i < tagList.tagCount(); i++) + { + NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i); + int b = tag.getShort("Slot"); + items[b] = ItemStack.loadItemStackFromNBT(tag); + if(tag.hasKey("Quantity")) + { + NBTBase qtag = tag.getTag("Quantity"); + if(qtag instanceof NBTTagInt) + items[b].stackSize = ((NBTTagInt)qtag).data; + else if(qtag instanceof NBTTagShort) + items[b].stackSize = ((NBTTagShort)qtag).data; + } + } + } + + public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) + { + EntityItem item = new EntityItem(world, dropLocation.x, dropLocation.y, dropLocation.z, stack); + item.motionX = world.rand.nextGaussian() * 0.05; + item.motionY = world.rand.nextGaussian() * 0.05 + 0.2F; + item.motionZ = world.rand.nextGaussian() * 0.05; + world.spawnEntityInWorld(item); + } + + public static ItemStack copyStack(ItemStack stack, int quantity) + { + if(stack == null) + return null; + + stack = stack.copy(); + stack.stackSize = quantity; + return stack; + } + + public static int getInsertableQuantity(InventoryRange inv, ItemStack stack) + { + int quantity = 0; + stack = copyStack(stack, Integer.MAX_VALUE); + for(int slot : inv.slots) + quantity+=fitStackInSlot(inv, slot, stack); + + return quantity; + } + + public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) + { + ItemStack base = inv.inv.getStackInSlot(slot); + if(!canStack(base, stack) || !inv.canInsertItem(slot, stack)) + return 0; + + int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit()-base.stackSize) : inv.inv.getInventoryStackLimit(); + return Math.min(fit, stack.stackSize); + } + + public static boolean mergeItemStack(InventoryRange inv, ItemStack stack, boolean doMerge) + { + if(doMerge && !mergeItemStack(inv, stack, false)) + return false; + + stack = stack.copy(); + for(int pass = 0; pass < 2; pass++) + { + for(int slot : inv.slots) + { + ItemStack base = inv.inv.getStackInSlot(slot); + int fit = fitStackInSlot(inv, slot, stack); + if(fit == 0) + continue; + + if(base != null) + { + stack.stackSize-=fit; + if(doMerge) + { + base.stackSize+=fit; + inv.inv.setInventorySlotContents(slot, base); + } + } + else if(pass == 1) + { + if(doMerge) + inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); + stack.stackSize-=fit; + } + if(stack.stackSize == 0) + return true; + } + } + return false; + } + + public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) + { + if(stack1 == null || stack2 == null) + return stack1 == stack2; + return stack1.itemID == stack2.itemID + && stack1.getItemDamage() == stack2.getItemDamage() + && stack1.stackSize == stack2.stackSize + && Objects.equal(stack1.getTagCompound(), stack2.getTagCompound()); + } + + public static IInventory getInventory(World world, int x, int y, int z) + { + TileEntity tile = world.getBlockTileEntity(x, y, z); + if(!(tile instanceof IInventory)) + return null; + + if(tile instanceof TileEntityChest) + return getChest((TileEntityChest) tile); + return (IInventory)tile; + + } + + public static final ForgeDirection[] chestSides = new ForgeDirection[]{ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; + public static IInventory getChest(TileEntityChest chest) + { + for(ForgeDirection fside : chestSides) + { + if(chest.worldObj.getBlockId(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ) == chest.getBlockType().blockID) + return new InventoryLargeChest("container.chestDouble", + (TileEntityChest)chest.worldObj.getBlockTileEntity(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ), chest); + } + return chest; + } + + public static boolean canStack(ItemStack stack1, ItemStack stack2) + { + return stack1 == null || stack2 == null || + (stack1.itemID == stack2.itemID && + (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && + ItemStack.areItemStackTagsEqual(stack2, stack1)) && + stack1.isStackable(); + } + + public static void consumeItem(IInventory inv, int slot) + { + ItemStack stack = inv.getStackInSlot(slot); + Item item = stack.getItem(); + if(item.hasContainerItem()) + { + ItemStack container = item.getContainerItemStack(stack); + inv.setInventorySlotContents(slot, container); + } + else + { + inv.decrStackSize(slot, 1); + } + } + + public static int stackSize(IInventory inv, int slot) + { + ItemStack stack = inv.getStackInSlot(slot); + return stack == null ? 0 : stack.stackSize; + } + + public static ItemStack getRemovableStack(InventoryRange inv, int slot) + { + ItemStack stack = inv.inv.getStackInSlot(slot); + if(stack == null || !inv.canExtractItem(slot, stack)) + return null; + + return stack; + } + + public static void dropOnClose(EntityPlayer player, IInventory inv) + { + for (int i = 0; i < inv.getSizeInventory(); i++) + { + ItemStack stack = inv.getStackInSlotOnClosing(i); + if (stack != null) + player.dropPlayerItem(stack); + } + } + + public static int actualDamage(ItemStack stack) + { + return Item.diamond.getDamage(stack); + } +} From 3d64337681f2a00d9ab919e20f37e14305328bf2 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sat, 21 Dec 2013 23:01:20 +1000 Subject: [PATCH 050/219] Cleaned, refactored and documented inventory package --- codechicken/lib/inventory/InventoryCopy.java | 9 +- codechicken/lib/inventory/InventoryNBT.java | 3 + codechicken/lib/inventory/InventoryRange.java | 3 + .../lib/inventory/InventorySimple.java | 3 + codechicken/lib/inventory/InventoryUtils.java | 114 +++++++++++++----- codechicken/lib/inventory/ItemKey.java | 65 ++++++++++ 6 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 codechicken/lib/inventory/ItemKey.java diff --git a/codechicken/lib/inventory/InventoryCopy.java b/codechicken/lib/inventory/InventoryCopy.java index c36ba0a..8bcfdd5 100644 --- a/codechicken/lib/inventory/InventoryCopy.java +++ b/codechicken/lib/inventory/InventoryCopy.java @@ -4,6 +4,9 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; +/** + * Creates a copy of an IInventory for extended simulation + */ public class InventoryCopy implements IInventory { public boolean[] accessible; @@ -33,11 +36,11 @@ public InventoryCopy open(InventoryRange access) int lslot = access.lastSlot(); if(lslot > accessible.length) { - boolean[] l_accessable = new boolean[lslot]; + boolean[] l_accessible = new boolean[lslot]; ItemStack[] l_items = new ItemStack[lslot]; - System.arraycopy(accessible, 0, l_accessable, 0, accessible.length); + System.arraycopy(accessible, 0, l_accessible, 0, accessible.length); System.arraycopy(items, 0, l_items, 0, items.length); - accessible = l_accessable; + accessible = l_accessible; items = l_items; } diff --git a/codechicken/lib/inventory/InventoryNBT.java b/codechicken/lib/inventory/InventoryNBT.java index e3da78a..a6e338c 100644 --- a/codechicken/lib/inventory/InventoryNBT.java +++ b/codechicken/lib/inventory/InventoryNBT.java @@ -5,6 +5,9 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +/** + * IInventory implementation which saves and loads from an NBT tag + */ public class InventoryNBT implements IInventory { protected ItemStack[] items; diff --git a/codechicken/lib/inventory/InventoryRange.java b/codechicken/lib/inventory/InventoryRange.java index 6efc0bd..f3d8c2d 100644 --- a/codechicken/lib/inventory/InventoryRange.java +++ b/codechicken/lib/inventory/InventoryRange.java @@ -4,6 +4,9 @@ import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.ItemStack; +/** + * Inventory wrapper for unified ISided/IInventory access + */ public class InventoryRange { public IInventory inv; diff --git a/codechicken/lib/inventory/InventorySimple.java b/codechicken/lib/inventory/InventorySimple.java index 90a24a1..12b1c8e 100644 --- a/codechicken/lib/inventory/InventorySimple.java +++ b/codechicken/lib/inventory/InventorySimple.java @@ -4,6 +4,9 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; +/** + * Simple IInventory implementation with an array of items, name and maximum stack size + */ public class InventorySimple implements IInventory { public ItemStack[] items; diff --git a/codechicken/lib/inventory/InventoryUtils.java b/codechicken/lib/inventory/InventoryUtils.java index 64bb560..921b3df 100644 --- a/codechicken/lib/inventory/InventoryUtils.java +++ b/codechicken/lib/inventory/InventoryUtils.java @@ -21,6 +21,9 @@ public class InventoryUtils { + /** + * Static default implementation for IInventory method + */ public static ItemStack decrStackSize(IInventory inv, int slot, int size) { ItemStack item = inv.getStackInSlot(slot); @@ -45,6 +48,9 @@ public static ItemStack decrStackSize(IInventory inv, int slot, int size) return null; } + /** + * Static default implementation for IInventory method + */ public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); @@ -53,9 +59,6 @@ public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) } /** - * - * @param base - * @param addition * @return The quantity of items from addition that can be added to base */ public static int incrStackSize(ItemStack base, ItemStack addition) @@ -67,9 +70,6 @@ public static int incrStackSize(ItemStack base, ItemStack addition) } /** - * - * @param base - * @param addition * @return The quantity of items from addition that can be added to base */ public static int incrStackSize(ItemStack base, int addition) @@ -84,11 +84,17 @@ else if (base.stackSize < base.getMaxStackSize()) return 0; } + /** + * NBT item saving function + */ public static NBTTagList writeItemStacksToTag(ItemStack[] items) { return writeItemStacksToTag(items, 64); } - + + /** + * NBT item saving function with support for stack sizes > 32K + */ public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) { NBTTagList tagList = new NBTTagList(); @@ -110,7 +116,10 @@ else if(maxQuantity > Byte.MAX_VALUE) } return tagList; } - + + /** + * NBT item loading function with support for stack sizes > 32K + */ public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) { for(int i = 0; i < tagList.tagCount(); i++) @@ -129,6 +138,9 @@ else if(qtag instanceof NBTTagShort) } } + /** + * Spawns an itemstack in the world at a location + */ public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) { EntityItem item = new EntityItem(world, dropLocation.x, dropLocation.y, dropLocation.z, stack); @@ -138,6 +150,9 @@ public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) world.spawnEntityInWorld(item); } + /** + * Copies an itemstack with a new quantity + */ public static ItemStack copyStack(ItemStack stack, int quantity) { if(stack == null) @@ -147,8 +162,11 @@ public static ItemStack copyStack(ItemStack stack, int quantity) stack.stackSize = quantity; return stack; } - - public static int getInsertableQuantity(InventoryRange inv, ItemStack stack) + + /** + * Gets the maximum quantity of an item that can be inserted into inv + */ + public static int getInsertibleQuantity(InventoryRange inv, ItemStack stack) { int quantity = 0; stack = copyStack(stack, Integer.MAX_VALUE); @@ -157,6 +175,11 @@ public static int getInsertableQuantity(InventoryRange inv, ItemStack stack) return quantity; } + + public static int getInsertibleQuantity(IInventory inv, ItemStack stack) + { + return getInsertibleQuantity(new InventoryRange(inv), stack); + } public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) { @@ -168,11 +191,17 @@ public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) return Math.min(fit, stack.stackSize); } - public static boolean mergeItemStack(InventoryRange inv, ItemStack stack, boolean doMerge) + public static int fitStackInSlot(IInventory inv, int slot, ItemStack stack) { - if(doMerge && !mergeItemStack(inv, stack, false)) - return false; + return fitStackInSlot(new InventoryRange(inv), slot, stack); + } + /** + * @param simulate. If set to true, no items will actually be inserted + * @return The number of items unable to be inserted + */ + public static int insertItem(InventoryRange inv, ItemStack stack, boolean simulate) + { stack = stack.copy(); for(int pass = 0; pass < 2; pass++) { @@ -186,7 +215,7 @@ public static boolean mergeItemStack(InventoryRange inv, ItemStack stack, boolea if(base != null) { stack.stackSize-=fit; - if(doMerge) + if(!simulate) { base.stackSize+=fit; inv.inv.setInventorySlotContents(slot, base); @@ -194,27 +223,53 @@ public static boolean mergeItemStack(InventoryRange inv, ItemStack stack, boolea } else if(pass == 1) { - if(doMerge) + if(!simulate) inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); stack.stackSize-=fit; } if(stack.stackSize == 0) - return true; + return 0; } } - return false; + return stack.stackSize; + } + + public static int insertItem(IInventory inv, ItemStack stack, boolean simulate) + { + return insertItem(new InventoryRange(inv), stack, simulate); + } + + /** + * Gets the stack in slot if it can be extracted + */ + public static ItemStack getExtractableStack(InventoryRange inv, int slot) + { + ItemStack stack = inv.inv.getStackInSlot(slot); + if(stack == null || !inv.canExtractItem(slot, stack)) + return null; + + return stack; + } + + public static ItemStack getExtractableStack(IInventory inv, int slot) + { + return getExtractableStack(new InventoryRange(inv), slot); } public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { if(stack1 == null || stack2 == null) return stack1 == stack2; + return stack1.itemID == stack2.itemID && stack1.getItemDamage() == stack2.getItemDamage() && stack1.stackSize == stack2.stackSize && Objects.equal(stack1.getTagCompound(), stack2.getTagCompound()); } - + + /** + * Gets an IInventory from a coordinate with support for double chests + */ public static IInventory getInventory(World world, int x, int y, int z) { TileEntity tile = world.getBlockTileEntity(x, y, z); @@ -248,6 +303,9 @@ public static boolean canStack(ItemStack stack1, ItemStack stack2) stack1.isStackable(); } + /** + * Consumes one item from slot in inv with support for containers. + */ public static void consumeItem(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); @@ -263,21 +321,18 @@ public static void consumeItem(IInventory inv, int slot) } } + /** + * Gets the size of the stack in a slot. Returns 0 on null stacks + */ public static int stackSize(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); return stack == null ? 0 : stack.stackSize; } - - public static ItemStack getRemovableStack(InventoryRange inv, int slot) - { - ItemStack stack = inv.inv.getStackInSlot(slot); - if(stack == null || !inv.canExtractItem(slot, stack)) - return null; - - return stack; - } + /** + * Drops all items from inv using getStackInSlotOnClosing + */ public static void dropOnClose(EntityPlayer player, IInventory inv) { for (int i = 0; i < inv.getSizeInventory(); i++) @@ -287,7 +342,10 @@ public static void dropOnClose(EntityPlayer player, IInventory inv) player.dropPlayerItem(stack); } } - + + /** + * Gets the actual damage of an item without asking the Item + */ public static int actualDamage(ItemStack stack) { return Item.diamond.getDamage(stack); diff --git a/codechicken/lib/inventory/ItemKey.java b/codechicken/lib/inventory/ItemKey.java new file mode 100644 index 0000000..e52a923 --- /dev/null +++ b/codechicken/lib/inventory/ItemKey.java @@ -0,0 +1,65 @@ +package codechicken.lib.inventory; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import com.google.common.base.Objects; +import static codechicken.lib.inventory.InventoryUtils.*; + +/** + * Comparable ItemStack with a hashCode implementation. + */ +public class ItemKey implements Comparable +{ + public ItemStack item; + private int hashcode = 0; + + public ItemKey(ItemStack k) + { + item = k; + } + + public ItemKey(int id, int damage) + { + this(new ItemStack(id, 1, damage)); + } + + public ItemKey(int id, int damage, NBTTagCompound compound) + { + this(id, damage); + item.setTagCompound(compound); + } + + @Override + public boolean equals(Object obj) + { + if(!(obj instanceof ItemKey)) + return false; + + ItemKey k = (ItemKey)obj; + return item.itemID == k.item.itemID && + actualDamage(item) == actualDamage(k.item) && + Objects.equal(item.stackTagCompound, k.item.stackTagCompound); + } + + @Override + public int hashCode() + { + return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(item.itemID, actualDamage(item), item.stackTagCompound)); + } + + public int compareInt(int a, int b) + { + return a == b ? 0 : a < b ? -1 : 1; + } + + @Override + public int compareTo(ItemKey o) + { + if(item.itemID != o.item.itemID) + return compareInt(item.itemID, o.item.itemID); + if(actualDamage(item) != actualDamage(o.item)) + return compareInt(actualDamage(item), actualDamage(o.item)); + return 0; + } +} From 3c81313a8c2c3666dc23881eae95f74fb9d628ea Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sat, 21 Dec 2013 23:01:53 +1000 Subject: [PATCH 051/219] Added temporary fix for issues with new mcp system. --- codechicken/lib/packet/MetaPacket.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/codechicken/lib/packet/MetaPacket.java b/codechicken/lib/packet/MetaPacket.java index c29a7ee..12cd7d1 100644 --- a/codechicken/lib/packet/MetaPacket.java +++ b/codechicken/lib/packet/MetaPacket.java @@ -58,14 +58,17 @@ public void readPacketData(DataInput datain) } @Override - public void writePacketData(DataOutput dataout) throws IOException - { + public void writePacketData(DataOutput dataout) { //send a dummy 250 super.writePacketData(dataout); - - for(Packet p : packets) - Packet.writePacket(p, dataout); - + + for(Packet p : packets)//TODO: fix extends + try { + Packet.writePacket(p, dataout); + } catch (IOException e) { + e.printStackTrace(); + } + //adjust sent size for Packet.writePacket Packet.sentSize-=getPacketSize()-super.getPacketSize(); } From ffc284349ed4b3bdd00e27d069d18d07ea156964 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sat, 21 Dec 2013 23:02:51 +1000 Subject: [PATCH 052/219] Added some more utility to Cuboid/Rotation --- codechicken/lib/vec/CuboidCoord.java | 45 ++++++++++++++++++++++++++-- codechicken/lib/vec/Rotation.java | 24 +++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java index 90b69ba..5551630 100644 --- a/codechicken/lib/vec/CuboidCoord.java +++ b/codechicken/lib/vec/CuboidCoord.java @@ -2,11 +2,19 @@ import net.minecraft.util.AxisAlignedBB; -public class CuboidCoord +import java.util.Iterator; + +public class CuboidCoord implements Iterable { public BlockCoord min; public BlockCoord max; - + + public CuboidCoord() + { + min = new BlockCoord(); + max = new BlockCoord(); + } + public CuboidCoord(BlockCoord min, BlockCoord max) { this.min = min; @@ -128,4 +136,37 @@ public CuboidCoord set(int[] ia) { return set(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); } + + public Iterator iterator() { + return new Iterator() { + BlockCoord b = null; + + public boolean hasNext() { + return b == null || !b.equals(max); + } + + public BlockCoord next() { + if(b == null) + b = min.copy(); + else { + if(b.z != max.z) + b.z++; + else { + b.z = min.z; + if(b.y != max.y) + b.y++; + else { + b.y = min.y; + b.x++; + } + } + } + return b; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } } diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java index 86a6c81..e3ee9d5 100644 --- a/codechicken/lib/vec/Rotation.java +++ b/codechicken/lib/vec/Rotation.java @@ -4,6 +4,7 @@ import java.math.MathContext; import java.math.RoundingMode; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import org.lwjgl.opengl.GL11; @@ -123,7 +124,7 @@ public static int rotationTo(int s1, int s2) throw new IllegalArgumentException("Faces "+s1+" and "+s2+" are opposites"); return rotSideMap[s1*6+s2]; } - + /** * @param player The placing player, used for obtaining the look vector * @param side The side of the block being placed on @@ -138,7 +139,7 @@ public static int getSidedRotation(EntityPlayer player, int side) { Vector3 axis = Rotation.axes[rotateSide(side^1, r)]; double d = look.scalarProject(axis); - if(max > d) + if(max > d)//TODO wrong way round { max = d; maxr = r; @@ -154,6 +155,25 @@ public static Transformation sideOrientation(int s, int r) { return quarterRotations[(r+sideRotOffsets[s])%4].with(sideRotations[s]); } + + /** + * @param entity The placing entity, used for obtaining the look vector + * @return The side towards which the entity is most directly looking. + */ + public static int getSideFromLookAngle(EntityLivingBase entity) + { + Vector3 look = new Vector3(entity.getLook(1)); + double max = 0; + int maxs = 0; + for(int s = 0; s < 6; s++) { + double d = look.scalarProject(axes[s]); + if(d > max) { + max = d; + maxs = s; + } + } + return maxs; + } public double angle; public Vector3 axis; From eb6f5e5e7bf3dd0dfa19aafba0235a3f237b2b08 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sat, 21 Dec 2013 23:43:28 +1000 Subject: [PATCH 053/219] Fix compile time compatibility with new and old forge --- codechicken/lib/packet/MetaPacket.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/codechicken/lib/packet/MetaPacket.java b/codechicken/lib/packet/MetaPacket.java index 12cd7d1..a3c2945 100644 --- a/codechicken/lib/packet/MetaPacket.java +++ b/codechicken/lib/packet/MetaPacket.java @@ -59,18 +59,18 @@ public void readPacketData(DataInput datain) @Override public void writePacketData(DataOutput dataout) { - //send a dummy 250 - super.writePacketData(dataout); + try {//TODO: fix super IOException + //send a dummy 250 + super.writePacketData(dataout); - for(Packet p : packets)//TODO: fix extends - try { + for(Packet p : packets) Packet.writePacket(p, dataout); - } catch (IOException e) { - e.printStackTrace(); - } - //adjust sent size for Packet.writePacket - Packet.sentSize-=getPacketSize()-super.getPacketSize(); + //adjust sent size for Packet.writePacket + Packet.sentSize-=getPacketSize()-super.getPacketSize(); + } catch (IOException e) { + e.printStackTrace(); + } } @Override From 5401f3afb0d5f1481e508d2d39715dae5ae32cfc Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 9 Jan 2014 02:55:11 +1000 Subject: [PATCH 054/219] Improved ASMReader parsing. Can now handle method/field instructions with spaces in the description Added equals method to colour --- codechicken/lib/asm/ASMReader.java | 5 ++++- codechicken/lib/colour/Colour.java | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/asm/ASMReader.java b/codechicken/lib/asm/ASMReader.java index c040935..e43de99 100644 --- a/codechicken/lib/asm/ASMReader.java +++ b/codechicken/lib/asm/ASMReader.java @@ -305,7 +305,10 @@ else if(split[0].startsWith("L")) break; case FIELD_INSN: case METHOD_INSN: - insn = ObfMapping.fromDesc(split[1]).toInsn(opcode); + StringBuilder sb = new StringBuilder(); + for(int i = 1; i < split.length; i++) + sb.append(split[i]); + insn = ObfMapping.fromDesc(sb.toString()).toInsn(opcode); break; case INVOKE_DYNAMIC_INSN: throw new Exception("Found INVOKEDYNAMIC while reading"); diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index 8960c07..41cf7a3 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -138,4 +138,9 @@ public Colour set(Colour colour) a = colour.a; return this; } + + public boolean equals(Colour colour) + { + return colour != null && rgba() == colour.rgba(); + } } From 477b77e7e1bdd3ec42105bdfc2897d72161599e4 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 15 Jan 2014 17:41:27 +1000 Subject: [PATCH 055/219] Added 9Seg Canvas --- codechicken/lib/gui/Canvas9Seg.java | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 codechicken/lib/gui/Canvas9Seg.java diff --git a/codechicken/lib/gui/Canvas9Seg.java b/codechicken/lib/gui/Canvas9Seg.java new file mode 100644 index 0000000..b558197 --- /dev/null +++ b/codechicken/lib/gui/Canvas9Seg.java @@ -0,0 +1,78 @@ +package codechicken.lib.gui; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.TextureDataHolder; +import codechicken.lib.render.TextureUtils; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; + +public class Canvas9Seg +{ + public final ResourceLocation tex; + public float[] seg_u = new float[4]; + public float[] seg_v = new float[4]; + public int[] seg_w = new int[3]; + public int[] seg_h = new int[3]; + + public Canvas9Seg(ResourceLocation tex) { + this.tex = tex; + load(); + } + + private int[] readMarkers(TextureDataHolder data, int stride, int size) { + int[] markers = new int[4]; + + int marker = 1; + int prev_col = data.data[0]; + for(int i = 1; i < size; i++) { + if(data.data[i*stride] != prev_col) { + markers[marker] = i; + prev_col = data.data[i*stride]; + if(++marker == 4) + break; + } + } + + markers[0] += 1; + markers[3] -= 1; + return markers; + } + + private void parseMarkers(TextureDataHolder data, int stride, int size, int[] sizes, float[] texcoords) { + int[] markers = readMarkers(data, stride, size); + for(int i = 0; i < 4; i++) { + texcoords[i] = markers[i]/(float)size; + if(i > 0) + sizes[i-1] = markers[i]-markers[i-1]; + } + } + + private void load() { + TextureDataHolder data = TextureUtils.loadTexture(tex); + parseMarkers(data, 1, data.width, seg_w, seg_u); + parseMarkers(data, data.width, data.height, seg_h, seg_v); + } + + private void drawSeg(int[] sw, int[] sh, int seg) { + Tessellator t = Tessellator.instance; + int u = seg%3; int v = seg/3; + t.addVertexWithUV(sw[u], sh[v], 0, seg_u[u], seg_v[v]); + t.addVertexWithUV(sw[u], sh[v+1], 0, seg_u[u], seg_v[v+1]); + t.addVertexWithUV(sw[u+1], sh[v+1], 0, seg_u[u+1], seg_v[v+1]); + t.addVertexWithUV(sw[u+1], sh[v], 0, seg_u[u+1], seg_v[v]); + } + + public void draw(int x, int y, int w, int h) { + CCRenderState.changeTexture(tex); + CCRenderState.reset(); + CCRenderState.startDrawing(7); + + int[] sw = new int[]{x, x+seg_w[0], x+w-seg_w[2], x+w}; + int[] sh = new int[]{y, y+seg_h[0], y+h-seg_h[2], y+h}; + + for(int seg = 0; seg < 9; seg++) + drawSeg(sw, sh, seg); + + CCRenderState.draw(); + } +} From 7450370d99c6f23b8f8b963728a59e42eba5672b Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 28 Jan 2014 16:54:30 +1000 Subject: [PATCH 056/219] Added support for Qubicle Model files. --- codechicken/lib/render/CCModel.java | 81 ++- codechicken/lib/render/QBImporter.java | 755 +++++++++++++++++++++++++ codechicken/lib/render/UV.java | 8 + codechicken/lib/vec/BlockCoord.java | 35 ++ codechicken/lib/vec/CuboidCoord.java | 38 +- codechicken/lib/vec/Rectangle4i.java | 62 +- codechicken/lib/vec/Vector3.java | 40 ++ 7 files changed, 1006 insertions(+), 13 deletions(-) create mode 100644 codechicken/lib/render/QBImporter.java diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 6b0620f..d90a545 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -1,9 +1,6 @@ package codechicken.lib.render; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -702,6 +699,82 @@ public static CCModel createModel(List verts, List uvs, List int addIndex(List list, T elem) + { + int i = list.indexOf(elem)+1; + if(i == 0) { + list.add(elem); + i = list.size(); + } + return i; + } + + private static String clean(double d) { + return d == (int) d ? Integer.toString((int)d) : Double.toString(d); + } + + public static void exportObj(Map models, PrintWriter p) + { + List verts = new ArrayList(); + List uvs = new ArrayList(); + List normals = new ArrayList(); + List polys = new ArrayList(); + for(Map.Entry e : models.entrySet()) { + p.println("g "+e.getKey()); + CCModel m = e.getValue(); + + int vStart = verts.size(); + int uStart = uvs.size(); + int nStart = normals.size(); + boolean hasNormals = m.normals != null; + polys.clear(); + + for(int i = 0; i < m.verts.length; i++) { + int[] ia = new int[hasNormals ? 3 : 2]; + ia[0] = addIndex(verts, m.verts[i].vec); + ia[1] = addIndex(uvs, m.verts[i].uv); + if(hasNormals) + ia[2] = addIndex(normals, m.normals[i]); + polys.add(ia); + } + + if(vStart < verts.size()) { + p.println(); + for(int i = vStart; i < verts.size(); i++) { + Vector3 v = verts.get(i); + p.format("v %s %s %s\n", clean(v.x), clean(v.y), clean(v.z)); + } + } + if(uStart < uvs.size()) { + p.println(); + for(int i = uStart; i < uvs.size(); i++) { + UV uv = uvs.get(i); + p.format("vt %s %s\n", clean(uv.u), clean(uv.v)); + } + } + if(nStart < normals.size()) { + p.println(); + for(int i = nStart; i < normals.size(); i++) { + Vector3 n = normals.get(i); + p.format("vn %s %s %s\n", clean(n.x), clean(n.y), clean(n.z)); + } + } + + p.println(); + for(int i = 0; i < polys.size(); i++) { + if(i%m.vp == 0) + p.format("f"); + int[] ia = polys.get(i); + if(hasNormals) + p.format(" %d/%d/%d", ia[0], ia[1], ia[2]); + else + p.format(" %d/%d", ia[0], ia[1]); + if(i%m.vp == m.vp-1) + p.println(); + } + } + } + /** * Brings the UV coordinates of each face closer to the center UV by d. * Useful for fixing texture seams diff --git a/codechicken/lib/render/QBImporter.java b/codechicken/lib/render/QBImporter.java new file mode 100644 index 0000000..8af4aa3 --- /dev/null +++ b/codechicken/lib/render/QBImporter.java @@ -0,0 +1,755 @@ +package codechicken.lib.render; + +import codechicken.lib.vec.*; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.util.Icon; +import net.minecraft.util.ResourceLocation; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.*; + +public class QBImporter +{ + private static class ImagePackNode + { + Rectangle4i rect; + ImagePackNode child1; + ImagePackNode child2; + QBImage packed; + + public ImagePackNode(int x, int y, int w, int h) { + rect = new Rectangle4i(x, y, w, h); + } + + public boolean pack(QBImage img) { + if(child1 != null) + return child1.pack(img) || child2.pack(img); + + if(packed != null) + return false; + + int fit = getFit(img.width(), img.height()); + if(fit == 0) + return false; + + if((fit & 2) != 0) {//exact fit + packed = img; + img.packSlot = rect; + img.packT = new ImageTransform((fit&1)<<2); + return true; + } + + int w = (fit & 1) == 0 ? img.width() : img.height(); + int h = (fit & 1) == 0 ? img.height() : img.width(); + + if(rect.w - w > rect.h - h) {//create split with biggest leftover space + child1 = new ImagePackNode(rect.x, rect.y, w, rect.h); + child2 = new ImagePackNode(rect.x+w, rect.y, rect.w-w, rect.h); + } else { + child1 = new ImagePackNode(rect.x, rect.y, rect.w, h); + child2 = new ImagePackNode(rect.x, rect.y+h, rect.w, rect.h-h); + } + return child1.pack(img); + } + + private int getFit(int w, int h) { + if(w == rect.w && h == rect.h) + return 2; + if(w == rect.h && h == rect.w) + return 3; + if(rect.w >= w && rect.h >= h) + return 4; + if(rect.w >= h && rect.h >= w) + return 5; + + return 0; + } + + private static void nextSize(Rectangle4i rect, boolean square) { + if(square) { + rect.w <<= 1; + rect.h <<= 1; + } + else { + if(rect.w == rect.h) + rect.w *= 2; + else + rect.h *= 2; + } + } + + public static ImagePackNode pack(List images, boolean square) { + Collections.sort(images); + + int area = 0; + for(QBImage img : images) + area+=img.area(); + + ImagePackNode node = new ImagePackNode(0, 0, 2, 2); + while(node.rect.area() < area) + nextSize(node.rect, square); + + while(true) { + boolean packed = true; + for(QBImage img : images) + if(!node.pack(img)) { + packed = false; + break; + } + + if(packed) + return node; + + node.child1 = node.child2 = null; + nextSize(node.rect, square); + } + } + + public BufferedImage toImage() { + BufferedImage img = new BufferedImage(rect.w, rect.h, BufferedImage.TYPE_INT_ARGB); + write(img); + return img; + } + + private void write(BufferedImage img) { + if(child1 != null) { + child1.write(img); + child2.write(img); + } + else if(packed != null) { + ImageTransform t = packed.packT; + for(int u = 0; u < rect.w; u++) + for(int v = 0; v < rect.h; v++) { + int rgba = t.access(packed, u, v); + img.setRGB(u+rect.x, v+rect.y, rgba>>>8 | rgba<<24); + } + } + } + } + + private static class ImageTransform + { + int transform; + + public ImageTransform(int i) { + transform = i; + } + + public ImageTransform() { + this(0); + } + + public boolean transpose() { + return (transform&4) != 0; + } + + public boolean flipU() { + return (transform&1) != 0; + } + + public boolean flipV() { + return (transform&2) != 0; + } + + public int access(QBImage img, int u, int v) { + if(transpose()) { + int tmp = u; u = v; v = tmp; + } + if(flipU()) + u = img.width()-1-u; + if(flipV()) + v = img.height()-1-v; + + return img.data[u][v]; + } + + public UV transform(UV uv) { + if(transpose()) { + double tmp = uv.u; uv.u = uv.v; uv.v = tmp; + } + if(flipU()) + uv.u = 1-uv.u; + if(flipV()) + uv.v = 1-uv.v; + + return uv; + } + } + + public static class QBImage implements Comparable + { + int[][] data; + ImageTransform packT; + Rectangle4i packSlot; + + public int width() { + return data.length; + } + + public int height() { + return data[0].length; + } + + public int area() { + return width()*height(); + } + + @Override + public int compareTo(QBImage o) { + int a = area(); int b = o.area(); + return a > b ? -1 : a == b ? 0 : 1; + } + + public ImageTransform transformTo(QBImage img) { + if(width() == img.width() && height() == img.height()) + for(int i = 0; i < 4; i++) { + ImageTransform t = new ImageTransform(i); + if(equals(img, t)) + return t; + } + if(width() == img.height() && height() == img.width()) + for(int i = 4; i < 8; i++) { + ImageTransform t = new ImageTransform(i); + if(equals(img, t)) + return t; + } + return null; + } + + public boolean equals(QBImage img, ImageTransform t) { + for(int u = 0; u < img.width(); u++) + for(int v = 0; v < img.height(); v++) + if(t.access(this, u, v) != img.data[u][v]) + return false; + + return true; + } + + public void transform(UV uv) { + packT.transform(uv); + uv.u*=packSlot.w; + uv.v*=packSlot.h; + uv.u+=packSlot.x; + uv.v+=packSlot.y; + } + } + + + private static final int[][] vertOrder = new int[][] {//clockwise because MC is left handed + {3, 0}, + {1, 0}, + {1, 2}, + {3, 2}}; + + public static class QBQuad + { + public Vertex5[] verts = new Vertex5[4]; + public QBImage image = new QBImage(); + public ImageTransform t = new ImageTransform(); + public int side; + + public QBQuad(int side) { + this.side = side; + } + + public void applyImageT() { + for(Vertex5 vert : verts) { + t.transform(vert.uv); + image.transform(vert.uv); + } + } + + + public static QBQuad restore(Rectangle4i flat, int side, double d, QBImage img) { + QBQuad quad = new QBQuad(side); + quad.image = img; + + Transformation t = new Scale(-1, 1, -1).with(Rotation.sideOrientation(side, 0)).with(new Translation(new Vector3().setSide(side, d))); + quad.verts[0] = new Vertex5(flat.x, 0, flat.y, 0, 0); + quad.verts[1] = new Vertex5(flat.x+flat.w, 0, flat.y, 1, 0); + quad.verts[2] = new Vertex5(flat.x+flat.w, 0, flat.y+flat.h, 1, 1); + quad.verts[3] = new Vertex5(flat.x, 0, flat.y+flat.h, 0, 1); + for(Vertex5 vert : quad.verts) + vert.apply(t); + + return quad; + } + + public Rectangle4i flatten() { + Transformation t = Rotation.sideOrientation(side, 0).inverse().with(new Scale(-1, 0, -1)); + Vector3 vmin = verts[0].vec.copy().apply(t); + Vector3 vmax = verts[2].vec.copy().apply(t); + return new Rectangle4i((int)vmin.x, (int)vmin.z, (int)(vmax.x-vmin.x), (int)(vmax.z-vmin.z)); + } + } + + public static class QBCuboid + { + public QBMatrix mat; + public CuboidCoord c; + public int sides; + + public QBCuboid(QBMatrix mat, CuboidCoord c) { + this.mat = mat; + this.c = c; + sides = 0; + } + + public static boolean intersects(QBCuboid a, QBCuboid b) { + CuboidCoord c = a.c; + CuboidCoord d = b.c; + return c.min.x <= d.max.x && + d.min.x <= c.max.x && + c.min.y <= d.max.y && + d.min.y <= c.max.y && + c.min.z <= d.max.z && + d.min.z <= c.max.z; + } + + public static void clip(QBCuboid a, QBCuboid b) { + if(intersects(a, b)) { + a.clip(b); + b.clip(a); + } + } + + public void clip(QBCuboid o) { + CuboidCoord d = o.c; + for(int a = 0; a < 6; a+=2) + { + int a1 = (a+2)%6; + int a2 = (a+4)%6; + if(c.getSide(a1+1) <= d.getSide(a1+1) && + c.getSide(a1) >= d.getSide(a1) && + c.getSide(a2+1) <= d.getSide(a2+1) && + c.getSide(a2) >= d.getSide(a2)) { + + if(c.getSide(a) <= d.getSide(a+1) && c.getSide(a) >= d.getSide(a)) { + c.setSide(a, d.getSide(a + 1) + 1); + sides|=1<= d.getSide(a) && c.getSide(a+1) <= d.getSide(a+1)) { + c.setSide(a + 1, d.getSide(a) - 1); + sides|=2< quads) { + Cuboid6 box = c.bounds(); + for(int s = 0; s < 6; s++) + if((sides & 1<>1] = box.getSide(side); + + QBQuad quad = new QBQuad(side); + for(int i = 0; i < 4; i++) { + int rU = vertOrder[i][0]; + int rV = vertOrder[i][1]; + int sideU = Rotation.rotateSide(side, rU); + int sideV = Rotation.rotateSide(side, rV); + da[sideU>>1] = box.getSide(sideU); + da[sideV>>1] = box.getSide(sideV); + quad.verts[i] = new Vertex5(Vector3.fromAxes(da), (3-rU)/2, rV/2); + } + + int sideU = Rotation.rotateSide(side, 1); + int sideV = Rotation.rotateSide(side, 2); + quad.image.data = new int[c.size(sideU)][c.size(sideV)]; + QBImage image = quad.image; + + int[] ia = new int[3]; + ia[side>>1] = c.getSide(side); ia[sideU>>1] = c.getSide(sideU^1); ia[sideV>>1] = c.getSide(sideV^1); + BlockCoord b = BlockCoord.fromAxes(ia); + BlockCoord bU = BlockCoord.sideOffsets[sideU]; + BlockCoord bV = BlockCoord.sideOffsets[sideV]; + for(int u = 0; u < image.width(); u++) + for(int v = 0; v < image.height(); v++) + image.data[u][v] = mat.matrix[b.x+bU.x*u+bV.x*v][b.y+bU.y*u+bV.y*v][b.z+bU.z*u+bV.z*v]; + + return quad; + } + } + + public static class QBMatrix + { + public String name; + public BlockCoord pos; + public BlockCoord size; + public int[][][] matrix; + + public void readMatrix(DataInputStream din, boolean compressed) throws IOException { + if(compressed) { + int z = 0; + while (z < size.z) + { + int index = 0; + + while (true) + { + int data = din.readInt(); + + if (data == NEXTSLICEFLAG) + break; + + if (data == CODEFLAG) { + int count = readTni(din); + data = din.readInt(); + + for(int j = 0; j < count; j++, index++) + matrix[index % size.x][index / size.x][z] = data; + } + else { + matrix[index % size.x][index / size.x][z] = data; + index++; + } + } + z++; + } + } else { + for(int z = 0; z < size.z; z++) + for(int y = 0; y < size.y; y++) + for(int x = 0; x < size.x; x++) + matrix[x][y][z] = din.readInt(); + } + } + + public void convertBGRAtoRGBA() { + for(int z = 0; z < size.z; z++) + for(int y = 0; y < size.y; y++) + for(int x = 0; x < size.x; x++) { + int i = matrix[x][y][z]; + matrix[x][y][z] = Integer.reverseBytes(i>>>8)|i&0xFF; + } + } + + private boolean voxelFull(boolean[][][] solid, CuboidCoord c) { + for(BlockCoord b : c) + if(matrix[b.x][b.y][b.z] == 0) + return false; + for(BlockCoord b : c) + solid[b.x][b.y][b.z] = false; + return true; + } + + private QBCuboid expand(boolean[][][] solid, BlockCoord b) { + CuboidCoord c = new CuboidCoord(b); + solid[b.x][b.y][b.z] = false; + + for(int s = 0; s < 6; s++) { + CuboidCoord slice = c.copy(); + slice.shrink(s^1, slice.size(s)-1); + slice.expand(s, 1); + + while(slice.getSide(s) >= 0 && slice.getSide(s) < size.getSide(s)) { + if(!voxelFull(solid, slice)) + break; + slice.shrink(s ^ 1, 1); + slice.expand(s, 1); + c.expand(s, 1); + } + } + return new QBCuboid(this, c); + } + + public List rectangulate() { + List list = new ArrayList(); + boolean[][][] solid = new boolean[size.x][size.y][size.z]; + for(int z = 0; z < size.z; z++) + for(int y = 0; y < size.y; y++) + for(int x = 0; x < size.x; x++) + solid[x][y][z] = matrix[x][y][z] != 0; + + for(int x = 0; x < size.x; x++) + for(int z = 0; z < size.z; z++) + for(int y = 0; y < size.y; y++) + if(solid[x][y][z]) + list.add(expand(solid, new BlockCoord(x, y, z))); + + for(int i = 0; i < list.size(); i++) + for(int j = i+1; j < list.size(); j++) + QBCuboid.clip(list.get(i), list.get(j)); + + return list; + } + + public List extractQuads(boolean texturePlanes) { + List quads = new LinkedList(); + for(QBCuboid c : rectangulate()) + c.extractQuads(quads); + + if(texturePlanes) + optimisePlanes(quads); + + return quads; + } + + private void optimisePlanes(List quads) { + Multimap map = HashMultimap.create(); + for(QBQuad quad : quads) + map.put(quad.side | ((int)quad.verts[0].vec.getSide(quad.side))<<3, quad); + + quads.clear(); + for(Integer key : map.keySet()) { + Collection plane = map.get(key); + if(plane.size() == 1) { + quads.add(plane.iterator().next()); + continue; + } + + int side = key&7; + Rectangle4i rect = null; + for(QBQuad q : plane) + if(rect == null) + rect = q.flatten(); + else + rect.include(q.flatten()); + + QBImage img = new QBImage(); + img.data = new int[rect.w][rect.h]; + for(QBQuad q : plane) { + QBImage from = q.image; + Rectangle4i r = q.flatten(); + int du = r.x-rect.x; + int dv = r.y-rect.y; + for(int u = 0; u < from.width(); u++) + for(int v = 0; v < from.height(); v++) + img.data[du+u][dv+v] = from.data[u][v]; + } + + quads.add(QBQuad.restore(rect, side, key>>3, img)); + } + } + + public CCModel buildModel(List quads, BufferedImage img, boolean scaleMC) { + CCModel m = CCModel.quadModel(quads.size()*4); + int i = 0; + for(QBQuad quad : quads) { + quad.applyImageT(); + m.verts[i++] = quad.verts[0]; + m.verts[i++] = quad.verts[1]; + m.verts[i++] = quad.verts[2]; + m.verts[i++] = quad.verts[3]; + } + m.apply(new UVScale(1D/img.getWidth(), 1D/img.getHeight())); + m.apply(new Translation(pos.x, pos.y, pos.z)); + if(scaleMC) + m.apply(new Scale(1/16D)); + m.computeNormals(); + return m; + } + + private static void addImages(List quads, List images) { + for(QBQuad q : quads) { + QBImage img = q.image; + boolean matched = false; + for(QBImage img2 : images) { + ImageTransform t = img.transformTo(img2); + if(t != null) { + q.t = t; + q.image = img2; + matched = true; + break; + } + } + if(!matched) + images.add(img); + } + } + } + + public static final int TEXTUREPLANES = 1; + public static final int SQUARETEXTURE = 2; + public static final int MERGETEXTURES = 4; + public static final int SCALEMC = 8; + public static class QBModel + { + public QBMatrix[] matrices; + public boolean rightHanded; + + + + public RasterisedModel toRasterisedModel(int flags) { + List qbImages = new ArrayList(); + List> modelQuads = new ArrayList>(); + List images = new ArrayList(); + + boolean texturePlanes = (flags & TEXTUREPLANES) != 0; + boolean squareTextures = (flags & SQUARETEXTURE) != 0; + boolean mergeTextures = (flags & MERGETEXTURES) != 0; + boolean scaleMC = (flags & SCALEMC) != 0; + + for(QBMatrix mat : matrices) { + List quads = mat.extractQuads(texturePlanes); + modelQuads.add(quads); + QBMatrix.addImages(quads, qbImages); + if(!mergeTextures) { + images.add(ImagePackNode.pack(qbImages, squareTextures).toImage()); + qbImages.clear(); + } + } + + if(mergeTextures) + images.add(ImagePackNode.pack(qbImages, squareTextures).toImage()); + + RasterisedModel m = new RasterisedModel(images); + for(int i = 0; i < matrices.length; i++) { + QBMatrix mat = matrices[i]; + BufferedImage img = images.get(mergeTextures ? 0 : i); + m.add(mat.name, mat.buildModel(modelQuads.get(i), img, scaleMC)); + } + return m; + } + } + + public static class RasterisedModel + { + private class Holder { + CCModel m; + int img; + + public Holder(CCModel m, int img) { + this.m = m; + this.img = img; + } + } + + private Map map = new HashMap(); + private List images; + private String[] icons; + + public RasterisedModel(List images) { + this.images = images; + icons = new String[images.size()]; + } + + public void add(String name, CCModel m) { + map.put(name, new Holder(m, Math.min(map.size(), images.size()-1))); + } + + public CCModel getModel(String key) { + return map.get(key).m; + } + + public Icon getIcon(String key, IconRegister r, String iconName) { + int img = map.get(key).img; + if(icons[img] != null && !iconName.equals(icons[img])) + throw new IllegalArgumentException("Attempted to get a previously registered icon by a different name: "+icons[img]+", "+iconName); + if(icons[img] != null) + return r.registerIcon(iconName); + + icons[img] = iconName; + return TextureUtils.getTextureSpecial(r, iconName).addTexture(new TextureDataHolder(images.get(img))); + } + + private void exportImg(BufferedImage img, File imgFile) throws IOException { + if(!imgFile.exists()) + imgFile.createNewFile(); + ImageIO.write(img, "PNG", imgFile); + } + + public void export(File objFile, File imgDir) { + try { + if(!objFile.exists()) + objFile.createNewFile(); + if(!imgDir.exists()) + imgDir.mkdirs(); + + Map modelMap = new HashMap(); + for(Map.Entry e : map.entrySet()) + modelMap.put(e.getKey(), e.getValue().m); + + PrintWriter p = new PrintWriter(objFile); + CCModel.exportObj(modelMap, p); + p.close(); + + if(images.size() < map.size()) + exportImg(images.get(0), new File(imgDir, objFile.getName().replaceAll("(.+)\\..+", "$1.png"))); + else + for(Map.Entry e : map.entrySet()) + exportImg(images.get(e.getValue().img), new File(imgDir, e.getKey()+".png")); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private static String readAsciiString(DataInputStream din) throws IOException { + byte[] bytes = new byte[din.readByte()&0xFF]; + din.readFully(bytes); + return new String(bytes, "US-ASCII"); + } + + private static int readTni(DataInputStream din) throws IOException { + return Integer.reverseBytes(din.readInt()); + } + + private static final int CODEFLAG = Integer.reverseBytes(2); + private static final int NEXTSLICEFLAG = Integer.reverseBytes(6); + public static QBModel loadQB(InputStream input) throws IOException { + DataInputStream din = new DataInputStream(input); + + QBModel m = new QBModel(); + int version = din.readInt(); + int colorFormat = din.readInt(); + m.rightHanded = din.readInt() != 0; + boolean compressed = din.readInt() != 0; + boolean visEncoded = din.readInt() != 0; + + if(visEncoded) + throw new IllegalArgumentException("Encoded Visiblity States not supported"); + + m.matrices = new QBMatrix[readTni(din)]; + for(int i = 0; i < m.matrices.length; i++) { + QBMatrix mat = new QBMatrix(); + m.matrices[i] = mat; + mat.name = readAsciiString(din); + mat.size = new BlockCoord(readTni(din), readTni(din), readTni(din)); + mat.pos = new BlockCoord(readTni(din), readTni(din), readTni(din)); + mat.matrix = new int[mat.size.x][mat.size.y][mat.size.z]; + mat.readMatrix(din, compressed); + if(colorFormat == 1) + mat.convertBGRAtoRGBA(); + } + + return m; + } + + public static QBModel loadQB(ResourceLocation res) { + try + { + return loadQB(Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream()); + } + catch(Exception e) + { + throw new RuntimeException("failed to load model: "+res, e); + } + } + + /** + * try { + File dump = new File("packed.png"); + if(!dump.exists()) dump.createNewFile(); + ImageIO.write(img, "PNG", dump); + + File dump2 = new File("packed.obj"); + if(!dump2.exists()) dump2.createNewFile(); + PrintWriter p = new PrintWriter(dump2); + CCModel.exportObj(Collections.singletonMap(name, m), p); + p.close(); + } catch(IOException e) { + e.printStackTrace(); + } + */ +} diff --git a/codechicken/lib/render/UV.java b/codechicken/lib/render/UV.java index 6233302..9181e5a 100644 --- a/codechicken/lib/render/UV.java +++ b/codechicken/lib/render/UV.java @@ -68,4 +68,12 @@ public UV apply(IUVTransformation transform) transform.transform(this); return this; } + + @Override + public boolean equals(Object o) { + if(!(o instanceof UV)) + return false; + UV uv = (UV)o; + return u == uv.u && v == uv.v; + } } \ No newline at end of file diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java index e47dce1..547b830 100644 --- a/codechicken/lib/vec/BlockCoord.java +++ b/codechicken/lib/vec/BlockCoord.java @@ -35,6 +35,11 @@ public BlockCoord() { } + public static BlockCoord fromAxes(int[] ia) + { + return new BlockCoord(ia[2], ia[0], ia[1]); + } + @Override public boolean equals(Object obj) { @@ -146,6 +151,36 @@ public BlockCoord inset(int side, int amount) { return offset(side, -amount); } + + public int getSide(int side) { + switch(side) { + case 0: + case 1: + return y; + case 2: + case 3: + return z; + case 4: + case 5: + return x; + } + throw new IndexOutOfBoundsException("Switch Falloff"); + } + + public BlockCoord setSide(int s, int v) + { + switch(s) + { + case 0: + case 1: y = v; break; + case 2: + case 3: z = v; break; + case 4: + case 5: x = v; break; + default: throw new IndexOutOfBoundsException("Switch Falloff"); + } + return this; + } public static final BlockCoord[] sideOffsets = new BlockCoord[]{ new BlockCoord( 0,-1, 0), diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java index 5551630..509477a 100644 --- a/codechicken/lib/vec/CuboidCoord.java +++ b/codechicken/lib/vec/CuboidCoord.java @@ -69,7 +69,36 @@ public int size(int s) return 0; } } - + + public int getSide(int s) + { + switch(s) + { + case 0: return min.y; + case 1: return max.y; + case 2: return min.z; + case 3: return max.z; + case 4: return min.x; + case 5: return max.x; + } + throw new IndexOutOfBoundsException("Switch Falloff"); + } + + public CuboidCoord setSide(int s, int v) + { + switch(s) + { + case 0: min.y = v; break; + case 1: max.y = v; break; + case 2: min.z = v; break; + case 3: max.z = v; break; + case 4: min.x = v; break; + case 5: max.x = v; break; + default: throw new IndexOutOfBoundsException("Switch Falloff"); + } + return this; + } + public int getVolume() { return (max.x-min.x+1)*(max.y-min.y+1)*(max.z-min.z+1); @@ -108,9 +137,14 @@ public CuboidCoord copy() return new CuboidCoord(min.copy(), max.copy()); } + public Cuboid6 bounds() + { + return new Cuboid6(min.x, min.y, min.z, max.x+1, max.y+1, max.z+1); + } + public AxisAlignedBB toAABB() { - return AxisAlignedBB.getBoundingBox(min.x, min.y, min.z, max.x+1, max.y+1, max.z+1); + return bounds().toAABB(); } public void set(BlockCoord min, BlockCoord max) diff --git a/codechicken/lib/vec/Rectangle4i.java b/codechicken/lib/vec/Rectangle4i.java index 0792a97..0e29d35 100644 --- a/codechicken/lib/vec/Rectangle4i.java +++ b/codechicken/lib/vec/Rectangle4i.java @@ -18,6 +18,22 @@ public Rectangle4i(int x, int y, int w, int h) this.w = w; this.h = h; } + + public int x1() { + return x; + } + + public int y1() { + return y; + } + + public int x2() { + return x+w-1; + } + + public int y2() { + return y+h-1; + } public Rectangle4i offset(int dx, int dy) { @@ -25,13 +41,39 @@ public Rectangle4i offset(int dx, int dy) y+=dy; return this; } - + + @Deprecated public Rectangle4i with(int px, int py) { - if(x > px) x = px; - if(y > py) y = py; - if(x + w <= px) w = px-x+1; - if(y + h <= py) h = py-y+1; + return include(px, py); + } + + public Rectangle4i include(int px, int py) { + if(px < x) expand(px-x, 0); + if(px >= x+w) expand(px-x-w+1, 0); + if(py < y) expand(0, py-y); + if(py >= y+h) expand(0, py-y-h+1); + return this; + } + + public Rectangle4i include(Rectangle4i r) { + include(r.x, r.y); + return include(r.x2(), r.y2()); + } + + public Rectangle4i expand(int px, int py) { + if(px > 0) + w+=px; + else { + x+=px; + w-=px; + } + if(py > 0) + h+=py; + else { + y+=py; + h-=py; + } return this; } @@ -42,7 +84,13 @@ public boolean contains(int px, int py) public boolean intersects(Rectangle4i r) { - return x <= r.x+r.w && r.x <= x+w && - y <= r.y+r.h && r.y <= y+h; + return r.x+r.w > x && + r.x < x+w && + r.y+r.h > y && + r.y < y+h; + } + + public int area() { + return w * h; } } diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java index 3a76e61..09d0a7f 100644 --- a/codechicken/lib/vec/Vector3.java +++ b/codechicken/lib/vec/Vector3.java @@ -45,6 +45,11 @@ public Vector3(Vector3 vec) z = vec.z; } + public Vector3(double[] da) + { + this(da[0], da[1], da[2]); + } + public Vector3(Vec3 vec) { x = vec.xCoord; @@ -84,6 +89,11 @@ public static Vector3 fromTileEntityCenter(TileEntity e) return new Vector3(e.xCoord + 0.5, e.yCoord + 0.5, e.zCoord + 0.5); } + public static Vector3 fromAxes(double[] da) + { + return new Vector3(da[2], da[0], da[1]); + } + public Vector3 set(double d, double d1, double d2) { x = d; @@ -100,6 +110,36 @@ public Vector3 set(Vector3 vec) return this; } + public double getSide(int side) { + switch(side) { + case 0: + case 1: + return y; + case 2: + case 3: + return z; + case 4: + case 5: + return x; + } + throw new IndexOutOfBoundsException("Switch Falloff"); + } + + public Vector3 setSide(int s, double v) + { + switch(s) + { + case 0: + case 1: y = v; break; + case 2: + case 3: z = v; break; + case 4: + case 5: x = v; break; + default: throw new IndexOutOfBoundsException("Switch Falloff"); + } + return this; + } + public double dotProduct(Vector3 vec) { double d = vec.x * x + vec.y * y + vec.z * z; From ae652f51c23a51ef0d58bf84b035971d4f885b3e Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Mon, 3 Feb 2014 11:02:42 +1000 Subject: [PATCH 057/219] Added command line tool frontend. --- MANIFEST.MF | 2 + codechicken/lib/render/QBImporter.java | 37 +++--- codechicken/lib/tool/LibDownloader.java | 110 ++++++++++++++++++ codechicken/lib/tool/MCStripTransformer.java | 44 +++++++ codechicken/lib/tool/Main.java | 14 +++ codechicken/lib/tool/StripClassLoader.java | 50 ++++++++ codechicken/lib/tool/ToolMain.java | 44 +++++++ codechicken/lib/tool/module/JOptModule.java | 48 ++++++++ .../lib/tool/module/ModuleQBConverter.java | 70 +++++++++++ 9 files changed, 396 insertions(+), 23 deletions(-) create mode 100644 MANIFEST.MF create mode 100644 codechicken/lib/tool/LibDownloader.java create mode 100644 codechicken/lib/tool/MCStripTransformer.java create mode 100644 codechicken/lib/tool/Main.java create mode 100644 codechicken/lib/tool/StripClassLoader.java create mode 100644 codechicken/lib/tool/ToolMain.java create mode 100644 codechicken/lib/tool/module/JOptModule.java create mode 100644 codechicken/lib/tool/module/ModuleQBConverter.java diff --git a/MANIFEST.MF b/MANIFEST.MF new file mode 100644 index 0000000..9915f07 --- /dev/null +++ b/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Main-Class: codechicken.lib.tool.Main diff --git a/codechicken/lib/render/QBImporter.java b/codechicken/lib/render/QBImporter.java index 8af4aa3..05be9bb 100644 --- a/codechicken/lib/render/QBImporter.java +++ b/codechicken/lib/render/QBImporter.java @@ -239,7 +239,6 @@ public void transform(UV uv) { } } - private static final int[][] vertOrder = new int[][] {//clockwise because MC is left handed {3, 0}, {1, 0}, @@ -577,8 +576,6 @@ public static class QBModel public QBMatrix[] matrices; public boolean rightHanded; - - public RasterisedModel toRasterisedModel(int flags) { List qbImages = new ArrayList(); List> modelQuads = new ArrayList>(); @@ -727,29 +724,23 @@ public static QBModel loadQB(InputStream input) throws IOException { } public static QBModel loadQB(ResourceLocation res) { - try - { + try { return loadQB(Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream()); - } - catch(Exception e) - { + } catch(Exception e) { throw new RuntimeException("failed to load model: "+res, e); } } - /** - * try { - File dump = new File("packed.png"); - if(!dump.exists()) dump.createNewFile(); - ImageIO.write(img, "PNG", dump); - - File dump2 = new File("packed.obj"); - if(!dump2.exists()) dump2.createNewFile(); - PrintWriter p = new PrintWriter(dump2); - CCModel.exportObj(Collections.singletonMap(name, m), p); - p.close(); - } catch(IOException e) { - e.printStackTrace(); - } - */ + public static QBModel loadQB(File file) { + try { + FileInputStream fin = new FileInputStream(file); + try { + return loadQB(fin); + } finally { + fin.close(); + } + } catch(Exception e) { + throw new RuntimeException("failed to load model: "+file.getPath(), e); + } + } } diff --git a/codechicken/lib/tool/LibDownloader.java b/codechicken/lib/tool/LibDownloader.java new file mode 100644 index 0000000..0785b43 --- /dev/null +++ b/codechicken/lib/tool/LibDownloader.java @@ -0,0 +1,110 @@ +package codechicken.lib.tool; + +import java.io.*; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +public class LibDownloader +{ + private static String[] libs = new String[] { + "org/ow2/asm/asm-debug-all/4.1/asm-debug-all-4.1.jar", + "com/google/guava/guava/14.0/guava-14.0.jar", + "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar"}; + private static File libDir = new File("lib"); + + private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); + + public static void load() { + if(!libDir.exists()) + libDir.mkdir(); + if(!libDir.isDirectory()) + throw new RuntimeException("/lib is not a directory"); + + List missing = checkExists(); + for(String lib : missing) + download(lib); + addPaths(libs); + } + + private static void addPaths(String[] libs) { + try { + URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); + Method m_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); + m_addURL.setAccessible(true); + for(String lib : libs) + m_addURL.invoke(cl, new File(libDir, fileName(lib)).toURI().toURL()); + } + catch (Exception e) { + throw new RuntimeException("Failed to add libraries to classpath", e); + } + } + + private static void download(String lib) { + File libFile = new File(libDir, fileName(lib)); + try + { + URL libDownload = new URL("http://repo1.maven.org/maven2/"+lib); + URLConnection connection = libDownload.openConnection(); + connection.setConnectTimeout(5000); + connection.setReadTimeout(5000); + connection.setRequestProperty("User-Agent", "CodeChickenLib Downloader"); + int sizeGuess = connection.getContentLength(); + download(connection.getInputStream(), sizeGuess, libFile); + } + catch (Exception e) + { + libFile.delete(); + throw new RuntimeException("A download error occured", e); + } + } + + private static void download(InputStream is, int sizeGuess, File target) throws Exception + { + String name = target.getName(); + if (sizeGuess > downloadBuffer.capacity()) + throw new Exception(String.format("The file %s is too large to be downloaded", name)); + + downloadBuffer.clear(); + + int bytesRead, fullLength = 0; + + System.out.format("Downloading lib %s", name); + byte[] smallBuffer = new byte[1024]; + while ((bytesRead = is.read(smallBuffer)) >= 0) { + downloadBuffer.put(smallBuffer, 0, bytesRead); + fullLength += bytesRead; + System.out.format("\rDownloading lib %s %d%%", name, (int) (fullLength * 100 / sizeGuess)); + } + System.out.format("\rDownloaded lib %s \n", name); + is.close(); + downloadBuffer.limit(fullLength); + + if(!target.exists()) + target.createNewFile(); + + downloadBuffer.position(0); + FileOutputStream fos = new FileOutputStream(target); + fos.getChannel().write(downloadBuffer); + fos.close(); + } + + private static String fileName(String lib) { + return lib.replaceAll(".+/", ""); + } + + private static List checkExists() { + LinkedList list = new LinkedList(); + for(String lib : libs) { + File file = new File(libDir, fileName(lib)); + if(!file.exists()) + list.add(lib); + } + return list; + } + +} diff --git a/codechicken/lib/tool/MCStripTransformer.java b/codechicken/lib/tool/MCStripTransformer.java new file mode 100644 index 0000000..76a4a70 --- /dev/null +++ b/codechicken/lib/tool/MCStripTransformer.java @@ -0,0 +1,44 @@ +package codechicken.lib.tool; + +import codechicken.lib.asm.ASMHelper; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.Remapper; +import org.objectweb.asm.commons.RemappingMethodAdapter; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import java.util.Iterator; + +public class MCStripTransformer { + public static class ReferenceDetector extends Remapper { + boolean found = false; + + @Override + public String map(String typeName) { + if(typeName.startsWith("net/minecraft")) + found = true; + return typeName; + } + } + + public static byte[] transform(byte[] bytes) { + ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES); + + boolean changed = false; + Iterator it = cnode.methods.iterator(); + while(it.hasNext()) { + MethodNode mnode = it.next(); + ReferenceDetector r = new ReferenceDetector(); + mnode.accept(new RemappingMethodAdapter(mnode.access, mnode.desc, new MethodVisitor(Opcodes.ASM4) {}, r)); + if(r.found) { + it.remove(); + changed = true; + } + } + if(changed) + bytes = ASMHelper.createBytes(cnode, 0); + return bytes; + } +} diff --git a/codechicken/lib/tool/Main.java b/codechicken/lib/tool/Main.java new file mode 100644 index 0000000..083db03 --- /dev/null +++ b/codechicken/lib/tool/Main.java @@ -0,0 +1,14 @@ +package codechicken.lib.tool; + +public class Main +{ + public static void main(String[] args) { + LibDownloader.load(); + try { + Class c_toolMain = new StripClassLoader().loadClass("codechicken.lib.tool.ToolMain"); + c_toolMain.getDeclaredMethod("main", String[].class).invoke(null, new Object[]{args}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/codechicken/lib/tool/StripClassLoader.java b/codechicken/lib/tool/StripClassLoader.java new file mode 100644 index 0000000..51bf15a --- /dev/null +++ b/codechicken/lib/tool/StripClassLoader.java @@ -0,0 +1,50 @@ +package codechicken.lib.tool; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLClassLoader; + +public class StripClassLoader extends URLClassLoader +{ + public StripClassLoader() { + super(new URL[0], StripClassLoader.class.getClassLoader()); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if(!name.startsWith("codechicken.lib")) + return super.loadClass(name); + + try { + String resName = name.replace('.', '/')+".class"; + InputStream res = getResourceAsStream(resName); + if(res == null) + throw new ClassNotFoundException("Could not find resource: "+resName); + byte[] bytes = readFully(res); + bytes = transform(bytes); + return defineClass(name, bytes, 0, bytes.length); + + } catch(IOException e) { + throw new ClassNotFoundException(name, e); + } + } + + public static byte[] readFully(InputStream is) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int read; + byte[] data = new byte[16384]; + while ((read = is.read(data, 0, data.length)) > 0) + buffer.write(data, 0, read); + + return buffer.toByteArray(); + } + + private byte[] transform(byte[] bytes) { + + bytes = MCStripTransformer.transform(bytes); + return bytes; + } +} diff --git a/codechicken/lib/tool/ToolMain.java b/codechicken/lib/tool/ToolMain.java new file mode 100644 index 0000000..24dee52 --- /dev/null +++ b/codechicken/lib/tool/ToolMain.java @@ -0,0 +1,44 @@ +package codechicken.lib.tool; + +import codechicken.lib.tool.module.ModuleQBConverter; + +public class ToolMain +{ + public static interface Module { + public void main(String[] args); + public String name(); + public void printHelp(); + } + + public static Module[] modules = new Module[]{ + new ModuleQBConverter() + }; + + private static void printHelp() { + System.out.println("Usage: [module] [args]"); + System.out.println(" Modules: "); + for(Module m : modules) + System.out.println(" - "+m.name()); + System.out.println("-h [module] for module help"); + } + + public static void main(String[] args) { + if(args.length > 0) { + for(Module m : modules) + if(args[0].equals(m.name())) { + String[] args2 = new String[args.length-1]; + System.arraycopy(args, 1, args2, 0, args2.length); + m.main(args2); + return; + } + if(args[0].equals("-h") && args.length >= 2) { + for(Module m : modules) + if(args[1].equals(m.name())) { + m.printHelp(); + return; + } + } + } + printHelp(); + } +} diff --git a/codechicken/lib/tool/module/JOptModule.java b/codechicken/lib/tool/module/JOptModule.java new file mode 100644 index 0000000..f67e920 --- /dev/null +++ b/codechicken/lib/tool/module/JOptModule.java @@ -0,0 +1,48 @@ +package codechicken.lib.tool.module; + +import codechicken.lib.tool.ToolMain; +import joptsimple.OptionException; +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +import java.io.IOException; + +public abstract class JOptModule implements ToolMain.Module +{ + OptionParser parser = new OptionParser(); + + @Override + public void main(String[] args) { + OptionSet options; + try + { + options = parser.parse(args); + } + catch(OptionException ex) + { + System.err.println(ex.getLocalizedMessage()); + System.exit(-1); + return; + } + + try + { + main(parser, options); + } + catch(Exception e) + { + throw new RuntimeException(e); + } + } + + protected abstract void main(OptionParser parser, OptionSet options); + + @Override + public void printHelp() { + try { + parser.printHelpOn(System.out); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/codechicken/lib/tool/module/ModuleQBConverter.java b/codechicken/lib/tool/module/ModuleQBConverter.java new file mode 100644 index 0000000..c4ae0c0 --- /dev/null +++ b/codechicken/lib/tool/module/ModuleQBConverter.java @@ -0,0 +1,70 @@ +package codechicken.lib.tool.module; + +import codechicken.lib.render.QBImporter; +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +import java.io.File; + +import static java.util.Arrays.asList; + +public class ModuleQBConverter extends JOptModule +{ + public ModuleQBConverter() { + parser.acceptsAll(asList("?", "h", "help"), "Show the help"); + parser.acceptsAll(asList("i", "input"), "comma separated list of paths to models (.qb or directories)") + .withRequiredArg().ofType(File.class).withValuesSeparatedBy(',').required(); + parser.acceptsAll(asList("o", "out"), "Output Directory") + .withRequiredArg().ofType(File.class); + parser.acceptsAll(asList("o2", "textureplanes"), "2nd level optimisation. Merges coplanar polygons. Increases texture size"); + parser.acceptsAll(asList("s", "squaretextures"), "Produce square textures"); + parser.acceptsAll(asList("t", "mergetextures"), "Use the same texture for all models"); + parser.acceptsAll(asList("r", "scalemc"), "Resize model to mc standard (shrink by factor of 16)"); + } + + protected void main(OptionParser parser, OptionSet options) { + int flags = 0; + if(options.has("o2")) flags |= QBImporter.TEXTUREPLANES; + if(options.has("s")) flags |= QBImporter.SQUARETEXTURE; + if(options.has("t")) flags |= QBImporter.MERGETEXTURES; + if(options.has("r")) flags |= QBImporter.SCALEMC; + + File[] input = options.valuesOf("input").toArray(new File[0]); + File[] outDir = new File[input.length]; + if(options.has("out")) { + File output = (File)options.valueOf("out"); + if(output.isFile()) + throw new RuntimeException("Output Path is not a directory"); + if(!output.exists()) + output.mkdirs(); + + for(int i = 0; i < input.length; i++) + outDir[i] = output; + } else { + for(int i = 0; i < input.length; i++) + outDir[i] = input[i].isDirectory() ? input[i] : input[i].getParentFile(); + } + + for(int i = 0; i < input.length; i++) { + File file = input[i]; + if(file.isDirectory()) { + for(File file2 : file.listFiles()) + if(file2.getName().endsWith(".qb")) + convert(file2, outDir[i], flags); + } + else + convert(file, outDir[i], flags); + } + } + + private void convert(File in, File outDir, int flags) { + System.out.println("Converting: "+in.getName()); + QBImporter.RasterisedModel m = QBImporter.loadQB(in).toRasterisedModel(flags); + m.export(new File(outDir, in.getName().replace(".qb", ".obj")), outDir); + } + + @Override + public String name() { + return "QBConverter"; + } +} From eac0727165c2757b726678e57b75107448a0930d Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Mon, 3 Feb 2014 11:14:54 +1000 Subject: [PATCH 058/219] Strip obfuscated references in tool mode --- codechicken/lib/tool/MCStripTransformer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codechicken/lib/tool/MCStripTransformer.java b/codechicken/lib/tool/MCStripTransformer.java index 76a4a70..11edf66 100644 --- a/codechicken/lib/tool/MCStripTransformer.java +++ b/codechicken/lib/tool/MCStripTransformer.java @@ -17,7 +17,7 @@ public static class ReferenceDetector extends Remapper { @Override public String map(String typeName) { - if(typeName.startsWith("net/minecraft")) + if(typeName.startsWith("net/minecraft") || !typeName.contains("/")) found = true; return typeName; } From e274d1c5124fbac1d418e0a113d1063ecc49635b Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 11 Feb 2014 19:56:02 +1000 Subject: [PATCH 059/219] Added a few methods to CuboidCoord --- codechicken/lib/render/QBImporter.java | 4 +-- codechicken/lib/vec/CuboidCoord.java | 37 +++++++++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/codechicken/lib/render/QBImporter.java b/codechicken/lib/render/QBImporter.java index 05be9bb..f53184c 100644 --- a/codechicken/lib/render/QBImporter.java +++ b/codechicken/lib/render/QBImporter.java @@ -447,13 +447,13 @@ private QBCuboid expand(boolean[][][] solid, BlockCoord b) { for(int s = 0; s < 6; s++) { CuboidCoord slice = c.copy(); - slice.shrink(s^1, slice.size(s)-1); + slice.expand(s^1, -(slice.size(s)-1)); slice.expand(s, 1); while(slice.getSide(s) >= 0 && slice.getSide(s) < size.getSide(s)) { if(!voxelFull(solid, slice)) break; - slice.shrink(s ^ 1, 1); + slice.expand(s ^ 1, -1); slice.expand(s, 1); c.expand(s, 1); } diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java index 509477a..3d34116 100644 --- a/codechicken/lib/vec/CuboidCoord.java +++ b/codechicken/lib/vec/CuboidCoord.java @@ -36,22 +36,25 @@ public CuboidCoord(int x1, int y1, int z1, int x2, int y2, int z2) this(new BlockCoord(x1, y1, z1), new BlockCoord(x2, y2, z2)); } - public void expand(int side, int amount) + public CuboidCoord expand(int amount) { + return expand(amount, amount, amount); + } + + public CuboidCoord expand(int x, int y, int z) { + max.add(x, y, z); + min.sub(x, y, z); + return this; + } + + public CuboidCoord expand(int side, int amount) { if(side%2 == 0)//negative side min = min.offset(side, amount); else max = max.offset(side, amount); + return this; } - public void shrink(int side, int amount) - { - if(side%2 == 0)//negative side - min = min.inset(side, amount); - else - max = max.inset(side, amount); - } - public int size(int s) { switch(s) @@ -171,6 +174,20 @@ public CuboidCoord set(int[] ia) return set(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); } + public CuboidCoord include(BlockCoord coord) { + return include(coord.x, coord.y, coord.z); + } + + public CuboidCoord include(int x, int y, int z) { + if(x < min.x) min.x = x; + else if(x > max.x) max.x = x; + if(y < min.y) min.y = y; + else if(y > max.y) max.y = y; + if(z < min.z) min.z = z; + else if(z > max.z) max.z = z; + return this; + } + public Iterator iterator() { return new Iterator() { BlockCoord b = null; @@ -195,7 +212,7 @@ public BlockCoord next() { } } } - return b; + return b.copy(); } public void remove() { From 23b79b7b150714f7d38c4723d17a97b6624e4911 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 13 Feb 2014 15:50:23 +1000 Subject: [PATCH 060/219] Added a more intuitive renderFluidQuad function with doc --- codechicken/lib/render/RenderUtils.java | 35 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 0eafa56..c194da3 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -47,18 +47,28 @@ public boolean shouldBob() entityItem = new EntityItem(null); entityItem.hoverStart = 0; } - + public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) { + renderFluidQuad(point2, vectors[0].set(point4).subtract(point1), vectors[1].set(point1).subtract(point2), icon, res); + } + + /** + * Draws a tessellated quadrilateral bottom to top, left to right + * @param base The bottom left corner of the quad + * @param wide The bottom of the quad + * @param high The left side of the quad + * @param res Units per icon + */ + public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, Icon icon, double res) + { + Tessellator t = Tessellator.instance; + double u1 = icon.getMinU(); double du = icon.getMaxU()-icon.getMinU(); double v2 = icon.getMaxV(); double dv = icon.getMaxV()-icon.getMinV(); - - Vector3 wide = vectors[0].set(point4).subtract(point1); - Vector3 high = vectors[1].set(point1).subtract(point2); - Tessellator t = Tessellator.instance; - + double wlen = wide.mag(); double hlen = high.mag(); @@ -81,10 +91,10 @@ public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point Vector3 dy1 = vectors[4].set(high).multiply(y/hlen); Vector3 dy2 = vectors[5].set(high).multiply((y+ry)/hlen); - t.addVertexWithUV(point2.x+dx1.x+dy2.x, point2.y+dx1.y+dy2.y, point2.z+dx1.z+dy2.z, u1, v2-ry/res*dv); - t.addVertexWithUV(point2.x+dx1.x+dy1.x, point2.y+dx1.y+dy1.y, point2.z+dx1.z+dy1.z, u1, v2); - t.addVertexWithUV(point2.x+dx2.x+dy1.x, point2.y+dx2.y+dy1.y, point2.z+dx2.z+dy1.z, u1+rx/res*du, v2); - t.addVertexWithUV(point2.x+dx2.x+dy2.x, point2.y+dx2.y+dy2.y, point2.z+dx2.z+dy2.z, u1+rx/res*du, v2-ry/res*dv); + t.addVertexWithUV(base.x+dx1.x+dy2.x, base.y+dx1.y+dy2.y, base.z+dx1.z+dy2.z, u1, v2-ry/res*dv); + t.addVertexWithUV(base.x+dx1.x+dy1.x, base.y+dx1.y+dy1.y, base.z+dx1.z+dy1.z, u1, v2); + t.addVertexWithUV(base.x+dx2.x+dy1.x, base.y+dx2.y+dy1.y, base.z+dx2.z+dy1.z, u1+rx/res*du, v2); + t.addVertexWithUV(base.x+dx2.x+dy2.x, base.y+dx2.y+dy2.y, base.z+dx2.z+dy2.z, u1+rx/res*du, v2-ry/res*dv); y+=ry; } @@ -298,10 +308,9 @@ public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double d Icon tex = prepareFluidRender(stack, alpha); CCRenderState.startDrawing(7); renderFluidQuad( - new Vector3(rect.x, rect.y, 0), new Vector3(rect.x, rect.y+rect.h, 0), - new Vector3(rect.x+rect.w, rect.y+rect.h, 0), - new Vector3(rect.x+rect.w, rect.y, 0), tex, res); + new Vector3(rect.w,0, 0), + new Vector3(0, -rect.h, 0), tex, res); CCRenderState.draw(); postFluidRender(); } From 34154fc0115ce983338e7be54c2ed210495b810a Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 23 Feb 2014 15:43:35 +1000 Subject: [PATCH 061/219] Add spin parameter to RenderUtils.renderItemUniform --- codechicken/lib/render/RenderUtils.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index c194da3..9f0d3ad 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -314,8 +314,20 @@ public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double d CCRenderState.draw(); postFluidRender(); } - - public static void renderItemUniform(ItemStack item) + + + /** + * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately + */ + public static void renderItemUniform(ItemStack item) { + renderItemUniform(item, 0); + } + + /** + * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately + * @param spin The spin angle of the item around the y axis in degrees + */ + public static void renderItemUniform(ItemStack item, double spin) { IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, ENTITY); boolean is3D = customRenderer != null && customRenderer.shouldUseRenderHelper(ENTITY, item, BLOCK_3D); @@ -339,7 +351,7 @@ else if(is3D) GL11.glColor4f(1, 1, 1, 1); entityItem.setEntityItemStack(item); - uniformRenderItem.doRenderItem(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, 0); + uniformRenderItem.doRenderItem(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float)(spin*9/Math.PI)); if(larger) GL11.glScaled(d1, d1, d1); From ca675b5f31f41e98daab34eb9ffbb857043c8a7b Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Mon, 7 Apr 2014 14:02:47 +1000 Subject: [PATCH 062/219] Initial 1.7 commit --- codechicken/lib/asm/ASMHelper.java | 246 ++-- codechicken/lib/asm/ASMReader.java | 4 +- codechicken/lib/asm/ObfMapping.java | 264 ++-- codechicken/lib/colour/Colour.java | 3 +- codechicken/lib/colour/ColourRGBA.java | 43 +- codechicken/lib/config/ConfigFile.java | 128 +- codechicken/lib/data/MCDataInput.java | 4 +- codechicken/lib/data/MCDataOutput.java | 2 + .../lib/data/MCOutputStreamWrapper.java | 41 +- codechicken/lib/data/NBTDataWrapper.java | 246 ---- codechicken/lib/gui/Canvas9Seg.java | 2 +- codechicken/lib/gui/GuiDraw.java | 223 +++ codechicken/lib/inventory/InventoryCopy.java | 14 +- codechicken/lib/inventory/InventoryNBT.java | 14 +- .../lib/inventory/InventorySimple.java | 12 +- codechicken/lib/inventory/InventoryUtils.java | 273 ++-- codechicken/lib/inventory/ItemKey.java | 68 +- codechicken/lib/lang/LangUtil.java | 110 -- codechicken/lib/lighting/CCRBModel.java | 31 - codechicken/lib/lighting/LC.java | 100 +- codechicken/lib/lighting/LazyLightMatrix.java | 28 - codechicken/lib/lighting/LightMatrix.java | 168 +-- codechicken/lib/lighting/LightModel.java | 91 +- .../lib/lighting/PlanarLightModel.java | 41 +- codechicken/lib/packet/MetaPacket.java | 91 -- codechicken/lib/packet/PacketCustom.java | 1221 +++++------------ codechicken/lib/raytracer/RayTracer.java | 16 +- codechicken/lib/render/BlockRenderer.java | 126 ++ codechicken/lib/render/CCModel.java | 375 +++-- codechicken/lib/render/CCRenderPipeline.java | 135 ++ codechicken/lib/render/CCRenderState.java | 434 ++++-- codechicken/lib/render/ColourModifier.java | 22 - codechicken/lib/render/ColourMultiplier.java | 45 +- codechicken/lib/render/EntityDigIconFX.java | 8 +- codechicken/lib/render/IUVTransformation.java | 6 - codechicken/lib/render/IVertexModifier.java | 11 - .../lib/render/IconTransformation.java | 20 - .../lib/render/MultiIconTransformation.java | 41 - .../lib/render/PlaceholderTexture.java | 4 +- codechicken/lib/render/QBImporter.java | 8 +- codechicken/lib/render/RenderUtils.java | 154 +-- .../lib/render/SpriteSheetManager.java | 14 +- codechicken/lib/render/TextureFX.java | 42 +- codechicken/lib/render/TextureSpecial.java | 148 +- codechicken/lib/render/TextureUtils.java | 141 +- codechicken/lib/render/UV.java | 79 -- codechicken/lib/render/UVScale.java | 25 - codechicken/lib/render/UVTranslation.java | 20 - codechicken/lib/render/Vertex5.java | 22 +- .../lib/render/uv/IconTransformation.java | 23 + .../render/uv/MultiIconTransformation.java | 24 + codechicken/lib/render/uv/UV.java | 79 ++ codechicken/lib/render/uv/UVRotation.java | 53 + codechicken/lib/render/uv/UVScale.java | 36 + .../lib/render/uv/UVTransformation.java | 37 + .../lib/render/uv/UVTransformationList.java | 106 ++ codechicken/lib/render/uv/UVTranslation.java | 54 + codechicken/lib/util/Copyable.java | 5 + codechicken/lib/vec/BlockCoord.java | 3 +- codechicken/lib/vec/Cuboid6.java | 21 +- codechicken/lib/vec/CuboidCoord.java | 3 +- codechicken/lib/vec/ITransformation.java | 49 + .../IrreversibleTransformationException.java | 4 +- codechicken/lib/vec/Matrix4.java | 3 +- codechicken/lib/vec/Quat.java | 4 +- codechicken/lib/vec/Rotation.java | 2 +- codechicken/lib/vec/Scale.java | 58 +- codechicken/lib/vec/Transformation.java | 74 +- codechicken/lib/vec/Translation.java | 54 +- codechicken/lib/vec/Vector3.java | 3 +- codechicken/lib/world/ChunkExtension.java | 4 +- .../lib/world/WorldExtensionManager.java | 109 +- 72 files changed, 2902 insertions(+), 3270 deletions(-) delete mode 100644 codechicken/lib/data/NBTDataWrapper.java create mode 100644 codechicken/lib/gui/GuiDraw.java delete mode 100644 codechicken/lib/lang/LangUtil.java delete mode 100644 codechicken/lib/lighting/CCRBModel.java delete mode 100644 codechicken/lib/lighting/LazyLightMatrix.java delete mode 100644 codechicken/lib/packet/MetaPacket.java create mode 100644 codechicken/lib/render/BlockRenderer.java create mode 100644 codechicken/lib/render/CCRenderPipeline.java delete mode 100644 codechicken/lib/render/ColourModifier.java delete mode 100644 codechicken/lib/render/IUVTransformation.java delete mode 100644 codechicken/lib/render/IVertexModifier.java delete mode 100644 codechicken/lib/render/IconTransformation.java delete mode 100644 codechicken/lib/render/MultiIconTransformation.java delete mode 100644 codechicken/lib/render/UV.java delete mode 100644 codechicken/lib/render/UVScale.java delete mode 100644 codechicken/lib/render/UVTranslation.java create mode 100644 codechicken/lib/render/uv/IconTransformation.java create mode 100644 codechicken/lib/render/uv/MultiIconTransformation.java create mode 100644 codechicken/lib/render/uv/UV.java create mode 100644 codechicken/lib/render/uv/UVRotation.java create mode 100644 codechicken/lib/render/uv/UVScale.java create mode 100644 codechicken/lib/render/uv/UVTransformation.java create mode 100644 codechicken/lib/render/uv/UVTransformationList.java create mode 100644 codechicken/lib/render/uv/UVTranslation.java create mode 100644 codechicken/lib/util/Copyable.java create mode 100644 codechicken/lib/vec/ITransformation.java diff --git a/codechicken/lib/asm/ASMHelper.java b/codechicken/lib/asm/ASMHelper.java index 63dd0ed..d8f4e73 100644 --- a/codechicken/lib/asm/ASMHelper.java +++ b/codechicken/lib/asm/ASMHelper.java @@ -23,45 +23,42 @@ import codechicken.lib.asm.InstructionComparator.InsnListSection; public class ASMHelper -{ +{ public static class CodeBlock { public Label start = new Label(); public Label end = new Label(); } - + public static class ForBlock extends CodeBlock { public Label cmp = new Label(); public Label inc = new Label(); public Label body = new Label(); } - + public static abstract class MethodAltercator { public final ObfMapping method; - - public MethodAltercator(ObfMapping method) - { - this.method = method; + + public MethodAltercator(ObfMapping method) { + this.method = method.toClassloading(); } - + public abstract void alter(MethodNode mv); } - + public static abstract class MethodWriter { public final int access; public final ObfMapping method; public final String[] exceptions; - public MethodWriter(int access, ObfMapping method) - { + public MethodWriter(int access, ObfMapping method) { this(access, method, null); } - - public MethodWriter(int access, ObfMapping method, String[] exceptions) - { + + public MethodWriter(int access, ObfMapping method, String[] exceptions) { this.access = access; this.method = method; this.exceptions = exceptions; @@ -69,69 +66,60 @@ public MethodWriter(int access, ObfMapping method, String[] exceptions) public abstract void write(MethodNode mv); } - + public static class MethodInjector { public final ObfMapping method; public final InsnList needle; public final InsnList injection; public final boolean before; - - public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) - { + + public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) { this.method = method; this.needle = needle; this.injection = injection; this.before = before; } } - - public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) - { - for(MethodNode mnode : cnode.methods) - if(methodmap.matches(mnode)) + + public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) { + for (MethodNode mnode : cnode.methods) + if (methodmap.matches(mnode)) return mnode; return null; } - public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) - { - for(FieldNode fnode : cnode.fields) - if(fieldmap.matches(fnode)) + public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) { + for (FieldNode fnode : cnode.fields) + if (fieldmap.matches(fnode)) return fnode; return null; } - public static ClassNode createClassNode(byte[] bytes) - { + public static ClassNode createClassNode(byte[] bytes) { return createClassNode(bytes, 0); } - - public static ClassNode createClassNode(byte[] bytes, int flags) - { + + public static ClassNode createClassNode(byte[] bytes, int flags) { ClassNode cnode = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(cnode, flags); return cnode; } - public static byte[] createBytes(ClassNode cnode, int flags) - { + public static byte[] createBytes(ClassNode cnode, int flags) { ClassWriter cw = new CC_ClassWriter(flags); cnode.accept(cw); return cw.toByteArray(); } - - public static byte[] writeMethods(String name, byte[] bytes, Multimap writers) - { - if(writers.containsKey(name)) - { + + public static byte[] writeMethods(String name, byte[] bytes, Multimap writers) { + if (writers.containsKey(name)) { ClassNode cnode = createClassNode(bytes); - - for(MethodWriter mw : writers.get(name)) - { + + for (MethodWriter mw : writers.get(name)) { MethodNode mv = findMethod(mw.method, cnode); - if(mv == null) + if (mv == null) mv = (MethodNode) cnode.visitMethod(mw.access, mw.method.s_name, mw.method.s_desc, null, mw.exceptions); mv.access = mw.access; @@ -143,41 +131,33 @@ public static byte[] writeMethods(String name, byte[] bytes, Multimap injectors) - { - if(injectors.containsKey(name)) - { + + public static byte[] injectMethods(String name, byte[] bytes, Multimap injectors) { + if (injectors.containsKey(name)) { ClassNode cnode = createClassNode(bytes); - - for(MethodInjector injector : injectors.get(name)) - { + + for (MethodInjector injector : injectors.get(name)) { MethodNode method = findMethod(injector.method, cnode); - if(method == null) - throw new RuntimeException("Method not found: "+injector.method); + if (method == null) + throw new RuntimeException("Method not found: " + injector.method); System.out.println("Injecting into " + injector.method + "\n" + printInsnList(injector.injection)); - + List callNodes; - if(injector.before) + if (injector.before) callNodes = InstructionComparator.insnListFindStart(method.instructions, injector.needle); else callNodes = InstructionComparator.insnListFindEnd(method.instructions, injector.needle); - - if(callNodes.size() == 0) - { - throw new RuntimeException("Needle not found in Haystack: " + injector.method+"\n" + printInsnList(injector.needle)); + + if (callNodes.size() == 0) { + throw new RuntimeException("Needle not found in Haystack: " + injector.method + "\n" + printInsnList(injector.needle)); } - - for(AbstractInsnNode node : callNodes) - { - if(injector.before) - { - System.out.println("Injected before: "+printInsn(node)); + + for (AbstractInsnNode node : callNodes) { + if (injector.before) { + System.out.println("Injected before: " + printInsn(node)); method.instructions.insertBefore(node, cloneInsnList(injector.injection)); - } - else - { - System.out.println("Injected after: "+printInsn(node)); + } else { + System.out.println("Injected after: " + printInsn(node)); method.instructions.insert(node, cloneInsnList(injector.injection)); } } @@ -187,144 +167,126 @@ public static byte[] injectMethods(String name, byte[] bytes, Multimap cloneLabels(InsnList insns) - { + + public static Map cloneLabels(InsnList insns) { HashMap labelMap = new HashMap(); - for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) - if(insn.getType() == 8) + for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + if (insn.getType() == 8) labelMap.put((LabelNode) insn, new LabelNode()); return labelMap; } - - public static InsnList cloneInsnList(InsnList insns) - { + + public static InsnList cloneInsnList(InsnList insns) { return cloneInsnList(cloneLabels(insns), insns); } - - public static InsnList cloneInsnList(Map labelMap, InsnList insns) - { + + public static InsnList cloneInsnList(Map labelMap, InsnList insns) { InsnList clone = new InsnList(); - for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) + for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) clone.add(insn.clone(labelMap)); - + return clone; } - - public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) - { + + public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) { ArrayList clone = new ArrayList(); - for(TryCatchBlockNode node : tcblocks) + for (TryCatchBlockNode node : tcblocks) clone.add(new TryCatchBlockNode( - labelMap.get(node.start), - labelMap.get(node.end), - labelMap.get(node.handler), + labelMap.get(node.start), + labelMap.get(node.end), + labelMap.get(node.handler), node.type)); - + return clone; } - - public static List cloneLocals(Map labelMap, List locals) - { + + public static List cloneLocals(Map labelMap, List locals) { ArrayList clone = new ArrayList(); - for(LocalVariableNode node : locals) + for (LocalVariableNode node : locals) clone.add(new LocalVariableNode( - node.name, node.desc, node.signature, - labelMap.get(node.start), - labelMap.get(node.end), + node.name, node.desc, node.signature, + labelMap.get(node.start), + labelMap.get(node.end), node.index)); - + return clone; } - - public static void copy(MethodNode src, MethodNode dst) - { + + public static void copy(MethodNode src, MethodNode dst) { Map labelMap = cloneLabels(src.instructions); dst.instructions = cloneInsnList(labelMap, src.instructions); dst.tryCatchBlocks = cloneTryCatchBlocks(labelMap, src.tryCatchBlocks); - if(src.localVariables != null) + if (src.localVariables != null) dst.localVariables = cloneLocals(labelMap, src.localVariables); dst.visibleAnnotations = src.visibleAnnotations; dst.invisibleAnnotations = src.invisibleAnnotations; dst.visitMaxs(src.maxStack, src.maxLocals); } - public static byte[] alterMethods(String name, byte[] bytes, HashMultimap altercators) - { - if(altercators.containsKey(name)) - { + public static byte[] alterMethods(String name, byte[] bytes, HashMultimap altercators) { + if (altercators.containsKey(name)) { ClassNode cnode = createClassNode(bytes); - - for(MethodAltercator injector : altercators.get(name)) - { + + for (MethodAltercator injector : altercators.get(name)) { MethodNode method = findMethod(injector.method, cnode); - if(method == null) - throw new RuntimeException("Method not found: "+injector.method); - + if (method == null) + throw new RuntimeException("Method not found: " + injector.method); + injector.alter(method); } - + bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); } return bytes; } - - public static String printInsnList(InsnListSection subsection) - { - InsnListPrinter p = new InsnListPrinter(); + + public static String printInsnList(InsnListSection subsection) { + InsnListPrinter p = new InsnListPrinter(); p.visitInsnList(subsection); return p.textString(); } - public static int getLocal(List list, String name) - { + public static int getLocal(List list, String name) { int found = -1; - for(LocalVariableNode node : list) - { - if(node.name.equals(name)) - { - if(found >= 0) - throw new RuntimeException("Duplicate local variable: "+name+" not coded to handle this scenario."); - + for (LocalVariableNode node : list) { + if (node.name.equals(name)) { + if (found >= 0) + throw new RuntimeException("Duplicate local variable: " + name + " not coded to handle this scenario."); + found = node.index; } } return found; } - public static void replaceMethodCode(MethodNode original, MethodNode replacement) - { + public static void replaceMethodCode(MethodNode original, MethodNode replacement) { original.instructions.clear(); - if(original.localVariables != null) + if (original.localVariables != null) original.localVariables.clear(); - if(original.tryCatchBlocks != null) + if (original.tryCatchBlocks != null) original.tryCatchBlocks.clear(); replacement.accept(original); } - public static void removeBlock(InsnList insns, InsnListSection block) - { + public static void removeBlock(InsnList insns, InsnListSection block) { AbstractInsnNode insn = block.first; - while(true) - { + while (true) { AbstractInsnNode next = insn.getNext(); insns.remove(insn); - if(insn == block.last) + if (insn == block.last) break; insn = next; } diff --git a/codechicken/lib/asm/ASMReader.java b/codechicken/lib/asm/ASMReader.java index e43de99..fd15f1e 100644 --- a/codechicken/lib/asm/ASMReader.java +++ b/codechicken/lib/asm/ASMReader.java @@ -301,14 +301,14 @@ else if(split[0].startsWith("L")) insn = new VarInsnNode(opcode, Integer.parseInt(split[1])); break; case TYPE_INSN: - insn = new ObfMapping(split[1]).toInsn(opcode); + insn = new ObfMapping(split[1]).toClassloading().toInsn(opcode); break; case FIELD_INSN: case METHOD_INSN: StringBuilder sb = new StringBuilder(); for(int i = 1; i < split.length; i++) sb.append(split[i]); - insn = ObfMapping.fromDesc(sb.toString()).toInsn(opcode); + insn = ObfMapping.fromDesc(sb.toString()).toClassloading().toInsn(opcode); break; case INVOKE_DYNAMIC_INSN: throw new Exception("Found INVOKEDYNAMIC while reading"); diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index 846e8cf..0aabd5a 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -1,8 +1,12 @@ package codechicken.lib.asm; import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; -import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; @@ -19,219 +23,235 @@ public class ObfMapping { - /** - * CCC will deal with this. - */ - public static Remapper runtimeMapper = FMLDeobfuscatingRemapper.INSTANCE; + public static class ObfRemapper extends Remapper + { + private HashMap fields = new HashMap(); + private HashMap funcs = new HashMap(); + + public ObfRemapper() { + try { + Field rawFieldMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawFieldMaps"); + Field rawMethodMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawMethodMaps"); + rawFieldMapsField.setAccessible(true); + rawMethodMapsField.setAccessible(true); + Map> rawFieldMaps = (Map>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + Map> rawMethodMaps = (Map>) rawMethodMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + + if(rawFieldMaps == null) + throw new IllegalStateException("codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); + + for(Map map : rawFieldMaps.values()) + for(Entry entry : map.entrySet()) + if(entry.getValue().startsWith("field")) + fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':'))); + for(Map map : rawMethodMaps.values()) + for(Entry entry : map.entrySet()) + if(entry.getValue().startsWith("func")) + funcs.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf('('))); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String mapMethodName(String owner, String name, String desc) { + String s = funcs.get(name); + return s == null ? name : s; + } + + @Override + public String mapFieldName(String owner, String name, String desc) { + String s = fields.get(name); + return s == null ? name : s; + } + + @Override + public String map(String typeName) { + return FMLDeobfuscatingRemapper.INSTANCE.unmap(typeName); + } + } + + public static ObfRemapper obfMapper = new ObfRemapper(); public static Remapper mcpMapper = null; - + public static final boolean obfuscated; - - static - { + + static { boolean obf = true; - try - { - obf = ((LaunchClassLoader)ObfMapping.class.getClassLoader()).getClassBytes("net.minecraft.world.World") == null; - } - catch(IOException iox) {} + try { + obf = Launch.classLoader.getClassBytes("net.minecraft.world.World") == null; + } catch (IOException ignored) {} obfuscated = obf; } - + public String s_owner; public String s_name; public String s_desc; - - public boolean runtime; - - public ObfMapping(String owner) - { + + public ObfMapping(String owner) { this(owner, "", ""); } - - public ObfMapping(String owner, String name, String desc) - { + + public ObfMapping(String owner, String name, String desc) { this.s_owner = owner; this.s_name = name; this.s_desc = desc; - if(s_owner.contains(".")) + if (s_owner.contains(".")) throw new IllegalArgumentException(s_owner); - - if(mcpMapper != null) - map(mcpMapper); } - - public ObfMapping(ObfMapping descmap, String subclass) - { + + public ObfMapping(ObfMapping descmap, String subclass) { this(subclass, descmap.s_name, descmap.s_desc); } - public static ObfMapping fromDesc(String s) - { + public static ObfMapping fromDesc(String s) { int lastDot = s.lastIndexOf('.'); - if(lastDot < 0) + if (lastDot < 0) return new ObfMapping(s, "", ""); int sep = s.indexOf('(');//methods int sep_end = sep; - if(sep < 0) { + if (sep < 0) { sep = s.indexOf(' ');//some stuffs - sep_end = sep+1; + sep_end = sep + 1; } - if(sep < 0) { + if (sep < 0) { sep = s.indexOf(':');//fields - sep_end = sep+1; + sep_end = sep + 1; } - if(sep < 0) + if (sep < 0) return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), ""); - return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot+1, sep), s.substring(sep_end)); + return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1, sep), s.substring(sep_end)); } - - public ObfMapping subclass(String subclass) - { + + public ObfMapping subclass(String subclass) { return new ObfMapping(this, subclass); } - public boolean matches(MethodNode node) - { + public boolean matches(MethodNode node) { return s_name.equals(node.name) && s_desc.equals(node.desc); } - - public boolean matches(MethodInsnNode node) - { + + public boolean matches(MethodInsnNode node) { return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc); } - public AbstractInsnNode toInsn(int opcode) - { - if(isClass()) + public AbstractInsnNode toInsn(int opcode) { + if (isClass()) return new TypeInsnNode(opcode, s_owner); - else if(isMethod()) + else if (isMethod()) return new MethodInsnNode(opcode, s_owner, s_name, s_desc); else return new FieldInsnNode(opcode, s_owner, s_name, s_desc); } - - public void visitTypeInsn(MethodVisitor mv, int opcode) - { + + public void visitTypeInsn(MethodVisitor mv, int opcode) { mv.visitTypeInsn(opcode, s_owner); } - - public void visitMethodInsn(MethodVisitor mv, int opcode) - { + + public void visitMethodInsn(MethodVisitor mv, int opcode) { mv.visitMethodInsn(opcode, s_owner, s_name, s_desc); } - public void visitFieldInsn(MethodVisitor mv, int opcode) - { + public void visitFieldInsn(MethodVisitor mv, int opcode) { mv.visitFieldInsn(opcode, s_owner, s_name, s_desc); } - public boolean isClass(String name) - { + public boolean isClass(String name) { return name.replace('.', '/').equals(s_owner); } - public boolean matches(String name, String desc) - { + public boolean matches(String name, String desc) { return s_name.equals(name) && s_desc.equals(desc); } - public boolean matches(FieldNode node) - { + public boolean matches(FieldNode node) { return s_name.equals(node.name) && s_desc.equals(node.desc); } - - public boolean matches(FieldInsnNode node) - { + + public boolean matches(FieldInsnNode node) { return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc); } - public String javaClass() - { + public String javaClass() { return s_owner.replace('/', '.'); } - + @Override - public boolean equals(Object obj) - { - if(!(obj instanceof ObfMapping)) + public boolean equals(Object obj) { + if (!(obj instanceof ObfMapping)) return false; - - ObfMapping desc = (ObfMapping)obj; + + ObfMapping desc = (ObfMapping) obj; return s_owner.equals(desc.s_owner) && s_name.equals(desc.s_name) && s_desc.equals(desc.s_desc); } - + @Override - public int hashCode() - { + public int hashCode() { return Objects.hashCode(s_desc, s_name, s_owner); } - + @Override - public String toString() - { - if(s_name.length() == 0) - return "["+s_owner+"]"; - if(s_desc.length() == 0) - return "["+s_owner+"."+s_name+"]"; - return "["+(isMethod() ? methodDesc() : fieldDesc())+"]"; + public String toString() { + if (s_name.length() == 0) + return "[" + s_owner + "]"; + if (s_desc.length() == 0) + return "[" + s_owner + "." + s_name + "]"; + return "[" + (isMethod() ? methodDesc() : fieldDesc()) + "]"; } - public String methodDesc() - { - return s_owner+"."+s_name+s_desc; + public String methodDesc() { + return s_owner + "." + s_name + s_desc; } - public String fieldDesc() - { - return s_owner+"."+s_name+":"+s_desc; + public String fieldDesc() { + return s_owner + "." + s_name + ":" + s_desc; } - - public boolean isClass() - { + + public boolean isClass() { return s_name.length() == 0; } - - public boolean isMethod() - { + + public boolean isMethod() { return s_desc.contains("("); } - - public boolean isField() - { + + public boolean isField() { return !isClass() && !isMethod(); } - - public ObfMapping map(Remapper mapper) - { - if(isMethod()) + + public ObfMapping map(Remapper mapper) { + if(mapper == null) + return this; + + if (isMethod()) s_name = mapper.mapMethodName(s_owner, s_name, s_desc); - else if(isField()) + else if (isField()) s_name = mapper.mapFieldName(s_owner, s_name, s_desc); - + s_owner = mapper.mapType(s_owner); - - if(isMethod()) + + if (isMethod()) s_desc = mapper.mapMethodDesc(s_desc); - else if(s_desc.length() > 0) + else if (s_desc.length() > 0) s_desc = mapper.mapDesc(s_desc); - + return this; } - - public ObfMapping toRuntime() - { - if(!runtime) - map(runtimeMapper); - - runtime = true; + + public ObfMapping toRuntime() { + map(mcpMapper); return this; } - - public ObfMapping copy() - { + + public ObfMapping toClassloading() { + map(obfuscated ? obfMapper : mcpMapper); + return this; + } + + public ObfMapping copy() { return new ObfMapping(s_owner, s_name, s_desc); } } diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index 41cf7a3..3fa78c2 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -1,5 +1,6 @@ package codechicken.lib.colour; +import codechicken.lib.util.Copyable; import org.lwjgl.opengl.GL11; import codechicken.lib.math.MathHelper; @@ -7,7 +8,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public abstract class Colour +public abstract class Colour implements Copyable { public byte r; public byte g; diff --git a/codechicken/lib/colour/ColourRGBA.java b/codechicken/lib/colour/ColourRGBA.java index 54baf91..61d4a29 100644 --- a/codechicken/lib/colour/ColourRGBA.java +++ b/codechicken/lib/colour/ColourRGBA.java @@ -1,40 +1,49 @@ package codechicken.lib.colour; -public class ColourRGBA extends Colour -{ - public ColourRGBA(int colour) - { +public class ColourRGBA extends Colour { + public ColourRGBA(int colour) { super((colour >> 24) & 0xFF, (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF); } - public ColourRGBA(double r, double g, double b, double a) - { + public ColourRGBA(double r, double g, double b, double a) { super((int) (255 * r), (int) (255 * g), (int) (255 * b), (int) (255 * a)); } - public ColourRGBA(int r, int g, int b, int a) - { + public ColourRGBA(int r, int g, int b, int a) { super(r, g, b, a); } - public ColourRGBA(ColourRGBA colour) - { + public ColourRGBA(ColourRGBA colour) { super(colour); } - public int pack() - { + public int pack() { return pack(this); } @Override - public Colour copy() - { + public Colour copy() { return new ColourRGBA(this); } - public static int pack(Colour colour) - { - return (colour.r&0xFF) << 24 | (colour.g&0xFF) << 16 | (colour.b&0xFF) << 8 | (colour.a&0xFF); + public static int pack(Colour colour) { + return (colour.r & 0xFF) << 24 | (colour.g & 0xFF) << 16 | (colour.b & 0xFF) << 8 | (colour.a & 0xFF); + } + + public static int multiply(int c1, int c2) { + if(c1 == -1) return c2; + if(c2 == -1) return c1; + int r = (((c1 >>> 24) * (c2 >>> 24)) & 0xFF00) << 16; + int g = (((c1 >> 16 & 0xFF) * (c2 >> 16 & 0xFF)) & 0xFF00) << 8; + int b = ((c1 >> 8 & 0xFF) * (c2 >> 8 & 0xFF)) & 0xFF00; + int a = ((c1 & 0xFF) * (c2 & 0xFF)) >> 8; + return r|g|b|a; + } + + public static int multiplyC(int c, float f) { + int r = (int) ((c >>> 24) * f); + int g = (int) ((c >> 16 & 0xFF) * f); + int b = (int) ((c >> 8 & 0xFF) * f); + return r<<24 | g<<16 | b<<8 | c&0xFF; } } diff --git a/codechicken/lib/config/ConfigFile.java b/codechicken/lib/config/ConfigFile.java index 6b84756..3e6e5e1 100644 --- a/codechicken/lib/config/ConfigFile.java +++ b/codechicken/lib/config/ConfigFile.java @@ -8,146 +8,118 @@ import java.io.PrintWriter; public class ConfigFile extends ConfigTagParent -{ - public ConfigFile(File file) - { - if(!file.exists()) - { - try - { +{ + public ConfigFile(File file) { + try { + if(!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + if (!file.exists()) file.createNewFile(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + } catch (IOException e) { + throw new RuntimeException(e); } this.file = file; newlinemode = 2; loadConfig(); } - - private void loadConfig() - { + + private void loadConfig() { loading = true; BufferedReader reader; - try - { + try { reader = new BufferedReader(new FileReader(file)); - - while(true) - { + + while (true) { reader.mark(2000); String line = reader.readLine(); - if(line != null && line.startsWith("#")) - { - if(comment == null || comment.equals("")) + if (line != null && line.startsWith("#")) { + if (comment == null || comment.equals("")) comment = line.substring(1); else - comment = comment+"\n"+line.substring(1); - } - else - { + comment = comment + "\n" + line.substring(1); + } else { reader.reset(); break; } } loadChildren(reader); reader.close(); - - } - catch(IOException e) - { + + } catch (IOException e) { throw new RuntimeException(e); } - + loading = false; } - + @Override - public ConfigFile setComment(String header) - { + public ConfigFile setComment(String header) { super.setComment(header); return this; } - + @Override - public ConfigFile setSortMode(int mode) - { + public ConfigFile setSortMode(int mode) { super.setSortMode(mode); return this; } - + @Override - public String getNameQualifier() - { + public String getNameQualifier() { return ""; } - - public static String readLine(BufferedReader reader) throws IOException - { + + public static String readLine(BufferedReader reader) throws IOException { String line = reader.readLine(); - if(line != null) + if (line != null) return line.replace("\t", ""); return line; } - - public static String formatLine(String line) - { + + public static String formatLine(String line) { line = line.replace("\t", ""); - if(line.startsWith("#")) - { + if (line.startsWith("#")) { return line; - } - else if(line.contains("=")) - { - line = line.substring(0, line.indexOf("=")).replace(" ", "")+line.substring(line.indexOf("=")); + } else if (line.contains("=")) { + line = line.substring(0, line.indexOf("=")).replace(" ", "") + line.substring(line.indexOf("=")); return line; - } - else - { + } else { line = line.replace(" ", ""); return line; } } - - public static void writeLine(PrintWriter writer, String line, int tabs) - { - for(int i = 0; i < tabs; i++) + + public static void writeLine(PrintWriter writer, String line, int tabs) { + for (int i = 0; i < tabs; i++) writer.print('\t'); - + writer.println(line); } - - public void saveConfig() - { - if(loading) + + public void saveConfig() { + if (loading) return; - + PrintWriter writer; - try - { + try { writer = new PrintWriter(file); - } - catch(FileNotFoundException e) - { + } catch (FileNotFoundException e) { throw new RuntimeException(e); } - + writeComment(writer, 0); ConfigFile.writeLine(writer, "", 0); saveTagTree(writer, 0, ""); writer.flush(); writer.close(); } - - public boolean isLoading() - { + + public boolean isLoading() { return loading; } - + public File file; private boolean loading; - + public static final byte[] lineend = new byte[]{0xD, 0xA}; } diff --git a/codechicken/lib/data/MCDataInput.java b/codechicken/lib/data/MCDataInput.java index d1169bd..fda1d45 100644 --- a/codechicken/lib/data/MCDataInput.java +++ b/codechicken/lib/data/MCDataInput.java @@ -12,11 +12,13 @@ public interface MCDataInput public short readShort(); public int readUShort(); public byte readByte(); - public int readUByte(); + public short readUByte(); public double readDouble(); public float readFloat(); public boolean readBoolean(); public char readChar(); + public int readVarShort(); + public int readVarInt(); public byte[] readByteArray(int length); public String readString(); public BlockCoord readCoord(); diff --git a/codechicken/lib/data/MCDataOutput.java b/codechicken/lib/data/MCDataOutput.java index 40d694e..fbe6710 100644 --- a/codechicken/lib/data/MCDataOutput.java +++ b/codechicken/lib/data/MCDataOutput.java @@ -15,6 +15,8 @@ public interface MCDataOutput public MCDataOutput writeFloat(float f); public MCDataOutput writeBoolean(boolean b); public MCDataOutput writeChar(char c); + public MCDataOutput writeVarInt(int i); + public MCDataOutput writeVarShort(int s); public MCDataOutput writeByteArray(byte[] array); public MCDataOutput writeString(String s); public MCDataOutput writeCoord(int x, int y, int z); diff --git a/codechicken/lib/data/MCOutputStreamWrapper.java b/codechicken/lib/data/MCOutputStreamWrapper.java index 71e5163..f8d94c5 100644 --- a/codechicken/lib/data/MCOutputStreamWrapper.java +++ b/codechicken/lib/data/MCOutputStreamWrapper.java @@ -3,6 +3,7 @@ import java.io.DataOutputStream; import java.io.IOException; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; @@ -122,7 +123,31 @@ public MCOutputStreamWrapper writeChar(char c) } return this; } - + + @Override + public MCDataOutput writeVarInt(int i) { + while ((i & 0x80) != 0) + { + writeByte(i & 0x7F | 0x80); + i >>>= 7; + } + + writeByte(i); + return this; + } + + @Override + public MCDataOutput writeVarShort(int s) { + int low = s & 0x7FFF; + int high = (s & 0x7F8000) >> 15; + if (high != 0) + low |= 0x8000; + writeShort(low); + if (high != 0) + writeByte(high); + return this; + } + public MCOutputStreamWrapper writeByteArray(byte[] barray) { try @@ -174,16 +199,12 @@ public MCOutputStreamWrapper writeItemStack(ItemStack stack) return this; } - public MCOutputStreamWrapper writeItemStack(ItemStack stack, boolean large) - { - if (stack == null) - { + public MCOutputStreamWrapper writeItemStack(ItemStack stack, boolean large) { + if (stack == null) { writeShort(-1); - } - else - { - writeShort(stack.itemID); - if(large) + } else { + writeShort(Item.getIdFromItem(stack.getItem())); + if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); diff --git a/codechicken/lib/data/NBTDataWrapper.java b/codechicken/lib/data/NBTDataWrapper.java deleted file mode 100644 index 19cf013..0000000 --- a/codechicken/lib/data/NBTDataWrapper.java +++ /dev/null @@ -1,246 +0,0 @@ -package codechicken.lib.data; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagByte; -import net.minecraft.nbt.NBTTagByteArray; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagDouble; -import net.minecraft.nbt.NBTTagFloat; -import net.minecraft.nbt.NBTTagInt; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagLong; -import net.minecraft.nbt.NBTTagShort; -import net.minecraft.nbt.NBTTagString; -import net.minecraftforge.fluids.FluidStack; -import codechicken.lib.vec.BlockCoord; - -public class NBTDataWrapper implements MCDataInput, MCDataOutput -{ - private NBTTagList readList; - private int readTag = 0; - private NBTTagList writeList; - - public NBTDataWrapper(NBTTagList input) - { - readList = input; - } - - public NBTDataWrapper() - { - writeList = new NBTTagList(); - } - - public NBTTagList toTag() - { - return writeList; - } - - @Override - public NBTDataWrapper writeLong(long l) - { - writeList.appendTag(new NBTTagLong(null, l)); - return this; - } - - @Override - public NBTDataWrapper writeInt(int i) - { - writeList.appendTag(new NBTTagInt(null, i)); - return this; - } - - @Override - public NBTDataWrapper writeShort(int s) - { - writeList.appendTag(new NBTTagShort(null, (short) s)); - return this; - } - - @Override - public NBTDataWrapper writeByte(int b) - { - writeList.appendTag(new NBTTagByte(null, (byte) b)); - return this; - } - - @Override - public NBTDataWrapper writeDouble(double d) - { - writeList.appendTag(new NBTTagDouble(null, d)); - return this; - } - - @Override - public NBTDataWrapper writeFloat(float f) - { - writeList.appendTag(new NBTTagFloat(null, f)); - return this; - } - - @Override - public NBTDataWrapper writeBoolean(boolean b) - { - writeList.appendTag(new NBTTagByte(null, (byte) (b ? 1 : 0))); - return this; - } - - @Override - public NBTDataWrapper writeChar(char c) - { - writeList.appendTag(new NBTTagShort(null, (short)c)); - return this; - } - - @Override - public NBTDataWrapper writeByteArray(byte[] array) - { - writeList.appendTag(new NBTTagByteArray(null, array)); - return this; - } - - @Override - public NBTDataWrapper writeString(String s) - { - writeList.appendTag(new NBTTagString(null, s)); - return this; - } - - @Override - public NBTDataWrapper writeCoord(int x, int y, int z) - { - writeInt(x); - writeInt(y); - writeInt(z); - return this; - } - - @Override - public NBTDataWrapper writeCoord(BlockCoord coord) - { - writeCoord(coord.x, coord.y, coord.z); - return this; - } - - @Override - public NBTDataWrapper writeNBTTagCompound(NBTTagCompound tag) - { - writeList.appendTag(tag); - return this; - } - - @Override - public NBTDataWrapper writeItemStack(ItemStack stack) - { - writeList.appendTag(stack.writeToNBT(new NBTTagCompound())); - return this; - } - - @Override - public NBTDataWrapper writeFluidStack(FluidStack liquid) - { - writeList.appendTag(liquid.writeToNBT(new NBTTagCompound())); - return this; - } - - @Override - public long readLong() - { - return ((NBTTagLong)readTag()).data; - } - - @Override - public int readInt() - { - return ((NBTTagInt)readTag()).data; - } - - @Override - public short readShort() - { - return ((NBTTagShort)readTag()).data; - } - - @Override - public int readUShort() - { - return ((NBTTagShort)readTag()).data & 0xFFFF; - } - - @Override - public byte readByte() - { - return ((NBTTagByte)readTag()).data; - } - - @Override - public int readUByte() - { - return ((NBTTagByte)readTag()).data & 0xFF; - } - - @Override - public double readDouble() - { - return ((NBTTagDouble)readTag()).data; - } - - @Override - public float readFloat() - { - return ((NBTTagFloat)readTag()).data; - } - - @Override - public boolean readBoolean() - { - return ((NBTTagByte)readTag()).data != 0; - } - - @Override - public char readChar() - { - return (char)((NBTTagShort)readTag()).data; - } - - @Override - public byte[] readByteArray(int length) - { - return ((NBTTagByteArray)readTag()).byteArray; - } - - @Override - public String readString() - { - return ((NBTTagString)readTag()).data; - } - - @Override - public BlockCoord readCoord() - { - return new BlockCoord(readInt(), readInt(), readInt()); - } - - @Override - public NBTTagCompound readNBTTagCompound() - { - return (NBTTagCompound)readTag(); - } - - @Override - public ItemStack readItemStack() - { - return ItemStack.loadItemStackFromNBT(readNBTTagCompound()); - } - - @Override - public FluidStack readFluidStack() - { - return FluidStack.loadFluidStackFromNBT(readNBTTagCompound()); - } - - private NBTBase readTag() - { - return readList.tagAt(readTag++); - } -} diff --git a/codechicken/lib/gui/Canvas9Seg.java b/codechicken/lib/gui/Canvas9Seg.java index b558197..055bb42 100644 --- a/codechicken/lib/gui/Canvas9Seg.java +++ b/codechicken/lib/gui/Canvas9Seg.java @@ -65,7 +65,7 @@ private void drawSeg(int[] sw, int[] sh, int seg) { public void draw(int x, int y, int w, int h) { CCRenderState.changeTexture(tex); CCRenderState.reset(); - CCRenderState.startDrawing(7); + CCRenderState.startDrawing(); int[] sw = new int[]{x, x+seg_w[0], x+w-seg_w[2], x+w}; int[] sh = new int[]{y, y+seg_h[0], y+h-seg_h[2], y+h}; diff --git a/codechicken/lib/gui/GuiDraw.java b/codechicken/lib/gui/GuiDraw.java new file mode 100644 index 0000000..b930d26 --- /dev/null +++ b/codechicken/lib/gui/GuiDraw.java @@ -0,0 +1,223 @@ +package codechicken.lib.gui; + +import java.awt.Dimension; +import java.awt.Point; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import net.minecraft.util.EnumChatFormatting; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import codechicken.lib.math.MathHelper; +import codechicken.lib.render.CCRenderState; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.util.ResourceLocation; + +public class GuiDraw +{ + public static class GuiHook extends Gui + { + public void setZLevel(float f) { + zLevel = f; + } + + public float getZLevel() { + return zLevel; + } + + public void incZLevel(float f) { + zLevel += f; + } + + @Override + public void drawGradientRect(int par1, int par2, int par3, int par4, int par5, int par6) { + super.drawGradientRect(par1, par2, par3, par4, par5, par6); + } + } + + public static final GuiHook gui = new GuiHook(); + public static FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + public static TextureManager renderEngine = Minecraft.getMinecraft().renderEngine; + + public static void drawRect(int x, int y, int w, int h, int colour) { + drawGradientRect(x, y, w, h, colour, colour); + } + + public static void drawGradientRect(int x, int y, int w, int h, int colour1, int colour2) { + gui.drawGradientRect(x, y, x + w, y + h, colour1, colour2); + } + + public static void drawTexturedModalRect(int x, int y, int tx, int ty, int w, int h) { + gui.drawTexturedModalRect(x, y, tx, ty, w, h); + } + + public static void drawString(String text, int x, int y, int colour, boolean shadow) { + if (shadow) + fontRenderer.drawStringWithShadow(text, x, y, colour); + else + fontRenderer.drawString(text, x, y, colour); + } + + public static void drawString(String text, int x, int y, int colour) { + drawString(text, x, y, colour, true); + } + + public static void drawStringC(String text, int x, int y, int w, int h, int colour, boolean shadow) { + drawString(text, x + (w - getStringWidth(text)) / 2, y + (h - 8) / 2, colour, shadow); + } + + public static void drawStringC(String text, int x, int y, int w, int h, int colour) { + drawStringC(text, x, y, w, h, colour, true); + } + + public static void drawStringC(String text, int x, int y, int colour, boolean shadow) { + drawString(text, x - getStringWidth(text) / 2, y, colour, shadow); + } + + public static void drawStringC(String text, int x, int y, int colour) { + drawStringC(text, x, y, colour, true); + } + + public static void drawStringR(String text, int x, int y, int colour, boolean shadow) { + drawString(text, x - getStringWidth(text), y, colour, shadow); + } + + public static void drawStringR(String text, int x, int y, int colour) { + drawStringR(text, x, y, colour, true); + } + + + public static int getStringWidth(String s) { + if (s == null || s.equals("")) + return 0; + return fontRenderer.getStringWidth(EnumChatFormatting.getTextWithoutFormattingCodes(s)); + } + + public static Dimension displaySize() { + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight); + return new Dimension(res.getScaledWidth(), res.getScaledHeight()); + } + + public static Dimension displayRes() { + Minecraft mc = Minecraft.getMinecraft(); + return new Dimension(mc.displayWidth, mc.displayHeight); + } + + public static Point getMousePosition() { + Dimension size = displaySize(); + Dimension res = displayRes(); + return new Point(Mouse.getX() * size.width / res.width, size.height - Mouse.getY() * size.height / res.height - 1); + } + + public static void changeTexture(String s) { + CCRenderState.changeTexture(s); + } + + public static void changeTexture(ResourceLocation r) { + CCRenderState.changeTexture(r); + } + + public static void drawTip(int x, int y, String text) { + drawMultilineTip(x, y, Arrays.asList(text)); + } + + /** + * Append a string in the tooltip list with TOOLTIP_LINESPACE to have a small gap between it and the next line + */ + public static final String TOOLTIP_LINESPACE = "\u00A7h"; + /** + * Have a string in the tooltip list with TOOLTIP_HANDLER + getTipLineId(handler) for a custom handler + */ + public static final String TOOLTIP_HANDLER = "\u00A7x"; + private static List tipLineHandlers = new ArrayList(); + + public static interface ITooltipLineHandler + { + public Dimension getSize(); + + public void draw(int x, int y); + } + + public static int getTipLineId(ITooltipLineHandler handler) { + tipLineHandlers.add(handler); + return tipLineHandlers.size()-1; + } + + public static ITooltipLineHandler getTipLine(String line) { + if(!line.startsWith(TOOLTIP_HANDLER)) + return null; + return tipLineHandlers.get(Integer.parseInt(line.substring(2))); + } + + public static void drawMultilineTip(int x, int y, List list) { + if (list.isEmpty()) + return; + + GL11.glDisable(GL12.GL_RESCALE_NORMAL); + GL11.glDisable(GL11.GL_DEPTH_TEST); + RenderHelper.disableStandardItemLighting(); + + int w = 0; + int h = -2; + for (int i = 0; i < list.size(); i++) { + String s = list.get(i); + ITooltipLineHandler line = getTipLine(s); + Dimension d = line != null ? + line.getSize() : + new Dimension(getStringWidth(s), list.get(i).endsWith(TOOLTIP_LINESPACE) && i + 1 < list.size() ? 12 : 10); + w = Math.max(w, d.width); + h += d.height; + } + + if (x < 8) x = 8; + else if (x > displaySize().width - w - 8) x -= 24 + w;//flip side of cursor + y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h); + + gui.incZLevel(300); + drawTooltipBox(x - 4, y - 4, w + 7, h + 7); + for (String s : list) { + ITooltipLineHandler line = getTipLine(s); + if(line != null) { + line.draw(x, y); + y += line.getSize().height; + } + else { + fontRenderer.drawStringWithShadow(s, x, y, -1); + y += s.endsWith(TOOLTIP_LINESPACE) ? 12 : 10; + } + } + + tipLineHandlers.clear(); + gui.incZLevel(-300); + + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + RenderHelper.enableGUIStandardItemLighting(); + } + + public static void drawTooltipBox(int x, int y, int w, int h) { + int bg = 0xf0100010; + drawGradientRect(x + 1, y, w - 1, 1, bg, bg); + drawGradientRect(x + 1, y + h, w - 1, 1, bg, bg); + drawGradientRect(x + 1, y + 1, w - 1, h - 1, bg, bg);//center + drawGradientRect(x, y + 1, 1, h - 1, bg, bg); + drawGradientRect(x + w, y + 1, 1, h - 1, bg, bg); + int grad1 = 0x505000ff; + int grad2 = 0x5028007F; + drawGradientRect(x + 1, y + 2, 1, h - 3, grad1, grad2); + drawGradientRect(x + w - 1, y + 2, 1, h - 3, grad1, grad2); + + drawGradientRect(x + 1, y + 1, w - 1, 1, grad1, grad1); + drawGradientRect(x + 1, y + h - 1, w - 1, 1, grad2, grad2); + } +} diff --git a/codechicken/lib/inventory/InventoryCopy.java b/codechicken/lib/inventory/InventoryCopy.java index 8bcfdd5..5843404 100644 --- a/codechicken/lib/inventory/InventoryCopy.java +++ b/codechicken/lib/inventory/InventoryCopy.java @@ -76,11 +76,11 @@ public ItemStack getStackInSlotOnClosing(int slot) public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; - onInventoryChanged(); + markDirty(); } @Override - public String getInvName() + public String getInventoryName() { return "copy"; } @@ -91,12 +91,13 @@ public boolean isUseableByPlayer(EntityPlayer player) return true; } - public void openChest() + @Override + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -106,9 +107,8 @@ public int getInventoryStackLimit() return 64; } - @Override - public void onInventoryChanged() + public void markDirty() { } @@ -119,7 +119,7 @@ public boolean isItemValidForSlot(int i, ItemStack itemstack) } @Override - public boolean isInvNameLocalized() + public boolean hasCustomInventoryName() { return true; } diff --git a/codechicken/lib/inventory/InventoryNBT.java b/codechicken/lib/inventory/InventoryNBT.java index a6e338c..45aa54f 100644 --- a/codechicken/lib/inventory/InventoryNBT.java +++ b/codechicken/lib/inventory/InventoryNBT.java @@ -28,7 +28,7 @@ private void writeNBT() private void readNBT() { if(tag.hasKey("items")) - InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items")); + InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items", 10)); } @Override @@ -59,11 +59,11 @@ public ItemStack getStackInSlotOnClosing(int slot) public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; - onInventoryChanged(); + markDirty(); } @Override - public String getInvName() + public String getInventoryName() { return "NBT"; } @@ -75,7 +75,7 @@ public int getInventoryStackLimit() } @Override - public void onInventoryChanged() + public void markDirty() { writeNBT(); } @@ -87,12 +87,12 @@ public boolean isUseableByPlayer(EntityPlayer var1) } @Override - public void openChest() + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -103,7 +103,7 @@ public boolean isItemValidForSlot(int i, ItemStack itemstack) } @Override - public boolean isInvNameLocalized() + public boolean hasCustomInventoryName() { return true; } diff --git a/codechicken/lib/inventory/InventorySimple.java b/codechicken/lib/inventory/InventorySimple.java index 12b1c8e..4481c23 100644 --- a/codechicken/lib/inventory/InventorySimple.java +++ b/codechicken/lib/inventory/InventorySimple.java @@ -83,11 +83,11 @@ public ItemStack getStackInSlotOnClosing(int slot) public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; - onInventoryChanged(); + markDirty(); } @Override - public String getInvName() + public String getInventoryName() { return name; } @@ -105,12 +105,12 @@ public boolean isUseableByPlayer(EntityPlayer var1) } @Override - public void openChest() + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -121,13 +121,13 @@ public boolean isItemValidForSlot(int i, ItemStack itemstack) } @Override - public boolean isInvNameLocalized() + public boolean hasCustomInventoryName() { return true; } @Override - public void onInventoryChanged() + public void markDirty() { } } diff --git a/codechicken/lib/inventory/InventoryUtils.java b/codechicken/lib/inventory/InventoryUtils.java index 921b3df..7f063e1 100644 --- a/codechicken/lib/inventory/InventoryUtils.java +++ b/codechicken/lib/inventory/InventoryUtils.java @@ -5,44 +5,54 @@ import codechicken.lib.vec.Vector3; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryLargeChest; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagInt; import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagShort; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.world.World; -import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.common.util.ForgeDirection; public class InventoryUtils { + /** + * Constructor for ItemStack with tag + */ + public static ItemStack newItemStack(Item item, int size, int damage, NBTTagCompound tag) { + ItemStack stack = new ItemStack(item, size, damage); + stack.stackTagCompound = tag; + return stack; + } + + /** + * Gets the actual damage of an item without asking the Item + */ + public static int actualDamage(ItemStack stack) { + return Items.diamond.getDamage(stack); + } + /** * Static default implementation for IInventory method */ - public static ItemStack decrStackSize(IInventory inv, int slot, int size) - { + public static ItemStack decrStackSize(IInventory inv, int slot, int size) { ItemStack item = inv.getStackInSlot(slot); - - if(item != null) - { - if(item.stackSize <= size) - { - ItemStack itemstack = item; + + if (item != null) { + if (item.stackSize <= size) { inv.setInventorySlotContents(slot, null); - inv.onInventoryChanged(); - return itemstack; + inv.markDirty(); + return item; } ItemStack itemstack1 = item.splitStack(size); - if(item.stackSize == 0) - { + if (item.stackSize == 0) inv.setInventorySlotContents(slot, null); - } - inv.onInventoryChanged(); + + inv.markDirty(); return itemstack1; } return null; @@ -51,8 +61,7 @@ public static ItemStack decrStackSize(IInventory inv, int slot, int size) /** * Static default implementation for IInventory method */ - public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) - { + public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); inv.setInventorySlotContents(slot, null); return stack; @@ -61,56 +70,50 @@ public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) /** * @return The quantity of items from addition that can be added to base */ - public static int incrStackSize(ItemStack base, ItemStack addition) - { + public static int incrStackSize(ItemStack base, ItemStack addition) { if (canStack(base, addition)) return incrStackSize(base, addition.stackSize); - + return 0; } - + /** * @return The quantity of items from addition that can be added to base */ - public static int incrStackSize(ItemStack base, int addition) - { + public static int incrStackSize(ItemStack base, int addition) { int totalSize = base.stackSize + addition; if (totalSize <= base.getMaxStackSize()) return addition; else if (base.stackSize < base.getMaxStackSize()) return base.getMaxStackSize() - base.stackSize; - + return 0; } /** * NBT item saving function */ - public static NBTTagList writeItemStacksToTag(ItemStack[] items) - { + public static NBTTagList writeItemStacksToTag(ItemStack[] items) { return writeItemStacksToTag(items, 64); } /** * NBT item saving function with support for stack sizes > 32K */ - public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) - { + public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity) { NBTTagList tagList = new NBTTagList(); - for(int i = 0; i < items.length; i++) - { - if (items[i] != null) - { + for (int i = 0; i < items.length; i++) { + if (items[i] != null) { NBTTagCompound tag = new NBTTagCompound(); tag.setShort("Slot", (short) i); items[i].writeToNBT(tag); - - if(maxQuantity > Short.MAX_VALUE) + + if (maxQuantity > Short.MAX_VALUE) tag.setInteger("Quantity", items[i].stackSize); - else if(maxQuantity > Byte.MAX_VALUE) + else if (maxQuantity > Byte.MAX_VALUE) tag.setShort("Quantity", (short) items[i].stackSize); - + tagList.appendTag(tag); } } @@ -120,29 +123,20 @@ else if(maxQuantity > Byte.MAX_VALUE) /** * NBT item loading function with support for stack sizes > 32K */ - public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) - { - for(int i = 0; i < tagList.tagCount(); i++) - { - NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i); + public static void readItemStacksFromTag(ItemStack[] items, NBTTagList tagList) { + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound tag = tagList.getCompoundTagAt(i); int b = tag.getShort("Slot"); items[b] = ItemStack.loadItemStackFromNBT(tag); - if(tag.hasKey("Quantity")) - { - NBTBase qtag = tag.getTag("Quantity"); - if(qtag instanceof NBTTagInt) - items[b].stackSize = ((NBTTagInt)qtag).data; - else if(qtag instanceof NBTTagShort) - items[b].stackSize = ((NBTTagShort)qtag).data; - } + if (tag.hasKey("Quantity")) + items[b].stackSize = ((NBTBase.NBTPrimitive) tag.getTag("Quantity")).func_150287_d(); } } /** * Spawns an itemstack in the world at a location */ - public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) - { + public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) { EntityItem item = new EntityItem(world, dropLocation.x, dropLocation.y, dropLocation.z, stack); item.motionX = world.rand.nextGaussian() * 0.05; item.motionY = world.rand.nextGaussian() * 0.05 + 0.2F; @@ -153,11 +147,10 @@ public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) /** * Copies an itemstack with a new quantity */ - public static ItemStack copyStack(ItemStack stack, int quantity) - { - if(stack == null) + public static ItemStack copyStack(ItemStack stack, int quantity) { + if (stack == null) return null; - + stack = stack.copy(); stack.stackSize = quantity; return stack; @@ -166,102 +159,87 @@ public static ItemStack copyStack(ItemStack stack, int quantity) /** * Gets the maximum quantity of an item that can be inserted into inv */ - public static int getInsertibleQuantity(InventoryRange inv, ItemStack stack) - { + public static int getInsertibleQuantity(InventoryRange inv, ItemStack stack) { int quantity = 0; stack = copyStack(stack, Integer.MAX_VALUE); - for(int slot : inv.slots) - quantity+=fitStackInSlot(inv, slot, stack); - + for (int slot : inv.slots) + quantity += fitStackInSlot(inv, slot, stack); + return quantity; } - public static int getInsertibleQuantity(IInventory inv, ItemStack stack) - { + public static int getInsertibleQuantity(IInventory inv, ItemStack stack) { return getInsertibleQuantity(new InventoryRange(inv), stack); } - - public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) - { + + public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) { ItemStack base = inv.inv.getStackInSlot(slot); - if(!canStack(base, stack) || !inv.canInsertItem(slot, stack)) + if (!canStack(base, stack) || !inv.canInsertItem(slot, stack)) return 0; - int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit()-base.stackSize) : inv.inv.getInventoryStackLimit(); + int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit() - base.stackSize) : inv.inv.getInventoryStackLimit(); return Math.min(fit, stack.stackSize); } - public static int fitStackInSlot(IInventory inv, int slot, ItemStack stack) - { + public static int fitStackInSlot(IInventory inv, int slot, ItemStack stack) { return fitStackInSlot(new InventoryRange(inv), slot, stack); } /** - * @param simulate. If set to true, no items will actually be inserted + * @param simulate If set to true, no items will actually be inserted * @return The number of items unable to be inserted */ - public static int insertItem(InventoryRange inv, ItemStack stack, boolean simulate) - { + public static int insertItem(InventoryRange inv, ItemStack stack, boolean simulate) { stack = stack.copy(); - for(int pass = 0; pass < 2; pass++) - { - for(int slot : inv.slots) - { + for (int pass = 0; pass < 2; pass++) { + for (int slot : inv.slots) { ItemStack base = inv.inv.getStackInSlot(slot); int fit = fitStackInSlot(inv, slot, stack); - if(fit == 0) + if (fit == 0) continue; - - if(base != null) - { - stack.stackSize-=fit; - if(!simulate) - { - base.stackSize+=fit; + + if (base != null) { + stack.stackSize -= fit; + if (!simulate) { + base.stackSize += fit; inv.inv.setInventorySlotContents(slot, base); } - } - else if(pass == 1) - { - if(!simulate) + } else if (pass == 1) { + if (!simulate) inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); - stack.stackSize-=fit; + stack.stackSize -= fit; } - if(stack.stackSize == 0) + if (stack.stackSize == 0) return 0; } } return stack.stackSize; } - public static int insertItem(IInventory inv, ItemStack stack, boolean simulate) - { + public static int insertItem(IInventory inv, ItemStack stack, boolean simulate) { return insertItem(new InventoryRange(inv), stack, simulate); } /** * Gets the stack in slot if it can be extracted */ - public static ItemStack getExtractableStack(InventoryRange inv, int slot) - { + public static ItemStack getExtractableStack(InventoryRange inv, int slot) { ItemStack stack = inv.inv.getStackInSlot(slot); - if(stack == null || !inv.canExtractItem(slot, stack)) + if (stack == null || !inv.canExtractItem(slot, stack)) return null; return stack; } - public static ItemStack getExtractableStack(IInventory inv, int slot) - { + public static ItemStack getExtractableStack(IInventory inv, int slot) { return getExtractableStack(new InventoryRange(inv), slot); } - public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) - { - if(stack1 == null || stack2 == null) + public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { + if (stack1 == null || stack2 == null) return stack1 == stack2; - return stack1.itemID == stack2.itemID + return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() && stack1.stackSize == stack2.stackSize && Objects.equal(stack1.getTagCompound(), stack2.getTagCompound()); @@ -270,53 +248,46 @@ public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) /** * Gets an IInventory from a coordinate with support for double chests */ - public static IInventory getInventory(World world, int x, int y, int z) - { - TileEntity tile = world.getBlockTileEntity(x, y, z); - if(!(tile instanceof IInventory)) + public static IInventory getInventory(World world, int x, int y, int z) { + TileEntity tile = world.getTileEntity(x, y, z); + if (!(tile instanceof IInventory)) return null; - - if(tile instanceof TileEntityChest) + + if (tile instanceof TileEntityChest) return getChest((TileEntityChest) tile); - return (IInventory)tile; - + return (IInventory) tile; + } - + public static final ForgeDirection[] chestSides = new ForgeDirection[]{ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; - public static IInventory getChest(TileEntityChest chest) - { - for(ForgeDirection fside : chestSides) - { - if(chest.worldObj.getBlockId(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ) == chest.getBlockType().blockID) - return new InventoryLargeChest("container.chestDouble", - (TileEntityChest)chest.worldObj.getBlockTileEntity(chest.xCoord+fside.offsetX, chest.yCoord+fside.offsetY, chest.zCoord+fside.offsetZ), chest); + + public static IInventory getChest(TileEntityChest chest) { + for (ForgeDirection fside : chestSides) { + if (chest.getWorldObj().getBlock(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ) == chest.getBlockType()) + return new InventoryLargeChest("container.chestDouble", + (TileEntityChest) chest.getWorldObj().getTileEntity(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ), chest); } return chest; } - public static boolean canStack(ItemStack stack1, ItemStack stack2) - { - return stack1 == null || stack2 == null || - (stack1.itemID == stack2.itemID && - (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && - ItemStack.areItemStackTagsEqual(stack2, stack1)) && - stack1.isStackable(); + public static boolean canStack(ItemStack stack1, ItemStack stack2) { + return stack1 == null || stack2 == null || + (stack1.getItem() == stack2.getItem() && + (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && + ItemStack.areItemStackTagsEqual(stack2, stack1)) && + stack1.isStackable(); } /** * Consumes one item from slot in inv with support for containers. */ - public static void consumeItem(IInventory inv, int slot) - { + public static void consumeItem(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); Item item = stack.getItem(); - if(item.hasContainerItem()) - { - ItemStack container = item.getContainerItemStack(stack); + if (item.hasContainerItem(stack)) { + ItemStack container = item.getContainerItem(stack); inv.setInventorySlotContents(slot, container); - } - else - { + } else { inv.decrStackSize(slot, 1); } } @@ -324,8 +295,7 @@ public static void consumeItem(IInventory inv, int slot) /** * Gets the size of the stack in a slot. Returns 0 on null stacks */ - public static int stackSize(IInventory inv, int slot) - { + public static int stackSize(IInventory inv, int slot) { ItemStack stack = inv.getStackInSlot(slot); return stack == null ? 0 : stack.stackSize; } @@ -333,21 +303,30 @@ public static int stackSize(IInventory inv, int slot) /** * Drops all items from inv using getStackInSlotOnClosing */ - public static void dropOnClose(EntityPlayer player, IInventory inv) - { - for (int i = 0; i < inv.getSizeInventory(); i++) - { + public static void dropOnClose(EntityPlayer player, IInventory inv) { + for (int i = 0; i < inv.getSizeInventory(); i++) { ItemStack stack = inv.getStackInSlotOnClosing(i); if (stack != null) - player.dropPlayerItem(stack); + player.dropPlayerItemWithRandomChoice(stack, false); } } - /** - * Gets the actual damage of an item without asking the Item - */ - public static int actualDamage(ItemStack stack) - { - return Item.diamond.getDamage(stack); + public static NBTTagCompound savePersistant(ItemStack stack, NBTTagCompound tag) { + stack.writeToNBT(tag); + tag.removeTag("id"); + tag.setString("name", Item.itemRegistry.getNameForObject(stack.getItem())); + return tag; + } + + public static ItemStack loadPersistant(NBTTagCompound tag) { + String name = tag.getString("name"); + Item item = (Item) Item.itemRegistry.getObject(name); + if(item == null) return null; + int count = tag.hasKey("Count") ? tag.getByte("Count") : 1; + int damage = tag.hasKey("Damage") ? tag.getShort("Damage") : 0; + ItemStack stack = new ItemStack(item, count, damage); + if(tag.hasKey("tag", 10)) + stack.stackTagCompound = tag.getCompoundTag("tag"); + return stack; } } diff --git a/codechicken/lib/inventory/ItemKey.java b/codechicken/lib/inventory/ItemKey.java index e52a923..0adb687 100644 --- a/codechicken/lib/inventory/ItemKey.java +++ b/codechicken/lib/inventory/ItemKey.java @@ -1,9 +1,12 @@ package codechicken.lib.inventory; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import com.google.common.base.Objects; +import net.minecraftforge.oredict.OreDictionary; + import static codechicken.lib.inventory.InventoryUtils.*; /** @@ -11,55 +14,52 @@ */ public class ItemKey implements Comparable { - public ItemStack item; + public ItemStack stack; private int hashcode = 0; - - public ItemKey(ItemStack k) - { - item = k; + + public ItemKey(ItemStack k) { + stack = k; + } + + public ItemKey(Item item, int damage) { + this(new ItemStack(item, 1, damage)); } - public ItemKey(int id, int damage) - { - this(new ItemStack(id, 1, damage)); + public ItemKey(Item item, NBTTagCompound tag) { + this(item, OreDictionary.WILDCARD_VALUE, tag); } - - public ItemKey(int id, int damage, NBTTagCompound compound) - { - this(id, damage); - item.setTagCompound(compound); + + public ItemKey(Item item, int damage, NBTTagCompound tag) { + this(item, damage); + stack.setTagCompound(tag); } @Override - public boolean equals(Object obj) - { - if(!(obj instanceof ItemKey)) + public boolean equals(Object obj) { + if (!(obj instanceof ItemKey)) return false; - - ItemKey k = (ItemKey)obj; - return item.itemID == k.item.itemID && - actualDamage(item) == actualDamage(k.item) && - Objects.equal(item.stackTagCompound, k.item.stackTagCompound); + + ItemKey k = (ItemKey) obj; + return stack.getItem() == k.stack.getItem() && + actualDamage(stack) == actualDamage(k.stack) && + Objects.equal(stack.stackTagCompound, k.stack.stackTagCompound); } - + @Override - public int hashCode() - { - return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(item.itemID, actualDamage(item), item.stackTagCompound)); + public int hashCode() { + return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(stack.getItem(), actualDamage(stack), stack.stackTagCompound)); } - - public int compareInt(int a, int b) - { + + public int compareInt(int a, int b) { return a == b ? 0 : a < b ? -1 : 1; } @Override - public int compareTo(ItemKey o) - { - if(item.itemID != o.item.itemID) - return compareInt(item.itemID, o.item.itemID); - if(actualDamage(item) != actualDamage(o.item)) - return compareInt(actualDamage(item), actualDamage(o.item)); + public int compareTo(ItemKey o) { + if (stack.getItem() != o.stack.getItem()) + return compareInt(Item.getIdFromItem(stack.getItem()), Item.getIdFromItem(o.stack.getItem())); + if (actualDamage(stack) != actualDamage(o.stack)) + return compareInt(actualDamage(stack), actualDamage(o.stack)); return 0; } } diff --git a/codechicken/lib/lang/LangUtil.java b/codechicken/lib/lang/LangUtil.java deleted file mode 100644 index 767887b..0000000 --- a/codechicken/lib/lang/LangUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -package codechicken.lib.lang; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.SortedSet; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.Language; -import net.minecraft.client.resources.Resource; -import net.minecraft.client.resources.ResourceManager; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.StatCollector; - -import cpw.mods.fml.common.registry.LanguageRegistry; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -/** - * Easy localisation access. - */ -public class LangUtil -{ - public static LangUtil instance = new LangUtil(null); - - public String prefix; - - public LangUtil(String prefix) - { - this.prefix = prefix; - } - - public static String translateG(String s, Object... format) - { - return instance.translate(s, format); - } - - public String translate(String s, Object... format) - { - if(prefix != null && !s.startsWith(prefix+".")) - s = prefix+"."+s; - String ret = LanguageRegistry.instance().getStringLocalization(s); - if(ret.length() == 0) - ret = LanguageRegistry.instance().getStringLocalization(s, "en_US"); - if(ret.length() == 0) - ret = StatCollector.translateToLocal(s); - if(ret.length() == 0) - return s; - if(format.length > 0) - ret = String.format(ret, format); - return ret; - } - - public void addLangFile(InputStream resource, String lang) throws IOException - { - LanguageRegistry reg = LanguageRegistry.instance(); - BufferedReader reader = new BufferedReader(new InputStreamReader(resource, "UTF-8")); - while(true) - { - String read = reader.readLine(); - if(read == null) - break; - - int equalIndex = read.indexOf('='); - if(equalIndex == -1) - continue; - String key = read.substring(0, equalIndex); - String value = read.substring(equalIndex+1); - if(prefix != null) - key = prefix+"."+key; - reg.addStringLocalization(key, lang, value); - } - } - - @SideOnly(Side.CLIENT) - public static LangUtil loadLangDir(String domain) - { - return new LangUtil(domain).addLangDir(new ResourceLocation(domain, "lang")); - } - - @SideOnly(Side.CLIENT) - public LangUtil addLangDir(ResourceLocation dir) - { - ResourceManager resManager = Minecraft.getMinecraft().getResourceManager(); - for(Language lang : (SortedSet)Minecraft.getMinecraft().getLanguageManager().getLanguages()) - { - String langID = lang.getLanguageCode(); - Resource langRes; - try - { - langRes = resManager.getResource(new ResourceLocation(dir.getResourceDomain(), dir.getResourcePath()+'/'+langID+".lang")); - } - catch(Exception e) - { - continue; - } - try - { - addLangFile(langRes.getInputStream(), langID); - } - catch(IOException e) - { - System.err.println("Failed to load lang resource. domain="+prefix+", resource="+langRes); - e.printStackTrace(); - } - } - - return this; - } -} diff --git a/codechicken/lib/lighting/CCRBModel.java b/codechicken/lib/lighting/CCRBModel.java deleted file mode 100644 index a3074b0..0000000 --- a/codechicken/lib/lighting/CCRBModel.java +++ /dev/null @@ -1,31 +0,0 @@ -package codechicken.lib.lighting; - -import codechicken.lib.render.CCModel; -import codechicken.lib.render.Vertex5; - -public class CCRBModel extends CCModel -{ - public LC[] lightCoefficents; - - /** - * Lighting sides and coefficients are computed for each vertex of the model. All faces must be axis planar and all verts are assumed to be in the range (0,0,0) to (1,1,1) - */ - public CCRBModel(CCModel m) - { - super(m.vertexMode); - verts = new Vertex5[m.verts.length]; - copy(m, 0, this, 0, m.verts.length); - if(normals == null) - computeNormals(); - if(colours == null) - setColour(-1); - computeLighting(); - } - - private void computeLighting() - { - lightCoefficents = new LC[verts.length]; - for(int k = 0; k < verts.length; k++) - lightCoefficents[k] = LC.compute(verts[k].vec, normals[k]); - } -} diff --git a/codechicken/lib/lighting/LC.java b/codechicken/lib/lighting/LC.java index baa3ab7..c2409fb 100644 --- a/codechicken/lib/lighting/LC.java +++ b/codechicken/lib/lighting/LC.java @@ -1,59 +1,89 @@ package codechicken.lib.lighting; import codechicken.lib.render.CCModel; +import codechicken.lib.util.Copyable; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -public class LC +public class LC implements Copyable { - public LC(int s, float e, float f, float g, float h) - { - side = s; - fa = e; - fb = f; - fc = g; - fd = h; - } - public int side; public float fa; public float fb; public float fc; public float fd; - - public static LC compute(Vector3 vec, Vector3 normal) - { + + public LC() { + this(0, 0, 0, 0, 0); + } + + public LC(int s, float a, float b, float c, float d) { + side = s; + fa = a; + fb = b; + fc = c; + fd = d; + } + + public LC set(int s, float a, float b, float c, float d) { + side = s; + fa = a; + fb = b; + fc = c; + fd = d; + return this; + } + + public LC set(LC lc) { + return set(lc.side, lc.fa, lc.fb, lc.fc, lc.fd); + } + + public LC compute(Vector3 vec, Vector3 normal) { int side = CCModel.findSide(normal); - if(side < 0) - return new LC(12, 1, 0, 0, 0); + if (side < 0) + return set(12, 1, 0, 0, 0); return compute(vec, side); } - - public static LC compute(Vector3 vec, int side) - { + + public LC compute(Vector3 vec, int side) { boolean offset = false; - switch(side) - { - case 0: offset = vec.y <= 0; break; - case 1: offset = vec.y >= 1; break; - case 2: offset = vec.z <= 0; break; - case 3: offset = vec.z >= 1; break; - case 4: offset = vec.x <= 0; break; - case 5: offset = vec.x >= 1; break; + switch (side) { + case 0: + offset = vec.y <= 0; + break; + case 1: + offset = vec.y >= 1; + break; + case 2: + offset = vec.z <= 0; + break; + case 3: + offset = vec.z >= 1; + break; + case 4: + offset = vec.x <= 0; + break; + case 5: + offset = vec.x >= 1; + break; } - if(!offset) - side+=6; + if (!offset) + side += 6; return computeO(vec, side); } - public static LC computeO(Vector3 vec, int side) - { - Vector3 v1 = Rotation.axes[((side&0xE)+3)%6]; - Vector3 v2 = Rotation.axes[((side&0xE)+5)%6]; + public LC computeO(Vector3 vec, int side) { + Vector3 v1 = Rotation.axes[((side & 0xE) + 3) % 6]; + Vector3 v2 = Rotation.axes[((side & 0xE) + 5) % 6]; float d1 = (float) vec.scalarProject(v1); - float d2 = 1-d1; + float d2 = 1 - d1; float d3 = (float) vec.scalarProject(v2); - float d4 = 1-d3; - return new LC(side, d2*d4, d2*d3, d1*d4, d1*d3); + float d4 = 1 - d3; + return set(side, d2 * d4, d2 * d3, d1 * d4, d1 * d3); + } + + @Override + public LC copy() { + return new LC(side, fa, fb, fc, fd); } } \ No newline at end of file diff --git a/codechicken/lib/lighting/LazyLightMatrix.java b/codechicken/lib/lighting/LazyLightMatrix.java deleted file mode 100644 index 3c957cd..0000000 --- a/codechicken/lib/lighting/LazyLightMatrix.java +++ /dev/null @@ -1,28 +0,0 @@ -package codechicken.lib.lighting; - -import net.minecraft.world.IBlockAccess; -import codechicken.lib.vec.BlockCoord; - -public class LazyLightMatrix -{ - private BlockCoord pos = new BlockCoord(); - private IBlockAccess access; - private boolean computed = false; - private LightMatrix lightMatrix = new LightMatrix(); - - public LightMatrix lightMatrix() - { - if(computed) - return lightMatrix; - computed = true; - lightMatrix.computeAt(access, pos.x, pos.y, pos.z); - return lightMatrix; - } - - public void setPos(IBlockAccess access, int x, int y, int z) - { - computed = false; - this.access = access; - pos.set(x, y, z); - } -} \ No newline at end of file diff --git a/codechicken/lib/lighting/LightMatrix.java b/codechicken/lib/lighting/LightMatrix.java index 882ea0b..54cf902 100644 --- a/codechicken/lib/lighting/LightMatrix.java +++ b/codechicken/lib/lighting/LightMatrix.java @@ -1,30 +1,31 @@ package codechicken.lib.lighting; -import codechicken.lib.render.CCModel; +import codechicken.lib.colour.ColourRGBA; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.IVertexModifier; -import codechicken.lib.render.UV; import codechicken.lib.vec.BlockCoord; import codechicken.lib.vec.Vector3; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.Tessellator; import net.minecraft.world.IBlockAccess; /** * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> (x+1, y+1, z+1) */ -public class LightMatrix implements IVertexModifier +public class LightMatrix implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); + public int computed = 0; public float[][] ao = new float[13][4]; public int[][] brightness = new int[13][4]; + + public IBlockAccess access; public BlockCoord pos = new BlockCoord(); - + + private int sampled = 0; private float[] aSamples = new float[27]; private int[] bSamples = new int[27]; - private Vector3 v_temp = new Vector3(); - + /** * The 9 positions in the sample array for each side, sides >= 6 are centered on sample 13 (the block itself) */ @@ -73,137 +74,88 @@ public class LightMatrix implements IVertexModifier } System.out.println(Arrays.deepToString(ssamplem)); }*/ - - public void computeAt(IBlockAccess a, int x, int y, int z) - { + + public void locate(IBlockAccess a, int x, int y, int z) { + access = a; pos.set(x, y, z); computed = 0; - //inc x, inc z, inc y - sample( 0, aSamples, bSamples, a, x-1, y-1, z-1); - sample( 1, aSamples, bSamples, a, x , y-1, z-1); - sample( 2, aSamples, bSamples, a, x+1, y-1, z-1); - sample( 3, aSamples, bSamples, a, x-1, y-1, z ); - sample( 4, aSamples, bSamples, a, x , y-1, z ); - sample( 5, aSamples, bSamples, a, x+1, y-1, z ); - sample( 6, aSamples, bSamples, a, x-1, y-1, z+1); - sample( 7, aSamples, bSamples, a, x , y-1, z+1); - sample( 8, aSamples, bSamples, a, x+1, y-1, z+1); - sample( 9, aSamples, bSamples, a, x-1, y , z-1); - sample(10, aSamples, bSamples, a, x , y , z-1); - sample(11, aSamples, bSamples, a, x+1, y , z-1); - sample(12, aSamples, bSamples, a, x-1, y , z ); - sample(13, aSamples, bSamples, a, x , y , z ); - sample(14, aSamples, bSamples, a, x+1, y , z ); - sample(15, aSamples, bSamples, a, x-1, y , z+1); - sample(16, aSamples, bSamples, a, x , y , z+1); - sample(17, aSamples, bSamples, a, x+1, y , z+1); - sample(18, aSamples, bSamples, a, x-1, y+1, z-1); - sample(19, aSamples, bSamples, a, x , y+1, z-1); - sample(20, aSamples, bSamples, a, x+1, y+1, z-1); - sample(21, aSamples, bSamples, a, x-1, y+1, z ); - sample(22, aSamples, bSamples, a, x , y+1, z ); - sample(23, aSamples, bSamples, a, x+1, y+1, z ); - sample(24, aSamples, bSamples, a, x-1, y+1, z+1); - sample(25, aSamples, bSamples, a, x , y+1, z+1); - sample(26, aSamples, bSamples, a, x+1, y+1, z+1); + sampled = 0; } - - public int[] brightness(int side) - { + + public void sample(int i) { + if ((sampled & 1 << i) == 0) { + int x = pos.x + (i % 3) - 1; + int y = pos.y + (i / 9) - 1; + int z = pos.z + (i / 3 % 3) - 1; + Block b = access.getBlock(x, y, z); + bSamples[i] = access.getLightBrightnessForSkyBlocks(x, y, z, b.getLightValue(access, x, y, z)); + aSamples[i] = b.getAmbientOcclusionLightValue(); + } + } + + public int[] brightness(int side) { sideSample(side); return brightness[side]; } - - public float[] ao(int side) - { + + public float[] ao(int side) { sideSample(side); return ao[side]; } - - public void sideSample(int side) - { - if((computed&1<>2 & 0xFF00FF; + return (a + b + c + d) >> 2 & 0xFF00FF; } - public void setColour(Tessellator tess, LC lc, int c) - { - float[] a = ao(lc.side); - float f = (a[0]*lc.fa + a[1]*lc.fb + a[2]*lc.fc + a[3]*lc.fd); - CCRenderState.vertexColour((int)((c>>>24)*f), (int)((c>>16&0xFF)*f), (int)((c>>8&0xFF)*f), (c&0xFF)); + @Override + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); + return true; } - public void setBrightness(Tessellator tess, LC lc) - { - int[] b = brightness(lc.side); - tess.setBrightness((int)(b[0]*lc.fa + b[1]*lc.fb + b[2]*lc.fc+b[3]*lc.fd) & 0xFF00FF); - } - @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - LC lc; - if(m instanceof CCRBModel) - lc = ((CCRBModel)m).lightCoefficents[i]; - else - lc = LC.compute(v_temp.set(vec).add(-pos.x, -pos.y, -pos.z), normal); - - setColour(tess, lc, (m == null || m.colours == null) ? -1 : m.colours[i]); - setBrightness(tess, lc); + public void operate() { + LC lc = CCRenderState.lc; + float[] a = ao(lc.side); + float f = (a[0] * lc.fa + a[1] * lc.fb + a[2] * lc.fc + a[3] * lc.fd); + int[] b = brightness(lc.side); + CCRenderState.setColour(ColourRGBA.multiplyC(CCRenderState.colour, f)); + CCRenderState.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); } - + @Override - public boolean needsNormals() - { - return true; + public int operationID() { + return operationIndex; } } \ No newline at end of file diff --git a/codechicken/lib/lighting/LightModel.java b/codechicken/lib/lighting/LightModel.java index 831298d..88bf784 100644 --- a/codechicken/lib/lighting/LightModel.java +++ b/codechicken/lib/lighting/LightModel.java @@ -3,60 +3,55 @@ import net.minecraft.client.renderer.Tessellator; import codechicken.lib.render.CCModel; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.IVertexModifier; -import codechicken.lib.render.UV; +import codechicken.lib.render.uv.UV; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -public class LightModel implements IVertexModifier +public class LightModel implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); + public static class Light { public Vector3 ambient = new Vector3(); public Vector3 diffuse = new Vector3(); public Vector3 position; - - public Light(Vector3 pos) - { + + public Light(Vector3 pos) { position = pos.copy().normalize(); } - - public Light setDiffuse(Vector3 vec) - { + + public Light setDiffuse(Vector3 vec) { diffuse.set(vec); return this; } - - public Light setAmbient(Vector3 vec) - { + + public Light setAmbient(Vector3 vec) { ambient.set(vec); return this; } } public static LightModel standardLightModel; - static - { + static { standardLightModel = new LightModel() .setAmbient(new Vector3(0.4, 0.4, 0.4)) .addLight(new Light(new Vector3(0.2, 1, -0.7)) - .setDiffuse(new Vector3(0.6, 0.6, 0.6))) + .setDiffuse(new Vector3(0.6, 0.6, 0.6))) .addLight(new Light(new Vector3(-0.2, 1, 0.7)) - .setDiffuse(new Vector3(0.6, 0.6, 0.6))); + .setDiffuse(new Vector3(0.6, 0.6, 0.6))); } private Vector3 ambient = new Vector3(); private Light[] lights = new Light[8]; private int lightCount; - - public LightModel addLight(Light light) - { + + public LightModel addLight(Light light) { lights[lightCount++] = light; return this; } - - public LightModel setAmbient(Vector3 vec) - { + + public LightModel setAmbient(Vector3 vec) { ambient.set(vec); return this; } @@ -66,46 +61,48 @@ public LightModel setAmbient(Vector3 vec) * @param normal The normal at the vertex * @return The lighting applied colour */ - public int apply(int colour, Vector3 normal) - { + public int apply(int colour, Vector3 normal) { Vector3 n_colour = ambient.copy(); - for(int l = 0; l < lightCount; l++) - { + for (int l = 0; l < lightCount; l++) { Light light = lights[l]; double n_l = light.position.dotProduct(normal); double f = n_l > 0 ? 1 : 0; - n_colour.x += light.ambient.x + f*light.diffuse.x*n_l; - n_colour.y += light.ambient.y + f*light.diffuse.y*n_l; - n_colour.z += light.ambient.z + f*light.diffuse.z*n_l; + n_colour.x += light.ambient.x + f * light.diffuse.x * n_l; + n_colour.y += light.ambient.y + f * light.diffuse.y * n_l; + n_colour.z += light.ambient.z + f * light.diffuse.z * n_l; } - if(n_colour.x > 1) + if (n_colour.x > 1) n_colour.x = 1; - if(n_colour.y > 1) + if (n_colour.y > 1) n_colour.y = 1; - if(n_colour.z > 1) + if (n_colour.z > 1) n_colour.z = 1; - - n_colour.multiply((colour >>> 24)/255D, (colour >> 16 & 0xFF)/255D, (colour >> 8 & 0xFF)/255D); - return (int)(n_colour.x*255)<<24 | (int)(n_colour.y*255)<<16 | (int)(n_colour.z*255)<<8 | colour&0xFF; + + n_colour.multiply((colour >>> 24) / 255D, (colour >> 16 & 0xFF) / 255D, (colour >> 8 & 0xFF) / 255D); + return (int) (n_colour.x * 255) << 24 | (int) (n_colour.y * 255) << 16 | (int) (n_colour.z * 255) << 8 | colour & 0xFF; } - + @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - CCRenderState.setColour(apply((m == null || m.colours == null) ? -1 : m.colours[i], normal)); + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + return true; } - + @Override - public boolean needsNormals() - { - return true; + public void operate() { + CCRenderState.setColour(apply(CCRenderState.colour, CCRenderState.normal)); } - - public PlanarLightModel reducePlanar() - { + + @Override + public int operationID() { + return operationIndex; + } + + public PlanarLightModel reducePlanar() { int[] colours = new int[6]; - for(int i = 0; i < 6; i++) + for (int i = 0; i < 6; i++) colours[i] = apply(-1, Rotation.axes[i]); return new PlanarLightModel(colours); } diff --git a/codechicken/lib/lighting/PlanarLightModel.java b/codechicken/lib/lighting/PlanarLightModel.java index f6f5b51..942521f 100644 --- a/codechicken/lib/lighting/PlanarLightModel.java +++ b/codechicken/lib/lighting/PlanarLightModel.java @@ -1,42 +1,35 @@ package codechicken.lib.lighting; -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.colour.Colour; import codechicken.lib.colour.ColourRGBA; -import codechicken.lib.render.CCModel; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.IVertexModifier; -import codechicken.lib.render.UV; -import codechicken.lib.vec.Vector3; /** * Faster precomputed version of LightModel that only works for axis planar sides */ -public class PlanarLightModel implements IVertexModifier +public class PlanarLightModel implements CCRenderState.IVertexOperation { public static PlanarLightModel standardLightModel = LightModel.standardLightModel.reducePlanar(); - - public ColourRGBA[] colours; - - public PlanarLightModel(int[] colours) - { - this.colours = new ColourRGBA[6]; - for(int i = 0; i < 6; i++) - this.colours[i] = new ColourRGBA(colours[i]); + + public int[] colours; + + public PlanarLightModel(int[] colours) { + this.colours = colours; } @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - ColourRGBA light = colours[CCModel.findSide(normal)]; - int colour = (m == null || m.colours == null) ? -1 : m.colours[i]; - Colour res = new ColourRGBA(colour).multiply(light); - CCRenderState.vertexColour(res.r&0xFF, res.g&0xFF, res.b&0xFF, res.a&0xFF) ; + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + return true; } @Override - public boolean needsNormals() - { - return true; + public void operate() { + CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colours[CCRenderState.side])); + } + + @Override + public int operationID() { + return LightModel.operationIndex; } } diff --git a/codechicken/lib/packet/MetaPacket.java b/codechicken/lib/packet/MetaPacket.java deleted file mode 100644 index a3c2945..0000000 --- a/codechicken/lib/packet/MetaPacket.java +++ /dev/null @@ -1,91 +0,0 @@ -package codechicken.lib.packet; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import codechicken.lib.asm.ObfMapping; - -import net.minecraft.network.packet.NetHandler; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.Packet250CustomPayload; - -/** - * A class that facilitates sending of multiple packets one after the other. - * It first sends an empty 250 packet and then it's payloads. - */ -public class MetaPacket extends Packet250CustomPayload -{ - static - { - try - { - String fieldName = new ObfMapping("net/minecraft/network/packet/Packet", "packetClassToIdMap", "Ljava/util/Map;").toRuntime().s_name; - Field field = Packet.class.getDeclaredField(fieldName); - field.setAccessible(true); - Map, Integer> packetClassToIdMap = (Map, Integer>) field.get(null); - packetClassToIdMap.put(MetaPacket.class, 250); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - } - - public ArrayList packets = new ArrayList(); - - public MetaPacket(Packet... packets) - { - super("", null); - - for(Packet p : packets) - this.packets.add(p); - } - - public MetaPacket(Collection packets) - { - this.packets.addAll(packets); - } - - @Override - public void readPacketData(DataInput datain) - { - throw new IllegalStateException("Meta packets can't be read"); - } - - @Override - public void writePacketData(DataOutput dataout) { - try {//TODO: fix super IOException - //send a dummy 250 - super.writePacketData(dataout); - - for(Packet p : packets) - Packet.writePacket(p, dataout); - - //adjust sent size for Packet.writePacket - Packet.sentSize-=getPacketSize()-super.getPacketSize(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void processPacket(NetHandler nethandler) - { - for(Packet p : packets)//Memory connection - p.processPacket(nethandler); - } - - @Override - public int getPacketSize() - { - int size = 0; - for(Packet p : packets) - size+=p.getPacketSize()+1; - return size; - } -} diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index e21f5ac..5d4e531 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -1,741 +1,356 @@ package codechicken.lib.packet; -import java.io.*; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.zip.Deflater; -import java.util.zip.Inflater; import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.vec.BlockCoord; +import com.google.common.collect.Maps; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.network.*; +import cpw.mods.fml.common.network.handshake.NetworkDispatcher; +import cpw.mods.fml.common.network.internal.FMLProxyPacket; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import cpw.mods.fml.common.network.FMLNetworkHandler; -import cpw.mods.fml.common.network.IConnectionHandler; -import cpw.mods.fml.common.network.IPacketHandler; -import cpw.mods.fml.common.network.ITinyPacketHandler; -import cpw.mods.fml.common.network.NetworkModHandler; -import cpw.mods.fml.common.network.NetworkRegistry; -import cpw.mods.fml.common.network.Player; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.compression.Snappy; +import io.netty.util.AttributeKey; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.NetClientHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.INetworkManager; -import net.minecraft.network.NetLoginHandler; -import net.minecraft.network.NetServerHandler; -import net.minecraft.network.packet.NetHandler; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.Packet131MapData; -import net.minecraft.network.packet.Packet1Login; -import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.network.INetHandler; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.Packet; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.INetHandlerPlayServer; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.management.PlayerInstance; +import net.minecraft.server.management.PlayerManager.PlayerInstance; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.fluids.FluidStack; +import java.util.EnumMap; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + public final class PacketCustom implements MCDataInput, MCDataOutput { - public static interface ICustomPacketHandler + public static interface ICustomPacketHandler { } - + public interface IClientPacketHandler extends ICustomPacketHandler { - public void handlePacket(PacketCustom packetCustom, NetClientHandler nethandler, Minecraft mc); + public void handlePacket(PacketCustom packetCustom, Minecraft mc, INetHandlerPlayClient handler); } - + public interface IServerPacketHandler extends ICustomPacketHandler { - public void handlePacket(PacketCustom packetCustom, NetServerHandler nethandler, EntityPlayerMP sender); - } - - public static class PacketAssembler - { - public class AssemblyEntry - { - public AssemblyEntry(Object channel, int type, int length) - { - this.channel = channel; - this.type = type; - data = new byte[length]; - } - - public void append(byte[] b, int off, int len) - { - System.arraycopy(b, off, data, pos, len); - pos+=len; - } - - public PacketCustom finished() - { - if(pos < data.length) - return null; - - return new PacketCustom(channel, type, data); - } - - Object channel; - int type; - int pos; - byte[] data; - } - - public HashMap assemblerMap = new HashMap(); - - public PacketCustom assemble(IPacketCarrier carrier, Packet packet) - { - int type = carrier.readType(packet); - if(type != 0x80) - return new PacketCustom(carrier.readChannel(packet), carrier.readType(packet), carrier.readData(packet)); - - byte[] data = carrier.readData(packet); - int asmID = readInt(data, 0); - AssemblyEntry e = assemblerMap.get(asmID); - if(e == null) - { - e = new AssemblyEntry(carrier.readChannel(packet), data[4]&0xFF, readInt(data, 5)); - assemblerMap.put(asmID, e); - return null; - } - - e.append(data, 4, data.length-4); - PacketCustom ret = e.finished(); - if(ret != null) - assemblerMap.remove(asmID); - return ret; - } + public void handlePacket(PacketCustom packetCustom, EntityPlayerMP sender, INetHandlerPlayServer handler); } - - private static abstract class CustomPacketHandler implements IPacketHandler - { - HashMap handlermap = new HashMap(); - - public CustomPacketHandler(String channel) - { - NetworkRegistry.instance().registerChannel(this, channel, getSide()); - } - @Override - public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) - { - PacketCustom packetCustom = assembler.assemble(carrier250, packet); - if(packetCustom == null) - return; - - ICustomPacketHandler handler = handlermap.get(packetCustom.getType()); - if(handler != null) - handle(handler, packetCustom, player); - } + public static AttributeKey cclHandler = new AttributeKey("ccl:handler"); - public void registerRange(int firstID, int lastID, ICustomPacketHandler handler) - { - for(int i = firstID; i <= lastID; i++) - handlermap.put(i, handler); - } - - public abstract Side getSide(); - public abstract void handle(ICustomPacketHandler handler, PacketCustom packet, Player player); - } - - private static class ClientPacketHandler extends CustomPacketHandler + @ChannelHandler.Sharable + public static class CustomInboundHandler extends SimpleChannelInboundHandler { - public ClientPacketHandler(String channel) - { - super(channel); - NetClientHandlerHelper.register(); - } + public EnumMap handlers = Maps.newEnumMap(Side.class); @Override - public Side getSide() - { - return Side.CLIENT; + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + super.handlerAdded(ctx); + ctx.channel().attr(cclHandler).set(this); } @Override - public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) - { - ((IClientPacketHandler)handler).handlePacket(packet, NetClientHandlerHelper.handler, Minecraft.getMinecraft()); + protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception { + handlers.get(ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get()) + .handle(ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(), + ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get(), + new PacketCustom(msg.payload())); } } - - private static class ServerPacketHandler extends CustomPacketHandler + + private static interface CustomHandler { - public ServerPacketHandler(String channel) - { - super(channel); - } + public void handle(INetHandler handler, String channel, PacketCustom packet) throws Exception; + } - @Override - public Side getSide() - { - return Side.SERVER; + public static class ClientInboundHandler implements CustomHandler + { + private IClientPacketHandler handler; + + public ClientInboundHandler(ICustomPacketHandler handler) { + this.handler = (IClientPacketHandler) handler; } @Override - public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) - { - ((IServerPacketHandler)handler).handlePacket(packet, ((EntityPlayerMP)player).playerNetServerHandler, (EntityPlayerMP)player); + public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { + if (netHandler instanceof INetHandlerPlayClient) + handler.handlePacket(packet, Minecraft.getMinecraft(), (INetHandlerPlayClient) netHandler); + else + System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } - - private static class ServerTinyPacketHandler - { - IServerPacketHandler serverHandler; - - public ServerTinyPacketHandler(IServerPacketHandler handler) - { - serverHandler = handler; - } - public void handle(PacketCustom packetCustom, NetHandler handler) - { - serverHandler.handlePacket(packetCustom, (NetServerHandler)handler, ((NetServerHandler)handler).playerEntity); - } - } - - private static class ClientTinyPacketHandler + public static class ServerInboundHandler implements CustomHandler { - IClientPacketHandler clientHandler; - - public ClientTinyPacketHandler(IClientPacketHandler handler) - { - clientHandler = handler; - } + private IServerPacketHandler handler; - public void handle(PacketCustom packetCustom, NetHandler handler) - { - clientHandler.handlePacket(packetCustom, (NetClientHandler)handler, Minecraft.getMinecraft()); - } - } - - public static final class CustomTinyPacketHandler implements ITinyPacketHandler - { - private ClientTinyPacketHandler clientDelegate; - private ServerTinyPacketHandler serverDelegate; - - @Override - public void handle(NetHandler handler, Packet131MapData packet) - { - PacketCustom packetCustom = assembler.assemble(carrier131, packet); - if(packetCustom == null) - return; - - if(handler instanceof NetServerHandler) - serverDelegate.handle(packetCustom, handler); - else - clientDelegate.handle(packetCustom, handler); + public ServerInboundHandler(ICustomPacketHandler handler) { + this.handler = (IServerPacketHandler) handler; } - private void registerSidedHandler(ICustomPacketHandler handler) - { - if(handler instanceof IClientPacketHandler) - { - if(clientDelegate != null) - throw new IllegalStateException("Client handler already registered"); - - clientDelegate = new ClientTinyPacketHandler((IClientPacketHandler) handler); - } - else if(handler instanceof IServerPacketHandler) - { - if(serverDelegate != null) - throw new IllegalStateException("Server handler already registered"); - - serverDelegate = new ServerTinyPacketHandler((IServerPacketHandler) handler); - } + @Override + public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { + if (netHandler instanceof NetHandlerPlayServer) + handler.handlePacket(packet, ((NetHandlerPlayServer) netHandler).playerEntity, (INetHandlerPlayServer) netHandler); else - { - throw new IllegalStateException("Handler is not a client or server handler"); - } + System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } - - private static class NetClientHandlerHelper implements IConnectionHandler + + public static interface IHandshakeHandler { - private static boolean registered = false; - public static NetClientHandler handler; - - public static void register() - { - if(registered) - return; - - NetworkRegistry.instance().registerConnectionHandler(new NetClientHandlerHelper()); - registered = true; - } - - @Override - public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) - { - handler = (NetClientHandler) netClientHandler; - } - - @Override - public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) - { - handler = (NetClientHandler) netClientHandler; - } - - @Override - public void connectionClosed(INetworkManager manager) - { - } - - @Override - public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) - { - return null; - } - - @Override - public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) - { - } - - @Override - public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) - { - } + public void handshakeRecieved(NetHandlerPlayServer netHandler); } - - public static interface IPacketCarrier - { - public int readType(Packet packet); - public byte[] readData(Packet packet); - public Object readChannel(Packet packet); - public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data); - public boolean shortCapped(); - } - - public static class Packet250Carrier implements IPacketCarrier + + public static class HandshakeInboundHandler extends ChannelInboundHandlerAdapter { - @Override - public int readType(Packet packet) - { - return ((Packet250CustomPayload)packet).data[0]&0xFF; - } + public IHandshakeHandler handler; - @Override - public byte[] readData(Packet packet) - { - byte[] data = ((Packet250CustomPayload)packet).data; - return Arrays.copyOfRange(data, 1, data.length); - } - - public Object readChannel(Packet packet) - { - return ((Packet250CustomPayload)packet).channel; + public HandshakeInboundHandler(IHandshakeHandler handler) { + this.handler = handler; } @Override - public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data) - { - byte[] pdata = new byte[data.length+1]; - pdata[0] = (byte) type; - System.arraycopy(data, 0, pdata, 1, data.length); - - Packet250CustomPayload payload = new Packet250CustomPayload(); - payload.channel = (String) channel; - payload.isChunkDataPacket = chunkDataPacket; - payload.data = pdata; - payload.length = payload.data.length; - return payload; - } - - public boolean shortCapped() - { - return true; + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof NetworkHandshakeEstablished) { + INetHandler netHandler = ((NetworkDispatcher) ctx.channel().attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).get()).getNetHandler(); + if (netHandler instanceof NetHandlerPlayServer) + handler.handshakeRecieved((NetHandlerPlayServer) netHandler); + } else + ctx.fireUserEventTriggered(evt); } } - - public static class Packet131Carrier implements IPacketCarrier - { - @Override - public int readType(Packet packet) - { - return ((Packet131MapData)packet).uniqueID&0xFF; - } - @Override - public byte[] readData(Packet packet) - { - return ((Packet131MapData)packet).itemData; - } - - public Object readChannel(Packet packet) - { - return ((Packet131MapData)packet).itemID; - } + public static String channelName(Object channelKey) { + if (channelKey instanceof String) + return (String) channelKey; + if (channelKey instanceof ModContainer) + return ((ModContainer) channelKey).getModId(); - @Override - public Packet write(Object channel, boolean chunkDataPacket, int type, byte[] data) - { - NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(channel); - Packet131MapData payload = new Packet131MapData((short) nmh.getNetworkId(), (short) type, data); - payload.isChunkDataPacket = chunkDataPacket; - return payload; - } + ModContainer mc = FMLCommonHandler.instance().findContainerFor(channelKey); + if (mc != null) + return mc.getModId(); - @Override - public boolean shortCapped() - { - return true; - } + throw new IllegalArgumentException("Invalid channel: " + channelKey); } - public static PacketAssembler assembler = new PacketAssembler(); - public static IPacketCarrier carrier250 = new Packet250Carrier(); - public static IPacketCarrier carrier131 = new Packet131Carrier(); - - public static IPacketCarrier carrierForChannel(Object channel) - { - if(channel instanceof String) - return carrier250; - if(FMLNetworkHandler.instance().findNetworkModHandler(channel) != null) - return carrier131; - - return null; - } - - private static int assemblyID = 0; - - public static void writeInt(byte[] b, int pos, int i) - { - b[pos++] = (byte) (i>>>24); - b[pos++] = (byte) (i>>16); - b[pos++] = (byte) (i>>8); - b[pos++] = (byte) (i); - } - - public static int readInt(byte[] b, int pos) - { - return (b[pos++]&0xFF)<<24| - (b[pos++]&0xFF)<<16| - (b[pos++]&0xFF)<<8| - b[pos++]&0xFF; - } - - private PacketCustom(Object channel, int type, byte[] data) - { - this.channel = channel; - this.type = type; - if(type > 0x80) - data = decompress(data); - datain = new DataInputStream(new ByteArrayInputStream(data)); + public static FMLEmbeddedChannel getOrCreateChannel(String channelName, Side side) { + if (!NetworkRegistry.INSTANCE.hasChannel(channelName, side)) + NetworkRegistry.INSTANCE.newChannel(channelName, new CustomInboundHandler()); + return NetworkRegistry.INSTANCE.getChannel(channelName, side); } - public PacketCustom(Object channel, int type) - { - if(type <= 0 || type >= 0x80) - throw new IllegalArgumentException("Packet type: "+type+" is not within required 0 < t < 0x80"); - - this.channel = channel; - this.type = type; - isChunkDataPacket = false; - - dataarrayout = new ByteArrayOutputStream(); - dataout = new DataOutputStream(dataarrayout); + public static void assignHandler(Object channelKey, ICustomPacketHandler handler) { + String channelName = channelName(channelKey); + Side side = handler instanceof IServerPacketHandler ? Side.SERVER : Side.CLIENT; + FMLEmbeddedChannel channel = getOrCreateChannel(channelName, side); + channel.attr(cclHandler).get().handlers.put(side, side == Side.SERVER ? new ServerInboundHandler(handler) : new ClientInboundHandler(handler)); } - public boolean incoming() - { - return dataout == null; + public static void assignHandshakeHandler(Object channelKey, IHandshakeHandler handler) { + FMLEmbeddedChannel channel = getOrCreateChannel(channelName(channelKey), Side.SERVER); + channel.pipeline().addLast(new HandshakeInboundHandler(handler)); } - - public int getType() - { - return type&0x7F; + + private ByteBuf byteBuf; + private String channel; + private int type; + + public PacketCustom(ByteBuf payload) { + byteBuf = payload; + + type = byteBuf.readUnsignedByte(); + if (type > 0x80) + decompress(); + type &= 0x7F; } - - public PacketCustom setChunkDataPacket() - { - isChunkDataPacket = true; - return this; + + public PacketCustom(Object channelKey, int type) { + if (type <= 0 || type >= 0x80) + throw new IllegalArgumentException("Packet type: " + type + " is not within required 0 < t < 0x80"); + + this.channel = channelName(channelKey); + this.type = type; + byteBuf = Unpooled.buffer(); + byteBuf.writeByte(type); } - - private byte[] decompress(byte[] cdata) - { - if((type&0x80) == 0) - return cdata; - + + /** + * Decompresses the remaining ByteBuf (after type has been read) using Snappy + */ + private void decompress() { Inflater inflater = new Inflater(); - try - { - byte[] ddata = new byte[readInt(cdata, 0)]; - inflater.setInput(cdata, 4, cdata.length-4); - inflater.inflate(ddata); - return ddata; - } - catch(Exception e) - { + try { + int len = byteBuf.readInt(); + ByteBuf out = Unpooled.buffer(len); + inflater.setInput(byteBuf.array(), byteBuf.readerIndex(), byteBuf.readableBytes()); + inflater.inflate(out.array()); + out.writerIndex(len); + byteBuf = out; + } catch (Exception e) { throw new RuntimeException(e); - } - finally - { + } finally { inflater.end(); } } - - public PacketCustom compressed() - { - if(incoming()) - throw new IllegalStateException("Tried to compress an incoming packet"); - if((type&0x80) != 0) - throw new IllegalStateException("Packet already compressed"); - type|=0x80; - return this; - } - - private byte[] compress(byte[] data) - { + + /** + * Compresses the payload ByteBuf after the type byte + */ + private void do_compress() { Deflater deflater = new Deflater(); - try - { - deflater.setInput(data, 0, data.length); + try { + byteBuf.readerIndex(1); + int len = byteBuf.readableBytes(); + deflater.setInput(byteBuf.array(), byteBuf.readerIndex(), len); deflater.finish(); - byte[] cbuf = new byte[data.length]; - int clen = deflater.deflate(cbuf, 0, data.length); - if(clen == data.length || !deflater.finished())//not worth compressing, gets larger - { - type &= 0x7F; - return data; - } - - byte[] cdata = new byte[clen+4]; - writeInt(cdata, 0, data.length); - System.arraycopy(cbuf, 0, cdata, 4, clen); - type|=0x80; - return cdata; - } - catch(Exception e) - { + ByteBuf out = Unpooled.buffer(len + 5); + int clen = deflater.deflate(out.array(), 5, len); + if (clen >= len - 5 || !deflater.finished())//not worth compressing, gets larger + return; + + out.setByte(0, type | 0x80); + out.setInt(1, len); + out.writerIndex(clen + 5); + byteBuf = out; + } catch (Exception e) { throw new RuntimeException(e); - } - finally - { + } finally { deflater.end(); } } - - public Packet toPacket() - { - if(incoming()) - throw new IllegalStateException("Tried to write an incoming packet"); - - try - { - dataout.close(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - - byte[] data = dataarrayout.toByteArray(); - if(data.length > 32000 || (type&0x80) != 0) - data = compress(data); - - IPacketCarrier carrier = carrierForChannel(channel); - if(data.length > 32000 && carrier.shortCapped()) - { - MetaPacket payload = new MetaPacket(); - int asmID = assemblyID++; - - byte[] hdata = new byte[9]; - writeInt(hdata, 0, asmID); - hdata[4] = (byte) type; - writeInt(hdata, 5, data.length); - payload.packets.add(carrier.write(channel, isChunkDataPacket, 0x80, hdata)); - - for(int i = 0; i < data.length; i+=32000) - { - int size = Math.min(data.length-i, 32000); - byte[] sdata = new byte[size+4]; - writeInt(sdata, 0, asmID); - System.arraycopy(data, i, sdata, 4, size); - payload.packets.add(carrier.write(channel, isChunkDataPacket, 0x80, sdata)); - } - - return payload; - } - - return carrier.write(channel, isChunkDataPacket, type, data); + + public boolean incoming() { + return channel == null; } - - public PacketCustom writeBoolean(boolean b) - { - try - { - dataout.writeBoolean(b); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public int getType() { + return type & 0x7F; + } + + public ByteBuf getByteBuf() { + return byteBuf; + } + + public PacketCustom compress() { + if (incoming()) + throw new IllegalStateException("Tried to compress an incoming packet"); + if ((type & 0x80) != 0) + throw new IllegalStateException("Packet already compressed"); + type |= 0x80; return this; } - - public PacketCustom writeByte(int b) - { - try - { - dataout.writeByte(b); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeBoolean(boolean b) { + byteBuf.writeBoolean(b); return this; } - - public PacketCustom writeShort(int s) - { - try - { - dataout.writeShort(s); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeByte(int b) { + byteBuf.writeByte(b); return this; } - - public PacketCustom writeInt(int i) - { - try - { - dataout.writeInt(i); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeShort(int s) { + byteBuf.writeShort(s); return this; } - - public PacketCustom writeFloat(float f) - { - try - { - dataout.writeFloat(f); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeInt(int i) { + byteBuf.writeInt(i); return this; } - - public PacketCustom writeDouble(double d) - { - try - { - dataout.writeDouble(d); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeFloat(float f) { + byteBuf.writeFloat(f); return this; } - - public PacketCustom writeLong(long l) - { - try - { - dataout.writeLong(l); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeDouble(double d) { + byteBuf.writeDouble(d); return this; } - + + public PacketCustom writeLong(long l) { + byteBuf.writeLong(l); + return this; + } + @Override - public PacketCustom writeChar(char c) - { - try - { - dataout.writeChar(c); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + public PacketCustom writeChar(char c) { + byteBuf.writeChar(c); return this; } - - public PacketCustom writeByteArray(byte[] barray) - { - try - { - dataout.write(barray); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeVarInt(int i) { + ByteBufUtils.writeVarInt(byteBuf, i, 5); return this; } - - public PacketCustom writeCoord(int x, int y, int z) - { + + public PacketCustom writeVarShort(int s) { + ByteBufUtils.writeVarShort(byteBuf, s); + return this; + } + + public PacketCustom writeByteArray(byte[] barray) { + byteBuf.writeBytes(barray); + return this; + } + + public PacketCustom writeString(String s) { + ByteBufUtils.writeUTF8String(byteBuf, s); + return this; + } + + public PacketCustom writeCoord(int x, int y, int z) { writeInt(x); writeInt(y); writeInt(z); return this; } - - public PacketCustom writeCoord(BlockCoord coord) - { + + public PacketCustom writeCoord(BlockCoord coord) { writeInt(coord.x); writeInt(coord.y); writeInt(coord.z); return this; } - - public PacketCustom writeString(String s) - { - try - { - if(s.length() > 65535) - throw new IOException("String length: "+s.length()+"too long."); - dataout.writeShort(s.length()); - dataout.writeChars(s); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public PacketCustom writeItemStack(ItemStack stack) - { + + public PacketCustom writeItemStack(ItemStack stack) { writeItemStack(stack, false); return this; } - - public PacketCustom writeItemStack(ItemStack stack, boolean large) - { - if (stack == null) - { + + public PacketCustom writeItemStack(ItemStack stack, boolean large) { + if (stack == null) { writeShort(-1); - } - else - { - writeShort(stack.itemID); - if(large) + } else { + writeShort(Item.getIdFromItem(stack.getItem())); + if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); @@ -744,228 +359,110 @@ public PacketCustom writeItemStack(ItemStack stack, boolean large) } return this; } - - public PacketCustom writeNBTTagCompound(NBTTagCompound compound) - { - try - { - if (compound == null) - { - writeShort(-1); - } - else - { - byte[] bytes = CompressedStreamTools.compress(compound); - writeShort((short)bytes.length); - writeByteArray(bytes); - } - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public PacketCustom writeNBTTagCompound(NBTTagCompound compound) { + ByteBufUtils.writeTag(byteBuf, compound); return this; } - public PacketCustom writeFluidStack(FluidStack fluid) - { - if (fluid == null) - { + public PacketCustom writeFluidStack(FluidStack fluid) { + if (fluid == null) { writeShort(-1); - } - else - { + } else { writeShort(fluid.fluidID); - writeInt(fluid.amount); + writeVarInt(fluid.amount); writeNBTTagCompound(fluid.tag); } return this; } - public boolean readBoolean() - { - try - { - return datain.readBoolean(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + public boolean readBoolean() { + return byteBuf.readBoolean(); } - - public int readUByte() - { - return readByte() & 0xFF; + + public short readUByte() { + return byteBuf.readUnsignedByte(); } - - public int readUShort() - { - return readShort() & 0xFFFF; + + public int readUShort() { + return byteBuf.readUnsignedShort(); } - - public byte readByte() - { - try - { - return datain.readByte(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public byte readByte() { + return byteBuf.readByte(); } - - public short readShort() - { - try - { - return datain.readShort(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public short readShort() { + return byteBuf.readShort(); } - - public int readInt() - { - try - { - return datain.readInt(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public int readInt() { + return byteBuf.readInt(); } - - public float readFloat() - { - try - { - return datain.readFloat(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public float readFloat() { + return byteBuf.readFloat(); } - - public double readDouble() - { - try - { - return datain.readDouble(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public double readDouble() { + return byteBuf.readDouble(); } - - public long readLong() - { - try - { - return datain.readLong(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public long readLong() { + return byteBuf.readLong(); } - - public char readChar() - { - try - { - return datain.readChar(); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public char readChar() { + return byteBuf.readChar(); } - - public BlockCoord readCoord() - { + + @Override + public int readVarShort() { + return ByteBufUtils.readVarShort(byteBuf); + } + + @Override + public int readVarInt() { + return ByteBufUtils.readVarInt(byteBuf, 5); + } + + public BlockCoord readCoord() { return new BlockCoord(readInt(), readInt(), readInt()); } - - public byte[] readByteArray(int length) - { - try - { - byte[] barray = new byte[length]; - datain.readFully(barray, 0, length); - return barray; - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public byte[] readByteArray(int length) { + byte[] barray = new byte[length]; + byteBuf.readBytes(barray, 0, length); + return barray; } - - public String readString() - { - try - { - int length = datain.readUnsignedShort(); - char[] chars = new char[length]; - for(int i = 0; i < length; i++) - chars[i] = readChar(); - - return new String(chars); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - + + public String readString() { + return ByteBufUtils.readUTF8String(byteBuf); } - public ItemStack readItemStack() - { + public ItemStack readItemStack() { return readItemStack(false); } - - public ItemStack readItemStack(boolean large) - { + + public ItemStack readItemStack(boolean large) { ItemStack item = null; short itemID = readShort(); - if (itemID >= 0) - { + if (itemID >= 0) { int stackSize = large ? readInt() : readByte(); short damage = readShort(); - item = new ItemStack(itemID, stackSize, damage); + item = new ItemStack(Item.getItemById(itemID), stackSize, damage); item.stackTagCompound = readNBTTagCompound(); } return item; } - - public NBTTagCompound readNBTTagCompound() - { - try - { - short len = readShort(); - - if (len < 0) - return null; - - byte[] bytes = readByteArray(len); - return CompressedStreamTools.decompress(bytes); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + + public NBTTagCompound readNBTTagCompound() { + return ByteBufUtils.readTag(byteBuf); } - - public FluidStack readFluidStack() - { + + public FluidStack readFluidStack() { FluidStack fluid = null; short fluidID = readShort(); @@ -975,121 +472,79 @@ public FluidStack readFluidStack() return fluid; } - private Object channel; - private int type; - private boolean isChunkDataPacket; - - private ByteArrayOutputStream dataarrayout; - private DataOutputStream dataout; - - private DataInputStream datain; - - private static HashMap clienthandlermap = new HashMap(); - private static HashMap serverhandlermap = new HashMap(); - - public static void assignHandler(String channel, int firstID, int lastID, ICustomPacketHandler IHandler) - { - Side side = IHandler instanceof IClientPacketHandler ? Side.CLIENT : Side.SERVER; - HashMap handlerMap = side.isClient() ? clienthandlermap : serverhandlermap; - CustomPacketHandler handler = handlerMap.get(channel); - - if(handler == null) - { - if(side.isClient()) - handler = new ClientPacketHandler(channel); - else - handler = new ServerPacketHandler(channel); - - handlerMap.put(channel, handler); - } - handler.registerRange(firstID, lastID, IHandler); + public FMLProxyPacket toPacket() { + if (incoming()) + throw new IllegalStateException("Tried to write an incoming packet"); + + if (byteBuf.readableBytes() > 32000 || (type & 0x80) != 0) + do_compress(); + + //FML packet impl returns the whole of the backing array, copy used portion of array to another ByteBuf + return new FMLProxyPacket(byteBuf.copy(), channel); } - public static void assignHandler(Object mod, ICustomPacketHandler handler) - { - NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mod); - if(nmh == null || nmh.getTinyPacketHandler() == null || !(nmh.getTinyPacketHandler() instanceof CustomTinyPacketHandler)) - throw new IllegalStateException("Invalid network tiny packet handler for mod: "+mod); - - ((CustomTinyPacketHandler)nmh.getTinyPacketHandler()).registerSidedHandler(handler); - } - - public void sendToPlayer(EntityPlayer player) - { + public void sendToPlayer(EntityPlayer player) { sendToPlayer(toPacket(), player); } - - public static void sendToPlayer(Packet packet, EntityPlayer player) - { - if(player == null) + + public static void sendToPlayer(Packet packet, EntityPlayer player) { + if (player == null) sendToClients(packet); else - ((EntityPlayerMP)player).playerNetServerHandler.sendPacketToPlayer(packet); + ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet); } - - public void sendToClients() - { + + public void sendToClients() { sendToClients(toPacket()); - } - - public static void sendToClients(Packet packet) - { + } + + public static void sendToClients(Packet packet) { MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayers(packet); } - - public void sendPacketToAllAround(double x, double y, double z, double range, int dim) - { + + public void sendPacketToAllAround(double x, double y, double z, double range, int dim) { sendToAllAround(toPacket(), x, y, z, range, dim); } - - public static void sendToAllAround(Packet packet, double x, double y, double z, double range, int dim) - { + + public static void sendToAllAround(Packet packet, double x, double y, double z, double range, int dim) { MinecraftServer.getServer().getConfigurationManager().sendToAllNear(x, y, z, range, dim, packet); } - - public void sendToDimension(int dim) - { + + public void sendToDimension(int dim) { sendToDimension(toPacket(), dim); } - - public static void sendToDimension(Packet packet, int dim) - { + + public static void sendToDimension(Packet packet, int dim) { MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayersInDimension(packet, dim); } - public void sendToChunk(World world, int chunkX, int chunkZ) - { + public void sendToChunk(World world, int chunkX, int chunkZ) { sendToChunk(toPacket(), world, chunkX, chunkZ); } - - public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) - { - PlayerInstance p = ((WorldServer)world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); - if(p != null) + + public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) { + PlayerInstance p = ((WorldServer) world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); + if (p != null) p.sendToAllPlayersWatchingChunk(packet); } - - public void sendToOps() - { + + public void sendToOps() { sendToOps(toPacket()); } - public static void sendToOps(Packet packet) - { - for(EntityPlayerMP player : (List)MinecraftServer.getServer().getConfigurationManager().playerEntityList) - if(MinecraftServer.getServer().getConfigurationManager().isPlayerOpped(player.username)) + public static void sendToOps(Packet packet) { + for (EntityPlayerMP player : (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + if (MinecraftServer.getServer().getConfigurationManager().isPlayerOpped(player.getCommandSenderName())) sendToPlayer(packet, player); } - + @SideOnly(Side.CLIENT) - public void sendToServer() - { + public void sendToServer() { sendToServer(toPacket()); } @SideOnly(Side.CLIENT) - public static void sendToServer(Packet packet) - { + public static void sendToServer(Packet packet) { Minecraft.getMinecraft().getNetHandler().addToSendQueue(packet); } } diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 44bb183..3fdb45c 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -13,7 +13,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.util.EnumMovingObjectType; +import net.minecraft.util.MovingObjectPosition.MovingObjectType; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; @@ -112,7 +112,7 @@ public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 c MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); if(mop != null) { - mop.typeOfHit = EnumMovingObjectType.TILE; + mop.typeOfHit = MovingObjectType.BLOCK; mop.blockX = pos.x; mop.blockY = pos.y; mop.blockZ = pos.z; @@ -125,7 +125,7 @@ public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 c MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); if(mop != null) { - mop.typeOfHit = EnumMovingObjectType.ENTITY; + mop.typeOfHit = MovingObjectType.ENTITY; mop.entityHit = e; } return mop; @@ -156,7 +156,7 @@ public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cub if(mop != null) { ExtendedMOP emop = new ExtendedMOP(mop, cuboid.data, s_dist); - emop.typeOfHit = EnumMovingObjectType.TILE; + emop.typeOfHit = MovingObjectType.BLOCK; emop.blockX = pos.x; emop.blockY = pos.y; emop.blockZ = pos.z; @@ -185,9 +185,7 @@ public void rayTraceCuboids(Vector3 start, Vector3 end, List cub public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) { - Block block = Block.blocksList[world.getBlockId(x, y, z)]; - if(block == null) - return null; + Block block = world.getBlock(x, y, z); Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1.0F); @@ -217,7 +215,7 @@ public static MovingObjectPosition reTrace(World world, EntityPlayer player, dou Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1); Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); - return world.rayTraceBlocks_do_do(headVec, endVec, true, false); + return world.func_147447_a(headVec, endVec, true, false, true); } public static Vec3 getCorrectedHeadVec(EntityPlayer player) diff --git a/codechicken/lib/render/BlockRenderer.java b/codechicken/lib/render/BlockRenderer.java new file mode 100644 index 0000000..c222d2a --- /dev/null +++ b/codechicken/lib/render/BlockRenderer.java @@ -0,0 +1,126 @@ +package codechicken.lib.render; + +import codechicken.lib.lighting.LC; +import codechicken.lib.vec.Cuboid6; + +public class BlockRenderer +{ + public static class BlockFace implements CCRenderState.IVertexSource + { + public Vertex5[] verts = new Vertex5[]{new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; + public LC[] lightCoords = new LC[]{new LC(), new LC(), new LC(), new LC()}; + public boolean lcComputed = false; + public int side; + + @Override + public Vertex5[] getVertices() { + return verts; + } + + @Override + public T getAttributes(CCRenderState.VertexAttribute attr) { + return attr == CCRenderState.lightCoordAttrib && lcComputed ? (T)lightCoords : null; + } + + @Override + public boolean hasAttribute(CCRenderState.VertexAttribute attr) { + return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib && lcComputed; + } + + @Override + public void prepareVertex() { + CCRenderState.side = side; + } + + public BlockFace computeLightCoords() { + if(!lcComputed) { + for (int i = 0; i < 4; i++) + lightCoords[i].compute(verts[i].vec, side); + lcComputed = true; + } + return this; + } + + public BlockFace loadCuboidFace(Cuboid6 c, int side) { + double x1 = c.min.x; + double x2 = c.max.x; + double y1 = c.min.y; + double y2 = c.max.y; + double z1 = c.min.z; + double z2 = c.max.z; + double u1; double u2; double v1; double v2; + this.side = side; + lcComputed = false; + + switch(side) { + case 0: + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[0].set(x1, y1, z2, u1, v2, 0); + verts[1].set(x1, y1, z1, u1, v1, 0); + verts[2].set(x2, y1, z1, u2, v1, 0); + verts[3].set(x2, y1, z2, u2, v2, 0); + break; + case 1: + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[0].set(x2, y2, z2, u2, v2, 1); + verts[1].set(x2, y2, z1, u2, v1, 1); + verts[2].set(x1, y2, z1, u1, v1, 1); + verts[3].set(x1, y2, z2, u1, v2, 1); + break; + case 2: + u1 = 1-x1; v1 = 1-y2; + u2 = 1-x2; v2 = 1-y1; + verts[0].set(x1, y1, z1, u1, v2, 2); + verts[1].set(x1, y2, z1, u1, v1, 2); + verts[2].set(x2, y2, z1, u2, v1, 2); + verts[3].set(x2, y1, z1, u2, v2, 2); + break; + case 3: + u1 = x1; v1 = 1-y2; + u2 = x2; v2 = 1-y1; + verts[0].set(x2, y1, z2, u2, v2, 3); + verts[1].set(x2, y2, z2, u2, v1, 3); + verts[2].set(x1, y2, z2, u1, v1, 3); + verts[3].set(x1, y1, z2, u1, v2, 3); + break; + case 4: + u1 = z1; v1 = 1-y2; + u2 = z2; v2 = 1-y1; + verts[0].set(x1, y1, z2, u2, v2, 4); + verts[1].set(x1, y2, z2, u2, v1, 4); + verts[2].set(x1, y2, z1, u1, v1, 4); + verts[3].set(x1, y1, z1, u1, v2, 4); + break; + case 5: + u1 = 1-z1; v1 = 1-y2; + u2 = 1-z2; v2 = 1-y1; + verts[0].set(x2, y1, z1, u1, v2, 5); + verts[1].set(x2, y2, z1, u1, v1, 5); + verts[2].set(x2, y2, z2, u2, v1, 5); + verts[3].set(x2, y1, z2, u2, v2, 5); + } + return this; + } + } + + private static BlockFace face = new BlockFace(); + + /** + * Renders faces of a cuboid with texture coordinates mapped to match a standard minecraft block + * @param bounds The bounding cuboid to render + * @param sideMask A mask of faces not to render + */ + public static void renderCuboid(Cuboid6 bounds, int sideMask) { + if(sideMask == 0x3F) + return; + + CCRenderState.setModel(face); + for(int s = 0; s < 6; s++) + if((sideMask & 1< { private static class PositionNormalEntry - { + { public Vector3 pos; public LinkedList normals = new LinkedList(); - + public PositionNormalEntry(Vector3 position) { pos = position; } - + public boolean positionEqual(Vector3 v) { return pos.x == v.x && pos.y == v.y && pos.z == v.z; } - + public PositionNormalEntry addNormal(Vector3 normal) { normals.add(normal); return this; } } - + public final int vertexMode; public final int vp; public Vertex5[] verts; - public Vector3[] normals; - public int[] colours; - + public ArrayList attributes = new ArrayList(); + protected CCModel(int vertexMode) { if(vertexMode != 7 && vertexMode != 4) throw new IllegalArgumentException("Models must be GL_QUADS or GL_TRIANGLES"); - + this.vertexMode = vertexMode; vp = vertexMode == 7 ? 4 : 3; } - + + public Vector3[] normals() { + return getAttributes(CCRenderState.normalAttrib); + } + + @Override + public Vertex5[] getVertices() { + return verts; + } + + @Override + public T getAttributes(CCRenderState.VertexAttribute attr) { + if(attr.attributeIndex < attributes.size()) + return (T) attributes.get(attr.attributeIndex); + + return null; + } + + @Override + public boolean hasAttribute(CCRenderState.VertexAttribute attrib) { + return attrib.attributeIndex < attributes.size() && attributes.get(attrib.attributeIndex) != null; + } + + @Override + public void prepareVertex() { + } + + public T getOrAllocate(CCRenderState.VertexAttribute attrib) { + T array = getAttributes(attrib); + if(array == null) { + while(attributes.size() <= attrib.attributeIndex) + attributes.add(null); + attributes.set(attrib.attributeIndex, array = attrib.newArray(verts.length)); + } + return array; + } + /** * Each pixel corresponds to one unit of position when generating the model * @param i Vertex index to start generating at @@ -87,7 +124,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou double y2 = y1+h; double z2 = z1+d; x1 /= f; x2 /= f; y1 /= f; y2 /= f; z1 /= f; z2 /= f; - + //bottom face u1 = (tx + d + w) / tw; v1 = (ty + d) / th; u2 = (tx + d*2 + w) / tw; v2 = ty / th; @@ -95,7 +132,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou verts[i++] = new Vertex5(x1, y1, z1, u1, v1); verts[i++] = new Vertex5(x2, y1, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); - + //top face u1 = (tx + d) / tw; v1 = (ty + d) / th; u2 = (tx + d + w) / tw; v2 = ty / th; @@ -103,7 +140,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y2, z2, u1, v2); - + //front face u1 = (tx + d + w) / tw; v1 = (ty + d) / th; u2 = (tx + d) / tw; v2 = (ty + d + h) / th; @@ -111,7 +148,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou verts[i++] = new Vertex5(x2, y2, z1, u1, v1); verts[i++] = new Vertex5(x2, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y1, z1, u2, v2); - + //back face u1 = (tx + d*2 + w*2) / tw; v1 = (ty + d) / th; u2 = (tx + d*2 + w) / tw; v2 = (ty + d + h) / th; @@ -119,7 +156,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou verts[i++] = new Vertex5(x1, y1, z2, u1, v2); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - + //left face u1 = (tx + d) / tw; v1 = (ty + d) / th; u2 = (tx) / tw; v2 = (ty + d + h) / th; @@ -127,7 +164,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y1, z2, u2, v2); - + //right face u1 = (tx + d*2 + w) / tw; v1 = (ty + d) / th; u2 = (tx + d + w) / tw; v2 = (ty + d + h) / th; @@ -135,7 +172,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou verts[i++] = new Vertex5(x2, y1, z1, u2, v2); verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x2, y2, z2, u1, v1); - + return this; } @@ -149,7 +186,7 @@ public CCModel generateBlock(int i, Cuboid6 bounds) { return generateBlock(i, bounds, 0); } - + public CCModel generateBlock(int i, Cuboid6 bounds, int mask) { return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z, mask); @@ -175,7 +212,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2, int mask) { double u1, v1, u2, v2; - + if((mask&1) == 0) {//bottom face u1 = x1; v1 = z1; u2 = x2; v2 = z2; @@ -184,7 +221,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x2, y1, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); } - + if((mask&2) == 0) {//top face u1 = x1+2; v1 = z1; u2 = x2+2; v2 = z2; @@ -193,7 +230,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y2, z2, u1, v2); } - + if((mask&4) == 0) {//east face u1 = 1-x1+4; v1 = 1-y2; u2 = 1-x2+4; v2 = 1-y1; @@ -202,7 +239,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z1, u2, v2); } - + if((mask&8) == 0) {//west face u1 = x1+6; v1 = 1-y2; u2 = x2+6; v2 = 1-y1; @@ -211,7 +248,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x1, y2, z2, u1, v1); verts[i++] = new Vertex5(x1, y1, z2, u1, v2); } - + if((mask&0x10) == 0) {//north face u1 = z1+8; v1 = 1-y2; u2 = z2+8; v2 = 1-y1; @@ -220,7 +257,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y1, z1, u1, v2); } - + if((mask&0x20) == 0) {//south face u1 = 1-z1+10; v1 = 1-y2; u2 = 1-z2+10; v2 = 1-y1; @@ -229,10 +266,10 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, verts[i++] = new Vertex5(x2, y2, z2, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); } - + return this; } - + public CCModel computeNormals() { return computeNormals(0, verts.length); @@ -249,10 +286,8 @@ public CCModel computeNormals(int start, int length) { if(length%vp != 0 || start%vp != 0) throw new IllegalArgumentException("Cannot generate normals across polygons"); - - if(normals == null) - normals = new Vector3[verts.length]; - + + Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib); for(int k = 0; k < length; k+=vp) { int i = k + start; @@ -262,44 +297,47 @@ public CCModel computeNormals(int start, int length) for(int d = 1; d < vp; d++) normals[i+d] = normals[i].copy(); } - + return this; } - + /** - * Computes lighting using the normals and the colour 0xFFFFFF. - * Per vert colouring will be added when needed. - * Make sure you have generated your normals on the model first. - * If you rotate your model after this, the lighting will no longer be valid - * @param light The light model to calculate + * Computes lighting using the normals add a light model + * If the model is rotated, the lighting will no longer be valid * @return The model */ public CCModel computeLighting(LightModel light) { - if(colours == null) + Vector3[] normals = normals(); + int[] colours = getAttributes(CCRenderState.colourAttrib); + if(colours == null) { setColour(-1); + colours = getAttributes(CCRenderState.colourAttrib); + } for(int k = 0; k < verts.length; k++) colours[k] = light.apply(colours[k], normals[k]); return this; } - + public CCModel setColour(int c) { - if(colours == null) - colours = new int[verts.length]; - for(int k = 0; k < verts.length; k++) - colours[k] = c; + int[] colours = getOrAllocate(CCRenderState.colourAttrib); + Arrays.fill(colours, c); return this; } /** - * Warning, only use this if you NEED to be identical to MC's light model, it's hideous. + * Computes the minecraft lighting coordinates for use with a LightMatrix + * @return The model */ - public CCRBModel withMCLighting() - { - return new CCRBModel(this); + public CCModel computeLightCoords() { + LC[] lcs = getOrAllocate(CCRenderState.lightCoordAttrib); + Vector3[] normals = normals(); + for(int i = 0; i < verts.length; i++) + lcs[i] = new LC().compute(verts[i].vec, normals[i]); + return this; } - + /** * Averages all normals at the same position to produce a smooth lighting effect. * @return The model @@ -307,6 +345,7 @@ public CCRBModel withMCLighting() public CCModel smoothNormals() { ArrayList map = new ArrayList(); + Vector3[] normals = normals(); nextvert: for(int k = 0; k < verts.length; k++) { Vector3 vec = verts[k].vec; @@ -316,24 +355,24 @@ public CCModel smoothNormals() e.addNormal(normals[k]); continue nextvert; } - + map.add(new PositionNormalEntry(vec).addNormal(normals[k])); } - + for(PositionNormalEntry e : map) { if(e.normals.size() <= 1) continue; - + Vector3 new_n = new Vector3(); for(Vector3 n : e.normals) new_n.add(n); - + new_n.normalize(); for(Vector3 n : e.normals) n.set(new_n); } - + return this; } @@ -341,134 +380,93 @@ public CCModel apply(Transformation t) { for(int k = 0; k < verts.length; k++) verts[k].apply(t); - + + Vector3[] normals = normals(); if(normals != null) for(int k = 0; k < normals.length; k++) t.applyN(normals[k]); - + return this; } - public CCModel apply(IUVTransformation uvt) + public CCModel apply(UVTransformation uvt) { for(int k = 0; k < verts.length; k++) verts[k].apply(uvt); - + return this; } - + public CCModel expand(int extraVerts) { int newLen = verts.length+extraVerts; verts = Arrays.copyOf(verts, newLen); - if(normals != null) - normals = Arrays.copyOf(normals, newLen); - if(colours != null) - colours = Arrays.copyOf(colours, newLen); + for(int i = 0; i < attributes.size(); i++) + if(attributes.get(i) != null) + attributes.set(i, CCRenderState.copyOf((CCRenderState.VertexAttribute)CCRenderState.getAttribute(i), attributes.get(i), newLen)); + return this; } - + public void render() { render(0, verts.length, null, null, null); } - + public void render(double x, double y, double z, double u, double v) { - render(new Translation(new Vector3(x, y, z)), new UVTranslation(u, v)); + render(new Vector3(x, y, z).translation(), new UVTranslation(u, v)); } - public void render(double x, double y, double z, IUVTransformation u) + public void render(double x, double y, double z, UVTransformation u) { - render(new Translation(new Vector3(x, y, z)), u); + render(new Vector3(x, y, z).translation(), u); } public void render(Transformation t, double u, double v) { render(t, new UVTranslation(u, v)); } - - public void render(Transformation t, IUVTransformation u) - { - render(t, u, ColourModifier.instance); - } - - public void render(Transformation t, IUVTransformation u, IVertexModifier m) + + public void render(CCRenderState.IVertexOperation... ops) { - render(0, verts.length, t, u, m); + render(0, verts.length, ops); } /** * Renders vertices start through start+length-1 of the model - * @param start The first vertex to render - * @param length The number of vertices to render - * @param t The transformation to apply to the mat - * @param u The u texture offset - * @param v The v texture offset + * @param start The first vertex index to render + * @param end The vertex index to render until + * @param ops Operations to apply */ - public void render(int start, int length, Transformation t, IUVTransformation u, IVertexModifier m) + public void render(int start, int end, CCRenderState.IVertexOperation... ops) { - boolean drawNormal = CCRenderState.useNormals() && normals != null; - boolean computeNormal = drawNormal || m != null && m.needsNormals(); - Vector3 normal = new Vector3(); - Vertex5 vert; - Vector3 vec = new Vector3(); - UV uv = new UV(); - Tessellator tess = Tessellator.instance; - for(int k = 0; k < length; k++) - { - int i = start+k; - if(computeNormal) - { - if(t != null) - t.applyN(normal.set(normals[i])); - else - normal = normals[i]; - - if(drawNormal) - tess.setNormal((float)normal.x, (float)normal.y, (float)normal.z); - } - - vert = verts[i]; - if(t != null) - t.apply(vec.set(vert.vec)); - else - vec = vert.vec; - - if(u != null) - u.transform(uv.set(vert.uv)); - else - uv = vert.uv; - - if(m != null) - m.applyModifiers(this, tess, vec, uv, normal, i); - - tess.addVertexWithUV(vec.x, vec.y, vec.z, uv.u, uv.v); - } + CCRenderState.setPipeline(this, start, end, ops); + CCRenderState.render(); } - + public static CCModel quadModel(int numVerts) { return newModel(7, numVerts); } - + public static CCModel triModel(int numVerts) { return newModel(4, numVerts); } - + public static CCModel newModel(int vertexMode, int numVerts) { CCModel model = newModel(vertexMode); model.verts = new Vertex5[numVerts]; return model; } - + public static CCModel newModel(int vertexMode) { return new CCModel(vertexMode); } - + public static double[] parseDoubles(String s, String token) { String[] as = s.split(token); @@ -482,7 +480,7 @@ public static void illegalAssert(boolean b, String err) { if(!b) throw new IllegalArgumentException(err); } - + public static void assertMatch(Matcher m, String s) { m.reset(s); @@ -497,7 +495,7 @@ public static void assertMatch(Matcher m, String s) public static final Matcher uvwMatcher = uvwPattern.matcher(""); public static final Matcher normalMatcher = normalPattern.matcher(""); public static final Matcher polyMatcher = polyPattern.matcher(""); - + /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file * @param input An input stream to a obj file @@ -511,14 +509,14 @@ public static Map parseObjModels(InputStream input, int vertexM if(coordSystem == null) coordSystem = new RedundantTransformation(); int vp = vertexMode == 7 ? 4 : 3; - + HashMap modelMap = new HashMap(); ArrayList verts = new ArrayList(); ArrayList uvs = new ArrayList(); ArrayList normals = new ArrayList(); ArrayList polys = new ArrayList(); String modelName = "unnamed"; - + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String line; @@ -527,7 +525,7 @@ public static Map parseObjModels(InputStream input, int vertexM line = line.replaceAll("\\s+", " ").trim(); if(line.startsWith("#") || line.length() == 0) continue; - + if(line.startsWith("v ")) { assertMatch(vertMatcher, line); @@ -584,13 +582,13 @@ public static Map parseObjModels(InputStream input, int vertexM modelName = line.substring(2); } } - + if(!polys.isEmpty()) modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); - + return modelMap; } - + public static void triangulate(List polys, int[][] polyVerts) { for(int i = 2; i < polyVerts.length; i++) @@ -600,7 +598,7 @@ public static void triangulate(List polys, int[][] polyVerts) polys.add(polyVerts[i-1]); } } - + public static void quadulate(List polys, int[][] polyVerts) { if(polyVerts.length == 4) @@ -624,7 +622,7 @@ public static void quadulate(List polys, int[][] polyVerts) /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param s The name of the obj resource + * @param res The resource for the obj file * @return A map of group names to models */ public static Map parseObjModels(ResourceLocation res) @@ -642,7 +640,7 @@ public static Map parseObjModels(ResourceLocation res, Transfor try { return parseObjModels( - Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), 4, coordSystem); } catch(IOException e) @@ -650,10 +648,10 @@ public static Map parseObjModels(ResourceLocation res, Transfor throw new RuntimeException("failed to load model: "+res, e); } } - + /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param s The name of the obj resource + * @param res The resource for the obj file * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models @@ -663,7 +661,7 @@ public static Map parseObjModels(ResourceLocation res, int vert try { return parseObjModels( - Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), vertexMode, coordSystem); } catch(Exception e) @@ -677,12 +675,12 @@ public static CCModel createModel(List verts, List uvs, List 0; CCModel model = CCModel.newModel(vertexMode, polys.size()); if(hasNormals) - model.normals = new Vector3[polys.size()]; - + model.getOrAllocate(CCRenderState.normalAttrib); + for(int i = 0; i < polys.size(); i++) { int[] ai = polys.get(i); @@ -690,12 +688,12 @@ public static CCModel createModel(List verts, List uvs, List 0 != hasNormals) throw new IllegalArgumentException("Normals are an all or nothing deal here."); - + model.verts[i] = new Vertex5(vert, uv.x, uv.y); if(hasNormals) - model.normals[i] = normals.get(ai[2]-1).copy(); + model.normals()[i] = normals.get(ai[2]-1).copy(); } - + return model; } @@ -726,7 +724,7 @@ public static void exportObj(Map models, PrintWriter p) int vStart = verts.size(); int uStart = uvs.size(); int nStart = normals.size(); - boolean hasNormals = m.normals != null; + boolean hasNormals = m.normals() != null; polys.clear(); for(int i = 0; i < m.verts.length; i++) { @@ -734,7 +732,7 @@ public static void exportObj(Map models, PrintWriter p) ia[0] = addIndex(verts, m.verts[i].vec); ia[1] = addIndex(uvs, m.verts[i].uv); if(hasNormals) - ia[2] = addIndex(normals, m.normals[i]); + ia[2] = addIndex(normals, m.normals()[i]); polys.add(ia); } @@ -788,7 +786,7 @@ public CCModel shrinkUVs(double d) { uv.add(verts[k+i].uv); } - uv.mul(1D/vp); + uv.multiply(1D/vp); for(int i = 0; i < vp; i++) { Vertex5 vert = verts[k+i]; @@ -798,7 +796,7 @@ public CCModel shrinkUVs(double d) } return this; } - + /** * @param side1 The side of this model * @param side2 The side of the new model @@ -811,30 +809,18 @@ public CCModel sidedCopy(int side1, int side2, Vector3 point) copy(this, 0, model, 0, model.verts.length); return model.apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point)); } - + /** * Copies length vertices and normals */ - public static void copy(CCModel src, int srcpos, CCModel dest, int destpos, int length) + public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int length) { for(int k = 0; k < length; k++) - dest.verts[destpos+k] = src.verts[srcpos+k].copy(); - - if(src.normals != null) - { - if(dest.normals == null) - dest.normals = new Vector3[dest.verts.length]; + dst.verts[destpos+k] = src.verts[srcpos+k].copy(); - for(int k = 0; k < length; k++) - dest.normals[destpos+k] = src.normals[srcpos+k].copy(); - } - - if(src.colours != null) - { - if(dest.colours == null) - dest.colours = new int[dest.verts.length]; - System.arraycopy(src.colours, srcpos, dest.colours, destpos, length); - } + for(int i = 0; i < src.attributes.size(); i++) + if(src.attributes.get(i) != null) + CCRenderState.arrayCopy(src.attributes.get(i), srcpos, dst.getOrAllocate(CCRenderState.getAttribute(i)), destpos, length); } /** @@ -849,11 +835,11 @@ public static void generateSidedModels(CCModel[] models, int side, Vector3 point { if(s == side) continue; - + models[s] = models[side].sidedCopy(side, s, point); } } - + /** * Generate models rotated to the other 3 horizontal of the block * @param models An array of 4 models @@ -870,12 +856,12 @@ public static void generateSidedModelsH(CCModel[] models, int side, Vector3 poin models[s] = models[side].sidedCopy(side, s, point); } } - + public CCModel backfacedCopy() { return generateBackface(this, 0, copy(), 0, verts.length); } - + /** * Generates copies of faces with clockwise vertices * @return The model @@ -885,7 +871,7 @@ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int int vp = src.vp; if(srcpos%vp != 0 || destpos%vp != 0 || length%vp != 0) throw new IllegalArgumentException("Vertices do not align with polygons"); - + int[][] o = new int[][]{{0, 0}, {1, vp-1}, {2, vp-2}, {3, vp-3}}; for(int i = 0; i < length; i++) { @@ -894,10 +880,12 @@ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int int di = destpos+b+o[d][1]; int si = srcpos+b+o[d][0]; dst.verts[di] = src.verts[si].copy(); - if(src.normals != null && src.normals[si] != null) - dst.normals[di] = src.normals[si].copy().negate(); - if(src.colours != null) - dst.colours[di] = src.colours[si]; + for(int a = 0; a < src.attributes.size(); a++) + if(src.attributes.get(a) != null) + CCRenderState.arrayCopy(src.attributes.get(a), si, dst.getOrAllocate(CCRenderState.getAttribute(a)), di, 1); + + if(dst.normals() != null && dst.normals()[di] != null) + dst.normals()[di].negate(); } return dst; } @@ -911,15 +899,15 @@ public CCModel generateSidedParts(int side, Vector3 point) if(verts.length%(6*vp) != 0) throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); int length = verts.length/6; - + for(int s = 0; s < 6; s++) { if(s == side) continue; - + generateSidedPart(side, s, point, length*side, length*s, length); } - + return this; } @@ -932,7 +920,7 @@ public CCModel generateSidedPartsH(int side, Vector3 point) if(verts.length%(4*vp) != 0) throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); int length = verts.length/4; - + for(int s = 2; s < 6; s++) { if(s == side) @@ -940,7 +928,7 @@ public CCModel generateSidedPartsH(int side, Vector3 point) generateSidedPart(side, s, point, length*(side-2), length*(s-2), length); } - + return this; } @@ -962,13 +950,14 @@ public CCModel apply(Transformation t, int srcpos, int destpos, int length) verts[destpos+k] = verts[srcpos+k].copy(); verts[destpos+k].vec.apply(t); } - + + Vector3[] normals = normals(); if(normals != null) for(int k = 0; k < length; k++) { normals[destpos+k] = normals[srcpos+k].copy(); t.applyN(normals[destpos+k]); } - + return this; } @@ -976,7 +965,7 @@ public static CCModel combine(Collection models) { if(models.isEmpty()) return null; - + int numVerts = 0; int vertexMode = -1; for(CCModel model : models) @@ -985,10 +974,10 @@ public static CCModel combine(Collection models) vertexMode = model.vertexMode; if(vertexMode != model.vertexMode) throw new IllegalArgumentException("Cannot combine models with different vertex modes"); - + numVerts+=model.verts.length; } - + CCModel c_model = newModel(vertexMode, numVerts); int i = 0; for(CCModel model : models) @@ -996,7 +985,7 @@ public static CCModel combine(Collection models) copy(model, 0, c_model, i, model.verts.length); i+=model.verts.length; } - + return c_model; } @@ -1013,7 +1002,7 @@ public CCModel copy() copy(this, 0, model, 0, verts.length); return model; } - + /** * @return The average of all vertices, for bones. */ @@ -1025,13 +1014,13 @@ public Vector3 collapse() v.multiply(1/(double)verts.length); return v; } - + public CCModel zOffset(Cuboid6 offsets) { for(int k = 0; k < verts.length; k++) { Vertex5 vert = verts[k]; - Vector3 normal = normals[k]; + Vector3 normal = normals()[k]; switch(findSide(normal)) { case 0: @@ -1056,7 +1045,7 @@ public CCModel zOffset(Cuboid6 offsets) } return this; } - + public static int findSide(Vector3 normal) { if(normal.y <=-0.99) return 0; diff --git a/codechicken/lib/render/CCRenderPipeline.java b/codechicken/lib/render/CCRenderPipeline.java new file mode 100644 index 0000000..d2dcaff --- /dev/null +++ b/codechicken/lib/render/CCRenderPipeline.java @@ -0,0 +1,135 @@ +package codechicken.lib.render; + +import java.util.ArrayList; + +import codechicken.lib.render.CCRenderState.IVertexOperation; +import codechicken.lib.render.CCRenderState.VertexAttribute; + +public class CCRenderPipeline +{ + public class PipelineBuilder + { + public PipelineBuilder add(IVertexOperation op) { + ops.add(op); + return this; + } + + public PipelineBuilder add(IVertexOperation... ops) { + for(int i = 0; i < ops.length; i++) + CCRenderPipeline.this.ops.add(ops[i]); + return this; + } + + public void build() { + rebuild(); + } + + public void render() { + rebuild(); + CCRenderState.render(); + } + } + + private class PipelineNode + { + public ArrayList deps = new ArrayList(); + public IVertexOperation op; + + public void add() { + if(op == null) + return; + + for(int i = 0; i < deps.size(); i++) + deps.get(i).add(); + deps.clear(); + sorted.add(op); + op = null; + } + } + + private ArrayList attribs = new ArrayList(); + private ArrayList ops = new ArrayList(); + private ArrayList nodes = new ArrayList(); + private ArrayList sorted = new ArrayList(); + private PipelineNode loading; + private PipelineBuilder builder = new PipelineBuilder(); + + public void setPipeline(IVertexOperation... ops) { + this.ops.clear(); + for(int i = 0; i < ops.length; i++) + this.ops.add(ops[i]); + rebuild(); + } + + public void reset() { + ops.clear(); + unbuild(); + } + + private void unbuild() { + for(int i = 0; i < attribs.size(); i++) + attribs.get(i).active = false; + attribs.clear(); + sorted.clear(); + } + + public void rebuild() { + if(ops.isEmpty() || CCRenderState.model == null) + return; + + //ensure enough nodes for all ops + while(nodes.size() < CCRenderState.operationCount()) + nodes.add(new PipelineNode()); + unbuild(); + + if(CCRenderState.useNormals) + addAttribute(CCRenderState.normalAttrib); + if(CCRenderState.baseColour != -1 || CCRenderState.alphaOverride >= 0) + addAttribute(CCRenderState.colourAttrib); + else if(CCRenderState.hasColour) + CCRenderState.setColour(-1); + + for(int i = 0; i < ops.size(); i++) { + IVertexOperation op = ops.get(i); + loading = nodes.get(op.operationID()); + boolean loaded = op.load(); + if(loaded) + loading.op = op; + + if(op instanceof VertexAttribute) + if(loaded) + attribs.add((VertexAttribute)op); + else + ((VertexAttribute)op).active = false; + } + + for(int i = 0; i < nodes.size(); i++) + nodes.get(i).add(); + } + + public void addRequirement(int opRef) { + loading.deps.add(nodes.get(opRef)); + } + + public void addDependency(VertexAttribute attrib) { + loading.deps.add(nodes.get(attrib.operationID())); + addAttribute(attrib); + } + + public void addAttribute(VertexAttribute attrib) { + if(!attrib.active) { + ops.add(attrib); + attrib.active = true; + } + } + + public void operate() { + for(int i = 0; i < sorted.size(); i++) + sorted.get(i).operate(); + } + + public PipelineBuilder builder() { + ops.clear(); + return builder; + } +} diff --git a/codechicken/lib/render/CCRenderState.java b/codechicken/lib/render/CCRenderState.java index 3ef7262..835cbb7 100644 --- a/codechicken/lib/render/CCRenderState.java +++ b/codechicken/lib/render/CCRenderState.java @@ -1,147 +1,383 @@ package codechicken.lib.render; import codechicken.lib.colour.ColourRGBA; -import net.minecraft.block.Block; +import codechicken.lib.lighting.LC; +import codechicken.lib.lighting.LightMatrix; +import codechicken.lib.util.Copyable; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Transformation; +import codechicken.lib.vec.Vector3; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.ResourceLocation; import net.minecraft.world.IBlockAccess; +import java.util.ArrayList; + +/** + * The core of the CodeChickenLib render system. + * Rendering operations are written to avoid object allocations by reusing static variables. + */ public class CCRenderState -{ - private static boolean useNormals; - private static boolean hasBrightness; - private static int brightness; - private static boolean useModelColours; - private static int colour; - private static boolean hasColour; - private static int alpha; - private static boolean alphaOverride; - - public static void useNormals(boolean b) - { - useNormals = b; +{ + private static int nextOperationIndex; + + public static int registerOperation() { + return nextOperationIndex++; } - - public static boolean useNormals() - { - return useNormals; + + public static int operationCount() { + return nextOperationIndex; } - - public static void useModelColours(boolean b) + + /** + * Represents an operation to be run for each vertex that operates on and modifies the current state + */ + public static interface IVertexOperation { - useModelColours = b; + /** + * Load any required references and add dependencies to the pipeline based on the current model (may be null) + * Return false if this operation is redundant in the pipeline with the given model + */ + public boolean load(); + + /** + * Perform the operation on the current render state + */ + public void operate(); + + /** + * Get the unique id representing this type of operation. Duplicate operation IDs within the pipeline may have unexpected results. + * ID shoulld be obtained from CCRenderState.registerOperation() and stored in a static variable + */ + public int operationID(); } - public static boolean useModelColours() - { - return useModelColours; + private static ArrayList> vertexAttributes = new ArrayList>(); + private static int registerVertexAttribute(VertexAttribute attr) { + vertexAttributes.add(attr); + return vertexAttributes.size()-1; } - - public static void setAlpha(int a) - { - alpha = a; - alphaOverride = true; + + public static VertexAttribute getAttribute(int index) { + return vertexAttributes.get(index); } - - public static void clearAlphaOverride() + + /** + * Management class for a vertex attrute such as colour, normal etc + * This class should handle the loading of the attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others + * @param The array type for this attrute eg. int[], Vector3[] + */ + public static abstract class VertexAttribute implements IVertexOperation { - alphaOverride = false; + public final int attributeIndex = registerVertexAttribute(this); + private final int operationIndex = registerOperation(); + /** + * Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when constructing the pipeline + */ + public boolean active = false; + + /** + * Construct a new array for storage of vertex attrutes in a model + */ + public abstract T newArray(int length); + + @Override + public int operationID() { + return operationIndex; + } } - - public static void vertexColour(int c) - { - if(alphaOverride) - setColour(c&0xFFFFFF00|alpha); - else - setColour(c); + + public static void arrayCopy(Object src, int srcPos, Object dst, int destPos, int length) { + System.arraycopy(src, srcPos, dst, destPos, length); + if(dst instanceof Copyable[]) { + Object[] oa = (Object[])dst; + Copyable[] c = (Copyable[])dst; + for(int i = destPos; i < destPos+length; i++) + if(c[i] != null) + oa[i] = c[i].copy(); + } } - public static void vertexColour(int r, int g, int b, int a) - { - if(alphaOverride) - Tessellator.instance.setColorRGBA(r, g, b, alpha); - else - Tessellator.instance.setColorRGBA(r, g, b, a); + public static T copyOf(VertexAttribute attr, T src, int length) { + T dst = attr.newArray(length); + arrayCopy(src, 0, dst, 0, length); + return dst; } - - public static void setBrightness(IBlockAccess world, int x, int y, int z) + + public static interface IVertexSource { - Block block = Block.blocksList[world.getBlockId(x, y, z)]; - setBrightness(block == null ? world.getLightBrightnessForSkyBlocks(x, y, z, 0) : block.getMixedBrightnessForBlock(world, x, y, z)); - setColour(0xFFFFFFFF); + public Vertex5[] getVertices(); + + /** + * Gets an array of vertex attrutes + * @param attr The vertex attrute to get + * @param The attrute array type + * @return An array, or null if not computed + */ + public T getAttributes(VertexAttribute attr); + + /** + * @return True if the specified attrute is provided by this model, either by returning an array from getAttributes or by setting the state in prepareVertex + */ + public boolean hasAttribute(VertexAttribute attr); + + /** + * Callback to set CCRenderState for a vertex before the pipeline runs + */ + public void prepareVertex(); } - public static void setBrightness(int b) - { - hasBrightness = true; - Tessellator.instance.setBrightness(brightness = b); + public static VertexAttribute normalAttrib = new VertexAttribute() { + private Vector3[] normalRef; + + @Override + public Vector3[] newArray(int length) { + return new Vector3[length]; + } + + @Override + public boolean load() { + normalRef = model.getAttributes(this); + if(model.hasAttribute(this)) + return normalRef != null; + + if(model.hasAttribute(sideAttrib)) { + pipeline.addDependency(sideAttrib); + return true; + } + throw new IllegalStateException("Normals requested but neither normal or side attrutes are provided by the model"); + } + + @Override + public void operate() { + if(normalRef != null) + setNormal(normalRef[vertexIndex]); + else + setNormal(Rotation.axes[side]); + } + }; + public static VertexAttribute colourAttrib = new VertexAttribute() { + private int[] colourRef; + + @Override + public int[] newArray(int length) { + return new int[length]; + } + + @Override + public boolean load() { + colourRef = model.getAttributes(this); + return colourRef != null || !model.hasAttribute(this); + } + + @Override + public void operate() { + if(colourRef != null) + setColour(ColourRGBA.multiply(baseColour, colourRef[vertexIndex])); + else + setColour(baseColour); + } + }; + public static VertexAttribute sideAttrib = new VertexAttribute() { + private int[] sideRef; + + @Override + public int[] newArray(int length) { + return new int[length]; + } + + @Override + public boolean load() { + sideRef = model.getAttributes(this); + if(model.hasAttribute(this)) + return sideRef != null; + + pipeline.addDependency(normalAttrib); + return true; + } + + @Override + public void operate() { + if(sideRef != null) + side = sideRef[vertexIndex]; + else + side = CCModel.findSide(normal); + } + }; + /** + * Uses the position of the lightmatrix to compute LC if not provided + */ + public static VertexAttribute lightCoordAttrib = new VertexAttribute() { + private LC[] lcRef; + private Vector3 vec = new Vector3();//for computation + private Vector3 pos = new Vector3(); + + @Override + public LC[] newArray(int length) { + return new LC[length]; + } + + @Override + public boolean load() { + lcRef = model.getAttributes(this); + if(model.hasAttribute(this)) + return lcRef != null; + + pos.set(lightMatrix.pos.x, lightMatrix.pos.y, lightMatrix.pos.z); + pipeline.addDependency(sideAttrib); + pipeline.addRequirement(Transformation.operationIndex); + return true; + } + + @Override + public void operate() { + if(lcRef != null) + lc.set(lcRef[vertexIndex]); + else + lc.compute(vec.set(vert.vec).sub(pos), side); + } + }; + + //pipeline state + public static IVertexSource model; + public static int firstVertexIndex; + public static int lastVertexIndex; + public static int vertexIndex; + public static CCRenderPipeline pipeline = new CCRenderPipeline(); + + //context + public static int baseColour; + public static int alphaOverride; + public static boolean useNormals; + public static LightMatrix lightMatrix = new LightMatrix(); + + //vertex outputs + public static Vertex5 vert = new Vertex5(); + public static boolean hasNormal; + public static Vector3 normal = new Vector3(); + public static boolean hasColour; + public static int colour; + public static boolean hasBrightness; + public static int brightness; + + //attrute storage + public static int side; + public static LC lc = new LC(); + + public static void reset() { + model = null; + pipeline.reset(); + hasNormal = hasColour = hasBrightness = false; + baseColour = alphaOverride = -1; } - - public static void setColourOpaque(int c) - { - setColour(c << 8 | 0xFF); + + public static void setPipeline(IVertexOperation... ops) { + pipeline.setPipeline(ops); } - - //RGBA - public static void setColour(int c) - { - hasColour = true; - colour = c; - Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF); + + public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) { + pipeline.reset(); + setModel(model, start, end); + pipeline.setPipeline(ops); } - - public static void changeTexture(String texture) - { - changeTexture(new ResourceLocation(texture)); + + public static void bindModel(IVertexSource model) { + if(CCRenderState.model != model) { + CCRenderState.model = model; + pipeline.rebuild(); + } } - - public static void changeTexture(ResourceLocation texture) - { - Minecraft.getMinecraft().renderEngine.bindTexture(texture); + + public static void setModel(IVertexSource source) { + setModel(source, 0, source.getVertices().length); } - public static void apply() - { + public static void setModel(IVertexSource source, int start, int end) { + bindModel(source); + firstVertexIndex = start; + lastVertexIndex = end; + } + + public static void render(IVertexOperation... ops) { + setPipeline(ops); + render(); + } + + public static void render() { + Vertex5[] verts = model.getVertices(); + for(vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) { + model.prepareVertex(); + vert.set(verts[vertexIndex]); + runPipeline(); + writeVert(); + } + } + + public static void runPipeline() { + pipeline.operate(); + } + + public static void writeVert() { + if(hasNormal) + Tessellator.instance.setNormal((float)normal.x, (float)normal.y, (float)normal.z); + if(hasColour) + Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); if(hasBrightness) Tessellator.instance.setBrightness(brightness); - if(hasColour) - Tessellator.instance.setColorRGBA(colour >> 24 & 0xFF, colour >> 16 & 0xFF, colour >> 8 & 0xFF, colour & 0xFF); + Tessellator.instance.addVertexWithUV(vert.vec.x, vert.vec.y, vert.vec.z, vert.uv.u, vert.uv.v); } - public static void reset() - { - hasBrightness = false; - useModelColours = false; - hasColour = false; - alphaOverride = false; - useNormals = false; + public static void setNormal(double x, double y, double z) { + hasNormal = true; + normal.set(x, y, z); } - public static void startDrawing(int i) - { - Tessellator.instance.startDrawing(i); - apply(); + public static void setNormal(Vector3 n) { + hasNormal = true; + normal.set(n); } - public static void draw() - { - Tessellator.instance.draw(); + public static void setColour(int c) { + hasColour = true; + colour = c; } - public static void pullLightmap() - { + public static void setBrightness(int b) { + hasBrightness = true; + brightness = b; + } + + public static void setBrightness(IBlockAccess world, int x, int y, int z) { + setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z)); + } + + public static void pullLightmap() { setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX); } - public static void applyBrightnessTexCoords() - { - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness&0xFFFF, brightness>>>16); + public static void changeTexture(String texture) { + changeTexture(new ResourceLocation(texture)); } - public static void glColour() - { - new ColourRGBA(colour).glColour(); + public static void changeTexture(ResourceLocation texture) { + Minecraft.getMinecraft().renderEngine.bindTexture(texture); + } + + public static void startDrawing() { + startDrawing(7); + } + + private static void startDrawing(int mode) { + Tessellator.instance.startDrawing(mode); + if(hasColour) + Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); + if(hasBrightness) + Tessellator.instance.setBrightness(brightness); + } + + public static void draw() { + Tessellator.instance.draw(); } } diff --git a/codechicken/lib/render/ColourModifier.java b/codechicken/lib/render/ColourModifier.java deleted file mode 100644 index b1808b6..0000000 --- a/codechicken/lib/render/ColourModifier.java +++ /dev/null @@ -1,22 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.vec.Vector3; - -public class ColourModifier implements IVertexModifier -{ - public static final ColourModifier instance = new ColourModifier(); - - @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - if(CCRenderState.useModelColours() && m != null && m.colours != null) - CCRenderState.vertexColour(m.colours[i]); - } - - @Override - public boolean needsNormals() - { - return false; - } -} diff --git a/codechicken/lib/render/ColourMultiplier.java b/codechicken/lib/render/ColourMultiplier.java index d672ff3..8e30758 100644 --- a/codechicken/lib/render/ColourMultiplier.java +++ b/codechicken/lib/render/ColourMultiplier.java @@ -1,34 +1,39 @@ package codechicken.lib.render; -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.colour.Colour; import codechicken.lib.colour.ColourRGBA; -import codechicken.lib.vec.Vector3; -public class ColourMultiplier implements IVertexModifier +public class ColourMultiplier implements CCRenderState.IVertexOperation { - public Colour colour; - - public ColourMultiplier(Colour colour) - { + private static ColourMultiplier instance = new ColourMultiplier(-1); + + public static ColourMultiplier instance(int colour) { + instance.colour = colour; + return instance; + } + + public static final int operationIndex = CCRenderState.registerOperation(); + public int colour; + + public ColourMultiplier(int colour) { this.colour = colour; } - - public ColourMultiplier(int colour) - { - this(new ColourRGBA(colour)); + + @Override + public boolean load() { + if(colour == -1) + return false; + + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + return true; } - + @Override - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i) - { - if(CCRenderState.useModelColours() && m != null && m.colours != null) - CCRenderState.vertexColour(new ColourRGBA(m.colours[i]).multiply(colour).rgba()); + public void operate() { + CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colour)); } @Override - public boolean needsNormals() - { - return false; + public int operationID() { + return operationIndex; } } diff --git a/codechicken/lib/render/EntityDigIconFX.java b/codechicken/lib/render/EntityDigIconFX.java index 5a8c064..e0e7571 100644 --- a/codechicken/lib/render/EntityDigIconFX.java +++ b/codechicken/lib/render/EntityDigIconFX.java @@ -5,12 +5,12 @@ import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.world.World; public class EntityDigIconFX extends EntityFX { - public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, Icon icon) + public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) { super(world, x, y, z, dx, dy, dz); particleIcon = icon; @@ -72,7 +72,7 @@ public void renderParticle(Tessellator par1Tessellator, float par2, float par3, par1Tessellator.addVertexWithUV(f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10, f7, f9); } - public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, Icon icon, EffectRenderer effectRenderer) + public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, EffectRenderer effectRenderer) { float border = 0.1F; Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2*border); @@ -99,7 +99,7 @@ public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, Ico .multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F)); } - public static void addBlockDestroyEffects(World world, Cuboid6 bounds, Icon[] icons, EffectRenderer effectRenderer) + public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, EffectRenderer effectRenderer) { Vector3 diff = bounds.max.copy().subtract(bounds.min); Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); diff --git a/codechicken/lib/render/IUVTransformation.java b/codechicken/lib/render/IUVTransformation.java deleted file mode 100644 index 386d583..0000000 --- a/codechicken/lib/render/IUVTransformation.java +++ /dev/null @@ -1,6 +0,0 @@ -package codechicken.lib.render; - -public interface IUVTransformation -{ - public void transform(UV texcoord); -} diff --git a/codechicken/lib/render/IVertexModifier.java b/codechicken/lib/render/IVertexModifier.java deleted file mode 100644 index 34cc286..0000000 --- a/codechicken/lib/render/IVertexModifier.java +++ /dev/null @@ -1,11 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.vec.Vector3; - -public interface IVertexModifier -{ - public void applyModifiers(CCModel m, Tessellator tess, Vector3 vec, UV uv, Vector3 normal, int i); - - public boolean needsNormals(); -} diff --git a/codechicken/lib/render/IconTransformation.java b/codechicken/lib/render/IconTransformation.java deleted file mode 100644 index 3a189c5..0000000 --- a/codechicken/lib/render/IconTransformation.java +++ /dev/null @@ -1,20 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.util.Icon; - -public class IconTransformation implements IUVTransformation -{ - public Icon icon; - - public IconTransformation(Icon icon) - { - this.icon = icon; - } - - @Override - public void transform(UV texcoord) - { - texcoord.u = icon.getInterpolatedU(texcoord.u%2*16); - texcoord.v = icon.getInterpolatedV(texcoord.v%2*16); - } -} diff --git a/codechicken/lib/render/MultiIconTransformation.java b/codechicken/lib/render/MultiIconTransformation.java deleted file mode 100644 index ea6e4e3..0000000 --- a/codechicken/lib/render/MultiIconTransformation.java +++ /dev/null @@ -1,41 +0,0 @@ -package codechicken.lib.render; - -import net.minecraft.util.Icon; - -/** - * Icon index is specified as (int)u>>1 - */ -public class MultiIconTransformation implements IUVTransformation -{ - public Icon[] icons; - - public MultiIconTransformation(Icon... icons) - { - this.icons = icons; - } - - @Override - public void transform(UV texcoord) - { - int i = (int)texcoord.u>>1; - Icon icon = icons[i%icons.length]; - texcoord.u = icon.getInterpolatedU(texcoord.u%2*16); - texcoord.v = icon.getInterpolatedV(texcoord.v%2*16); - } - - public static CCModel setIconIndex(CCModel m, int index) - { - return setIconIndex(m, 0, m.verts.length, index); - } - - public static CCModel setIconIndex(CCModel m, int start, int end, int index) - { - for(int k = start; k < end; k++) - { - UV uv = m.verts[k].uv; - uv.u = uv.u%2+index*2; - uv.v %= 2; - } - return m; - } -} diff --git a/codechicken/lib/render/PlaceholderTexture.java b/codechicken/lib/render/PlaceholderTexture.java index 34538a6..8ef54ee 100644 --- a/codechicken/lib/render/PlaceholderTexture.java +++ b/codechicken/lib/render/PlaceholderTexture.java @@ -1,7 +1,7 @@ package codechicken.lib.render; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.ResourceManager; +import net.minecraft.client.resources.IResourceManager; import net.minecraft.util.ResourceLocation; public class PlaceholderTexture extends TextureAtlasSprite @@ -12,7 +12,7 @@ protected PlaceholderTexture(String par1) } @Override - public boolean load(ResourceManager manager, ResourceLocation location) + public boolean load(IResourceManager manager, ResourceLocation location) { return false; } diff --git a/codechicken/lib/render/QBImporter.java b/codechicken/lib/render/QBImporter.java index f53184c..712036b 100644 --- a/codechicken/lib/render/QBImporter.java +++ b/codechicken/lib/render/QBImporter.java @@ -1,11 +1,13 @@ package codechicken.lib.render; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVScale; import codechicken.lib.vec.*; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.IconRegister; -import net.minecraft.util.Icon; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import javax.imageio.ImageIO; @@ -638,7 +640,7 @@ public CCModel getModel(String key) { return map.get(key).m; } - public Icon getIcon(String key, IconRegister r, String iconName) { + public IIcon getIcon(String key, IIconRegister r, String iconName) { int img = map.get(key).img; if(icons[img] != null && !iconName.equals(icons[img])) throw new IllegalArgumentException("Attempted to get a previously registered icon by a different name: "+icons[img]+", "+iconName); diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 9f0d3ad..2ee90dd 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -3,6 +3,8 @@ import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVTransformation; import org.lwjgl.opengl.GL11; import codechicken.lib.vec.Cuboid6; @@ -10,7 +12,7 @@ import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; @@ -48,7 +50,7 @@ public boolean shouldBob() entityItem.hoverStart = 0; } - public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, Icon icon, double res) + public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, double res) { renderFluidQuad(point2, vectors[0].set(point4).subtract(point1), vectors[1].set(point1).subtract(point2), icon, res); } @@ -60,7 +62,7 @@ public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point * @param high The left side of the quad * @param res Units per icon */ - public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, Icon icon, double res) + public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) { Tessellator t = Tessellator.instance; @@ -141,7 +143,7 @@ public static void drawCuboidOutline(Cuboid6 c) var2.draw(); } - public static void renderFluidCuboid(Cuboid6 bound, Icon tex, double res) + public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { renderFluidQuad(//bottom new Vector3(bound.min.x, bound.min.y, bound.min.z), @@ -236,7 +238,7 @@ public static boolean shouldRenderFluid(FluidStack stack) * @param stack The fluid stack to render * @return The icon of the fluid */ - public static Icon prepareFluidRender(FluidStack stack, int alpha) + public static IIcon prepareFluidRender(FluidStack stack, int alpha) { GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_BLEND); @@ -283,8 +285,8 @@ public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double den else bound.max.y = bound.min.y+(bound.max.y-bound.min.y)*density; - Icon tex = prepareFluidRender(stack, alpha); - CCRenderState.startDrawing(7); + IIcon tex = prepareFluidRender(stack, alpha); + CCRenderState.startDrawing(); renderFluidCuboid(bound, tex, res); CCRenderState.draw(); postFluidRender(); @@ -305,8 +307,8 @@ public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double d rect.h = height; } - Icon tex = prepareFluidRender(stack, alpha); - CCRenderState.startDrawing(7); + IIcon tex = prepareFluidRender(stack, alpha); + CCRenderState.startDrawing(); renderFluidQuad( new Vector3(rect.x, rect.y+rect.h, 0), new Vector3(rect.w,0, 0), @@ -333,9 +335,9 @@ public static void renderItemUniform(ItemStack item, double spin) boolean is3D = customRenderer != null && customRenderer.shouldUseRenderHelper(ENTITY, item, BLOCK_3D); boolean larger = false; - if (item.getItem() instanceof ItemBlock && RenderBlocks.renderItemIn3d(Block.blocksList[item.itemID].getRenderType())) + if (item.getItem() instanceof ItemBlock && RenderBlocks.renderItemIn3d(Block.getBlockFromItem(item.getItem()).getRenderType())) { - int renderType = Block.blocksList[item.itemID].getRenderType(); + int renderType = Block.getBlockFromItem(item.getItem()).getRenderType(); larger = !(renderType == 1 || renderType == 19 || renderType == 12 || renderType == 2); } else if(is3D) @@ -351,137 +353,9 @@ else if(is3D) GL11.glColor4f(1, 1, 1, 1); entityItem.setEntityItemStack(item); - uniformRenderItem.doRenderItem(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float)(spin*9/Math.PI)); + uniformRenderItem.doRender(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float)(spin*9/Math.PI)); if(larger) GL11.glScaled(d1, d1, d1); } - - private static Vertex5[] face = new Vertex5[]{new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; - public static void renderBlock(Cuboid6 c, int sideMask, IFaceRenderer r) - { - double x1 = c.min.x; - double x2 = c.max.x; - double y1 = c.min.y; - double y2 = c.max.y; - double z1 = c.min.z; - double z2 = c.max.z; - double u1 = 0; - double u2 = 0; - double v1 = 0; - double v2 = 0; - - if((sideMask&1) == 0) - { - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; - face[0].set(x1, y1, z2, u1, v2); - face[1].set(x1, y1, z1, u1, v1); - face[2].set(x2, y1, z1, u2, v1); - face[3].set(x2, y1, z2, u2, v2); - r.renderFace(face, c.min.y > 0 ? 6 : 0); - } - - if((sideMask&2) == 0) - { - u1 = x1+2; v1 = z1; - u2 = x2+2; v2 = z2; - face[0].set(x2, y2, z2, u2, v2); - face[1].set(x2, y2, z1, u2, v1); - face[2].set(x1, y2, z1, u1, v1); - face[3].set(x1, y2, z2, u1, v2); - r.renderFace(face, c.max.y < 1 ? 7 : 1); - } - - if((sideMask&4) == 0) - { - u1 = 1-x1+4; v1 = 1-y2; - u2 = 1-x2+4; v2 = 1-y1; - face[0].set(x1, y1, z1, u1, v2); - face[1].set(x1, y2, z1, u1, v1); - face[2].set(x2, y2, z1, u2, v1); - face[3].set(x2, y1, z1, u2, v2); - r.renderFace(face, c.min.z > 0 ? 8 : 2); - } - - if((sideMask&8) == 0) - { - u1 = x1+6; v1 = 1-y2; - u2 = x2+6; v2 = 1-y1; - face[0].set(x2, y1, z2, u2, v2); - face[1].set(x2, y2, z2, u2, v1); - face[2].set(x1, y2, z2, u1, v1); - face[3].set(x1, y1, z2, u1, v2); - r.renderFace(face, c.max.z < 1 ? 9 : 3); - } - - if((sideMask&0x10) == 0) - { - u1 = z1+8; v1 = 1-y2; - u2 = z2+8; v2 = 1-y1; - face[0].set(x1, y1, z2, u2, v2); - face[1].set(x1, y2, z2, u2, v1); - face[2].set(x1, y2, z1, u1, v1); - face[3].set(x1, y1, z1, u1, v2); - r.renderFace(face, c.min.x > 0 ? 10 : 4); - } - - if((sideMask&0x20) == 0) - { - u1 = 1-z1+10; v1 = 1-y2; - u2 = 1-z2+10; v2 = 1-y1; - face[0].set(x2, y1, z1, u1, v2); - face[1].set(x2, y2, z1, u1, v1); - face[2].set(x2, y2, z2, u2, v1); - face[3].set(x2, y1, z2, u2, v2); - r.renderFace(face, c.max.x < 1 ? 11 : 5); - } - } - - public static void renderBlock(Cuboid6 bounds, int sideMask, final Transformation t, final IUVTransformation u, final IVertexModifier m) - { - renderBlock(bounds, sideMask, new IFaceRenderer(){ - boolean drawNormal = CCRenderState.useNormals(); - boolean computeNormal = drawNormal || m != null && m.needsNormals(); - Vector3 normal = new Vector3(); - Vertex5 vert; - Vector3 vec = new Vector3(); - UV uv = new UV(); - - @Override - public void renderFace(Vertex5[] face, int side) - { - Tessellator tess = Tessellator.instance; - for(int i = 0; i < face.length; i++) - { - if(computeNormal) - { - if(t != null) - t.applyN(normal.set(Rotation.axes[side%6])); - else - normal = Rotation.axes[side%6]; - - if(drawNormal) - tess.setNormal((float)normal.x, (float)normal.y, (float)normal.z); - } - - vert = face[i]; - if(t != null) - t.apply(vec.set(vert.vec)); - else - vec = vert.vec; - - if(u != null) - u.transform(uv.set(vert.uv)); - else - uv = vert.uv; - - if(m != null) - m.applyModifiers(null, tess, vec, uv, normal, i); - - tess.addVertexWithUV(vec.x, vec.y, vec.z, uv.u, uv.v); - } - } - }); - } } diff --git a/codechicken/lib/render/SpriteSheetManager.java b/codechicken/lib/render/SpriteSheetManager.java index 0d8c28f..f8a1157 100644 --- a/codechicken/lib/render/SpriteSheetManager.java +++ b/codechicken/lib/render/SpriteSheetManager.java @@ -3,19 +3,19 @@ import java.util.ArrayList; import java.util.HashMap; -import codechicken.lib.render.TextureUtils.IIconRegister; +import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; public class SpriteSheetManager { @SideOnly(Side.CLIENT) - public static class SpriteSheet implements IIconRegister + public static class SpriteSheet implements IIconSelfRegister { private int tilesX; private int tilesY; @@ -42,7 +42,7 @@ public void requestIndicies(int... indicies) setupSprite(i); } - public void registerIcons(IconRegister register) + public void registerIcons(IIconRegister register) { TextureMap textureMap = (TextureMap)register; @@ -79,9 +79,9 @@ private void reloadTexture() spriteHeight = texture.height/tilesY; } - public Icon getSprite(int index) + public IIcon getSprite(int index) { - Icon i = sprites[index]; + IIcon i = sprites[index]; if(i == null) throw new IllegalArgumentException("Sprite at index: "+index+" from texture file "+resource+" was not preloaded."); return i; diff --git a/codechicken/lib/render/TextureFX.java b/codechicken/lib/render/TextureFX.java index 3685226..c46ebeb 100644 --- a/codechicken/lib/render/TextureFX.java +++ b/codechicken/lib/render/TextureFX.java @@ -13,55 +13,47 @@ public class TextureFX public int tileSizeSquare = 256; public int tileSizeMask = 15; public int tileSizeSquareMask = 255; - + public boolean anaglyphEnabled; public TextureSpecial texture; - public TextureFX(int spriteIndex, SpriteSheet sheet) - { + public TextureFX(int spriteIndex, SpriteSheet sheet) { texture = sheet.bindTextureFX(spriteIndex, this); } - - public TextureFX(int size, String name) - { + + public TextureFX(int size, String name) { texture = new TextureSpecial(name).blank(size).selfRegister().addTextureFX(this); } - - public TextureFX setAtlas(int index) - { + + public TextureFX setAtlas(int index) { texture.atlasIndex = index; return this; } - public void setup() - { + public void setup() { imageData = new int[tileSizeSquare]; } - - public void onTextureDimensionsUpdate(int width, int height) - { - if(width != height) - throw new IllegalArgumentException("Non-Square textureFX not supported ("+width+":"+height+")"); - + + public void onTextureDimensionsUpdate(int width, int height) { + if (width != height) + throw new IllegalArgumentException("Non-Square textureFX not supported (" + width + ":" + height + ")"); + tileSizeBase = width; tileSizeSquare = tileSizeBase * tileSizeBase; tileSizeMask = tileSizeBase - 1; tileSizeSquareMask = tileSizeSquare - 1; setup(); } - - public void update() - { + + public void update() { anaglyphEnabled = Minecraft.getMinecraft().gameSettings.anaglyph; onTick(); } - public void onTick() - { + public void onTick() { } - - public boolean changed() - { + + public boolean changed() { return true; } } diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java index d5adcdb..3fe2beb 100644 --- a/codechicken/lib/render/TextureSpecial.java +++ b/codechicken/lib/render/TextureSpecial.java @@ -1,150 +1,148 @@ package codechicken.lib.render; +import java.awt.image.BufferedImage; import java.util.ArrayList; + import codechicken.lib.render.SpriteSheetManager.SpriteSheet; -import codechicken.lib.render.TextureUtils.IIconRegister; +import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureUtil; -import net.minecraft.client.resources.ResourceManager; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; @SideOnly(Side.CLIENT) -public class TextureSpecial extends TextureAtlasSprite implements IIconRegister -{ +public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegister { //sprite sheet fields private int spriteIndex; private SpriteSheet spriteSheet; - + //textureFX fields private TextureFX textureFX; - - private int blankSize = -1; + private int blankSize = -1; private ArrayList baseTextures; - + private boolean selfRegister; public int atlasIndex; - - protected TextureSpecial(String par1) - { + + protected TextureSpecial(String par1) { super(par1); } - - public TextureSpecial addTexture(TextureDataHolder t) - { - if(baseTextures == null) + + public TextureSpecial addTexture(TextureDataHolder t) { + if (baseTextures == null) baseTextures = new ArrayList(); baseTextures.add(t); return this; } - - public TextureSpecial baseFromSheet(SpriteSheet spriteSheet, int spriteIndex) - { + + public TextureSpecial baseFromSheet(SpriteSheet spriteSheet, int spriteIndex) { this.spriteSheet = spriteSheet; this.spriteIndex = spriteIndex; return this; } - - public TextureSpecial addTextureFX(TextureFX fx) - { + + public TextureSpecial addTextureFX(TextureFX fx) { textureFX = fx; return this; } - + @Override - public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) - { + public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) { super.initSprite(sheetWidth, sheetHeight, originX, originY, rotated); - if(textureFX != null) + if (textureFX != null) textureFX.onTextureDimensionsUpdate(width, height); } - + @Override - public void updateAnimation() - { - if(textureFX != null) - { + public void updateAnimation() { + if (textureFX != null) { textureFX.update(); - if(textureFX.changed()) - TextureUtil.uploadTextureSub(textureFX.imageData, width, height, originX, originY, false, false); + if (textureFX.changed()) + TextureUtil.uploadTextureSub(0, textureFX.imageData, width, height, originX, originY, false, false, false); } } - + + @Override + public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) { + return true; + } + + public void addFrame(int[] data) { + GameSettings settings = Minecraft.getMinecraft().gameSettings; + BufferedImage[] images = new BufferedImage[settings.mipmapLevels+1]; + images[0] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + images[0].setRGB(0, 0, width, height, data, 0, width); + + super.loadSprite(images, null, settings.anisotropicFiltering > 1); + } + @Override - public boolean load(ResourceManager manager, ResourceLocation location) - { - if(baseTextures != null) - { - for(TextureDataHolder tex : baseTextures) - { - framesTextureData.add(tex.data); + public boolean load(IResourceManager manager, ResourceLocation location) { + if (baseTextures != null) { + for (TextureDataHolder tex : baseTextures) { width = tex.width; height = tex.height; + addFrame(tex.data); } } - - if(spriteSheet != null) - { + + if (spriteSheet != null) { TextureDataHolder tex = spriteSheet.createSprite(spriteIndex); width = tex.width; height = tex.height; - framesTextureData.add(tex.data); + addFrame(tex.data); } - - if(blankSize > 0) - { + + if (blankSize > 0) { width = height = blankSize; - framesTextureData.add(new int[blankSize*blankSize]); + addFrame(new int[blankSize * blankSize]); } - - if(framesTextureData.isEmpty()) - throw new RuntimeException("No base frame for texture: "+getIconName()); - - return true; + + if (framesTextureData.isEmpty()) + throw new RuntimeException("No base frame for texture: " + getIconName()); + + return false; } - + @Override - public boolean hasAnimationMetadata() - { + public boolean hasAnimationMetadata() { return textureFX != null || super.hasAnimationMetadata(); } - + @Override - public int getFrameCount() - { - if(textureFX != null) + public int getFrameCount() { + if (textureFX != null) return 1; - + return super.getFrameCount(); } - public TextureSpecial blank(int size) - { + public TextureSpecial blank(int size) { blankSize = size; return this; } - - public TextureSpecial selfRegister() - { + + public TextureSpecial selfRegister() { selfRegister = true; TextureUtils.addIconRegistrar(this); return this; } - + @Override - public void registerIcons(IconRegister register) - { - if(selfRegister) - ((TextureMap)register).setTextureEntry(getIconName(), this); + public void registerIcons(IIconRegister register) { + if (selfRegister) + ((TextureMap) register).setTextureEntry(getIconName(), this); } - + @Override - public int atlasIndex() - { + public int atlasIndex() { return atlasIndex; } } diff --git a/codechicken/lib/render/TextureUtils.java b/codechicken/lib/render/TextureUtils.java index ce52719..8556332 100644 --- a/codechicken/lib/render/TextureUtils.java +++ b/codechicken/lib/render/TextureUtils.java @@ -7,6 +7,7 @@ import javax.imageio.ImageIO; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; @@ -15,138 +16,118 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.Icon; +import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.ForgeSubscribe; public class TextureUtils -{ - public static interface IIconRegister +{ + public static interface IIconSelfRegister { - public void registerIcons(IconRegister register); + public void registerIcons(IIconRegister register); + public int atlasIndex(); } - - static - { + + static { MinecraftForge.EVENT_BUS.register(new TextureUtils()); } - - private static ArrayList iconRegistrars = new ArrayList(); - - public static void addIconRegistrar(IIconRegister registrar) - { + + private static ArrayList iconRegistrars = new ArrayList(); + + public static void addIconRegistrar(IIconSelfRegister registrar) { iconRegistrars.add(registrar); } - - @ForgeSubscribe - public void textureLoad(TextureStitchEvent.Pre event) - { - for(IIconRegister reg : iconRegistrars) - if(reg.atlasIndex() == event.map.textureType) + + @SubscribeEvent + public void textureLoad(TextureStitchEvent.Pre event) { + for (IIconSelfRegister reg : iconRegistrars) + if (reg.atlasIndex() == event.map.getTextureType()) reg.registerIcons(event.map); } - + /** * @return an array of ARGB pixel data */ - public static int[] loadTextureData(ResourceLocation resource) - { + public static int[] loadTextureData(ResourceLocation resource) { return loadTexture(resource).data; } - public static Colour[] loadTextureColours(ResourceLocation resource) - { + public static Colour[] loadTextureColours(ResourceLocation resource) { int[] idata = loadTextureData(resource); Colour[] data = new Colour[idata.length]; - for(int i = 0; i < data.length; i++) + for (int i = 0; i < data.length; i++) data[i] = new ColourARGB(idata[i]); return data; } - - public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException - { + + public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException { return Minecraft.getMinecraft().getResourceManager().getResource(textureFile).getInputStream(); } - - public static BufferedImage loadBufferedImage(ResourceLocation textureFile) - { - try - { + + public static BufferedImage loadBufferedImage(ResourceLocation textureFile) { + try { return loadBufferedImage(getTextureResource(textureFile)); - } - catch(Exception e) - { - System.err.println("Failed to load texture file: "+textureFile); + } catch (Exception e) { + System.err.println("Failed to load texture file: " + textureFile); e.printStackTrace(); } return null; } - public static BufferedImage loadBufferedImage(InputStream in) throws IOException - { + public static BufferedImage loadBufferedImage(InputStream in) throws IOException { BufferedImage img = ImageIO.read(in); in.close(); return img; } - public static TextureManager engine() - { + public static TextureManager engine() { return Minecraft.getMinecraft().renderEngine; } - public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) - { - for(int y = 0; y < height; y++) - for(int x = 0; x < width; x++) - { - int fp = (y+fromY)*fromWidth+x+fromX; - int tp = (y+toX)*toWidth+x+toX; + public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) { + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { + int fp = (y + fromY) * fromWidth + x + fromX; + int tp = (y + toX) * toWidth + x + toX; toTex[tp] = fromTex[fp]; } } - public static void bindAtlas(int atlasIndex) - { + public static void bindAtlas(int atlasIndex) { engine().bindTexture(atlasIndex == 0 ? TextureMap.locationBlocksTexture : TextureMap.locationItemsTexture); } - - public static Icon getBlankIcon(int size, IconRegister iconRegister) - { - TextureMap textureMap = (TextureMap)iconRegister; - String s = "blank_"+size; - if(textureMap.getTextureExtry(s) == null) - { + + public static IIcon getBlankIcon(int size, IIconRegister iconRegister) { + TextureMap textureMap = (TextureMap) iconRegister; + String s = "blank_" + size; + if (textureMap.getTextureExtry(s) == null) { TextureSpecial icon = new TextureSpecial(s).blank(size); textureMap.setTextureEntry(s, icon); } return iconRegister.registerIcon(s); } - - public static TextureSpecial getTextureSpecial(IconRegister iconRegister, String name) - { + + public static TextureSpecial getTextureSpecial(IIconRegister iconRegister, String name) { TextureMap textureMap = (TextureMap) iconRegister; - Icon entry = textureMap.getTextureExtry(name); - if(entry != null) - throw new IllegalStateException("Texture: "+name+" is already registered"); - + IIcon entry = textureMap.getTextureExtry(name); + if (entry != null) + throw new IllegalStateException("Texture: " + name + " is already registered"); + TextureSpecial icon = new TextureSpecial(name); textureMap.setTextureEntry(name, icon); return icon; } - public static void prepareTexture(int target, int texture, int min_mag_filter, int wrap) - { + public static void prepareTexture(int target, int texture, int min_mag_filter, int wrap) { GL11.glBindTexture(target, texture); GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, min_mag_filter); GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, min_mag_filter); - switch(target) - { + switch (target) { case GL12.GL_TEXTURE_3D: GL11.glTexParameteri(target, GL12.GL_TEXTURE_WRAP_R, wrap); case GL11.GL_TEXTURE_2D: @@ -156,32 +137,28 @@ public static void prepareTexture(int target, int texture, int min_mag_filter, i } } - public static TextureDataHolder loadTexture(ResourceLocation resource) - { + public static TextureDataHolder loadTexture(ResourceLocation resource) { BufferedImage img = loadBufferedImage(resource); - if(img == null) - throw new RuntimeException("Texture not found: "+resource); + if (img == null) + throw new RuntimeException("Texture not found: " + resource); return new TextureDataHolder(img); } /** * Uses an empty placeholder texture to tell if the map has been reloaded since the last call to refresh texture and the texture with name needs to be reacquired to be valid */ - public static boolean refreshTexture(TextureMap map, String name) - { - if(map.getTextureExtry(name) == null) - { + public static boolean refreshTexture(TextureMap map, String name) { + if (map.getTextureExtry(name) == null) { map.setTextureEntry(name, new PlaceholderTexture(name)); return true; } return false; } - public static Icon safeIcon(Icon icon) - { - if(icon == null) - icon = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); - + public static IIcon safeIcon(IIcon icon) { + if (icon == null) + icon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); + return icon; } } diff --git a/codechicken/lib/render/UV.java b/codechicken/lib/render/UV.java deleted file mode 100644 index 9181e5a..0000000 --- a/codechicken/lib/render/UV.java +++ /dev/null @@ -1,79 +0,0 @@ -package codechicken.lib.render; - -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - -public class UV -{ - public double u; - public double v; - - public UV() - { - } - - public UV(double u, double v) - { - this.u = u; - this.v = v; - } - - public UV(UV uv) - { - this(uv.u, uv.v); - } - - public UV set(double u, double v) - { - this.u = u; - this.v = v; - return this; - } - - public UV set(UV uv) - { - u = uv.u; - v = uv.v; - return this; - } - - public UV copy() - { - return new UV(this); - } - - public UV add(UV uv) - { - u+=uv.u; - v+=uv.v; - return this; - } - - public UV mul(double d) - { - u*=d; - v*=d; - return this; - } - - public String toString() - { - MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "UV("+new BigDecimal(u, cont)+", "+new BigDecimal(v, cont)+")"; - } - - public UV apply(IUVTransformation transform) - { - transform.transform(this); - return this; - } - - @Override - public boolean equals(Object o) { - if(!(o instanceof UV)) - return false; - UV uv = (UV)o; - return u == uv.u && v == uv.v; - } -} \ No newline at end of file diff --git a/codechicken/lib/render/UVScale.java b/codechicken/lib/render/UVScale.java deleted file mode 100644 index 3abdce0..0000000 --- a/codechicken/lib/render/UVScale.java +++ /dev/null @@ -1,25 +0,0 @@ -package codechicken.lib.render; - -public class UVScale implements IUVTransformation -{ - double su; - double sv; - - public UVScale(double scaleu, double scalev) - { - su = scaleu; - sv = scalev; - } - - public UVScale(double d) - { - this(d, d); - } - - @Override - public void transform(UV uv) - { - uv.u*=su; - uv.v*=sv; - } -} diff --git a/codechicken/lib/render/UVTranslation.java b/codechicken/lib/render/UVTranslation.java deleted file mode 100644 index ffd2565..0000000 --- a/codechicken/lib/render/UVTranslation.java +++ /dev/null @@ -1,20 +0,0 @@ -package codechicken.lib.render; - -public class UVTranslation implements IUVTransformation -{ - public double du; - public double dv; - - public UVTranslation(double u, double v) - { - du = u; - dv = v; - } - - @Override - public void transform(UV texcoord) - { - texcoord.u+=du; - texcoord.v+=dv; - } -} diff --git a/codechicken/lib/render/Vertex5.java b/codechicken/lib/render/Vertex5.java index 4c6780b..41683af 100644 --- a/codechicken/lib/render/Vertex5.java +++ b/codechicken/lib/render/Vertex5.java @@ -4,10 +4,13 @@ import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVTransformation; +import codechicken.lib.util.Copyable; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; -public class Vertex5 +public class Vertex5 implements Copyable { public Vector3 vec; public UV uv; @@ -32,7 +35,7 @@ public Vertex5(double x, double y, double z, double u, double v) { this(new Vector3(x, y, z), new UV(u, v)); } - + public Vertex5 set(double x, double y, double z, double u, double v) { vec.set(x, y, z); @@ -40,6 +43,19 @@ public Vertex5 set(double x, double y, double z, double u, double v) return this; } + public Vertex5 set(double x, double y, double z, double u, double v, int tex) + { + vec.set(x, y, z); + uv.set(u, v, tex); + return this; + } + + public Vertex5 set(Vertex5 vert) { + vec.set(vert.vec); + uv.set(vert.uv); + return this; + } + public Vertex5(Vertex5 vertex5) { this(vertex5.vec.copy(), vertex5.uv.copy()); @@ -62,7 +78,7 @@ public Vertex5 apply(Transformation t) return this; } - public Vertex5 apply(IUVTransformation t) + public Vertex5 apply(UVTransformation t) { uv.apply(t); return this; diff --git a/codechicken/lib/render/uv/IconTransformation.java b/codechicken/lib/render/uv/IconTransformation.java new file mode 100644 index 0000000..ff7b975 --- /dev/null +++ b/codechicken/lib/render/uv/IconTransformation.java @@ -0,0 +1,23 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.vec.IrreversibleTransformationException; +import net.minecraft.util.IIcon; + +public class IconTransformation extends UVTransformation { + public IIcon icon; + + public IconTransformation(IIcon icon) { + this.icon = icon; + } + + @Override + public void apply(UV uv) { + uv.u = icon.getInterpolatedU(uv.u * 16); + uv.v = icon.getInterpolatedV(uv.v * 16); + } + + @Override + public UVTransformation inverse() { + throw new IrreversibleTransformationException(this); + } +} diff --git a/codechicken/lib/render/uv/MultiIconTransformation.java b/codechicken/lib/render/uv/MultiIconTransformation.java new file mode 100644 index 0000000..7080f43 --- /dev/null +++ b/codechicken/lib/render/uv/MultiIconTransformation.java @@ -0,0 +1,24 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.vec.IrreversibleTransformationException; +import net.minecraft.util.IIcon; + +public class MultiIconTransformation extends UVTransformation { + public IIcon[] icons; + + public MultiIconTransformation(IIcon... icons) { + this.icons = icons; + } + + @Override + public void apply(UV uv) { + IIcon icon = icons[uv.tex % icons.length]; + uv.u = icon.getInterpolatedU(uv.u * 16); + uv.v = icon.getInterpolatedV(uv.v * 16); + } + + @Override + public UVTransformation inverse() { + throw new IrreversibleTransformationException(this); + } +} diff --git a/codechicken/lib/render/uv/UV.java b/codechicken/lib/render/uv/UV.java new file mode 100644 index 0000000..708b243 --- /dev/null +++ b/codechicken/lib/render/uv/UV.java @@ -0,0 +1,79 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.util.Copyable; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UV implements Copyable { + public double u; + public double v; + public int tex; + + public UV() { + } + + public UV(double u, double v) { + this(u, v, 0); + } + + public UV(double u, double v, int tex) { + this.u = u; + this.v = v; + this.tex = tex; + } + + public UV(UV uv) { + this(uv.u, uv.v, uv.tex); + } + + public UV set(double u, double v, int tex) { + this.u = u; + this.v = v; + this.tex = tex; + return this; + } + + public UV set(double u, double v) { + return set(u, v, tex); + } + + public UV set(UV uv) { + return set(uv.u, uv.v, uv.tex); + } + + public UV copy() { + return new UV(this); + } + + public UV add(UV uv) { + u += uv.u; + v += uv.v; + return this; + } + + public UV multiply(double d) { + u *= d; + v *= d; + return this; + } + + public String toString() { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UV(" + new BigDecimal(u, cont) + ", " + new BigDecimal(v, cont) + ")"; + } + + public UV apply(UVTransformation t) { + t.apply(this); + return this; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof UV)) + return false; + UV uv = (UV) o; + return u == uv.u && v == uv.v; + } +} \ No newline at end of file diff --git a/codechicken/lib/render/uv/UVRotation.java b/codechicken/lib/render/uv/UVRotation.java new file mode 100644 index 0000000..e57ee3f --- /dev/null +++ b/codechicken/lib/render/uv/UVRotation.java @@ -0,0 +1,53 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.math.MathHelper; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UVRotation extends UVTransformation +{ + public double angle; + + /** + * @param angle The angle to rotate counterclockwise in radians + */ + public UVRotation(double angle) { + this.angle = angle; + } + + @Override + public void apply(UV uv) { + double c = MathHelper.cos(angle); + double s = MathHelper.sin(angle); + double u2 = c*uv.u + s*uv.v; + uv.v = - s*uv.u + c*uv.v; + uv.u = u2; + } + + @Override + public UVTransformation inverse() { + return new UVRotation(-angle); + } + + @Override + public UVTransformation merge(UVTransformation next) { + if(next instanceof UVRotation) + return new UVRotation(angle+((UVRotation)next).angle); + + return null; + } + + @Override + public boolean isRedundant() { + return MathHelper.between(-1E-5, angle, 1E-5); + } + + @Override + public String toString() + { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UVRotation(" + new BigDecimal(angle, cont) + ")"; + } +} diff --git a/codechicken/lib/render/uv/UVScale.java b/codechicken/lib/render/uv/UVScale.java new file mode 100644 index 0000000..db229ec --- /dev/null +++ b/codechicken/lib/render/uv/UVScale.java @@ -0,0 +1,36 @@ +package codechicken.lib.render.uv; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UVScale extends UVTransformation { + double su; + double sv; + + public UVScale(double scaleu, double scalev) { + su = scaleu; + sv = scalev; + } + + public UVScale(double d) { + this(d, d); + } + + @Override + public void apply(UV uv) { + uv.u *= su; + uv.v *= sv; + } + + @Override + public UVTransformation inverse() { + return new UVScale(1 / su, 1 / sv); + } + + @Override + public String toString() { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UVScale(" + new BigDecimal(su, cont) + ", " + new BigDecimal(sv, cont) + ")"; + } +} diff --git a/codechicken/lib/render/uv/UVTransformation.java b/codechicken/lib/render/uv/UVTransformation.java new file mode 100644 index 0000000..0d9afd2 --- /dev/null +++ b/codechicken/lib/render/uv/UVTransformation.java @@ -0,0 +1,37 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.ITransformation; + +/** + * Abstract supertype for any UV transformation + */ +public abstract class UVTransformation extends ITransformation implements CCRenderState.IVertexOperation +{ + public static final int operationIndex = CCRenderState.registerOperation(); + + public UVTransformation at(UV point) { + return new UVTransformationList(new UVTranslation(-point.u, -point.v), this, new UVTranslation(point.u, point.v)); + } + + public UVTransformationList with(UVTransformation t) { + return new UVTransformationList(this, t); + } + + @Override + public boolean load() { + return !isRedundant(); + } + + @Override + public void operate() { + apply(CCRenderState.vert.uv); + } + + @Override + public int operationID() { + return operationIndex; + } +} + + diff --git a/codechicken/lib/render/uv/UVTransformationList.java b/codechicken/lib/render/uv/UVTransformationList.java new file mode 100644 index 0000000..ec69ae9 --- /dev/null +++ b/codechicken/lib/render/uv/UVTransformationList.java @@ -0,0 +1,106 @@ +package codechicken.lib.render.uv; + +import java.util.ArrayList; +import java.util.Iterator; + +public class UVTransformationList extends UVTransformation +{ + private ArrayList transformations = new ArrayList(); + + public UVTransformationList(UVTransformation... transforms) + { + for(UVTransformation t : transforms) + if(t instanceof UVTransformationList) + transformations.addAll(((UVTransformationList)t).transformations); + else + transformations.add(t); + + compact(); + } + + @Override + public void apply(UV uv) + { + for(int i = 0; i < transformations.size(); i++) + transformations.get(i).apply(uv); + } + + @Override + public UVTransformationList with(UVTransformation t) + { + if(t.isRedundant()) + return this; + + if(t instanceof UVTransformationList) + transformations.addAll(((UVTransformationList)t).transformations); + else + transformations.add(t); + + compact(); + return this; + } + + public UVTransformationList prepend(UVTransformation t) + { + if(t.isRedundant()) + return this; + + if(t instanceof UVTransformationList) + transformations.addAll(0, ((UVTransformationList)t).transformations); + else + transformations.add(0, t); + + compact(); + return this; + } + + private void compact() { + ArrayList newList = new ArrayList(transformations.size()); + Iterator iterator = transformations.iterator(); + UVTransformation prev = null; + while(iterator.hasNext()) { + UVTransformation t = iterator.next(); + if(t.isRedundant()) + continue; + + if(prev != null) { + UVTransformation m = prev.merge(t); + if(m == null) + newList.add(prev); + else if(m.isRedundant()) + t = null; + else + t = m; + } + prev = t; + } + if(prev != null) + newList.add(prev); + + if(newList.size() < transformations.size()) + transformations = newList; + } + + @Override + public boolean isRedundant() { + return transformations.size() == 0; + } + + @Override + public UVTransformation inverse() + { + UVTransformationList rev = new UVTransformationList(); + for(int i = transformations.size()-1; i >= 0; i--) + rev.with(transformations.get(i).inverse()); + return rev; + } + + @Override + public String toString() + { + String s = ""; + for(UVTransformation t : transformations) + s+="\n"+t.toString(); + return s.trim(); + } +} diff --git a/codechicken/lib/render/uv/UVTranslation.java b/codechicken/lib/render/uv/UVTranslation.java new file mode 100644 index 0000000..cd87544 --- /dev/null +++ b/codechicken/lib/render/uv/UVTranslation.java @@ -0,0 +1,54 @@ +package codechicken.lib.render.uv; + +import codechicken.lib.math.MathHelper; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +public class UVTranslation extends UVTransformation { + public double du; + public double dv; + + public UVTranslation(double u, double v) { + du = u; + dv = v; + } + + @Override + public void apply(UV uv) { + uv.u += du; + uv.v += dv; + } + + @Override + public UVTransformation at(UV point) { + return this; + } + + @Override + public UVTransformation inverse() { + return new UVTranslation(-du, -dv); + } + + @Override + public UVTransformation merge(UVTransformation next) { + if (next instanceof UVTranslation) { + UVTranslation t = (UVTranslation)next; + return new UVTranslation(du+t.du, dv+t.dv); + } + + return null; + } + + @Override + public boolean isRedundant() { + return MathHelper.between(-1E-5, du, 1E-5) && MathHelper.between(-1E-5, dv, 1E-5); + } + + @Override + public String toString() { + MathContext cont = new MathContext(4, RoundingMode.HALF_UP); + return "UVTranslation(" + new BigDecimal(du, cont) + ", " + new BigDecimal(dv, cont) + ")"; + } +} diff --git a/codechicken/lib/util/Copyable.java b/codechicken/lib/util/Copyable.java new file mode 100644 index 0000000..2f78c39 --- /dev/null +++ b/codechicken/lib/util/Copyable.java @@ -0,0 +1,5 @@ +package codechicken.lib.util; + +public interface Copyable { + public T copy(); +} diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java index 547b830..061a4cd 100644 --- a/codechicken/lib/vec/BlockCoord.java +++ b/codechicken/lib/vec/BlockCoord.java @@ -1,9 +1,10 @@ package codechicken.lib.vec; +import codechicken.lib.util.Copyable; import net.minecraft.tileentity.TileEntity; import codechicken.lib.math.MathHelper; -public class BlockCoord implements Comparable +public class BlockCoord implements Comparable, Copyable { public int x; public int y; diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index d44d331..8101cf1 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -4,10 +4,11 @@ import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.util.Copyable; import net.minecraft.block.Block; import net.minecraft.util.AxisAlignedBB; -public class Cuboid6 +public class Cuboid6 implements Copyable { public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); @@ -47,7 +48,23 @@ public Cuboid6 copy() { return new Cuboid6(this); } - + + public Cuboid6 set(Cuboid6 c) { + return set(c.min, c.max); + } + + public Cuboid6 set(Vector3 min, Vector3 max) { + this.min.set(min); + this.max.set(max); + return this; + } + + public Cuboid6 set(double minx, double miny, double minz, double maxx, double maxy, double maxz) { + min.set(minx, miny, minz); + max.set(maxx, maxy, maxz); + return this; + } + public Cuboid6 add(Vector3 vec) { min.add(vec); diff --git a/codechicken/lib/vec/CuboidCoord.java b/codechicken/lib/vec/CuboidCoord.java index 3d34116..a3c598a 100644 --- a/codechicken/lib/vec/CuboidCoord.java +++ b/codechicken/lib/vec/CuboidCoord.java @@ -1,10 +1,11 @@ package codechicken.lib.vec; +import codechicken.lib.util.Copyable; import net.minecraft.util.AxisAlignedBB; import java.util.Iterator; -public class CuboidCoord implements Iterable +public class CuboidCoord implements Iterable, Copyable { public BlockCoord min; public BlockCoord max; diff --git a/codechicken/lib/vec/ITransformation.java b/codechicken/lib/vec/ITransformation.java new file mode 100644 index 0000000..ab823f0 --- /dev/null +++ b/codechicken/lib/vec/ITransformation.java @@ -0,0 +1,49 @@ +package codechicken.lib.vec; + +/** + * Abstract supertype for any VectorN transformation + * @param The vector type + * @param The transformation type + */ +public abstract class ITransformation +{ + /** + * Applies this transformation to vec + */ + public abstract void apply(Vector vec); + + /** + * @param point The point to apply this transformation around + * @return Wraps this transformation in a translation to point and then back from point + */ + public abstract Transformation at(Vector point); + + /** + * Creates a TransformationList composed of this transformation followed by t + * If this is a TransformationList, the transformation will be appended and this returned + */ + public abstract Transformation with(Transformation t); + + /** + * Returns a simplified transformation that performs this, followed by next. If such a transformation does not exist, returns null + */ + public Transformation merge(Transformation next) { + return null; + } + + /** + * Returns true if this transformation is redundant, eg. Scale(1, 1, 1), Translation(0, 0, 0) or Rotation(0, a, b, c) + */ + public boolean isRedundant() { + return false; + } + + public abstract Transformation inverse(); + + /** + * Scala ++ operator + */ + public Transformation $plus$plus(Transformation t) { + return with(t); + } +} diff --git a/codechicken/lib/vec/IrreversibleTransformationException.java b/codechicken/lib/vec/IrreversibleTransformationException.java index c7d5c4d..015add0 100644 --- a/codechicken/lib/vec/IrreversibleTransformationException.java +++ b/codechicken/lib/vec/IrreversibleTransformationException.java @@ -3,9 +3,9 @@ @SuppressWarnings("serial") public class IrreversibleTransformationException extends RuntimeException { - public Transformation t; + public ITransformation t; - public IrreversibleTransformationException(Transformation t) + public IrreversibleTransformationException(ITransformation t) { this.t = t; } diff --git a/codechicken/lib/vec/Matrix4.java b/codechicken/lib/vec/Matrix4.java index 10afb16..1ac8a13 100644 --- a/codechicken/lib/vec/Matrix4.java +++ b/codechicken/lib/vec/Matrix4.java @@ -7,12 +7,13 @@ import java.nio.ByteOrder; import java.nio.DoubleBuffer; +import codechicken.lib.util.Copyable; import org.lwjgl.opengl.GL11; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class Matrix4 extends Transformation +public class Matrix4 extends Transformation implements Copyable { private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); diff --git a/codechicken/lib/vec/Quat.java b/codechicken/lib/vec/Quat.java index e639552..404daa6 100644 --- a/codechicken/lib/vec/Quat.java +++ b/codechicken/lib/vec/Quat.java @@ -4,14 +4,14 @@ import java.math.MathContext; import java.math.RoundingMode; import codechicken.lib.math.MathHelper; +import codechicken.lib.util.Copyable; -public class Quat +public class Quat implements Copyable { public double x; public double y; public double z; public double s; - public static final double SQRT2 = Math.sqrt(2D); public Quat() { diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java index e3ee9d5..af253f2 100644 --- a/codechicken/lib/vec/Rotation.java +++ b/codechicken/lib/vec/Rotation.java @@ -139,7 +139,7 @@ public static int getSidedRotation(EntityPlayer player, int side) { Vector3 axis = Rotation.axes[rotateSide(side^1, r)]; double d = look.scalarProject(axis); - if(max > d)//TODO wrong way round + if(d > max) { max = d; maxr = r; diff --git a/codechicken/lib/vec/Scale.java b/codechicken/lib/vec/Scale.java index ca36bf5..a6e38b1 100644 --- a/codechicken/lib/vec/Scale.java +++ b/codechicken/lib/vec/Scale.java @@ -9,72 +9,62 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class Scale extends Transformation -{ - private Vector3 factor; - - public Scale(Vector3 factor) - { +public class Scale extends Transformation { + public Vector3 factor; + + public Scale(Vector3 factor) { this.factor = factor; } - public Scale(double factor) - { + public Scale(double factor) { this(new Vector3(factor, factor, factor)); } - - public Scale(double x, double y, double z) - { + + public Scale(double x, double y, double z) { this(new Vector3(x, y, z)); } @Override - public void apply(Vector3 vec) - { + public void apply(Vector3 vec) { vec.multiply(factor); } - + @Override - public void applyN(Vector3 normal) - { + public void applyN(Vector3 normal) { } - + @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.scale(factor); } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { + public void glApply() { GL11.glScaled(factor.x, factor.y, factor.z); } - + @Override - public Transformation inverse() - { - return new Scale(1/factor.x, 1/factor.y, 1/factor.z); + public Transformation inverse() { + return new Scale(1 / factor.x, 1 / factor.y, 1 / factor.z); } - + @Override public Transformation merge(Transformation next) { - if(next instanceof Scale) + if (next instanceof Scale) return new Scale(factor.copy().multiply(((Scale) next).factor)); - + return null; } - + @Override public boolean isRedundant() { return factor.equalsT(Vector3.one); } - + @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Scale("+new BigDecimal(factor.x, cont)+", "+new BigDecimal(factor.y, cont)+", "+new BigDecimal(factor.z, cont)+")"; + return "Scale(" + new BigDecimal(factor.x, cont) + ", " + new BigDecimal(factor.y, cont) + ", " + new BigDecimal(factor.z, cont) + ")"; } } diff --git a/codechicken/lib/vec/Transformation.java b/codechicken/lib/vec/Transformation.java index 5e0e12d..8b323df 100644 --- a/codechicken/lib/vec/Transformation.java +++ b/codechicken/lib/vec/Transformation.java @@ -1,72 +1,54 @@ package codechicken.lib.vec; +import codechicken.lib.render.CCRenderState; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; /** - * Interface for any 3D vector transformation + * Abstract supertype for any 3D vector transformation */ -public abstract class Transformation -{ - /** - * Applies this transformation to a position vector - * @param vec The vector to transform - */ - public abstract void apply(Vector3 vec); - +public abstract class Transformation extends ITransformation implements CCRenderState.IVertexOperation +{ + public static final int operationIndex = CCRenderState.registerOperation(); + /** * Applies this transformation to a normal (doesn't translate) * @param normal The normal to transform */ public abstract void applyN(Vector3 normal); - + /** * Applies this transformation to a matrix as a multiplication on the right hand side. * @param mat The matrix to combine this transformation with */ public abstract void apply(Matrix4 mat); - - /** - * @param point The point in OBJECT space to apply this transformation around - * @return Wraps this transformation in a translation to point and then back from point - */ - public Transformation at(Vector3 point) - { + + public Transformation at(Vector3 point) { return new TransformationList(new Translation(-point.x, -point.y, -point.z), this, point.translation()); } - - /** - * Creates a transformation list composed of this transformation followed by t - * If this is a TransformationList, the transformation will be appended and this returned - */ - public TransformationList with(Transformation t) - { + + public TransformationList with(Transformation t) { return new TransformationList(this, t); } - - /** - * Returns a simplified transformation that performs this, followed by next. If such a transformation does not exist, returns null - */ - public Transformation merge(Transformation next) - { - return null; - } - - /** - * Returns true if this transformation is redundant, eg. Scale(1, 1, 1), Translation(0, 0, 0) or Rotation(0, a, b, c) - */ - public boolean isRedundant() - { - return false; - } - + @SideOnly(Side.CLIENT) public abstract void glApply(); - public abstract Transformation inverse(); - - public TransformationList $plus$plus(Transformation t) - { - return with(t); + @Override + public boolean load() { + CCRenderState.pipeline.addRequirement(CCRenderState.normalAttrib.operationID()); + return !isRedundant(); + } + + @Override + public void operate() { + apply(CCRenderState.vert.vec); + if(CCRenderState.normalAttrib.active) + applyN(CCRenderState.normal); + } + + @Override + public int operationID() { + return operationIndex; } } diff --git a/codechicken/lib/vec/Translation.java b/codechicken/lib/vec/Translation.java index ad2776e..63c18e5 100644 --- a/codechicken/lib/vec/Translation.java +++ b/codechicken/lib/vec/Translation.java @@ -9,73 +9,63 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class Translation extends Transformation -{ - private Vector3 vec; - - public Translation(Vector3 vec) - { +public class Translation extends Transformation { + public Vector3 vec; + + public Translation(Vector3 vec) { this.vec = vec; } - public Translation(double x, double y, double z) - { + public Translation(double x, double y, double z) { this(new Vector3(x, y, z)); } @Override - public void apply(Vector3 vec) - { + public void apply(Vector3 vec) { vec.add(this.vec); } - + @Override - public void applyN(Vector3 normal) - { + public void applyN(Vector3 normal) { } @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.translate(vec); } - + @Override - public Transformation at(Vector3 point) - { + public Transformation at(Vector3 point) { return this; } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { + public void glApply() { GL11.glTranslated(vec.x, vec.y, vec.z); } - + @Override - public Transformation inverse() - { + public Transformation inverse() { return new Translation(-vec.x, -vec.y, -vec.z); } - + @Override public Transformation merge(Transformation next) { - if(next instanceof Translation) + if (next instanceof Translation) return new Translation(vec.copy().add(((Translation) next).vec)); - + return null; } - + @Override public boolean isRedundant() { return vec.equalsT(Vector3.zero); } - + @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Translation("+new BigDecimal(vec.x, cont)+", "+new BigDecimal(vec.y, cont)+", "+new BigDecimal(vec.z, cont)+")"; + return "Translation(" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ")"; } } diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java index 09d0a7f..944029b 100644 --- a/codechicken/lib/vec/Vector3.java +++ b/codechicken/lib/vec/Vector3.java @@ -4,6 +4,7 @@ import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.util.Copyable; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; import org.lwjgl.util.vector.Vector4f; @@ -17,7 +18,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; -public class Vector3 +public class Vector3 implements Copyable { public static Vector3 zero = new Vector3(); public static Vector3 one = new Vector3(1, 1, 1); diff --git a/codechicken/lib/world/ChunkExtension.java b/codechicken/lib/world/ChunkExtension.java index 1315e3a..0dc3c90 100644 --- a/codechicken/lib/world/ChunkExtension.java +++ b/codechicken/lib/world/ChunkExtension.java @@ -2,11 +2,11 @@ import java.util.HashSet; +import net.minecraft.network.Packet; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.packet.Packet; public abstract class ChunkExtension { @@ -42,7 +42,7 @@ public void unload() public final void sendPacketToPlayers(Packet packet) { for(EntityPlayerMP player : watchedPlayers) - player.playerNetServerHandler.sendPacketToPlayer(packet); + player.playerNetServerHandler.sendPacket(packet); } public final void watchPlayer(EntityPlayerMP player) diff --git a/codechicken/lib/world/WorldExtensionManager.java b/codechicken/lib/world/WorldExtensionManager.java index 536a190..97c3d02 100644 --- a/codechicken/lib/world/WorldExtensionManager.java +++ b/codechicken/lib/world/WorldExtensionManager.java @@ -5,17 +5,16 @@ import java.util.HashMap; import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.ITickHandler; -import cpw.mods.fml.common.TickType; -import cpw.mods.fml.common.registry.TickRegistry; +import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.EmptyChunk; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.ForgeSubscribe; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; @@ -26,7 +25,7 @@ public class WorldExtensionManager { public static class WorldExtensionEventHandler { - @ForgeSubscribe + @SubscribeEvent public void onChunkDataLoad(ChunkDataEvent.Load event) { if(!worldMap.containsKey(event.world)) @@ -38,7 +37,7 @@ public void onChunkDataLoad(ChunkDataEvent.Load event) extension.loadChunkData(event.getChunk(), event.getData()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkDataSave(ChunkDataEvent.Save event) { for(WorldExtension extension : worldMap.get(event.world)) @@ -48,7 +47,7 @@ public void onChunkDataSave(ChunkDataEvent.Save event) removeChunk(event.world, event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { if(!worldMap.containsKey(event.world)) @@ -60,7 +59,7 @@ public void onChunkLoad(ChunkEvent.Load event) extension.loadChunk(event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkUnLoad(ChunkEvent.Unload event) { if(event.getChunk() instanceof EmptyChunk) @@ -73,7 +72,7 @@ public void onChunkUnLoad(ChunkEvent.Unload event) removeChunk(event.world, event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onWorldSave(WorldEvent.Save event) { if(worldMap.containsKey(event.world)) @@ -81,14 +80,14 @@ public void onWorldSave(WorldEvent.Save event) extension.save(); } - @ForgeSubscribe + @SubscribeEvent public void onWorldLoad(WorldEvent.Load event) { if(!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); } - @ForgeSubscribe + @SubscribeEvent public void onWorldUnLoad(WorldEvent.Unload event) { if(worldMap.containsKey(event.world))//because force closing unloads a world twice @@ -96,7 +95,7 @@ public void onWorldUnLoad(WorldEvent.Unload event) extension.unload(); } - @ForgeSubscribe + @SubscribeEvent public void onChunkWatch(Watch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); @@ -104,82 +103,34 @@ public void onChunkWatch(Watch event) extension.watchChunk(chunk, event.player); } - @ForgeSubscribe + @SubscribeEvent + @SideOnly(Side.CLIENT) public void onChunkUnWatch(UnWatch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); for(WorldExtension extension : worldMap.get(event.player.worldObj)) extension.unwatchChunk(chunk, event.player); } - } - - public static class WorldExtensionClientTickHandler implements ITickHandler - { - @Override - public void tickStart(EnumSet type, Object... tickData) - { - if(type.contains(TickType.CLIENT)) - { - World world = Minecraft.getMinecraft().theWorld; - if(worldMap.containsKey(world)) - preTick(world); - } - } - @Override - public void tickEnd(EnumSet type, Object... tickData) + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void clientTick(TickEvent.ClientTickEvent event) { - if(type.contains(TickType.CLIENT)) - { - World world = Minecraft.getMinecraft().theWorld; - if(worldMap.containsKey(world)) + World world = Minecraft.getMinecraft().theWorld; + if (worldMap.containsKey(world)) + if (event.phase == TickEvent.Phase.START) + preTick(world); + else postTick(world); - } - } - - @Override - public EnumSet ticks() - { - return EnumSet.of(TickType.CLIENT); - } - - @Override - public String getLabel() - { - return "WorldExtenstions"; - } - } - - public static class WorldExtensionServerTickHandler implements ITickHandler - { - @Override - public void tickStart(EnumSet type, Object... tickData) - { - if(type.contains(TickType.WORLD)) - { - preTick((World)tickData[0]); - } } - @Override - public void tickEnd(EnumSet type, Object... tickData) + @SubscribeEvent + public void clientTick(TickEvent.WorldTickEvent event) { - if(type.contains(TickType.WORLD)) - { - postTick((World)tickData[0]); - } - } - - @Override - public EnumSet ticks() - { - return EnumSet.of(TickType.WORLD, TickType.CLIENT); - } - - @Override - public String getLabel() - { - return "WorldExtenstions"; + if(event.phase == TickEvent.Phase.START) + preTick(event.world); + else + postTick(event.world); } } @@ -199,11 +150,7 @@ private static void init() { initialised = true; MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); - TickRegistry.registerTickHandler(new WorldExtensionServerTickHandler(), Side.SERVER); - if(FMLCommonHandler.instance().getSide().isClient()) - { - TickRegistry.registerTickHandler(new WorldExtensionClientTickHandler(), Side.CLIENT); - } + FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); } private static HashMap worldMap = new HashMap(); From 0a5aee875b93f03b34d6ea9a07b0694ca375afd3 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Mon, 7 Apr 2014 14:04:01 +1000 Subject: [PATCH 063/219] Update version numbers --- mcversion.txt | 2 +- version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mcversion.txt b/mcversion.txt index 6463e95..0a182f2 100644 --- a/mcversion.txt +++ b/mcversion.txt @@ -1 +1 @@ -1.6.4 \ No newline at end of file +1.7.2 \ No newline at end of file diff --git a/version.txt b/version.txt index afaf360..1cc5f65 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0.0 \ No newline at end of file +1.1.0 \ No newline at end of file From 99865de25579838b6fec349af20274a0fac92822 Mon Sep 17 00:00:00 2001 From: Progwml6 Date: Mon, 7 Apr 2014 01:57:55 -0400 Subject: [PATCH 064/219] added gradle build script & other things needed to build --- .gitignore | 33 +++++ build.gradle | 155 +++++++++++++++++++++ build.properties | 3 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 51106 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++++++++++++++++++++++ gradlew.bat | 90 +++++++++++++ settings.gradle | 19 +++ 8 files changed, 470 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 build.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..46eb940 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +#ant stuff +/bin/ +#Remove OS generated garbage +*/.DS_Store +.DS_Store +.DS_Store? +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db +#gradle stuff +/.gradle +/build/ +/run/ +#IDEA files from Gradle +.idea/ +/*.iml +/*.ipr +/*.iws +#Vim backups +*~ +#eclipse stuffs +/.classpath +/.project +/.settings/ +/debug/ +*.lock +/.metadata/ +/config/ +/logs/ +options.txt +/saves/ \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..079610c --- /dev/null +++ b/build.gradle @@ -0,0 +1,155 @@ +// This sets us up for building a forge project - you need all of these +buildscript { + repositories { + mavenCentral() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' + } +} + +// Apply the forge plugin - this adds all the magic for automatically obfuscating, deobfuscating etc +apply plugin: 'forge' + +// This is our group +group = "codechicken" // http://maven.apache.org/guides/mini/guide-naming-conventions.html +// This is our actual project within the group. +archivesBaseName = "CodeChickenLib" + +// Define properties file +ext.configFile = file "build.properties" + +configFile.withReader { + // Load config. It shall from now be referenced as simply config or project.config + def prop = new Properties() + prop.load(it) + project.ext.config = new ConfigSlurper().parse prop +} + +version = "${project.config.mod_version}." + System.getenv("BUILD_NUMBER") ?: "1" + +println config.minecraft_version + "-" + config.forge_version +// Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here +minecraft { + version = config.minecraft_version + "-" + config.forge_version +} + + +// this sets our output jar to have a 'tag' of 'universal' on it +// It also adds the minecraft version in a custom version name +// The result is files named ---universal.jar +jar { + classifier = 'universal' + version = "${project.minecraft.version}-${project.version}" + /*manifest { + attributes 'Main-Class': 'codechicken.lib.tool.Main' + }*/ + +} + +sourceSets { + main { + java { + srcDir '/' + include 'CodeChicken/**/*' + } + } +} + + +// Add in a source jar for people, should they desire to download such a thing +task sourceJar(type: Jar) { + from sourceSets.main.allSource + classifier = 'src' + version = "${project.minecraft.version}-${project.version}" +} + +// Add in an mcp named jar, for those who wish to run in a development environment (assuming mcp naming matches) +task deobfJar(type: Jar) { + from sourceSets.main.output + classifier = 'dev' + version = "${project.minecraft.version}-${project.version}" + /*manifest { + attributes 'Main-Class': 'codechicken.lib.tool.Main' + }*/ + +} + +// Tell the artifact system about our extra jars +artifacts { + archives sourceJar, deobfJar +} + +// Configure an upload task. this is setup for uploading to files.minecraftforge.net. There are other examples around +uploadArchives { + dependsOn 'reobf' + repositories { + if (project.hasProperty("filesmaven")) { + logger.info('Publishing to files server') + + mavenDeployer { + configuration = configurations.deployJars + + repository(url: project.filesmaven.url) { + authentication(userName: project.filesmaven.username, privateKey: project.filesmaven.key) + } + + // This is just the pom data for the maven repo + pom { + groupId = project.group + // Force the maven upload to use the - syntax preferred at files + version = "${project.minecraft.version}-${project.version}" + artifactId = project.archivesBaseName + project { + name project.archivesBaseName + packaging 'jar' + description 'CodeChickenLib' + url 'https://github.com/Chicken-Bones/CodeChickenLib' + + scm { + url 'https://github.com/Chicken-Bones/CodeChickenLib' + connection 'scm:git:git://github.com/Chicken-Bones/CodeChickenLib.git' + developerConnection 'scm:git:git@github.com:Chicken-Bones/CodeChickenLib.git' + } + + issueManagement { + system 'github' + url 'https://github.com/Chicken-Bones/CodeChickenLib/issues' + } + + licenses { + license { + name 'GNU Lesser Public License (GPL), Version 2.1' + url 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt' + distribution 'repo' + } + } + + developers { + developer { + id 'chicken-bones' + name 'chicken-bones' + roles { role 'developer' } + } + } + } + } + } + } else { + logger.info('Publishing to repo folder') + + mavenDeployer { + pom.version = "${project.minecraft.version}-${project.version}" + repository(url: 'file://localhost/' + project.file('repo').getAbsolutePath()) + } + } + } +} \ No newline at end of file diff --git a/build.properties b/build.properties new file mode 100644 index 0000000..f4a818c --- /dev/null +++ b/build.properties @@ -0,0 +1,3 @@ +minecraft_version=1.7.2 +forge_version=10.12.0.1054 +mod_version=1.6.0 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..3c7abdf12790879c06b07176de29647f77aa4129 GIT binary patch literal 51106 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

CflOl1i4(-2^1KXo)&I5QlgjRKFQgM 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 z zP_KwBCnXDLTSTI9$@zwgB(mp+)3lmOadZUKrV}r{V0`rAEHnwtTEst z{4z0MSwpdQle8@5Cr`lrN1_3bylt;)N9&*~)gHbkdj(`lYv4CIH6^j#3e+ZN*%r4p zZg$33*(p2*DA2_e+L+R85%=iUhDr-Ak=`KHpT6$$)x0z)t*Wza(?xB!Uz?RtEWN@j zf{`@lyD5Z42Y)%{=&Gwb2}W~lWv>b>)MjtCk*UE$ZcCZ&<7y#k9%H8r=Ii#}wD+9> z5&9`Cth7|LQFxV41b(DYezS@klgX;JxGI$xqv)ubwbFxi3}wTj^1*&ORQ>_^3YtUe zM!K5(sy9qL^?RqS@`KaD+8`s1CUVtJAqqdr@QW5PKGAg7v}bjvyUQrxv_p2MJ8e!2 zh_m#N@=Y2uW;mEd%>!>Bgr;dq@CLYneRnDu$Aed*H~6=rDE^7nyoTr=V&w&irh}Ql z4v{;o(x~nPx*ECV+QP&ciGt8*HMbDgk^}lT>Mmb%R3tlI3Q4b{-JMEp(6J)Y@9mrF z(Wf2Dh&=`H0>yiF9zJj}(=ye&amdHeww4(t`eEi0G`v-3712txxwF(459yYM74O^< zT1VQn3LZ-B%|%4~oMmV)pZLU?(Xr?D68Vg-ih6_0j<`1mHS@K@ks$NTCpJAMT=QcR z{XB@n+n^nOl`Wz-`e*dQx_xPmpNa$hH+PI5#e4mVYTq@~(PXOcF#(FG%4Ld26dNp- zL%G#_&KHwUE8o1T)`Zn1BfBs#5VKhvH=0`IFUf=raf;WE#rgsleAsulIiBw-v)cWJ z>pANb$6ne-^PTKbh>P63e!xC6faID_UfUh9N9xrR4=5itQxpOcfl4*-i_) z_bowR)7#XH=bMxVIQ=TNlQUBm>nJZen)M9TMlSsvRUf$MQO+BDNZY`A`?6smIS2&K zt0@h&9Y52chtkO!u6fLIaQN53Hy90}I!}Z2xSFdBxB+!=-)gIz@Xhba4uQV=Yloa* z3=*mcYpoKFyw=+EMxRr9pU-vT-+s^Nl=)n$MogGa-KKA~%}!IVW_Thy>q+Fy4LDES z^VEVd=IQiDX;K(Bm19Z|pUe=jL~k@;PTOY*zSR@EgO9x*0czd(#7XPWS;WD;Bhgj^ z#iW^FLvX8146_iq8?4h@j2bP>2Wv2}(I=93K^#W16`xO#z!Nmaj_t(#v$=6AtbCw{ zH)k-xlFF6WV9F$G{0^fgbEx88x4x}?ewA}_lXG)3lGDSy)uVc|lQFweIf+wSxaeX*WRPsMr2-`c z6$DvDb&RIc+{ZY^0r}Ld5*hdqZkbxTrE775-x4#H#T~w6I-@1c-^a((_K0T|X);1v z-FF4HVh`GV*jaU;#UpTR_xyep%AfVIh3{ko=@B}zGFmcKOqw~erE8;316`_>)_jBi zGPm-|o3UXle#Aqv0-yxvWRh<5@hdJBgHrEem^3VHpX)))^5q$XR0T-jU@i|j7x*$~ z5o9ouEmXE-BlOY-6^)J(<`9g0nN`l;5fpM1$-vTr5zS%D;DN#_Iee3|6<>}4+z+jl%JPEgyQ8G*%XGEL08BhdLkVKl5_0HP!}%zd+RHFA$~r&p`BFzrXz( zj{a9}{=fKaaG(EzqJ0`K6Q|Ax<8n5j2NaQ!>NtV~0yYpBnI z`Q8`;9z~*~@V2UnVos;_L7hAbg3v3N(O0@R^$~^BSG{NT(H&vGlMNirG4AQQ6E9$!mm#z6wU|49Xemsf z(%R#1V1H|1lFuKn>?%ov+2jtP(%d2s@%AxIX{Uo2NgBKFa*$wny#hZ1>zRwWa){iC zn*2z!U_Ljh1e8To%8H!Z@Kn)`$Y*r!>>P%=b1w7R)kMgfTI|yc(g#$v3HM9-HoI1v zdARCT15Kf6yvtSEpkoS=c}RWq08Bk?PLmA%Iz2H71#pB(wu@hEr;>A93iGp}Kw;K` z2knL#8IqTiGzHhy140FtH8~uTgx!XEo57F96gzU^QxO!vx5IW=VVaX$Ox*+LJeygy zKK{zJ0!brte1+b2>|md?b9rfGL)_3k1Mm=3{fho1=>>-ai`B{L z_ocFO$s}a8H8q>_y^NQPYrLbVC7q!?z3bv+HA|@Za!X1Bq*0A)q~s9XEjBg|e`@n{ zk!Rq@n(T#|vl^wTAd)EIQH6 zVAzzfiu0)jOCxPz_WPSE&C3|goIfia+FgrBSD7W!tUlnos&~AwyJPSmvp@Wef>uCl0}3`iJaLepUPKZ$153@d0?h zQt0r|Ii`#oc6pLwvOZ9h7j!ub_s`oEwXWeu%qFifR<74~R3;_r>ot>ZQ;#Ua)8JD9!Z|QWU6Wd{(tpDVU$5e6(WzAl39)vMf90jjz)Fu8Z}&4ktSqJlhbSr zN!%wfAsS1>BD*Z5=)1J6fIKw<6^QHW#bmirKpC7WG5=Fwp(9^%VzE5mY#G{k5T?;3 zyp);&A-Zk`cTP#X>?K#}Dy=9IhtoM5v5{GhOnn>)D7!p$7-UF(+)2ZJ3N=HFHB9B@ zx(35ZQ$Qn4kv5A$n3H`#39Bcnid-dHM3yO{uqR|>5-mh=t`e$XH5)NnYCNh!k;()4 zjV4;XFsy07Tm4!N{G^kYanfr9eQcA&YagxhVk26;BGRNWHjPXuTD>|9wpAVx%f!0a zC^L3=lIS~enGAE6sB>>;=*b;Ct7d98(lOrjlM7@-qCO|5Xdu?O$J*poxtb|S9#ibg zweZm1crG_)wuq*DlHHi8SsP=+n{kQT42GMbyVay?+=E=T2|ZLy zCUe~bC?Xy2VCo{ZwMIUzk_sFyDD`x+?pmN&#kvyshQkM${C$ScA8GGe?F={X7dP=< zy$ABLBhd_(MS5g;txLYjq}*vRg+Tbia{%`RctHdIHK2g!#_i(PrVXy)mCQ5G_=j5 zTk1oU*U7R$OY7WLY2q6^X%ygC&RLB3S*(RH<&ijZo|#XYi>kU1Yc*sbD6Dz&-0QrZ zPQ6AkDPF1`7cNW#P%vIgF3akxq%E6P+mdwMe9xMT3rB5qaupg>dBZPkJe;m|H;?%4 z4^49_dkhZG%b=^9ILWYsJj_2TH-<<9sV!bQ#ln;kz*;-IvXY=aPZgd=goXHg$F|sZ+kHg8JZLEx4%B>YKD6D@#<3eZPS`V>XA3 zZ!cdbcyOcDe>{SiY5iGzb*Aq!Oyr*sq0WrOVfD>y+USxfojl-=M`eb%InudDZ!jzy z-Kh)M8Hepp1e`KSm}Daq>{%(W;+bSSrS`4?G=`1$DwusP zt@zNV>mFtE7V`s%B)>>zWgxO9(~fVk5?wSCA;({AimK3OnO2cF%`aP=Y19I()OHWW;nV89~82VT)!lobw9n7nqHtrHh!L~X9N_etyK)DWpzqge$Y zxe;bF4y~L)r*gACxq!2NO=3Au8c9=bOaZqJ@!;mPXtZ`%Fi<{Uc?L3bum{{Tt)%z8 zdR+))n4n%Hbj&HzTBtWyPga>u5xO#?3IM zp*chnhg0yu1$JC_c*JK44J?x}LC;K#{a zG~TZ>*kD`n0G!H9SThD9o9>^pq|+Utg}{7-L|FBy;;iW=%CFB2hSWH^OpB}G+ZFvVa~l|KcrrlklNSW~l$ zM7Du*YFGkP=%!o8%39ZoPm`-CHPT~dcJ_XY@2$~i_#YUX>q!y;p~B(#0j;a9>t|m# zkLyVSKfQOjUTp2`Ag+sjQ+{^djR$bV{%-{E;PTJA{; zvDtk#L_ki2CJ;sw3K|f_dkDC+2w-+NU{w(k`vL*rP}$iO0a3MT>s)WLN6Y){+>m-r8?083w~5 ztZEVwUfPGGIkODtcaUu^WSRbo-jNA@%?zJ()LMRoq^MGjQTgkkV|$x1Pw9Y~2tnGcaceyobo>R4F0?FBRY@Ffmrr zD?))W0cfTX*Ei@683@ZvVFi;;zoTSlj(AE?NZZLI^Ks7}Ir?B?VaDIubdwSDDACyT z+*rs=lr5#5hbz87X__z}Yc4ts)S^_BDO_pZR2_?!TJ~VY*#>7TKyA)Y7?3(M^-ghq zt4c+nFLg(vFLVC0RIVQ6i3Yb3Sf>f#>Xd<0VwZQo&HzJ~t-mPlXWd^{Y)49H4p+M= z4`06FGAZlhs@{X0UfzX6v)ii-Z)x?&FuC5*`DQ09)PRR}y<3TJUGee-tb*H=k!;}t zqF(HO0KU%k0OT(VA=Ap<(e%pRVKvI$QFh)hssIn~;{hucLwonMu7$k|nip_a#azg0>rO_mT;5g3dCG^CoDm_L9M(ARK)(*%qovJah8j1B zZf84{aAJc<&yJGq(1zGfFBTw5DoScbR6%GTxRa@o)$wUuCl9_MH8Jt7CXcHI)8Q>C z@}AyhO7m#F#V5x(9^g-&mh_s>mdeZlTGOkCMr`yvL^o0+RV*UU#g7hKy*N%sz7d%g zQJ^HDNIxM43JWOWnA3zRK4DIy7QKqe!eOqoSLt$h~j)Vja1@{;Qbd7ZDC{k*!; z*SS5;Gi*=n->f0!K9uyApO8r@Xp6R3+J>K`p8+m&8YG3fgJ^`5&{yeYEu4JDng(JOD?BQs1ge7XU zgeA>;V{{i%8N*DRL35{%Zw7r<(2}weIC)m8Fdd4x1;Xyjfpi{@M~RY9Fq+75j`inMft)SsCP)ZM;CMfuCnE@vFP;>mS>|oy@V^#2&{67E9n&_ffmA&B`5RfVe5D>?I&sh9RR~w0posogHh{cz* zz{1ew|Fy3tDQZdMe0ldwnQksRFSd4>pVLbEgszXPo@OW_7Rf_WQSiO!b7#Pgjb{8&XciIf&)@)S5@|(?HPT=B07j>)I zPEnJjV%_i5Nh;gJGpJ$o@YZ(bS?3{cefQ8pKFXj<2nnbVIaBHr5L%hgBH~5SO!HQD zj#B9Nzr?HcsfriOyNg8h9$_kbR_dGMxpU2Lit>|qu`v)w_e;6(q>7sC=%BvGwOcgK z%sc?ujBkg!KL11IjjE;(IpY@C+C$37h+w-D&i=JENKggzar8ThU zW*{P=*@AJs_P_V)g-^bCP2BX~{;{F4pE6_juMlHBD1@BztG&?^4hV?wzh4OdYEc!W zYN3VmB|86-JI=DzzlyY2IBdJ_RC za+iSXjgSa)FdsMB8Gao5j*D(5KinT4O%xB^8jrM-1Va4E!Nr}TqP1|ZKAKH?773t& z_eBL2y}@92m+niql7-Npzd(0m`+u@;;^dvzSiH1Hr`*Ef)$C+oiyiD~Ic`@d-jxU2 zS-Hy&xUqPv4Lq}W>kXV!`R4A2xC;X^sC*0ehM{wNB{Y)l$)JnRq16QS-pbFz_9Bf^ z0{0Jt##fUn$j7$oYdgJ{9<0R$olT!6m>UvKA6~=Ej*I1}w zQ^9(Ud*s);jkzX^rQkBFAr_?I6%%F7COnx`=x1<}wUAqBMZ6Z(6E_d+m#oIe#x-d# z3iNebwkO|+9h)jGD&Ieylz9ujSd^R69Ydzn6=<~}4`kYRb*en#ZCX|c1cP9}mWtDvG&dj73EFgF;M2F_TtkXQDCvZjLvi zAH5*EsCSm?&nZyrxS%|#K6EO+NE*Y>!!V883K$H1y;?&~Vl@n_lu70W_BeA}x=>Or z@Q6Gx9tWF8amvu3I+1!{uRzNJU9=QQ!8r;_N=RC3uPZI*IxF{-T)h%Q6SHnnaPJ?b zo7Y&QGP9-3(H0nKo8p))S~h+*IRRA1=7=J2bVb{iPpn>17F?1!oG|9+=kjFrYRwA^vF_f z{BwJJ7lG=J`Hs%VXs<>lG3Xs{un(~E$7-*h{Y0;xgD^lAF&D`mOT;*Ipcz%A?>?2ftXQJ?Ttx$ z@c=K*`O~D4`nAyR9zc7`;rEuC>%3r72qmNk8-ibeK^K$@$(3F3t;l_`qFj~b^t~8j zm8Y6Qt(R6PEnZ1STkvM^%0zg|*hQm@ZocxN zXgf)?gLgc2f|t9Fz;Q2C;;+7SNLbiSF&MSJjP8IE4p-r=uqTEUU6C6GdinR0YK$-M zmraJ@`IlBdo3n=j%0DvTus6fLI&f~`9YxjD=W5pR41LBYQt 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..244a668 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Mar 26 13:33:58 CDT 2014 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +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" + which java >/dev/null 2>&1 || 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 + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@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 + +@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= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +: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 %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="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! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..398e21f --- /dev/null +++ b/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'sunstrike' at '21/11/13 14:14' with Gradle 1.9 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'CodeChickenLib' From 4babca7004022e851c6ff7f37ac0c1f87a3f6f3c Mon Sep 17 00:00:00 2001 From: Progwml6 Date: Mon, 7 Apr 2014 02:01:46 -0400 Subject: [PATCH 065/219] remove files from old build system, update version #, manifest now via gradle --- MANIFEST.MF | 2 -- build.gradle | 8 ++++---- build.properties | 2 +- mcversion.txt | 1 - version.txt | 1 - 5 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 MANIFEST.MF delete mode 100644 mcversion.txt delete mode 100644 version.txt diff --git a/MANIFEST.MF b/MANIFEST.MF deleted file mode 100644 index 9915f07..0000000 --- a/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: codechicken.lib.tool.Main diff --git a/build.gradle b/build.gradle index 079610c..efa5cca 100644 --- a/build.gradle +++ b/build.gradle @@ -49,9 +49,9 @@ minecraft { jar { classifier = 'universal' version = "${project.minecraft.version}-${project.version}" - /*manifest { + manifest { attributes 'Main-Class': 'codechicken.lib.tool.Main' - }*/ + } } @@ -77,9 +77,9 @@ task deobfJar(type: Jar) { from sourceSets.main.output classifier = 'dev' version = "${project.minecraft.version}-${project.version}" - /*manifest { + manifest { attributes 'Main-Class': 'codechicken.lib.tool.Main' - }*/ + } } diff --git a/build.properties b/build.properties index f4a818c..8779295 100644 --- a/build.properties +++ b/build.properties @@ -1,3 +1,3 @@ minecraft_version=1.7.2 forge_version=10.12.0.1054 -mod_version=1.6.0 +mod_version=1.1.0 diff --git a/mcversion.txt b/mcversion.txt deleted file mode 100644 index 0a182f2..0000000 --- a/mcversion.txt +++ /dev/null @@ -1 +0,0 @@ -1.7.2 \ No newline at end of file diff --git a/version.txt b/version.txt deleted file mode 100644 index 1cc5f65..0000000 --- a/version.txt +++ /dev/null @@ -1 +0,0 @@ -1.1.0 \ No newline at end of file From 4699a9e86e5619676b738731367fa3141daf879e Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Mon, 7 Apr 2014 23:13:05 +1000 Subject: [PATCH 066/219] Add MCP mapper for ObfMapping in dev environments from a fields/methods.csv conf directory --- codechicken/lib/asm/ObfMapping.java | 147 ++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 8 deletions(-) diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index 0aabd5a..5945248 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -1,11 +1,18 @@ package codechicken.lib.asm; +import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import codechicken.lib.config.ConfigFile; +import codechicken.lib.config.ConfigTag; +import com.google.common.base.Charsets; +import com.google.common.io.LineProcessor; +import com.google.common.io.Resources; +import cpw.mods.fml.relauncher.FMLInjectionData; import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.MethodVisitor; @@ -21,6 +28,8 @@ import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import javax.swing.*; + public class ObfMapping { public static class ObfRemapper extends Remapper @@ -37,16 +46,16 @@ public ObfRemapper() { Map> rawFieldMaps = (Map>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); Map> rawMethodMaps = (Map>) rawMethodMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); - if(rawFieldMaps == null) + if (rawFieldMaps == null) throw new IllegalStateException("codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); - for(Map map : rawFieldMaps.values()) - for(Entry entry : map.entrySet()) - if(entry.getValue().startsWith("field")) + for (Map map : rawFieldMaps.values()) + for (Entry entry : map.entrySet()) + if (entry.getValue().startsWith("field")) fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':'))); - for(Map map : rawMethodMaps.values()) - for(Entry entry : map.entrySet()) - if(entry.getValue().startsWith("func")) + for (Map map : rawMethodMaps.values()) + for (Entry entry : map.entrySet()) + if (entry.getValue().startsWith("func")) funcs.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf('('))); } catch (Exception e) { @@ -72,9 +81,129 @@ public String map(String typeName) { } } + public static class MCPRemapper extends Remapper implements LineProcessor + { + public static ConfigFile config; + + public static File[] getConfFiles() { + if (config == null) + config = new ConfigFile(new File((File) FMLInjectionData.data()[6], "config/CodeChickenLib.cfg")).setComment("CodeChickenLib configuration file."); + + ConfigTag tag = config.getTag("dev.mappingDir").setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping"); + for (int i = 0; i < 6; i++) { + File dir = confDirectoryGuess(i, tag); + if (dir == null || dir.isFile()) + continue; + + File[] mappings; + try { + mappings = parseConfDir(dir); + } catch (Exception e) { + if (i >= 3) + e.printStackTrace(); + continue; + } + + tag.setValue(dir.getPath()); + return mappings; + } + + throw new RuntimeException("Failed to select mappings directory, set it manually in the config"); + } + + public static File confDirectoryGuess(int i, ConfigTag tag) { + File mcDir = (File) FMLInjectionData.data()[6]; + switch (i) { + case 0: + return tag.value != null ? new File(tag.getValue()) : null; + case 1: + return new File(mcDir, "../conf"); + case 2: + return new File(mcDir, "../build/unpacked/conf"); + default: + JFileChooser fc = new JFileChooser(mcDir); + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fc.setDialogTitle("Select an mcp conf dir for the deobfuscator."); + int ret = fc.showDialog(null, "Select"); + return ret == JFileChooser.APPROVE_OPTION ? fc.getSelectedFile() : null; + } + } + + public static File[] parseConfDir(File confDir) { + File srgDir = new File(confDir, "conf"); + if (!srgDir.exists()) + srgDir = confDir; + + File srgs = new File(srgDir, "packaged.srg"); + if (!srgs.exists()) + srgs = new File(srgDir, "joined.srg"); + if (!srgs.exists()) + throw new RuntimeException("Could not find packaged.srg or joined.srg"); + + File mapDir = new File(confDir, "mappings"); + if (!mapDir.exists()) + mapDir = confDir; + + File methods = new File(mapDir, "methods.csv"); + if (!methods.exists()) + throw new RuntimeException("Could not find methods.csv"); + File fields = new File(mapDir, "fields.csv"); + if (!fields.exists()) + throw new RuntimeException("Could not find fields.csv"); + + return new File[]{srgs, methods, fields}; + } + + private HashMap fields = new HashMap(); + private HashMap funcs = new HashMap(); + + public MCPRemapper() { + File[] mappings = getConfFiles(); + try { + Resources.readLines(mappings[1].toURI().toURL(), Charsets.UTF_8, this); + Resources.readLines(mappings[2].toURI().toURL(), Charsets.UTF_8, this); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public String mapMethodName(String owner, String name, String desc) { + String s = funcs.get(name); + return s == null ? name : s; + } + + @Override + public String mapFieldName(String owner, String name, String desc) { + String s = fields.get(name); + return s == null ? name : s; + } + + @Override + public boolean processLine(String line) throws IOException { + int i = line.indexOf(','); + String srg = line.substring(0, i); + int i2 = i + 1; + i = line.indexOf(',', i2); + String mcp = line.substring(i2, i); + (srg.startsWith("func") ? funcs : fields).put(srg, mcp); + return true; + } + + @Override + public Void getResult() { + return null; + } + } + public static ObfRemapper obfMapper = new ObfRemapper(); public static Remapper mcpMapper = null; + public static void loadMCPRemapper() { + if (mcpMapper == null) + mcpMapper = new MCPRemapper(); + } + public static final boolean obfuscated; static { @@ -83,6 +212,8 @@ public String map(String typeName) { obf = Launch.classLoader.getClassBytes("net.minecraft.world.World") == null; } catch (IOException ignored) {} obfuscated = obf; + if (!obf) + loadMCPRemapper(); } public String s_owner; @@ -223,7 +354,7 @@ public boolean isField() { } public ObfMapping map(Remapper mapper) { - if(mapper == null) + if (mapper == null) return this; if (isMethod()) From 91c65cf1dcd929a4dc8aad316f54905b1b5f6481 Mon Sep 17 00:00:00 2001 From: Soaryn Date: Tue, 8 Apr 2014 03:18:16 -0400 Subject: [PATCH 067/219] Fixes access to TextureUtil.uploadTextureSub Since TextureUtil.uploadTextureMipmap is private, I used the next available function which does the same thing with a needless for loop in our case. It, however, is public static :) --- codechicken/lib/render/TextureSpecial.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java index 3fe2beb..5d2ee55 100644 --- a/codechicken/lib/render/TextureSpecial.java +++ b/codechicken/lib/render/TextureSpecial.java @@ -65,7 +65,8 @@ public void updateAnimation() { if (textureFX != null) { textureFX.update(); if (textureFX.changed()) - TextureUtil.uploadTextureSub(0, textureFX.imageData, width, height, originX, originY, false, false, false); + //TextureUtil.uploadTextureSub(0, textureFX.imageData, width, height, originX, originY, false, false, false); not accessible + TextureUtil.uploadTextureMipmap(new int[][]{textureFX.imageData}, width, height, originX, originY, false, false); } } From 4e87c9bfe76803e4a8ee4aecf0e5e7159ec0841c Mon Sep 17 00:00:00 2001 From: Progwml6 Date: Tue, 8 Apr 2014 03:54:33 -0400 Subject: [PATCH 068/219] make gradle play nice w/ files in the repo root --- build.gradle | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index efa5cca..359951a 100644 --- a/build.gradle +++ b/build.gradle @@ -54,17 +54,15 @@ jar { } } - sourceSets { main { java { - srcDir '/' - include 'CodeChicken/**/*' - } + srcDir "\\" + include 'codechicken\\**\\*.java' + } } } - // Add in a source jar for people, should they desire to download such a thing task sourceJar(type: Jar) { from sourceSets.main.allSource From 41997e15e9a0bf7aa7ffa99f4d96225a5f3612da Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 9 Apr 2014 13:20:40 +1000 Subject: [PATCH 069/219] Replace private minecraft accesses with alternatives until transformers are accepted by forge. --- codechicken/lib/packet/PacketCustom.java | 9 ++++++++- codechicken/lib/render/TextureSpecial.java | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index 5d4e531..463454d 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -34,6 +34,7 @@ import net.minecraft.network.play.INetHandlerPlayClient; import net.minecraft.network.play.INetHandlerPlayServer; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.PlayerManager; import net.minecraft.server.management.PlayerManager.PlayerInstance; import net.minecraft.world.World; import net.minecraft.world.WorldServer; @@ -523,9 +524,15 @@ public void sendToChunk(World world, int chunkX, int chunkZ) { } public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) { + PlayerManager playerManager = ((WorldServer)world).getPlayerManager(); + for (EntityPlayerMP player : (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + if(playerManager.isPlayerWatchingChunk(player, chunkX, chunkZ)) + sendToPlayer(packet, player); + + /* Commented until forge accepts access tranformer request PlayerInstance p = ((WorldServer) world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); if (p != null) - p.sendToAllPlayersWatchingChunk(packet); + p.sendToAllPlayersWatchingChunk(packet);*/ } public void sendToOps() { diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java index 5d2ee55..777749a 100644 --- a/codechicken/lib/render/TextureSpecial.java +++ b/codechicken/lib/render/TextureSpecial.java @@ -65,7 +65,6 @@ public void updateAnimation() { if (textureFX != null) { textureFX.update(); if (textureFX.changed()) - //TextureUtil.uploadTextureSub(0, textureFX.imageData, width, height, originX, originY, false, false, false); not accessible TextureUtil.uploadTextureMipmap(new int[][]{textureFX.imageData}, width, height, originX, originY, false, false); } } From 2d9f409c7d2aaff599d962a124148e0b2da5a36e Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 9 Apr 2014 13:38:05 +1000 Subject: [PATCH 070/219] Organised imports --- codechicken/lib/asm/ASMHelper.java | 25 ++++++----------- codechicken/lib/asm/ASMReader.java | 18 +++---------- codechicken/lib/asm/ClassHeirachyManager.java | 15 +++++------ codechicken/lib/asm/InsnListPrinter.java | 27 ++++--------------- .../lib/asm/InstructionComparator.java | 19 ++----------- codechicken/lib/asm/ObfMapping.java | 27 +++++++------------ codechicken/lib/colour/Colour.java | 6 ++--- codechicken/lib/colour/CustomGradient.java | 7 +++-- codechicken/lib/config/ConfigFile.java | 7 +---- codechicken/lib/config/ConfigTag.java | 6 ++--- codechicken/lib/config/ConfigTagParent.java | 6 +---- codechicken/lib/config/SimpleProperties.java | 6 +---- codechicken/lib/data/MCDataInput.java | 2 +- codechicken/lib/data/MCDataOutput.java | 2 +- .../lib/data/MCOutputStreamWrapper.java | 8 +++--- codechicken/lib/gui/GuiDraw.java | 21 +++++++-------- codechicken/lib/inventory/InventoryUtils.java | 3 +-- codechicken/lib/inventory/ItemKey.java | 5 ++-- codechicken/lib/lighting/LightMatrix.java | 1 - codechicken/lib/lighting/LightModel.java | 3 --- codechicken/lib/packet/PacketCustom.java | 4 --- codechicken/lib/raytracer/RayTracer.java | 6 ++--- codechicken/lib/render/CCModel.java | 26 ++++++------------ codechicken/lib/render/CCModelLibrary.java | 6 +---- codechicken/lib/render/CCRenderPipeline.java | 4 +-- codechicken/lib/render/FontUtils.java | 3 +-- codechicken/lib/render/RenderUtils.java | 23 +++++++--------- codechicken/lib/render/ShaderProgram.java | 10 +++---- .../lib/render/SpriteSheetManager.java | 7 +++-- codechicken/lib/render/TextureSpecial.java | 6 ++--- codechicken/lib/render/TextureUtils.java | 23 +++++++--------- codechicken/lib/render/Vertex5.java | 8 +++--- codechicken/lib/tool/LibDownloader.java | 4 ++- codechicken/lib/vec/BlockCoord.java | 2 +- codechicken/lib/vec/Cuboid6.java | 8 +++--- codechicken/lib/vec/Matrix4.java | 11 ++++---- codechicken/lib/vec/Quat.java | 5 ++-- codechicken/lib/vec/Rotation.java | 15 +++++------ codechicken/lib/vec/Scale.java | 9 +++---- codechicken/lib/vec/TransformationList.java | 6 ++--- codechicken/lib/vec/Translation.java | 9 +++---- codechicken/lib/vec/Vector3.java | 19 ++++++------- codechicken/lib/world/ChunkExtension.java | 10 +++---- codechicken/lib/world/WorldExtension.java | 6 ++--- .../lib/world/WorldExtensionInstantiator.java | 2 +- .../lib/world/WorldExtensionManager.java | 14 +++++----- 46 files changed, 167 insertions(+), 293 deletions(-) diff --git a/codechicken/lib/asm/ASMHelper.java b/codechicken/lib/asm/ASMHelper.java index d8f4e73..d4b03c1 100644 --- a/codechicken/lib/asm/ASMHelper.java +++ b/codechicken/lib/asm/ASMHelper.java @@ -1,26 +1,17 @@ package codechicken.lib.asm; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import codechicken.lib.asm.InstructionComparator.InsnListSection; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.LocalVariableNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.TryCatchBlockNode; +import org.objectweb.asm.tree.*; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - -import codechicken.lib.asm.InstructionComparator.InsnListSection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ASMHelper { diff --git a/codechicken/lib/asm/ASMReader.java b/codechicken/lib/asm/ASMReader.java index fd15f1e..ce1aa5b 100644 --- a/codechicken/lib/asm/ASMReader.java +++ b/codechicken/lib/asm/ASMReader.java @@ -1,5 +1,8 @@ package codechicken.lib.asm; +import com.google.common.collect.ImmutableMap; +import org.objectweb.asm.tree.*; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -7,21 +10,6 @@ import java.util.HashMap; import java.util.Map; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.IincInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.IntInsnNode; -import org.objectweb.asm.tree.JumpInsnNode; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.LdcInsnNode; -import org.objectweb.asm.tree.LineNumberNode; -import org.objectweb.asm.tree.MultiANewArrayInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - - -import com.google.common.collect.ImmutableMap; - import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.tree.AbstractInsnNode.*; diff --git a/codechicken/lib/asm/ClassHeirachyManager.java b/codechicken/lib/asm/ClassHeirachyManager.java index d04cb52..7fd93e1 100644 --- a/codechicken/lib/asm/ClassHeirachyManager.java +++ b/codechicken/lib/asm/ClassHeirachyManager.java @@ -1,14 +1,13 @@ package codechicken.lib.asm; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import org.objectweb.asm.tree.ClassNode; - import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; - import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.LaunchClassLoader; +import org.objectweb.asm.tree.ClassNode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; /** * This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed evaluation up slightly by automatically caching superclasses when they are first loaded. @@ -67,11 +66,9 @@ public static String unKey(String name) } /** - * Returns true if clazz extends, either directly or indirectly, superclass. * @param name The class in question * @param superclass The class being extended - * @param bytes The bytes for the class. Only needed if not already defined. - * @return + * @return true if clazz extends, either directly or indirectly, superclass. */ public static boolean classExtends(String name, String superclass) { diff --git a/codechicken/lib/asm/InsnListPrinter.java b/codechicken/lib/asm/InsnListPrinter.java index 5c72282..5c3c078 100644 --- a/codechicken/lib/asm/InsnListPrinter.java +++ b/codechicken/lib/asm/InsnListPrinter.java @@ -1,30 +1,13 @@ package codechicken.lib.asm; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.HashMap; - +import codechicken.lib.asm.InstructionComparator.InsnListSection; import org.objectweb.asm.Label; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.FrameNode; -import org.objectweb.asm.tree.IincInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.IntInsnNode; -import org.objectweb.asm.tree.InvokeDynamicInsnNode; -import org.objectweb.asm.tree.JumpInsnNode; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.LdcInsnNode; -import org.objectweb.asm.tree.LineNumberNode; -import org.objectweb.asm.tree.LookupSwitchInsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MultiANewArrayInsnNode; -import org.objectweb.asm.tree.TableSwitchInsnNode; -import org.objectweb.asm.tree.TypeInsnNode; -import org.objectweb.asm.tree.VarInsnNode; +import org.objectweb.asm.tree.*; import org.objectweb.asm.util.Textifier; -import codechicken.lib.asm.InstructionComparator.InsnListSection; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; public class InsnListPrinter extends Textifier { diff --git a/codechicken/lib/asm/InstructionComparator.java b/codechicken/lib/asm/InstructionComparator.java index 3d4b07c..9e516b1 100644 --- a/codechicken/lib/asm/InstructionComparator.java +++ b/codechicken/lib/asm/InstructionComparator.java @@ -1,29 +1,14 @@ package codechicken.lib.asm; +import org.objectweb.asm.tree.*; + import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.IincInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.IntInsnNode; -import org.objectweb.asm.tree.JumpInsnNode; -import org.objectweb.asm.tree.LabelNode; -import org.objectweb.asm.tree.LdcInsnNode; -import org.objectweb.asm.tree.LineNumberNode; -import org.objectweb.asm.tree.LookupSwitchInsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.TableSwitchInsnNode; -import org.objectweb.asm.tree.TypeInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - import static org.objectweb.asm.tree.AbstractInsnNode.*; -import codechicken.lib.asm.ObfMapping; - public class InstructionComparator { public static class InsnListSection diff --git a/codechicken/lib/asm/ObfMapping.java b/codechicken/lib/asm/ObfMapping.java index 5945248..3f8d85d 100644 --- a/codechicken/lib/asm/ObfMapping.java +++ b/codechicken/lib/asm/ObfMapping.java @@ -1,34 +1,25 @@ package codechicken.lib.asm; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - import codechicken.lib.config.ConfigFile; import codechicken.lib.config.ConfigTag; import com.google.common.base.Charsets; +import com.google.common.base.Objects; import com.google.common.io.LineProcessor; import com.google.common.io.Resources; +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.relauncher.FMLInjectionData; import net.minecraft.launchwrapper.Launch; - import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.FieldNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.TypeInsnNode; - -import com.google.common.base.Objects; - -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import org.objectweb.asm.tree.*; import javax.swing.*; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; public class ObfMapping { diff --git a/codechicken/lib/colour/Colour.java b/codechicken/lib/colour/Colour.java index 3fa78c2..ea8a636 100644 --- a/codechicken/lib/colour/Colour.java +++ b/codechicken/lib/colour/Colour.java @@ -1,12 +1,10 @@ package codechicken.lib.colour; -import codechicken.lib.util.Copyable; -import org.lwjgl.opengl.GL11; - import codechicken.lib.math.MathHelper; - +import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; public abstract class Colour implements Copyable { diff --git a/codechicken/lib/colour/CustomGradient.java b/codechicken/lib/colour/CustomGradient.java index b4a5a0b..ba3270f 100644 --- a/codechicken/lib/colour/CustomGradient.java +++ b/codechicken/lib/colour/CustomGradient.java @@ -1,11 +1,10 @@ package codechicken.lib.colour; -import java.awt.image.BufferedImage; - -import net.minecraft.util.ResourceLocation; - import codechicken.lib.math.MathHelper; import codechicken.lib.render.TextureUtils; +import net.minecraft.util.ResourceLocation; + +import java.awt.image.BufferedImage; public class CustomGradient { diff --git a/codechicken/lib/config/ConfigFile.java b/codechicken/lib/config/ConfigFile.java index 3e6e5e1..bddec27 100644 --- a/codechicken/lib/config/ConfigFile.java +++ b/codechicken/lib/config/ConfigFile.java @@ -1,11 +1,6 @@ package codechicken.lib.config; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintWriter; +import java.io.*; public class ConfigFile extends ConfigTagParent { diff --git a/codechicken/lib/config/ConfigTag.java b/codechicken/lib/config/ConfigTag.java index 98472a4..cd3b8ad 100644 --- a/codechicken/lib/config/ConfigTag.java +++ b/codechicken/lib/config/ConfigTag.java @@ -1,12 +1,12 @@ package codechicken.lib.config; +import codechicken.lib.colour.Colour; +import codechicken.lib.colour.ColourRGBA; + import java.io.PrintWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; -import codechicken.lib.colour.Colour; -import codechicken.lib.colour.ColourRGBA; - public class ConfigTag extends ConfigTagParent { public ConfigTag(ConfigTagParent parent, String name) diff --git a/codechicken/lib/config/ConfigTagParent.java b/codechicken/lib/config/ConfigTagParent.java index 0db27f9..d293ad9 100644 --- a/codechicken/lib/config/ConfigTagParent.java +++ b/codechicken/lib/config/ConfigTagParent.java @@ -3,11 +3,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Map; -import java.util.TreeMap; +import java.util.*; import java.util.Map.Entry; public abstract class ConfigTagParent diff --git a/codechicken/lib/config/SimpleProperties.java b/codechicken/lib/config/SimpleProperties.java index aa2c34f..4a33669 100644 --- a/codechicken/lib/config/SimpleProperties.java +++ b/codechicken/lib/config/SimpleProperties.java @@ -1,10 +1,6 @@ package codechicken.lib.config; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; +import java.io.*; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map.Entry; diff --git a/codechicken/lib/data/MCDataInput.java b/codechicken/lib/data/MCDataInput.java index fda1d45..496c4a3 100644 --- a/codechicken/lib/data/MCDataInput.java +++ b/codechicken/lib/data/MCDataInput.java @@ -1,9 +1,9 @@ package codechicken.lib.data; +import codechicken.lib.vec.BlockCoord; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; -import codechicken.lib.vec.BlockCoord; public interface MCDataInput { diff --git a/codechicken/lib/data/MCDataOutput.java b/codechicken/lib/data/MCDataOutput.java index fbe6710..cf7cf89 100644 --- a/codechicken/lib/data/MCDataOutput.java +++ b/codechicken/lib/data/MCDataOutput.java @@ -1,9 +1,9 @@ package codechicken.lib.data; +import codechicken.lib.vec.BlockCoord; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; -import codechicken.lib.vec.BlockCoord; public interface MCDataOutput { diff --git a/codechicken/lib/data/MCOutputStreamWrapper.java b/codechicken/lib/data/MCOutputStreamWrapper.java index f8d94c5..49d4328 100644 --- a/codechicken/lib/data/MCOutputStreamWrapper.java +++ b/codechicken/lib/data/MCOutputStreamWrapper.java @@ -1,14 +1,14 @@ package codechicken.lib.data; -import java.io.DataOutputStream; -import java.io.IOException; - +import codechicken.lib.vec.BlockCoord; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; -import codechicken.lib.vec.BlockCoord; + +import java.io.DataOutputStream; +import java.io.IOException; public class MCOutputStreamWrapper implements MCDataOutput { diff --git a/codechicken/lib/gui/GuiDraw.java b/codechicken/lib/gui/GuiDraw.java index b930d26..59875ca 100644 --- a/codechicken/lib/gui/GuiDraw.java +++ b/codechicken/lib/gui/GuiDraw.java @@ -1,26 +1,23 @@ package codechicken.lib.gui; -import java.awt.Dimension; -import java.awt.Point; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import net.minecraft.util.EnumChatFormatting; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; - import codechicken.lib.math.MathHelper; import codechicken.lib.render.CCRenderState; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class GuiDraw { diff --git a/codechicken/lib/inventory/InventoryUtils.java b/codechicken/lib/inventory/InventoryUtils.java index 7f063e1..3f922e3 100644 --- a/codechicken/lib/inventory/InventoryUtils.java +++ b/codechicken/lib/inventory/InventoryUtils.java @@ -1,8 +1,7 @@ package codechicken.lib.inventory; -import com.google.common.base.Objects; - import codechicken.lib.vec.Vector3; +import com.google.common.base.Objects; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; diff --git a/codechicken/lib/inventory/ItemKey.java b/codechicken/lib/inventory/ItemKey.java index 0adb687..71d3c50 100644 --- a/codechicken/lib/inventory/ItemKey.java +++ b/codechicken/lib/inventory/ItemKey.java @@ -1,13 +1,12 @@ package codechicken.lib.inventory; +import com.google.common.base.Objects; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; - -import com.google.common.base.Objects; import net.minecraftforge.oredict.OreDictionary; -import static codechicken.lib.inventory.InventoryUtils.*; +import static codechicken.lib.inventory.InventoryUtils.actualDamage; /** * Comparable ItemStack with a hashCode implementation. diff --git a/codechicken/lib/lighting/LightMatrix.java b/codechicken/lib/lighting/LightMatrix.java index 54cf902..d35e420 100644 --- a/codechicken/lib/lighting/LightMatrix.java +++ b/codechicken/lib/lighting/LightMatrix.java @@ -3,7 +3,6 @@ import codechicken.lib.colour.ColourRGBA; import codechicken.lib.render.CCRenderState; import codechicken.lib.vec.BlockCoord; -import codechicken.lib.vec.Vector3; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.world.IBlockAccess; diff --git a/codechicken/lib/lighting/LightModel.java b/codechicken/lib/lighting/LightModel.java index 88bf784..aa33a80 100644 --- a/codechicken/lib/lighting/LightModel.java +++ b/codechicken/lib/lighting/LightModel.java @@ -1,9 +1,6 @@ package codechicken.lib.lighting; -import net.minecraft.client.renderer.Tessellator; -import codechicken.lib.render.CCModel; import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.uv.UV; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index 463454d..cc9c651 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -4,7 +4,6 @@ import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.vec.BlockCoord; - import com.google.common.collect.Maps; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ModContainer; @@ -13,14 +12,12 @@ import cpw.mods.fml.common.network.internal.FMLProxyPacket; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; - import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.compression.Snappy; import io.netty.util.AttributeKey; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; @@ -35,7 +32,6 @@ import net.minecraft.network.play.INetHandlerPlayServer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.PlayerManager; -import net.minecraft.server.management.PlayerManager.PlayerInstance; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.fluids.FluidStack; diff --git a/codechicken/lib/raytracer/RayTracer.java b/codechicken/lib/raytracer/RayTracer.java index 3fdb45c..12d9d49 100644 --- a/codechicken/lib/raytracer/RayTracer.java +++ b/codechicken/lib/raytracer/RayTracer.java @@ -1,7 +1,5 @@ package codechicken.lib.raytracer; -import java.util.List; - import codechicken.lib.math.MathHelper; import codechicken.lib.vec.BlockCoord; import codechicken.lib.vec.Cuboid6; @@ -13,11 +11,13 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.util.MovingObjectPosition.MovingObjectType; import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.MovingObjectPosition.MovingObjectType; import net.minecraft.util.Vec3; import net.minecraft.world.World; +import java.util.List; + public class RayTracer { private Vector3 vec = new Vector3(); diff --git a/codechicken/lib/render/CCModel.java b/codechicken/lib/render/CCModel.java index 9d37b26..526119e 100644 --- a/codechicken/lib/render/CCModel.java +++ b/codechicken/lib/render/CCModel.java @@ -1,31 +1,21 @@ package codechicken.lib.render; -import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import codechicken.lib.lighting.LC; +import codechicken.lib.lighting.LightModel; import codechicken.lib.render.uv.UV; import codechicken.lib.render.uv.UVTransformation; import codechicken.lib.render.uv.UVTranslation; import codechicken.lib.util.Copyable; +import codechicken.lib.vec.*; import net.minecraft.client.Minecraft; import net.minecraft.util.ResourceLocation; -import codechicken.lib.lighting.LightModel; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.RedundantTransformation; -import codechicken.lib.vec.Transformation; -import codechicken.lib.vec.TransformationList; -import codechicken.lib.vec.Vector3; -import static codechicken.lib.vec.Rotation.*; +import java.io.*; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static codechicken.lib.vec.Rotation.sideRotations; public class CCModel implements CCRenderState.IVertexSource, Copyable { diff --git a/codechicken/lib/render/CCModelLibrary.java b/codechicken/lib/render/CCModelLibrary.java index bb246c1..0987aab 100644 --- a/codechicken/lib/render/CCModelLibrary.java +++ b/codechicken/lib/render/CCModelLibrary.java @@ -1,10 +1,6 @@ package codechicken.lib.render; -import codechicken.lib.vec.Matrix4; -import codechicken.lib.vec.Quat; -import codechicken.lib.vec.Rotation; -import codechicken.lib.vec.Scale; -import codechicken.lib.vec.Vector3; +import codechicken.lib.vec.*; import static codechicken.lib.math.MathHelper.phi; diff --git a/codechicken/lib/render/CCRenderPipeline.java b/codechicken/lib/render/CCRenderPipeline.java index d2dcaff..b25141e 100644 --- a/codechicken/lib/render/CCRenderPipeline.java +++ b/codechicken/lib/render/CCRenderPipeline.java @@ -1,10 +1,10 @@ package codechicken.lib.render; -import java.util.ArrayList; - import codechicken.lib.render.CCRenderState.IVertexOperation; import codechicken.lib.render.CCRenderState.VertexAttribute; +import java.util.ArrayList; + public class CCRenderPipeline { public class PipelineBuilder diff --git a/codechicken/lib/render/FontUtils.java b/codechicken/lib/render/FontUtils.java index 97ac4a5..b927046 100644 --- a/codechicken/lib/render/FontUtils.java +++ b/codechicken/lib/render/FontUtils.java @@ -1,10 +1,9 @@ package codechicken.lib.render; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.item.ItemStack; +import org.lwjgl.opengl.GL11; public class FontUtils { diff --git a/codechicken/lib/render/RenderUtils.java b/codechicken/lib/render/RenderUtils.java index 2ee90dd..d878113 100644 --- a/codechicken/lib/render/RenderUtils.java +++ b/codechicken/lib/render/RenderUtils.java @@ -1,31 +1,26 @@ package codechicken.lib.render; -import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; -import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; - -import codechicken.lib.render.uv.UV; -import codechicken.lib.render.uv.UVTransformation; -import org.lwjgl.opengl.GL11; - import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Rectangle4i; -import codechicken.lib.vec.Transformation; -import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -import net.minecraft.util.IIcon; import net.minecraft.block.Block; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.entity.RenderItem; import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; import net.minecraftforge.client.IItemRenderer; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import org.lwjgl.opengl.GL11; + +import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; +import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; public class RenderUtils { diff --git a/codechicken/lib/render/ShaderProgram.java b/codechicken/lib/render/ShaderProgram.java index df8dd16..d813ffa 100644 --- a/codechicken/lib/render/ShaderProgram.java +++ b/codechicken/lib/render/ShaderProgram.java @@ -1,16 +1,16 @@ package codechicken.lib.render; -import static org.lwjgl.opengl.ARBShaderObjects.*; +import org.lwjgl.opengl.ARBShaderObjects; +import org.lwjgl.opengl.ARBVertexShader; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Matrix4f; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import org.lwjgl.opengl.ARBShaderObjects; -import org.lwjgl.opengl.ARBVertexShader; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.vector.Matrix4f; +import static org.lwjgl.opengl.ARBShaderObjects.*; public class ShaderProgram { diff --git a/codechicken/lib/render/SpriteSheetManager.java b/codechicken/lib/render/SpriteSheetManager.java index f8a1157..b64436a 100644 --- a/codechicken/lib/render/SpriteSheetManager.java +++ b/codechicken/lib/render/SpriteSheetManager.java @@ -1,17 +1,16 @@ package codechicken.lib.render; -import java.util.ArrayList; -import java.util.HashMap; - import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; - import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; +import java.util.ArrayList; +import java.util.HashMap; + public class SpriteSheetManager { @SideOnly(Side.CLIENT) diff --git a/codechicken/lib/render/TextureSpecial.java b/codechicken/lib/render/TextureSpecial.java index 777749a..03eb55c 100644 --- a/codechicken/lib/render/TextureSpecial.java +++ b/codechicken/lib/render/TextureSpecial.java @@ -1,8 +1,5 @@ package codechicken.lib.render; -import java.awt.image.BufferedImage; -import java.util.ArrayList; - import codechicken.lib.render.SpriteSheetManager.SpriteSheet; import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; @@ -16,6 +13,9 @@ import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; +import java.awt.image.BufferedImage; +import java.util.ArrayList; + @SideOnly(Side.CLIENT) public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegister { //sprite sheet fields diff --git a/codechicken/lib/render/TextureUtils.java b/codechicken/lib/render/TextureUtils.java index 8556332..0c04353 100644 --- a/codechicken/lib/render/TextureUtils.java +++ b/codechicken/lib/render/TextureUtils.java @@ -1,27 +1,24 @@ package codechicken.lib.render; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; - -import javax.imageio.ImageIO; - -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; - import codechicken.lib.colour.Colour; import codechicken.lib.colour.ColourARGB; - +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.MinecraftForge; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; public class TextureUtils { diff --git a/codechicken/lib/render/Vertex5.java b/codechicken/lib/render/Vertex5.java index 41683af..358b1f8 100644 --- a/codechicken/lib/render/Vertex5.java +++ b/codechicken/lib/render/Vertex5.java @@ -1,15 +1,15 @@ package codechicken.lib.render; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - import codechicken.lib.render.uv.UV; import codechicken.lib.render.uv.UVTransformation; import codechicken.lib.util.Copyable; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + public class Vertex5 implements Copyable { public Vector3 vec; diff --git a/codechicken/lib/tool/LibDownloader.java b/codechicken/lib/tool/LibDownloader.java index 0785b43..a36f026 100644 --- a/codechicken/lib/tool/LibDownloader.java +++ b/codechicken/lib/tool/LibDownloader.java @@ -1,6 +1,8 @@ package codechicken.lib.tool; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; diff --git a/codechicken/lib/vec/BlockCoord.java b/codechicken/lib/vec/BlockCoord.java index 061a4cd..318677f 100644 --- a/codechicken/lib/vec/BlockCoord.java +++ b/codechicken/lib/vec/BlockCoord.java @@ -1,8 +1,8 @@ package codechicken.lib.vec; +import codechicken.lib.math.MathHelper; import codechicken.lib.util.Copyable; import net.minecraft.tileentity.TileEntity; -import codechicken.lib.math.MathHelper; public class BlockCoord implements Comparable, Copyable { diff --git a/codechicken/lib/vec/Cuboid6.java b/codechicken/lib/vec/Cuboid6.java index 8101cf1..4b4fa14 100644 --- a/codechicken/lib/vec/Cuboid6.java +++ b/codechicken/lib/vec/Cuboid6.java @@ -1,13 +1,13 @@ package codechicken.lib.vec; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - import codechicken.lib.util.Copyable; import net.minecraft.block.Block; import net.minecraft.util.AxisAlignedBB; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + public class Cuboid6 implements Copyable { public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); diff --git a/codechicken/lib/vec/Matrix4.java b/codechicken/lib/vec/Matrix4.java index 1ac8a13..5d85a13 100644 --- a/codechicken/lib/vec/Matrix4.java +++ b/codechicken/lib/vec/Matrix4.java @@ -1,5 +1,10 @@ package codechicken.lib.vec; +import codechicken.lib.util.Copyable; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; + import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -7,12 +12,6 @@ import java.nio.ByteOrder; import java.nio.DoubleBuffer; -import codechicken.lib.util.Copyable; -import org.lwjgl.opengl.GL11; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - public class Matrix4 extends Transformation implements Copyable { private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); diff --git a/codechicken/lib/vec/Quat.java b/codechicken/lib/vec/Quat.java index 404daa6..b938c2e 100644 --- a/codechicken/lib/vec/Quat.java +++ b/codechicken/lib/vec/Quat.java @@ -1,10 +1,11 @@ package codechicken.lib.vec; +import codechicken.lib.math.MathHelper; +import codechicken.lib.util.Copyable; + import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -import codechicken.lib.math.MathHelper; -import codechicken.lib.util.Copyable; public class Quat implements Copyable { diff --git a/codechicken/lib/vec/Rotation.java b/codechicken/lib/vec/Rotation.java index af253f2..0dd0b9f 100644 --- a/codechicken/lib/vec/Rotation.java +++ b/codechicken/lib/vec/Rotation.java @@ -1,18 +1,15 @@ package codechicken.lib.vec; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - +import codechicken.lib.math.MathHelper; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; - import org.lwjgl.opengl.GL11; -import codechicken.lib.math.MathHelper; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; public class Rotation extends Transformation { diff --git a/codechicken/lib/vec/Scale.java b/codechicken/lib/vec/Scale.java index a6e38b1..922755c 100644 --- a/codechicken/lib/vec/Scale.java +++ b/codechicken/lib/vec/Scale.java @@ -1,14 +1,13 @@ package codechicken.lib.vec; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; + import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -import org.lwjgl.opengl.GL11; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - public class Scale extends Transformation { public Vector3 factor; diff --git a/codechicken/lib/vec/TransformationList.java b/codechicken/lib/vec/TransformationList.java index 4b383ea..b9cee64 100644 --- a/codechicken/lib/vec/TransformationList.java +++ b/codechicken/lib/vec/TransformationList.java @@ -1,11 +1,11 @@ package codechicken.lib.vec; -import java.util.ArrayList; -import java.util.Iterator; - import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.util.ArrayList; +import java.util.Iterator; + public class TransformationList extends Transformation { private ArrayList transformations = new ArrayList(); diff --git a/codechicken/lib/vec/Translation.java b/codechicken/lib/vec/Translation.java index 63c18e5..9ef8286 100644 --- a/codechicken/lib/vec/Translation.java +++ b/codechicken/lib/vec/Translation.java @@ -1,14 +1,13 @@ package codechicken.lib.vec; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; + import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -import org.lwjgl.opengl.GL11; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - public class Translation extends Transformation { public Vector3 vec; diff --git a/codechicken/lib/vec/Vector3.java b/codechicken/lib/vec/Vector3.java index 944029b..8a690df 100644 --- a/codechicken/lib/vec/Vector3.java +++ b/codechicken/lib/vec/Vector3.java @@ -1,22 +1,19 @@ package codechicken.lib.vec; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - -import codechicken.lib.util.Copyable; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.vector.Vector3f; -import org.lwjgl.util.vector.Vector4f; - import codechicken.lib.math.MathHelper; - +import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; - import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Vector3f; +import org.lwjgl.util.vector.Vector4f; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; public class Vector3 implements Copyable { diff --git a/codechicken/lib/world/ChunkExtension.java b/codechicken/lib/world/ChunkExtension.java index 0dc3c90..c3f17b7 100644 --- a/codechicken/lib/world/ChunkExtension.java +++ b/codechicken/lib/world/ChunkExtension.java @@ -1,12 +1,12 @@ package codechicken.lib.world; -import java.util.HashSet; - -import net.minecraft.network.Packet; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.Packet; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.chunk.Chunk; + +import java.util.HashSet; public abstract class ChunkExtension { diff --git a/codechicken/lib/world/WorldExtension.java b/codechicken/lib/world/WorldExtension.java index 3df2593..3015f93 100644 --- a/codechicken/lib/world/WorldExtension.java +++ b/codechicken/lib/world/WorldExtension.java @@ -1,11 +1,11 @@ package codechicken.lib.world; -import java.util.HashMap; - -import net.minecraft.world.chunk.Chunk; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +import java.util.HashMap; public abstract class WorldExtension { diff --git a/codechicken/lib/world/WorldExtensionInstantiator.java b/codechicken/lib/world/WorldExtensionInstantiator.java index 754b441..23431b0 100644 --- a/codechicken/lib/world/WorldExtensionInstantiator.java +++ b/codechicken/lib/world/WorldExtensionInstantiator.java @@ -1,7 +1,7 @@ package codechicken.lib.world; -import net.minecraft.world.chunk.Chunk; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; public abstract class WorldExtensionInstantiator { diff --git a/codechicken/lib/world/WorldExtensionManager.java b/codechicken/lib/world/WorldExtensionManager.java index 97c3d02..dd7f192 100644 --- a/codechicken/lib/world/WorldExtensionManager.java +++ b/codechicken/lib/world/WorldExtensionManager.java @@ -1,25 +1,23 @@ package codechicken.lib.world; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashMap; - import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; - import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.EmptyChunk; -import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; -import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.ChunkWatchEvent.UnWatch; import net.minecraftforge.event.world.ChunkWatchEvent.Watch; +import net.minecraftforge.event.world.WorldEvent; + +import java.util.ArrayList; +import java.util.HashMap; public class WorldExtensionManager { From 12e30606697969a50155ebfe34d569deaa903301 Mon Sep 17 00:00:00 2001 From: Progwml6 Date: Wed, 9 Apr 2014 00:04:36 -0400 Subject: [PATCH 071/219] fix issue under linux --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 359951a..91f5528 100644 --- a/build.gradle +++ b/build.gradle @@ -57,9 +57,9 @@ jar { sourceSets { main { java { - srcDir "\\" - include 'codechicken\\**\\*.java' - } + srcDir project.projectDir + include 'codechicken/**/*.java' + } } } From 32fa471c44e458e5fd3848a71dabd60a208551e0 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 10 Apr 2014 18:37:39 +1000 Subject: [PATCH 072/219] Fix compression crash --- codechicken/lib/packet/PacketCustom.java | 1 + 1 file changed, 1 insertion(+) diff --git a/codechicken/lib/packet/PacketCustom.java b/codechicken/lib/packet/PacketCustom.java index cc9c651..6abbb60 100644 --- a/codechicken/lib/packet/PacketCustom.java +++ b/codechicken/lib/packet/PacketCustom.java @@ -237,6 +237,7 @@ private void do_compress() { } catch (Exception e) { throw new RuntimeException(e); } finally { + byteBuf.readerIndex(0); deflater.end(); } } From 0a14b64e125ba39c362d1d2db072d2b59c29322f Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 11 Apr 2014 08:30:40 +1000 Subject: [PATCH 073/219] Cleaned up directory layout --- .gitignore | 33 ------------------ build.gradle => build/build.gradle | 3 +- build.properties => build/build.properties | 0 .../gradle}/wrapper/gradle-wrapper.jar | Bin .../gradle}/wrapper/gradle-wrapper.properties | 0 gradlew => build/gradlew | 0 gradlew.bat => build/gradlew.bat | 0 settings.gradle => build/settings.gradle | 0 .../codechicken}/lib/asm/ASMHelper.java | 0 .../codechicken}/lib/asm/ASMReader.java | 0 .../codechicken}/lib/asm/CC_ClassWriter.java | 0 .../lib/asm/ClassHeirachyManager.java | 0 .../codechicken}/lib/asm/InsnListPrinter.java | 0 .../lib/asm/InstructionComparator.java | 0 .../codechicken}/lib/asm/ObfMapping.java | 0 .../codechicken}/lib/colour/Colour.java | 0 .../codechicken}/lib/colour/ColourARGB.java | 0 .../codechicken}/lib/colour/ColourRGBA.java | 0 .../lib/colour/CustomGradient.java | 0 .../codechicken}/lib/config/ConfigFile.java | 0 .../codechicken}/lib/config/ConfigTag.java | 0 .../lib/config/ConfigTagParent.java | 0 .../lib/config/SimpleProperties.java | 0 .../codechicken}/lib/data/MCDataInput.java | 0 .../lib/data/MCDataInputStream.java | 0 .../codechicken}/lib/data/MCDataOutput.java | 0 .../lib/data/MCDataOutputStream.java | 0 .../lib/data/MCOutputStreamWrapper.java | 0 .../codechicken}/lib/gui/Canvas9Seg.java | 0 .../codechicken}/lib/gui/GuiDraw.java | 0 .../lib/inventory/InventoryCopy.java | 0 .../lib/inventory/InventoryNBT.java | 0 .../lib/inventory/InventoryRange.java | 0 .../lib/inventory/InventorySimple.java | 0 .../lib/inventory/InventoryUtils.java | 0 .../codechicken}/lib/inventory/ItemKey.java | 0 .../codechicken}/lib/lighting/LC.java | 0 .../lib/lighting/LightMatrix.java | 0 .../codechicken}/lib/lighting/LightModel.java | 0 .../lib/lighting/PlanarLightModel.java | 0 .../codechicken}/lib/math/MathHelper.java | 0 .../lib/packet/ICustomPacketTile.java | 0 .../codechicken}/lib/packet/PacketCustom.java | 0 .../lib/raytracer/ExtendedMOP.java | 0 .../lib/raytracer/IndexedCuboid6.java | 0 .../codechicken}/lib/raytracer/RayTracer.java | 0 .../lib/render/BlockRenderer.java | 0 .../codechicken}/lib/render/CCModel.java | 0 .../lib/render/CCModelLibrary.java | 0 .../lib/render/CCRenderPipeline.java | 0 .../lib/render/CCRenderState.java | 0 .../lib/render/ColourMultiplier.java | 0 .../lib/render/EntityDigIconFX.java | 0 .../codechicken}/lib/render/FontUtils.java | 0 .../lib/render/IFaceRenderer.java | 0 .../lib/render/ManagedTextureFX.java | 0 .../lib/render/PlaceholderTexture.java | 0 .../codechicken}/lib/render/QBImporter.java | 0 .../codechicken}/lib/render/RenderUtils.java | 0 .../lib/render/ShaderProgram.java | 0 .../lib/render/SpriteSheetManager.java | 0 .../lib/render/TextureDataHolder.java | 0 .../codechicken}/lib/render/TextureFX.java | 0 .../lib/render/TextureSpecial.java | 0 .../codechicken}/lib/render/TextureUtils.java | 0 .../codechicken}/lib/render/Vertex5.java | 0 .../lib/render/uv/IconTransformation.java | 0 .../render/uv/MultiIconTransformation.java | 0 .../codechicken}/lib/render/uv/UV.java | 0 .../lib/render/uv/UVRotation.java | 0 .../codechicken}/lib/render/uv/UVScale.java | 0 .../lib/render/uv/UVTransformation.java | 0 .../lib/render/uv/UVTransformationList.java | 0 .../lib/render/uv/UVTranslation.java | 0 .../codechicken}/lib/tool/LibDownloader.java | 0 .../lib/tool/MCStripTransformer.java | 0 .../codechicken}/lib/tool/Main.java | 0 .../lib/tool/StripClassLoader.java | 0 .../codechicken}/lib/tool/ToolMain.java | 0 .../lib/tool/module/JOptModule.java | 0 .../lib/tool/module/ModuleQBConverter.java | 0 .../codechicken}/lib/util/Copyable.java | 0 .../codechicken}/lib/vec/AxisCycle.java | 0 .../codechicken}/lib/vec/BlockCoord.java | 0 .../codechicken}/lib/vec/Cuboid6.java | 0 .../codechicken}/lib/vec/CuboidCoord.java | 0 .../codechicken}/lib/vec/ITransformation.java | 0 .../IrreversibleTransformationException.java | 0 .../codechicken}/lib/vec/Line3.java | 0 .../codechicken}/lib/vec/Matrix4.java | 0 .../codechicken}/lib/vec/Quat.java | 0 .../codechicken}/lib/vec/Rectangle4i.java | 0 .../lib/vec/RedundantTransformation.java | 0 .../codechicken}/lib/vec/Rotation.java | 0 .../codechicken}/lib/vec/Scale.java | 0 .../codechicken}/lib/vec/SwapYZ.java | 0 .../codechicken}/lib/vec/Transformation.java | 0 .../lib/vec/TransformationList.java | 0 .../codechicken}/lib/vec/Translation.java | 0 .../lib/vec/VariableTransformation.java | 0 .../codechicken}/lib/vec/Vector3.java | 0 .../lib/world/ChunkExtension.java | 0 .../lib/world/WorldExtension.java | 0 .../lib/world/WorldExtensionInstantiator.java | 0 .../lib/world/WorldExtensionManager.java | 0 105 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 .gitignore rename build.gradle => build/build.gradle (98%) rename build.properties => build/build.properties (100%) rename {gradle => build/gradle}/wrapper/gradle-wrapper.jar (100%) rename {gradle => build/gradle}/wrapper/gradle-wrapper.properties (100%) rename gradlew => build/gradlew (100%) rename gradlew.bat => build/gradlew.bat (100%) rename settings.gradle => build/settings.gradle (100%) rename {codechicken => src/codechicken}/lib/asm/ASMHelper.java (100%) rename {codechicken => src/codechicken}/lib/asm/ASMReader.java (100%) rename {codechicken => src/codechicken}/lib/asm/CC_ClassWriter.java (100%) rename {codechicken => src/codechicken}/lib/asm/ClassHeirachyManager.java (100%) rename {codechicken => src/codechicken}/lib/asm/InsnListPrinter.java (100%) rename {codechicken => src/codechicken}/lib/asm/InstructionComparator.java (100%) rename {codechicken => src/codechicken}/lib/asm/ObfMapping.java (100%) rename {codechicken => src/codechicken}/lib/colour/Colour.java (100%) rename {codechicken => src/codechicken}/lib/colour/ColourARGB.java (100%) rename {codechicken => src/codechicken}/lib/colour/ColourRGBA.java (100%) rename {codechicken => src/codechicken}/lib/colour/CustomGradient.java (100%) rename {codechicken => src/codechicken}/lib/config/ConfigFile.java (100%) rename {codechicken => src/codechicken}/lib/config/ConfigTag.java (100%) rename {codechicken => src/codechicken}/lib/config/ConfigTagParent.java (100%) rename {codechicken => src/codechicken}/lib/config/SimpleProperties.java (100%) rename {codechicken => src/codechicken}/lib/data/MCDataInput.java (100%) rename {codechicken => src/codechicken}/lib/data/MCDataInputStream.java (100%) rename {codechicken => src/codechicken}/lib/data/MCDataOutput.java (100%) rename {codechicken => src/codechicken}/lib/data/MCDataOutputStream.java (100%) rename {codechicken => src/codechicken}/lib/data/MCOutputStreamWrapper.java (100%) rename {codechicken => src/codechicken}/lib/gui/Canvas9Seg.java (100%) rename {codechicken => src/codechicken}/lib/gui/GuiDraw.java (100%) rename {codechicken => src/codechicken}/lib/inventory/InventoryCopy.java (100%) rename {codechicken => src/codechicken}/lib/inventory/InventoryNBT.java (100%) rename {codechicken => src/codechicken}/lib/inventory/InventoryRange.java (100%) rename {codechicken => src/codechicken}/lib/inventory/InventorySimple.java (100%) rename {codechicken => src/codechicken}/lib/inventory/InventoryUtils.java (100%) rename {codechicken => src/codechicken}/lib/inventory/ItemKey.java (100%) rename {codechicken => src/codechicken}/lib/lighting/LC.java (100%) rename {codechicken => src/codechicken}/lib/lighting/LightMatrix.java (100%) rename {codechicken => src/codechicken}/lib/lighting/LightModel.java (100%) rename {codechicken => src/codechicken}/lib/lighting/PlanarLightModel.java (100%) rename {codechicken => src/codechicken}/lib/math/MathHelper.java (100%) rename {codechicken => src/codechicken}/lib/packet/ICustomPacketTile.java (100%) rename {codechicken => src/codechicken}/lib/packet/PacketCustom.java (100%) rename {codechicken => src/codechicken}/lib/raytracer/ExtendedMOP.java (100%) rename {codechicken => src/codechicken}/lib/raytracer/IndexedCuboid6.java (100%) rename {codechicken => src/codechicken}/lib/raytracer/RayTracer.java (100%) rename {codechicken => src/codechicken}/lib/render/BlockRenderer.java (100%) rename {codechicken => src/codechicken}/lib/render/CCModel.java (100%) rename {codechicken => src/codechicken}/lib/render/CCModelLibrary.java (100%) rename {codechicken => src/codechicken}/lib/render/CCRenderPipeline.java (100%) rename {codechicken => src/codechicken}/lib/render/CCRenderState.java (100%) rename {codechicken => src/codechicken}/lib/render/ColourMultiplier.java (100%) rename {codechicken => src/codechicken}/lib/render/EntityDigIconFX.java (100%) rename {codechicken => src/codechicken}/lib/render/FontUtils.java (100%) rename {codechicken => src/codechicken}/lib/render/IFaceRenderer.java (100%) rename {codechicken => src/codechicken}/lib/render/ManagedTextureFX.java (100%) rename {codechicken => src/codechicken}/lib/render/PlaceholderTexture.java (100%) rename {codechicken => src/codechicken}/lib/render/QBImporter.java (100%) rename {codechicken => src/codechicken}/lib/render/RenderUtils.java (100%) rename {codechicken => src/codechicken}/lib/render/ShaderProgram.java (100%) rename {codechicken => src/codechicken}/lib/render/SpriteSheetManager.java (100%) rename {codechicken => src/codechicken}/lib/render/TextureDataHolder.java (100%) rename {codechicken => src/codechicken}/lib/render/TextureFX.java (100%) rename {codechicken => src/codechicken}/lib/render/TextureSpecial.java (100%) rename {codechicken => src/codechicken}/lib/render/TextureUtils.java (100%) rename {codechicken => src/codechicken}/lib/render/Vertex5.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/IconTransformation.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/MultiIconTransformation.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/UV.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/UVRotation.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/UVScale.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/UVTransformation.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/UVTransformationList.java (100%) rename {codechicken => src/codechicken}/lib/render/uv/UVTranslation.java (100%) rename {codechicken => src/codechicken}/lib/tool/LibDownloader.java (100%) rename {codechicken => src/codechicken}/lib/tool/MCStripTransformer.java (100%) rename {codechicken => src/codechicken}/lib/tool/Main.java (100%) rename {codechicken => src/codechicken}/lib/tool/StripClassLoader.java (100%) rename {codechicken => src/codechicken}/lib/tool/ToolMain.java (100%) rename {codechicken => src/codechicken}/lib/tool/module/JOptModule.java (100%) rename {codechicken => src/codechicken}/lib/tool/module/ModuleQBConverter.java (100%) rename {codechicken => src/codechicken}/lib/util/Copyable.java (100%) rename {codechicken => src/codechicken}/lib/vec/AxisCycle.java (100%) rename {codechicken => src/codechicken}/lib/vec/BlockCoord.java (100%) rename {codechicken => src/codechicken}/lib/vec/Cuboid6.java (100%) rename {codechicken => src/codechicken}/lib/vec/CuboidCoord.java (100%) rename {codechicken => src/codechicken}/lib/vec/ITransformation.java (100%) rename {codechicken => src/codechicken}/lib/vec/IrreversibleTransformationException.java (100%) rename {codechicken => src/codechicken}/lib/vec/Line3.java (100%) rename {codechicken => src/codechicken}/lib/vec/Matrix4.java (100%) rename {codechicken => src/codechicken}/lib/vec/Quat.java (100%) rename {codechicken => src/codechicken}/lib/vec/Rectangle4i.java (100%) rename {codechicken => src/codechicken}/lib/vec/RedundantTransformation.java (100%) rename {codechicken => src/codechicken}/lib/vec/Rotation.java (100%) rename {codechicken => src/codechicken}/lib/vec/Scale.java (100%) rename {codechicken => src/codechicken}/lib/vec/SwapYZ.java (100%) rename {codechicken => src/codechicken}/lib/vec/Transformation.java (100%) rename {codechicken => src/codechicken}/lib/vec/TransformationList.java (100%) rename {codechicken => src/codechicken}/lib/vec/Translation.java (100%) rename {codechicken => src/codechicken}/lib/vec/VariableTransformation.java (100%) rename {codechicken => src/codechicken}/lib/vec/Vector3.java (100%) rename {codechicken => src/codechicken}/lib/world/ChunkExtension.java (100%) rename {codechicken => src/codechicken}/lib/world/WorldExtension.java (100%) rename {codechicken => src/codechicken}/lib/world/WorldExtensionInstantiator.java (100%) rename {codechicken => src/codechicken}/lib/world/WorldExtensionManager.java (100%) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 46eb940..0000000 --- a/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -#ant stuff -/bin/ -#Remove OS generated garbage -*/.DS_Store -.DS_Store -.DS_Store? -.Spotlight-V100 -.Trashes -Icon? -ehthumbs.db -Thumbs.db -#gradle stuff -/.gradle -/build/ -/run/ -#IDEA files from Gradle -.idea/ -/*.iml -/*.ipr -/*.iws -#Vim backups -*~ -#eclipse stuffs -/.classpath -/.project -/.settings/ -/debug/ -*.lock -/.metadata/ -/config/ -/logs/ -options.txt -/saves/ \ No newline at end of file diff --git a/build.gradle b/build/build.gradle similarity index 98% rename from build.gradle rename to build/build.gradle index 91f5528..84ce131 100644 --- a/build.gradle +++ b/build/build.gradle @@ -57,8 +57,7 @@ jar { sourceSets { main { java { - srcDir project.projectDir - include 'codechicken/**/*.java' + srcDir new File(project.projectDir.parentFile, "src") } } } diff --git a/build.properties b/build/build.properties similarity index 100% rename from build.properties rename to build/build.properties diff --git a/gradle/wrapper/gradle-wrapper.jar b/build/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from gradle/wrapper/gradle-wrapper.jar rename to build/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/build/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from gradle/wrapper/gradle-wrapper.properties rename to build/gradle/wrapper/gradle-wrapper.properties diff --git a/gradlew b/build/gradlew similarity index 100% rename from gradlew rename to build/gradlew diff --git a/gradlew.bat b/build/gradlew.bat similarity index 100% rename from gradlew.bat rename to build/gradlew.bat diff --git a/settings.gradle b/build/settings.gradle similarity index 100% rename from settings.gradle rename to build/settings.gradle diff --git a/codechicken/lib/asm/ASMHelper.java b/src/codechicken/lib/asm/ASMHelper.java similarity index 100% rename from codechicken/lib/asm/ASMHelper.java rename to src/codechicken/lib/asm/ASMHelper.java diff --git a/codechicken/lib/asm/ASMReader.java b/src/codechicken/lib/asm/ASMReader.java similarity index 100% rename from codechicken/lib/asm/ASMReader.java rename to src/codechicken/lib/asm/ASMReader.java diff --git a/codechicken/lib/asm/CC_ClassWriter.java b/src/codechicken/lib/asm/CC_ClassWriter.java similarity index 100% rename from codechicken/lib/asm/CC_ClassWriter.java rename to src/codechicken/lib/asm/CC_ClassWriter.java diff --git a/codechicken/lib/asm/ClassHeirachyManager.java b/src/codechicken/lib/asm/ClassHeirachyManager.java similarity index 100% rename from codechicken/lib/asm/ClassHeirachyManager.java rename to src/codechicken/lib/asm/ClassHeirachyManager.java diff --git a/codechicken/lib/asm/InsnListPrinter.java b/src/codechicken/lib/asm/InsnListPrinter.java similarity index 100% rename from codechicken/lib/asm/InsnListPrinter.java rename to src/codechicken/lib/asm/InsnListPrinter.java diff --git a/codechicken/lib/asm/InstructionComparator.java b/src/codechicken/lib/asm/InstructionComparator.java similarity index 100% rename from codechicken/lib/asm/InstructionComparator.java rename to src/codechicken/lib/asm/InstructionComparator.java diff --git a/codechicken/lib/asm/ObfMapping.java b/src/codechicken/lib/asm/ObfMapping.java similarity index 100% rename from codechicken/lib/asm/ObfMapping.java rename to src/codechicken/lib/asm/ObfMapping.java diff --git a/codechicken/lib/colour/Colour.java b/src/codechicken/lib/colour/Colour.java similarity index 100% rename from codechicken/lib/colour/Colour.java rename to src/codechicken/lib/colour/Colour.java diff --git a/codechicken/lib/colour/ColourARGB.java b/src/codechicken/lib/colour/ColourARGB.java similarity index 100% rename from codechicken/lib/colour/ColourARGB.java rename to src/codechicken/lib/colour/ColourARGB.java diff --git a/codechicken/lib/colour/ColourRGBA.java b/src/codechicken/lib/colour/ColourRGBA.java similarity index 100% rename from codechicken/lib/colour/ColourRGBA.java rename to src/codechicken/lib/colour/ColourRGBA.java diff --git a/codechicken/lib/colour/CustomGradient.java b/src/codechicken/lib/colour/CustomGradient.java similarity index 100% rename from codechicken/lib/colour/CustomGradient.java rename to src/codechicken/lib/colour/CustomGradient.java diff --git a/codechicken/lib/config/ConfigFile.java b/src/codechicken/lib/config/ConfigFile.java similarity index 100% rename from codechicken/lib/config/ConfigFile.java rename to src/codechicken/lib/config/ConfigFile.java diff --git a/codechicken/lib/config/ConfigTag.java b/src/codechicken/lib/config/ConfigTag.java similarity index 100% rename from codechicken/lib/config/ConfigTag.java rename to src/codechicken/lib/config/ConfigTag.java diff --git a/codechicken/lib/config/ConfigTagParent.java b/src/codechicken/lib/config/ConfigTagParent.java similarity index 100% rename from codechicken/lib/config/ConfigTagParent.java rename to src/codechicken/lib/config/ConfigTagParent.java diff --git a/codechicken/lib/config/SimpleProperties.java b/src/codechicken/lib/config/SimpleProperties.java similarity index 100% rename from codechicken/lib/config/SimpleProperties.java rename to src/codechicken/lib/config/SimpleProperties.java diff --git a/codechicken/lib/data/MCDataInput.java b/src/codechicken/lib/data/MCDataInput.java similarity index 100% rename from codechicken/lib/data/MCDataInput.java rename to src/codechicken/lib/data/MCDataInput.java diff --git a/codechicken/lib/data/MCDataInputStream.java b/src/codechicken/lib/data/MCDataInputStream.java similarity index 100% rename from codechicken/lib/data/MCDataInputStream.java rename to src/codechicken/lib/data/MCDataInputStream.java diff --git a/codechicken/lib/data/MCDataOutput.java b/src/codechicken/lib/data/MCDataOutput.java similarity index 100% rename from codechicken/lib/data/MCDataOutput.java rename to src/codechicken/lib/data/MCDataOutput.java diff --git a/codechicken/lib/data/MCDataOutputStream.java b/src/codechicken/lib/data/MCDataOutputStream.java similarity index 100% rename from codechicken/lib/data/MCDataOutputStream.java rename to src/codechicken/lib/data/MCDataOutputStream.java diff --git a/codechicken/lib/data/MCOutputStreamWrapper.java b/src/codechicken/lib/data/MCOutputStreamWrapper.java similarity index 100% rename from codechicken/lib/data/MCOutputStreamWrapper.java rename to src/codechicken/lib/data/MCOutputStreamWrapper.java diff --git a/codechicken/lib/gui/Canvas9Seg.java b/src/codechicken/lib/gui/Canvas9Seg.java similarity index 100% rename from codechicken/lib/gui/Canvas9Seg.java rename to src/codechicken/lib/gui/Canvas9Seg.java diff --git a/codechicken/lib/gui/GuiDraw.java b/src/codechicken/lib/gui/GuiDraw.java similarity index 100% rename from codechicken/lib/gui/GuiDraw.java rename to src/codechicken/lib/gui/GuiDraw.java diff --git a/codechicken/lib/inventory/InventoryCopy.java b/src/codechicken/lib/inventory/InventoryCopy.java similarity index 100% rename from codechicken/lib/inventory/InventoryCopy.java rename to src/codechicken/lib/inventory/InventoryCopy.java diff --git a/codechicken/lib/inventory/InventoryNBT.java b/src/codechicken/lib/inventory/InventoryNBT.java similarity index 100% rename from codechicken/lib/inventory/InventoryNBT.java rename to src/codechicken/lib/inventory/InventoryNBT.java diff --git a/codechicken/lib/inventory/InventoryRange.java b/src/codechicken/lib/inventory/InventoryRange.java similarity index 100% rename from codechicken/lib/inventory/InventoryRange.java rename to src/codechicken/lib/inventory/InventoryRange.java diff --git a/codechicken/lib/inventory/InventorySimple.java b/src/codechicken/lib/inventory/InventorySimple.java similarity index 100% rename from codechicken/lib/inventory/InventorySimple.java rename to src/codechicken/lib/inventory/InventorySimple.java diff --git a/codechicken/lib/inventory/InventoryUtils.java b/src/codechicken/lib/inventory/InventoryUtils.java similarity index 100% rename from codechicken/lib/inventory/InventoryUtils.java rename to src/codechicken/lib/inventory/InventoryUtils.java diff --git a/codechicken/lib/inventory/ItemKey.java b/src/codechicken/lib/inventory/ItemKey.java similarity index 100% rename from codechicken/lib/inventory/ItemKey.java rename to src/codechicken/lib/inventory/ItemKey.java diff --git a/codechicken/lib/lighting/LC.java b/src/codechicken/lib/lighting/LC.java similarity index 100% rename from codechicken/lib/lighting/LC.java rename to src/codechicken/lib/lighting/LC.java diff --git a/codechicken/lib/lighting/LightMatrix.java b/src/codechicken/lib/lighting/LightMatrix.java similarity index 100% rename from codechicken/lib/lighting/LightMatrix.java rename to src/codechicken/lib/lighting/LightMatrix.java diff --git a/codechicken/lib/lighting/LightModel.java b/src/codechicken/lib/lighting/LightModel.java similarity index 100% rename from codechicken/lib/lighting/LightModel.java rename to src/codechicken/lib/lighting/LightModel.java diff --git a/codechicken/lib/lighting/PlanarLightModel.java b/src/codechicken/lib/lighting/PlanarLightModel.java similarity index 100% rename from codechicken/lib/lighting/PlanarLightModel.java rename to src/codechicken/lib/lighting/PlanarLightModel.java diff --git a/codechicken/lib/math/MathHelper.java b/src/codechicken/lib/math/MathHelper.java similarity index 100% rename from codechicken/lib/math/MathHelper.java rename to src/codechicken/lib/math/MathHelper.java diff --git a/codechicken/lib/packet/ICustomPacketTile.java b/src/codechicken/lib/packet/ICustomPacketTile.java similarity index 100% rename from codechicken/lib/packet/ICustomPacketTile.java rename to src/codechicken/lib/packet/ICustomPacketTile.java diff --git a/codechicken/lib/packet/PacketCustom.java b/src/codechicken/lib/packet/PacketCustom.java similarity index 100% rename from codechicken/lib/packet/PacketCustom.java rename to src/codechicken/lib/packet/PacketCustom.java diff --git a/codechicken/lib/raytracer/ExtendedMOP.java b/src/codechicken/lib/raytracer/ExtendedMOP.java similarity index 100% rename from codechicken/lib/raytracer/ExtendedMOP.java rename to src/codechicken/lib/raytracer/ExtendedMOP.java diff --git a/codechicken/lib/raytracer/IndexedCuboid6.java b/src/codechicken/lib/raytracer/IndexedCuboid6.java similarity index 100% rename from codechicken/lib/raytracer/IndexedCuboid6.java rename to src/codechicken/lib/raytracer/IndexedCuboid6.java diff --git a/codechicken/lib/raytracer/RayTracer.java b/src/codechicken/lib/raytracer/RayTracer.java similarity index 100% rename from codechicken/lib/raytracer/RayTracer.java rename to src/codechicken/lib/raytracer/RayTracer.java diff --git a/codechicken/lib/render/BlockRenderer.java b/src/codechicken/lib/render/BlockRenderer.java similarity index 100% rename from codechicken/lib/render/BlockRenderer.java rename to src/codechicken/lib/render/BlockRenderer.java diff --git a/codechicken/lib/render/CCModel.java b/src/codechicken/lib/render/CCModel.java similarity index 100% rename from codechicken/lib/render/CCModel.java rename to src/codechicken/lib/render/CCModel.java diff --git a/codechicken/lib/render/CCModelLibrary.java b/src/codechicken/lib/render/CCModelLibrary.java similarity index 100% rename from codechicken/lib/render/CCModelLibrary.java rename to src/codechicken/lib/render/CCModelLibrary.java diff --git a/codechicken/lib/render/CCRenderPipeline.java b/src/codechicken/lib/render/CCRenderPipeline.java similarity index 100% rename from codechicken/lib/render/CCRenderPipeline.java rename to src/codechicken/lib/render/CCRenderPipeline.java diff --git a/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java similarity index 100% rename from codechicken/lib/render/CCRenderState.java rename to src/codechicken/lib/render/CCRenderState.java diff --git a/codechicken/lib/render/ColourMultiplier.java b/src/codechicken/lib/render/ColourMultiplier.java similarity index 100% rename from codechicken/lib/render/ColourMultiplier.java rename to src/codechicken/lib/render/ColourMultiplier.java diff --git a/codechicken/lib/render/EntityDigIconFX.java b/src/codechicken/lib/render/EntityDigIconFX.java similarity index 100% rename from codechicken/lib/render/EntityDigIconFX.java rename to src/codechicken/lib/render/EntityDigIconFX.java diff --git a/codechicken/lib/render/FontUtils.java b/src/codechicken/lib/render/FontUtils.java similarity index 100% rename from codechicken/lib/render/FontUtils.java rename to src/codechicken/lib/render/FontUtils.java diff --git a/codechicken/lib/render/IFaceRenderer.java b/src/codechicken/lib/render/IFaceRenderer.java similarity index 100% rename from codechicken/lib/render/IFaceRenderer.java rename to src/codechicken/lib/render/IFaceRenderer.java diff --git a/codechicken/lib/render/ManagedTextureFX.java b/src/codechicken/lib/render/ManagedTextureFX.java similarity index 100% rename from codechicken/lib/render/ManagedTextureFX.java rename to src/codechicken/lib/render/ManagedTextureFX.java diff --git a/codechicken/lib/render/PlaceholderTexture.java b/src/codechicken/lib/render/PlaceholderTexture.java similarity index 100% rename from codechicken/lib/render/PlaceholderTexture.java rename to src/codechicken/lib/render/PlaceholderTexture.java diff --git a/codechicken/lib/render/QBImporter.java b/src/codechicken/lib/render/QBImporter.java similarity index 100% rename from codechicken/lib/render/QBImporter.java rename to src/codechicken/lib/render/QBImporter.java diff --git a/codechicken/lib/render/RenderUtils.java b/src/codechicken/lib/render/RenderUtils.java similarity index 100% rename from codechicken/lib/render/RenderUtils.java rename to src/codechicken/lib/render/RenderUtils.java diff --git a/codechicken/lib/render/ShaderProgram.java b/src/codechicken/lib/render/ShaderProgram.java similarity index 100% rename from codechicken/lib/render/ShaderProgram.java rename to src/codechicken/lib/render/ShaderProgram.java diff --git a/codechicken/lib/render/SpriteSheetManager.java b/src/codechicken/lib/render/SpriteSheetManager.java similarity index 100% rename from codechicken/lib/render/SpriteSheetManager.java rename to src/codechicken/lib/render/SpriteSheetManager.java diff --git a/codechicken/lib/render/TextureDataHolder.java b/src/codechicken/lib/render/TextureDataHolder.java similarity index 100% rename from codechicken/lib/render/TextureDataHolder.java rename to src/codechicken/lib/render/TextureDataHolder.java diff --git a/codechicken/lib/render/TextureFX.java b/src/codechicken/lib/render/TextureFX.java similarity index 100% rename from codechicken/lib/render/TextureFX.java rename to src/codechicken/lib/render/TextureFX.java diff --git a/codechicken/lib/render/TextureSpecial.java b/src/codechicken/lib/render/TextureSpecial.java similarity index 100% rename from codechicken/lib/render/TextureSpecial.java rename to src/codechicken/lib/render/TextureSpecial.java diff --git a/codechicken/lib/render/TextureUtils.java b/src/codechicken/lib/render/TextureUtils.java similarity index 100% rename from codechicken/lib/render/TextureUtils.java rename to src/codechicken/lib/render/TextureUtils.java diff --git a/codechicken/lib/render/Vertex5.java b/src/codechicken/lib/render/Vertex5.java similarity index 100% rename from codechicken/lib/render/Vertex5.java rename to src/codechicken/lib/render/Vertex5.java diff --git a/codechicken/lib/render/uv/IconTransformation.java b/src/codechicken/lib/render/uv/IconTransformation.java similarity index 100% rename from codechicken/lib/render/uv/IconTransformation.java rename to src/codechicken/lib/render/uv/IconTransformation.java diff --git a/codechicken/lib/render/uv/MultiIconTransformation.java b/src/codechicken/lib/render/uv/MultiIconTransformation.java similarity index 100% rename from codechicken/lib/render/uv/MultiIconTransformation.java rename to src/codechicken/lib/render/uv/MultiIconTransformation.java diff --git a/codechicken/lib/render/uv/UV.java b/src/codechicken/lib/render/uv/UV.java similarity index 100% rename from codechicken/lib/render/uv/UV.java rename to src/codechicken/lib/render/uv/UV.java diff --git a/codechicken/lib/render/uv/UVRotation.java b/src/codechicken/lib/render/uv/UVRotation.java similarity index 100% rename from codechicken/lib/render/uv/UVRotation.java rename to src/codechicken/lib/render/uv/UVRotation.java diff --git a/codechicken/lib/render/uv/UVScale.java b/src/codechicken/lib/render/uv/UVScale.java similarity index 100% rename from codechicken/lib/render/uv/UVScale.java rename to src/codechicken/lib/render/uv/UVScale.java diff --git a/codechicken/lib/render/uv/UVTransformation.java b/src/codechicken/lib/render/uv/UVTransformation.java similarity index 100% rename from codechicken/lib/render/uv/UVTransformation.java rename to src/codechicken/lib/render/uv/UVTransformation.java diff --git a/codechicken/lib/render/uv/UVTransformationList.java b/src/codechicken/lib/render/uv/UVTransformationList.java similarity index 100% rename from codechicken/lib/render/uv/UVTransformationList.java rename to src/codechicken/lib/render/uv/UVTransformationList.java diff --git a/codechicken/lib/render/uv/UVTranslation.java b/src/codechicken/lib/render/uv/UVTranslation.java similarity index 100% rename from codechicken/lib/render/uv/UVTranslation.java rename to src/codechicken/lib/render/uv/UVTranslation.java diff --git a/codechicken/lib/tool/LibDownloader.java b/src/codechicken/lib/tool/LibDownloader.java similarity index 100% rename from codechicken/lib/tool/LibDownloader.java rename to src/codechicken/lib/tool/LibDownloader.java diff --git a/codechicken/lib/tool/MCStripTransformer.java b/src/codechicken/lib/tool/MCStripTransformer.java similarity index 100% rename from codechicken/lib/tool/MCStripTransformer.java rename to src/codechicken/lib/tool/MCStripTransformer.java diff --git a/codechicken/lib/tool/Main.java b/src/codechicken/lib/tool/Main.java similarity index 100% rename from codechicken/lib/tool/Main.java rename to src/codechicken/lib/tool/Main.java diff --git a/codechicken/lib/tool/StripClassLoader.java b/src/codechicken/lib/tool/StripClassLoader.java similarity index 100% rename from codechicken/lib/tool/StripClassLoader.java rename to src/codechicken/lib/tool/StripClassLoader.java diff --git a/codechicken/lib/tool/ToolMain.java b/src/codechicken/lib/tool/ToolMain.java similarity index 100% rename from codechicken/lib/tool/ToolMain.java rename to src/codechicken/lib/tool/ToolMain.java diff --git a/codechicken/lib/tool/module/JOptModule.java b/src/codechicken/lib/tool/module/JOptModule.java similarity index 100% rename from codechicken/lib/tool/module/JOptModule.java rename to src/codechicken/lib/tool/module/JOptModule.java diff --git a/codechicken/lib/tool/module/ModuleQBConverter.java b/src/codechicken/lib/tool/module/ModuleQBConverter.java similarity index 100% rename from codechicken/lib/tool/module/ModuleQBConverter.java rename to src/codechicken/lib/tool/module/ModuleQBConverter.java diff --git a/codechicken/lib/util/Copyable.java b/src/codechicken/lib/util/Copyable.java similarity index 100% rename from codechicken/lib/util/Copyable.java rename to src/codechicken/lib/util/Copyable.java diff --git a/codechicken/lib/vec/AxisCycle.java b/src/codechicken/lib/vec/AxisCycle.java similarity index 100% rename from codechicken/lib/vec/AxisCycle.java rename to src/codechicken/lib/vec/AxisCycle.java diff --git a/codechicken/lib/vec/BlockCoord.java b/src/codechicken/lib/vec/BlockCoord.java similarity index 100% rename from codechicken/lib/vec/BlockCoord.java rename to src/codechicken/lib/vec/BlockCoord.java diff --git a/codechicken/lib/vec/Cuboid6.java b/src/codechicken/lib/vec/Cuboid6.java similarity index 100% rename from codechicken/lib/vec/Cuboid6.java rename to src/codechicken/lib/vec/Cuboid6.java diff --git a/codechicken/lib/vec/CuboidCoord.java b/src/codechicken/lib/vec/CuboidCoord.java similarity index 100% rename from codechicken/lib/vec/CuboidCoord.java rename to src/codechicken/lib/vec/CuboidCoord.java diff --git a/codechicken/lib/vec/ITransformation.java b/src/codechicken/lib/vec/ITransformation.java similarity index 100% rename from codechicken/lib/vec/ITransformation.java rename to src/codechicken/lib/vec/ITransformation.java diff --git a/codechicken/lib/vec/IrreversibleTransformationException.java b/src/codechicken/lib/vec/IrreversibleTransformationException.java similarity index 100% rename from codechicken/lib/vec/IrreversibleTransformationException.java rename to src/codechicken/lib/vec/IrreversibleTransformationException.java diff --git a/codechicken/lib/vec/Line3.java b/src/codechicken/lib/vec/Line3.java similarity index 100% rename from codechicken/lib/vec/Line3.java rename to src/codechicken/lib/vec/Line3.java diff --git a/codechicken/lib/vec/Matrix4.java b/src/codechicken/lib/vec/Matrix4.java similarity index 100% rename from codechicken/lib/vec/Matrix4.java rename to src/codechicken/lib/vec/Matrix4.java diff --git a/codechicken/lib/vec/Quat.java b/src/codechicken/lib/vec/Quat.java similarity index 100% rename from codechicken/lib/vec/Quat.java rename to src/codechicken/lib/vec/Quat.java diff --git a/codechicken/lib/vec/Rectangle4i.java b/src/codechicken/lib/vec/Rectangle4i.java similarity index 100% rename from codechicken/lib/vec/Rectangle4i.java rename to src/codechicken/lib/vec/Rectangle4i.java diff --git a/codechicken/lib/vec/RedundantTransformation.java b/src/codechicken/lib/vec/RedundantTransformation.java similarity index 100% rename from codechicken/lib/vec/RedundantTransformation.java rename to src/codechicken/lib/vec/RedundantTransformation.java diff --git a/codechicken/lib/vec/Rotation.java b/src/codechicken/lib/vec/Rotation.java similarity index 100% rename from codechicken/lib/vec/Rotation.java rename to src/codechicken/lib/vec/Rotation.java diff --git a/codechicken/lib/vec/Scale.java b/src/codechicken/lib/vec/Scale.java similarity index 100% rename from codechicken/lib/vec/Scale.java rename to src/codechicken/lib/vec/Scale.java diff --git a/codechicken/lib/vec/SwapYZ.java b/src/codechicken/lib/vec/SwapYZ.java similarity index 100% rename from codechicken/lib/vec/SwapYZ.java rename to src/codechicken/lib/vec/SwapYZ.java diff --git a/codechicken/lib/vec/Transformation.java b/src/codechicken/lib/vec/Transformation.java similarity index 100% rename from codechicken/lib/vec/Transformation.java rename to src/codechicken/lib/vec/Transformation.java diff --git a/codechicken/lib/vec/TransformationList.java b/src/codechicken/lib/vec/TransformationList.java similarity index 100% rename from codechicken/lib/vec/TransformationList.java rename to src/codechicken/lib/vec/TransformationList.java diff --git a/codechicken/lib/vec/Translation.java b/src/codechicken/lib/vec/Translation.java similarity index 100% rename from codechicken/lib/vec/Translation.java rename to src/codechicken/lib/vec/Translation.java diff --git a/codechicken/lib/vec/VariableTransformation.java b/src/codechicken/lib/vec/VariableTransformation.java similarity index 100% rename from codechicken/lib/vec/VariableTransformation.java rename to src/codechicken/lib/vec/VariableTransformation.java diff --git a/codechicken/lib/vec/Vector3.java b/src/codechicken/lib/vec/Vector3.java similarity index 100% rename from codechicken/lib/vec/Vector3.java rename to src/codechicken/lib/vec/Vector3.java diff --git a/codechicken/lib/world/ChunkExtension.java b/src/codechicken/lib/world/ChunkExtension.java similarity index 100% rename from codechicken/lib/world/ChunkExtension.java rename to src/codechicken/lib/world/ChunkExtension.java diff --git a/codechicken/lib/world/WorldExtension.java b/src/codechicken/lib/world/WorldExtension.java similarity index 100% rename from codechicken/lib/world/WorldExtension.java rename to src/codechicken/lib/world/WorldExtension.java diff --git a/codechicken/lib/world/WorldExtensionInstantiator.java b/src/codechicken/lib/world/WorldExtensionInstantiator.java similarity index 100% rename from codechicken/lib/world/WorldExtensionInstantiator.java rename to src/codechicken/lib/world/WorldExtensionInstantiator.java diff --git a/codechicken/lib/world/WorldExtensionManager.java b/src/codechicken/lib/world/WorldExtensionManager.java similarity index 100% rename from codechicken/lib/world/WorldExtensionManager.java rename to src/codechicken/lib/world/WorldExtensionManager.java From 52f82017e7aa802ba2aed97977cc742a48c33d57 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Mon, 28 Apr 2014 19:40:13 +1000 Subject: [PATCH 074/219] Upgraded ASM lib --- src/codechicken/lib/asm/ASMBlock.java | 173 +++++++++++ src/codechicken/lib/asm/ASMHelper.java | 246 +++++---------- src/codechicken/lib/asm/ASMReader.java | 159 ++++------ .../lib/asm/ImportantInsnVisitor.java | 36 +++ src/codechicken/lib/asm/InsnComparator.java | 189 ++++++++++++ src/codechicken/lib/asm/InsnListPrinter.java | 197 ------------ src/codechicken/lib/asm/InsnListSection.java | 241 +++++++++++++++ .../lib/asm/InstructionComparator.java | 239 --------------- .../lib/asm/LocalVariablesSorterVisitor.java | 37 +++ .../lib/asm/ModularASMTransformer.java | 285 ++++++++++++++++++ src/codechicken/lib/asm/ObfMapping.java | 28 +- src/codechicken/lib/config/ConfigFile.java | 37 +-- .../lib/config/ConfigTagParent.java | 2 +- .../lib/config/DefaultingConfigFile.java | 18 ++ 14 files changed, 1141 insertions(+), 746 deletions(-) create mode 100644 src/codechicken/lib/asm/ASMBlock.java create mode 100644 src/codechicken/lib/asm/ImportantInsnVisitor.java create mode 100644 src/codechicken/lib/asm/InsnComparator.java delete mode 100644 src/codechicken/lib/asm/InsnListPrinter.java create mode 100644 src/codechicken/lib/asm/InsnListSection.java delete mode 100644 src/codechicken/lib/asm/InstructionComparator.java create mode 100644 src/codechicken/lib/asm/LocalVariablesSorterVisitor.java create mode 100644 src/codechicken/lib/asm/ModularASMTransformer.java create mode 100644 src/codechicken/lib/config/DefaultingConfigFile.java diff --git a/src/codechicken/lib/asm/ASMBlock.java b/src/codechicken/lib/asm/ASMBlock.java new file mode 100644 index 0000000..c355437 --- /dev/null +++ b/src/codechicken/lib/asm/ASMBlock.java @@ -0,0 +1,173 @@ +package codechicken.lib.asm; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableMap; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; + +import java.util.*; +import java.util.Map.Entry; + +import static org.objectweb.asm.tree.AbstractInsnNode.*; + +public class ASMBlock +{ + public InsnListSection list; + private BiMap labels; + + public ASMBlock(InsnListSection list, BiMap labels) { + this.list = list; + this.labels = labels; + } + + public ASMBlock(InsnListSection list) { + this(list, HashBiMap.create()); + } + + public ASMBlock(InsnList list) { + this(new InsnListSection(list)); + } + + public ASMBlock() { + this(new InsnListSection()); + } + + public LabelNode getOrAdd(String s) { + LabelNode l = get(s); + if (l == null) + labels.put(s, l = new LabelNode()); + return l; + } + + public LabelNode get(String s) { + return labels.get(s); + } + + public void replaceLabels(Map labelMap, Set usedLabels) { + for (AbstractInsnNode insn : list) + switch (insn.getType()) { + case LABEL: + AbstractInsnNode insn2 = insn.clone(labelMap); + if (insn2 == insn)//identity mapping + continue; + if (usedLabels.contains(insn2)) + throw new IllegalStateException("LabelNode cannot be a part of two InsnLists"); + list.replace(insn, insn2); + break; + case JUMP_INSN: + case FRAME: + case LOOKUPSWITCH_INSN: + case TABLESWITCH_INSN: + list.replace(insn, insn.clone(labelMap)); + } + + for(Entry entry : labelMap.entrySet()) { + String key = labels.inverse().get(entry.getKey()); + if(key != null) + labels.put(key, entry.getValue()); + } + } + + public void replaceLabels(Map labelMap) { + replaceLabels(labelMap, Collections.EMPTY_SET); + } + + public void replaceLabel(String s, LabelNode l) { + LabelNode old = get(s); + if (old != null) + replaceLabels(ImmutableMap.of(old, l)); + } + + /** + * Pulls all common labels from other into this + * @return this + */ + public ASMBlock mergeLabels(ASMBlock other) { + if(labels.isEmpty() || other.labels.isEmpty()) + return this; + + //common labels, give them our nodes + HashMap labelMap = list.identityLabelMap(); + for(Entry entry : other.labels.entrySet()) { + LabelNode old = labels.get(entry.getKey()); + if(old != null) + labelMap.put(old, entry.getValue()); + } + HashSet usedLabels = new HashSet(); + for (AbstractInsnNode insn = other.list.list.getFirst(); insn != null; insn = insn.getNext()) + if(insn.getType() == LABEL) + usedLabels.add((LabelNode) insn); + + replaceLabels(labelMap, usedLabels); + return this; + } + + /** + * Like mergeLabels but pulls insns from other list into this so LabelNodes can be transferred + * @return this + */ + public ASMBlock pullLabels(ASMBlock other) { + other.list.remove(); + return mergeLabels(other); + } + + public ASMBlock copy() { + BiMap labels = HashBiMap.create(); + Map labelMap = list.cloneLabels(); + + for(Entry entry : this.labels.entrySet()) + labels.put(entry.getKey(), labelMap.get(entry.getValue())); + + return new ASMBlock(list.copy(labelMap), labels); + } + + public ASMBlock applyLabels(InsnListSection list2) { + if(labels.isEmpty()) + return new ASMBlock(list2); + + Set cFlowLabels1 = labels.values(); + Set cFlowLabels2 = InsnComparator.getControlFlowLabels(list2); + ASMBlock block = new ASMBlock(list2); + + HashMap labelMap = new HashMap(); + + for(int i = 0, k = 0; i < list.size() && k < list2.size(); ) { + AbstractInsnNode insn1 = list.get(i); + if(!InsnComparator.insnImportant(insn1, cFlowLabels1)) { + i++; + continue; + } + + AbstractInsnNode insn2 = list2.get(k); + if(!InsnComparator.insnImportant(insn2, cFlowLabels2)) { + k++; + continue; + } + + if(insn1.getOpcode() != insn2.getOpcode()) + throw new IllegalArgumentException("Lists do not match:\n"+list+"\n\n"+list2); + + switch(insn1.getType()) { + case LABEL: + labelMap.put((LabelNode) insn1, (LabelNode) insn2); + break; + case JUMP_INSN: + labelMap.put(((JumpInsnNode) insn1).label, ((JumpInsnNode) insn2).label); + break; + } + i++; k++; + } + + for(Entry entry : labels.entrySet()) + block.labels.put(entry.getKey(), labelMap.get(entry.getValue())); + + return block; + } + + public InsnList rawListCopy() { + return list.copy().list; + } +} \ No newline at end of file diff --git a/src/codechicken/lib/asm/ASMHelper.java b/src/codechicken/lib/asm/ASMHelper.java index d4b03c1..7fa1aa3 100644 --- a/src/codechicken/lib/asm/ASMHelper.java +++ b/src/codechicken/lib/asm/ASMHelper.java @@ -1,76 +1,40 @@ package codechicken.lib.asm; -import codechicken.lib.asm.InstructionComparator.InsnListSection; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; +import codechicken.lib.config.ConfigFile; +import codechicken.lib.config.DefaultingConfigFile; +import cpw.mods.fml.relauncher.FMLInjectionData; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Label; import org.objectweb.asm.tree.*; +import org.objectweb.asm.util.TraceClassVisitor; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; public class ASMHelper { - public static class CodeBlock - { - public Label start = new Label(); - public Label end = new Label(); - } + public static ConfigFile config = loadConfig(); + public static Logger logger = LogManager.getLogger("CCL ASM"); - public static class ForBlock extends CodeBlock - { - public Label cmp = new Label(); - public Label inc = new Label(); - public Label body = new Label(); + private static ConfigFile loadConfig() { + File file = new File((File) FMLInjectionData.data()[6], "config/CodeChickenLib.cfg"); + if(ObfMapping.obfuscated) + return new DefaultingConfigFile(file); + else + return new ConfigFile(file).setComment("CodeChickenLib development configuration file."); } - public static abstract class MethodAltercator + public static interface Acceptor { - public final ObfMapping method; - - public MethodAltercator(ObfMapping method) { - this.method = method.toClassloading(); - } - - public abstract void alter(MethodNode mv); - } - - public static abstract class MethodWriter - { - public final int access; - public final ObfMapping method; - public final String[] exceptions; - - public MethodWriter(int access, ObfMapping method) { - this(access, method, null); - } - - public MethodWriter(int access, ObfMapping method, String[] exceptions) { - this.access = access; - this.method = method; - this.exceptions = exceptions; - } - - public abstract void write(MethodNode mv); - } - - public static class MethodInjector - { - public final ObfMapping method; - public final InsnList needle; - public final InsnList injection; - public final boolean before; - - public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) { - this.method = method; - this.needle = needle; - this.injection = injection; - this.before = before; - } + public void accept(ClassVisitor cv) throws IOException; } public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) { @@ -104,91 +68,16 @@ public static byte[] createBytes(ClassNode cnode, int flags) { return cw.toByteArray(); } - public static byte[] writeMethods(String name, byte[] bytes, Multimap writers) { - if (writers.containsKey(name)) { - ClassNode cnode = createClassNode(bytes); - - for (MethodWriter mw : writers.get(name)) { - MethodNode mv = findMethod(mw.method, cnode); - if (mv == null) - mv = (MethodNode) cnode.visitMethod(mw.access, mw.method.s_name, mw.method.s_desc, null, mw.exceptions); - - mv.access = mw.access; - mv.instructions.clear(); - mw.write(mv); - } - - bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); - } - return bytes; - } - - public static byte[] injectMethods(String name, byte[] bytes, Multimap injectors) { - if (injectors.containsKey(name)) { - ClassNode cnode = createClassNode(bytes); - - for (MethodInjector injector : injectors.get(name)) { - MethodNode method = findMethod(injector.method, cnode); - if (method == null) - throw new RuntimeException("Method not found: " + injector.method); - System.out.println("Injecting into " + injector.method + "\n" + printInsnList(injector.injection)); - - List callNodes; - if (injector.before) - callNodes = InstructionComparator.insnListFindStart(method.instructions, injector.needle); - else - callNodes = InstructionComparator.insnListFindEnd(method.instructions, injector.needle); - - if (callNodes.size() == 0) { - throw new RuntimeException("Needle not found in Haystack: " + injector.method + "\n" + printInsnList(injector.needle)); - } - - for (AbstractInsnNode node : callNodes) { - if (injector.before) { - System.out.println("Injected before: " + printInsn(node)); - method.instructions.insertBefore(node, cloneInsnList(injector.injection)); - } else { - System.out.println("Injected after: " + printInsn(node)); - method.instructions.insert(node, cloneInsnList(injector.injection)); - } - } - } - - bytes = createBytes(cnode, ClassWriter.COMPUTE_FRAMES); - } - return bytes; - } - - public static String printInsnList(InsnList list) { - InsnListPrinter p = new InsnListPrinter(); - p.visitInsnList(list); - return p.textString(); - } - - public static String printInsn(AbstractInsnNode insn) { - InsnListPrinter p = new InsnListPrinter(); - p.visitInsn(insn); - return p.textString(); + public static Map cloneLabels(InsnList list) { + return new InsnListSection(list).cloneLabels(); } - public static Map cloneLabels(InsnList insns) { - HashMap labelMap = new HashMap(); - for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) - if (insn.getType() == 8) - labelMap.put((LabelNode) insn, new LabelNode()); - return labelMap; + public static InsnList cloneInsnList(InsnList list) { + return new InsnListSection(list).copy().list; } - public static InsnList cloneInsnList(InsnList insns) { - return cloneInsnList(cloneLabels(insns), insns); - } - - public static InsnList cloneInsnList(Map labelMap, InsnList insns) { - InsnList clone = new InsnList(); - for (AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) - clone.add(insn.clone(labelMap)); - - return clone; + public static InsnList cloneInsnList(Map labelMap, InsnList list) { + return new InsnListSection(list).copy(labelMap).list; } public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) { @@ -204,7 +93,7 @@ public static List cloneTryCatchBlocks(Map cloneLocals(Map labelMap, List locals) { - ArrayList clone = new ArrayList(); + ArrayList clone = new ArrayList(locals.size()); for (LocalVariableNode node : locals) clone.add(new LocalVariableNode( node.name, node.desc, node.signature, @@ -226,28 +115,8 @@ public static void copy(MethodNode src, MethodNode dst) { dst.visitMaxs(src.maxStack, src.maxLocals); } - public static byte[] alterMethods(String name, byte[] bytes, HashMultimap altercators) { - if (altercators.containsKey(name)) { - ClassNode cnode = createClassNode(bytes); - - for (MethodAltercator injector : altercators.get(name)) { - MethodNode method = findMethod(injector.method, cnode); - if (method == null) - throw new RuntimeException("Method not found: " + injector.method); - - injector.alter(method); - } - - bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); - } - return bytes; - } - - - public static String printInsnList(InsnListSection subsection) { - InsnListPrinter p = new InsnListPrinter(); - p.visitInsnList(subsection); - return p.textString(); + public static String toString(InsnList list) { + return new InsnListSection(list).toString(); } public static int getLocal(List list, String name) { @@ -263,7 +132,7 @@ public static int getLocal(List list, String name) { return found; } - public static void replaceMethodCode(MethodNode original, MethodNode replacement) { + public static void replaceMethod(MethodNode original, MethodNode replacement) { original.instructions.clear(); if (original.localVariables != null) original.localVariables.clear(); @@ -272,14 +141,51 @@ public static void replaceMethodCode(MethodNode original, MethodNode replacement replacement.accept(original); } - public static void removeBlock(InsnList insns, InsnListSection block) { - AbstractInsnNode insn = block.first; - while (true) { - AbstractInsnNode next = insn.getNext(); - insns.remove(insn); - if (insn == block.last) - break; - insn = next; + public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals) { + try { + if(!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + if(!file.exists()) + file.createNewFile(); + + PrintWriter pout = new PrintWriter(file); + ClassVisitor cv = new TraceClassVisitor(pout); + if(filterImportant) cv = new ImportantInsnVisitor(cv); + if(sortLocals) cv = new LocalVariablesSorterVisitor(cv); + acceptor.accept(cv); + pout.close(); + } catch (IOException e) { + throw new RuntimeException(e); } } + + public static void dump(final byte[] bytes, File file, boolean filterImportant, boolean sortLocals) { + dump(new Acceptor() + { + @Override + public void accept(ClassVisitor cv) { + new ClassReader(bytes).accept(cv, ClassReader.EXPAND_FRAMES); + } + }, file, filterImportant, sortLocals); + } + + public static void dump(final InputStream is, File file, boolean filterImportant, boolean sortLocals) { + dump(new Acceptor() + { + @Override + public void accept(ClassVisitor cv) throws IOException { + new ClassReader(is).accept(cv, ClassReader.EXPAND_FRAMES); + } + }, file, filterImportant, sortLocals); + } + + public static void dump(final ClassNode cnode, File file, boolean filterImportant, boolean sortLocals) { + dump(new Acceptor() + { + @Override + public void accept(ClassVisitor cv) { + cnode.accept(cv); + } + }, file, filterImportant, sortLocals); + } } diff --git a/src/codechicken/lib/asm/ASMReader.java b/src/codechicken/lib/asm/ASMReader.java index ce1aa5b..e5ca2d2 100644 --- a/src/codechicken/lib/asm/ASMReader.java +++ b/src/codechicken/lib/asm/ASMReader.java @@ -1,67 +1,22 @@ package codechicken.lib.asm; -import com.google.common.collect.ImmutableMap; import org.objectweb.asm.tree.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.tree.AbstractInsnNode.*; public class ASMReader { - public static class ASMBlock - { - public InsnList insns = new InsnList(); - private HashMap labels = new HashMap(); - - public LabelNode getOrAdd(String s) - { - LabelNode l = get(s); - if(l == null) - labels.put(s, l = new LabelNode()); - return l; - } - - public LabelNode get(String s) - { - return labels.get(s); - } - - public void replace(String s, LabelNode l) - { - LabelNode old = get(s); - if(old != null) - { - Map map = ImmutableMap.of(old, l); - for(AbstractInsnNode insn = insns.getFirst(); insn != null; insn = insn.getNext()) - { - switch(insn.getType()) - { - case JUMP_INSN: - case FRAME: - case LOOKUPSWITCH_INSN: - case TABLESWITCH_INSN: - case LABEL: - insns.insert(insn, insn.clone(map)); - insns.remove(insn); - } - } - } - labels.put(s, l); - } - } - public static Map opCodes = new HashMap(); public static byte[] TYPE; - - static - { + + static { opCodes.put("NOP", NOP); opCodes.put("ACONST_NULL", ACONST_NULL); opCodes.put("ICONST_M1", ICONST_M1); @@ -219,7 +174,7 @@ public void replace(String s, LabelNode l) opCodes.put("MULTIANEWARRAY", MULTIANEWARRAY); opCodes.put("IFNULL", IFNULL); opCodes.put("IFNONNULL", IFNONNULL); - + //derived from classWriter, mapped to AbstractInsnNode TYPE = new byte[200]; String s = "AAAAAAAAAAAAAAAABBJ__CCCCC____________________AAAAAAAACC" @@ -230,95 +185,89 @@ public void replace(String s, LabelNode l) TYPE[i] = (byte) (s.charAt(i) - 'A'); } - public static Map loadResource(String res) - { + public static Map loadResource(String res) { return loadResource(ASMHelper.class.getResourceAsStream(res), res); } - - public static Map loadResource(InputStream in, String res) - { + + public static Map loadResource(InputStream in, String res) { HashMap blocks = new HashMap(); String current = "unnamed"; ASMBlock block = new ASMBlock(); - try - { + try { BufferedReader r = new BufferedReader(new InputStreamReader(in)); String line; - while((line = r.readLine()) != null) - { + while ((line = r.readLine()) != null) { { int hpos = line.indexOf('#'); - if(hpos >= 0) line = line.substring(0, hpos); + if (hpos >= 0) line = line.substring(0, hpos); } line = line.trim(); - if(line.length() == 0) continue; - if(line.startsWith("list ")) - { - if(block.insns.size() > 0) blocks.put(current, block); + if (line.length() == 0) continue; + if (line.startsWith("list ")) { + if (block.list.size() > 0) blocks.put(current, block); current = line.substring(5); block = new ASMBlock(); continue; } - - try - { + + try { AbstractInsnNode insn = null; String[] split = line.replace(" : ", ":").split(" "); Integer i_opcode = opCodes.get(split[0]); - if(i_opcode == null) - { - if(split[0].equals("LINENUMBER")) + if (i_opcode == null) { + if (split[0].equals("LINENUMBER")) insn = new LineNumberNode(Integer.parseInt(split[1]), block.getOrAdd(split[2])); - else if(split[0].startsWith("L")) + else if (split[0].startsWith("L")) insn = block.getOrAdd(split[0]); else throw new Exception("Unknown opcode " + split[0]); - } - else - { + } else { int opcode = i_opcode; - switch(TYPE[opcode]) - { + switch (TYPE[opcode]) { case INSN: insn = new InsnNode(opcode); - break; + break; case INT_INSN: insn = new IntInsnNode(opcode, Integer.parseInt(split[1])); - break; + break; case VAR_INSN: insn = new VarInsnNode(opcode, Integer.parseInt(split[1])); - break; + break; case TYPE_INSN: insn = new ObfMapping(split[1]).toClassloading().toInsn(opcode); - break; + break; case FIELD_INSN: case METHOD_INSN: StringBuilder sb = new StringBuilder(); - for(int i = 1; i < split.length; i++) + for (int i = 1; i < split.length; i++) sb.append(split[i]); insn = ObfMapping.fromDesc(sb.toString()).toClassloading().toInsn(opcode); - break; + break; case INVOKE_DYNAMIC_INSN: throw new Exception("Found INVOKEDYNAMIC while reading"); case JUMP_INSN: insn = new JumpInsnNode(opcode, block.getOrAdd(split[1])); - break; + break; case LDC_INSN: String cst = split[1]; - if(cst.contains("")) - insn = new LdcInsnNode(cst.substring(1, cst.length()-1)); - else if(cst.endsWith("L")) - insn = new LdcInsnNode(Long.valueOf(cst.substring(0, cst.length()-1))); - else if(cst.endsWith("F")) - insn = new LdcInsnNode(Float.valueOf(cst.substring(0, cst.length()-1))); - else if(cst.endsWith("D")) - insn = new LdcInsnNode(Double.valueOf(cst.substring(0, cst.length()-1))); + if(cst.equals("*")) + insn = new LdcInsnNode(null); + else if (cst.endsWith("\"")) + insn = new LdcInsnNode(cst.substring(1, cst.length() - 1)); + else if (cst.endsWith("L")) + insn = new LdcInsnNode(Long.valueOf(cst.substring(0, cst.length() - 1))); + else if (cst.endsWith("F")) + insn = new LdcInsnNode(Float.valueOf(cst.substring(0, cst.length() - 1))); + else if (cst.endsWith("D")) + insn = new LdcInsnNode(Double.valueOf(cst.substring(0, cst.length() - 1))); + else if (cst.contains(".")) + insn = new LdcInsnNode(Double.valueOf(cst)); else insn = new LdcInsnNode(Integer.valueOf(cst)); - break; + break; case IINC_INSN: insn = new IincInsnNode(opcode, Integer.parseInt(split[1])); - break; + break; case LABEL: throw new Exception("Use L# for labels"); case TABLESWITCH_INSN: @@ -326,29 +275,25 @@ else if(cst.endsWith("D")) throw new Exception("I don't know how to deal with this insn type"); case MULTIANEWARRAY_INSN: insn = new MultiANewArrayInsnNode(split[1], Integer.parseInt(split[2])); - break; + break; case FRAME: throw new Exception("Use ClassWriter.COMPUTE_FRAMES"); } } - - if(insn != null) - block.insns.add(insn); - } - catch(Exception e) - { - System.err.println("Error while reading ASM Block "+ - current+" from "+res+", line: "+line); + + if (insn != null) + block.list.add(insn); + } catch (Exception e) { + System.err.println("Error while reading ASM Block " + + current + " from " + res + ", line: " + line); e.printStackTrace(); } } - + r.close(); - if(block.insns.size() > 0) blocks.put(current, block); - } - catch(IOException e) - { - throw new RuntimeException("Failed to read ASM resource: "+res, e); + if (block.list.size() > 0) blocks.put(current, block); + } catch (IOException e) { + throw new RuntimeException("Failed to read ASM resource: " + res, e); } return blocks; } diff --git a/src/codechicken/lib/asm/ImportantInsnVisitor.java b/src/codechicken/lib/asm/ImportantInsnVisitor.java new file mode 100644 index 0000000..6af770f --- /dev/null +++ b/src/codechicken/lib/asm/ImportantInsnVisitor.java @@ -0,0 +1,36 @@ +package codechicken.lib.asm; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +public class ImportantInsnVisitor extends ClassVisitor +{ + public class ImportantInsnMethodVisitor extends MethodVisitor + { + MethodVisitor delegate; + + public ImportantInsnMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) { + super(Opcodes.ASM4, new MethodNode(access, name, desc, signature, exceptions)); + delegate = cv.visitMethod(access, name, desc, signature, exceptions); + } + + @Override + public void visitEnd() { + super.visitEnd(); + MethodNode mnode = (MethodNode)mv; + mnode.instructions = InsnComparator.getImportantList(mnode.instructions); + mnode.accept(delegate); + } + } + + public ImportantInsnVisitor(ClassVisitor cv) { + super(Opcodes.ASM4, cv); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + return new ImportantInsnMethodVisitor(access, name, desc, signature, exceptions); + } +} diff --git a/src/codechicken/lib/asm/InsnComparator.java b/src/codechicken/lib/asm/InsnComparator.java new file mode 100644 index 0000000..5ec9cf0 --- /dev/null +++ b/src/codechicken/lib/asm/InsnComparator.java @@ -0,0 +1,189 @@ +package codechicken.lib.asm; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import org.objectweb.asm.tree.*; + +import java.util.*; + +import static org.objectweb.asm.tree.AbstractInsnNode.*; + +public class InsnComparator +{ + public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2) { + return insn1.var == -1 || insn2.var == -1 || insn1.var == insn2.var; + } + + public static boolean methodInsnEqual(MethodInsnNode insn1, MethodInsnNode insn2) { + return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc); + } + + public static boolean fieldInsnEqual(FieldInsnNode insn1, FieldInsnNode insn2) { + return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc); + } + + public static boolean ldcInsnEqual(LdcInsnNode insn1, LdcInsnNode insn2) { + return insn1.cst == null || insn2.cst == null || insn1.cst.equals(insn2.cst); + } + + public static boolean typeInsnEqual(TypeInsnNode insn1, TypeInsnNode insn2) { + return insn1.desc.equals("*") || insn2.desc.equals("*") || insn1.desc.equals(insn2.desc); + } + + public static boolean iincInsnEqual(IincInsnNode node1, IincInsnNode node2) { + return node1.var == node2.var && node1.incr == node2.incr; + } + + public static boolean intInsnEqual(IntInsnNode node1, IntInsnNode node2) { + return node1.operand == -1 || node2.operand == -1 || node1.operand == node2.operand; + } + + public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) { + if (node1.getOpcode() != node2.getOpcode()) + return false; + + switch (node2.getType()) { + case VAR_INSN: + return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); + case TYPE_INSN: + return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); + case FIELD_INSN: + return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); + case METHOD_INSN: + return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); + case LDC_INSN: + return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); + case IINC_INSN: + return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); + case INT_INSN: + return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2); + default: + return true; + } + } + + public static boolean insnImportant(AbstractInsnNode insn, Set controlFlowLabels) { + switch(insn.getType()) { + case LINE: + case FRAME: + return false; + case LABEL: + return controlFlowLabels.contains(insn); + default: + return true; + } + } + + public static Set getControlFlowLabels(InsnListSection list) { + return getControlFlowLabels(list.list); + } + + public static Set getControlFlowLabels(InsnList list) { + HashSet controlFlowLabels = new HashSet(); + for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) { + switch (insn.getType()) { + case JUMP_INSN: + JumpInsnNode jinsn = (JumpInsnNode) insn; + controlFlowLabels.add(jinsn.label); + break; + case TABLESWITCH_INSN: + TableSwitchInsnNode tsinsn = (TableSwitchInsnNode) insn; + controlFlowLabels.add(tsinsn.dflt); + for (LabelNode label : tsinsn.labels) + controlFlowLabels.add(label); + break; + case LOOKUPSWITCH_INSN: + LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode) insn; + controlFlowLabels.add(lsinsn.dflt); + for (LabelNode label : lsinsn.labels) + controlFlowLabels.add(label); + break; + } + } + return controlFlowLabels; + } + + public static InsnList getImportantList(InsnList list) { + return getImportantList(new InsnListSection(list)).list; + } + + public static InsnListSection getImportantList(InsnListSection list) { + if (list.size() == 0) + return list; + + Set controlFlowLabels = getControlFlowLabels(list); + Map labelMap = Maps.asMap(controlFlowLabels, new Function() + { + @Override + public LabelNode apply(LabelNode input) { + return input; + } + }); + + InsnListSection importantNodeList = new InsnListSection(); + for(AbstractInsnNode insn : list) + if (insnImportant(insn, controlFlowLabels)) + importantNodeList.add(insn.clone(labelMap)); + + return importantNodeList; + } + + public static List find(InsnListSection haystack, InsnListSection needle) { + Set controlFlowLabels = getControlFlowLabels(haystack); + LinkedList list = new LinkedList(); + for (int start = 0; start <= haystack.size() - needle.size(); start++) { + InsnListSection section = matches(haystack.drop(start), needle, controlFlowLabels); + if (section != null) { + list.add(section); + start = section.end-1; + } + } + + return list; + } + + public static List find(InsnList haystack, InsnListSection needle) { + return find(new InsnListSection(haystack), needle); + } + + public static InsnListSection matches(InsnListSection haystack, InsnListSection needle, Set controlFlowLabels) { + int h = 0, n = 0; + for (; h < haystack.size() && n < needle.size(); h++) { + AbstractInsnNode insn = haystack.get(h); + if(!insnImportant(insn, controlFlowLabels)) + continue; + + if (!insnEqual(haystack.get(h), needle.get(n))) + return null; + n++; + } + if (n != needle.size()) + return null; + + return haystack.take(h); + } + + public static InsnListSection findOnce(InsnListSection haystack, InsnListSection needle) { + List list = find(haystack, needle); + if(list.size() != 1) + throw new RuntimeException("Needle found " + list.size() + " times in Haystack:\n" + haystack + "\n\n" + needle); + + return list.get(0); + } + + public static InsnListSection findOnce(InsnList haystack, InsnListSection needle) { + return findOnce(new InsnListSection(haystack), needle); + } + + public static List findN(InsnListSection haystack, InsnListSection needle) { + List list = find(haystack, needle); + if(list.isEmpty()) + throw new RuntimeException("Needle not found in Haystack:\n" + haystack + "\n\n" + needle); + + return list; + } + + public static List findN(InsnList haystack, InsnListSection needle) { + return findN(new InsnListSection(haystack), needle); + } +} diff --git a/src/codechicken/lib/asm/InsnListPrinter.java b/src/codechicken/lib/asm/InsnListPrinter.java deleted file mode 100644 index 5c3c078..0000000 --- a/src/codechicken/lib/asm/InsnListPrinter.java +++ /dev/null @@ -1,197 +0,0 @@ -package codechicken.lib.asm; - -import codechicken.lib.asm.InstructionComparator.InsnListSection; -import org.objectweb.asm.Label; -import org.objectweb.asm.tree.*; -import org.objectweb.asm.util.Textifier; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.HashMap; - -public class InsnListPrinter extends Textifier -{ - private boolean buildingLabelMap = false; - - public void visitInsnList(InsnList list) - { - text.clear(); - if(labelNames == null) - labelNames = new HashMap(); - else - labelNames.clear(); - - buildingLabelMap = true; - for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) - if(insn.getType() == 8) - visitLabel(((LabelNode)insn).getLabel()); - - text.clear(); - buildingLabelMap = false; - - for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) - _visitInsn(insn); - } - - public void visitInsnList(InsnListSection subsection) - { - text.clear(); - if(labelNames == null) - labelNames = new HashMap(); - else - labelNames.clear(); - - buildingLabelMap = true; - { - AbstractInsnNode insn = subsection.first; - while(true) - { - if(insn.getType() == 8) - visitLabel(((LabelNode)insn).getLabel()); - if(insn == subsection.last) - break; - insn = insn.getNext(); - } - } - - text.clear(); - buildingLabelMap = false; - - { - AbstractInsnNode insn = subsection.first; - while(true) - { - _visitInsn(insn); - if(insn == subsection.last) - break; - insn = insn.getNext(); - } - } - } - - public void visitInsn(AbstractInsnNode insn) - { - text.clear(); - if(labelNames == null) - labelNames = new HashMap(); - else - labelNames.clear(); - - _visitInsn(insn); - } - - private void _visitInsn(AbstractInsnNode insn) - { - switch(insn.getType()) - { - case 0: - visitInsn(insn.getOpcode()); - break; - case 1: - IntInsnNode iinsn = (IntInsnNode)insn; - visitIntInsn(iinsn.getOpcode(), iinsn.operand); - break; - case 2: - VarInsnNode vinsn = (VarInsnNode)insn; - visitVarInsn(vinsn.getOpcode(), vinsn.var); - break; - case 3: - TypeInsnNode tinsn = (TypeInsnNode)insn; - visitTypeInsn(tinsn.getOpcode(), tinsn.desc); - break; - case 4: - FieldInsnNode finsn = (FieldInsnNode)insn; - visitFieldInsn(finsn.getOpcode(), finsn.owner, finsn.name, finsn.desc); - break; - case 5: - MethodInsnNode minsn = (MethodInsnNode)insn; - visitMethodInsn(minsn.getOpcode(), minsn.owner, minsn.name, minsn.desc); - break; - case 6: - InvokeDynamicInsnNode idinsn = (InvokeDynamicInsnNode)insn; - visitInvokeDynamicInsn(idinsn.name, idinsn.desc, idinsn.bsm, idinsn.bsmArgs); - break; - case 7: - JumpInsnNode jinsn = (JumpInsnNode)insn; - visitJumpInsn(jinsn.getOpcode(), jinsn.label.getLabel()); - break; - case 8: - LabelNode linsn = (LabelNode)insn; - visitLabel(linsn.getLabel()); - break; - case 9: - LdcInsnNode ldcinsn = (LdcInsnNode)insn; - visitLdcInsn(ldcinsn.cst); - break; - case 10: - IincInsnNode iiinsn = (IincInsnNode)insn; - visitIincInsn(iiinsn.var, iiinsn.incr); - break; - case 11: - TableSwitchInsnNode tsinsn = (TableSwitchInsnNode)insn; - Label[] tslables = new Label[tsinsn.labels.size()]; - for(int i = 0; i < tslables.length; i++) - tslables[i] = tsinsn.labels.get(i).getLabel(); - visitTableSwitchInsn(tsinsn.min, tsinsn.max, tsinsn.dflt.getLabel(), tslables); - break; - case 12: - LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode)insn; - Label[] lslables = new Label[lsinsn.labels.size()]; - for(int i = 0; i < lslables.length; i++) - lslables[i] = lsinsn.labels.get(i).getLabel(); - int[] lskeys = new int[lsinsn.keys.size()]; - for(int i = 0; i < lskeys.length; i++) - lskeys[i] = lsinsn.keys.get(i); - visitLookupSwitchInsn(lsinsn.dflt.getLabel(), lskeys, lslables); - break; - case 13: - MultiANewArrayInsnNode ainsn = (MultiANewArrayInsnNode)insn; - visitMultiANewArrayInsn(ainsn.desc, ainsn.dims); - break; - case 14: - FrameNode fnode = (FrameNode)insn; - switch(fnode.type) - { - case -1: - case 0: - visitFrame(fnode.type, fnode.local.size(), fnode.local.toArray(), fnode.stack.size(), fnode.stack.toArray()); - break; - case 1: - visitFrame(fnode.type, fnode.local.size(), fnode.local.toArray(), 0, null); - break; - case 2: - visitFrame(fnode.type, fnode.local.size(), null, 0, null); - break; - case 3: - visitFrame(fnode.type, 0, null, 0, null); - break; - case 4: - visitFrame(fnode.type, 0, null, 1, fnode.stack.toArray()); - } - break; - case 15: - LineNumberNode lnode = (LineNumberNode)insn; - visitLineNumber(lnode.line, lnode.start.getLabel()); - break; - } - } - - @Override - public void visitLabel(Label label) - { - if(!buildingLabelMap && !labelNames.containsKey(label)) - { - labelNames.put(label, "LEXT"+labelNames.size()); - } - super.visitLabel(label); - } - - public String textString() - { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - print(pw); - pw.flush(); - return sw.toString(); - } -} diff --git a/src/codechicken/lib/asm/InsnListSection.java b/src/codechicken/lib/asm/InsnListSection.java new file mode 100644 index 0000000..bdadda2 --- /dev/null +++ b/src/codechicken/lib/asm/InsnListSection.java @@ -0,0 +1,241 @@ +package codechicken.lib.asm; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.tree.*; +import org.objectweb.asm.util.Textifier; +import org.objectweb.asm.util.TraceMethodVisitor; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import static org.objectweb.asm.tree.AbstractInsnNode.*; + +/** + * A section of an InsnList, may become invalid if the insn list is modified + */ +public class InsnListSection implements Iterable +{ + private class InsnListSectionIterator implements Iterator + { + int i = 0; + + @Override + public boolean hasNext() { + return i < size(); + } + + @Override + public AbstractInsnNode next() { + return get(i++); + } + + @Override + public void remove() { + InsnListSection.this.remove(--i); + } + } + + public InsnList list; + public int start; + public int end; + + public InsnListSection(InsnList list, int start, int end) { + this.list = list; + this.start = start; + this.end = end; + } + + public InsnListSection(InsnList list, AbstractInsnNode first, AbstractInsnNode last) { + this(list, list.indexOf(first), list.indexOf(last)+1); + } + + public InsnListSection(InsnList list) { + this(list, 0, list.size()); + } + + public InsnListSection() { + this(new InsnList()); + } + + public void accept(MethodVisitor mv) { + for(AbstractInsnNode insn : this) + insn.accept(mv); + } + + public AbstractInsnNode getFirst() { + return size() == 0 ? null : list.get(start); + } + + public AbstractInsnNode getLast() { + return size() == 0 ? null : list.get(end - 1); + } + + public int size() { + return end - start; + } + + public AbstractInsnNode get(int i) { + return list.get(start + i); + } + + public void set(int i, AbstractInsnNode insn) { + list.set(get(i), insn); + } + + public void remove(int i) { + list.remove(get(i)); + end--; + } + + public void replace(AbstractInsnNode location, AbstractInsnNode insn) { + list.set(location, insn); + } + + public void add(AbstractInsnNode insn) { + list.add(insn); + end++; + } + + public void insertBefore(InsnList insns) { + int s = insns.size(); + if(this.list.size() == 0) + list.insert(insns); + else + list.insertBefore(list.get(start), insns); + start+=s; + end+=s; + } + + public void insert(InsnList insns) { + if(end == 0) + list.insert(insns); + else + list.insert(list.get(end-1), insns); + } + + public void replace(InsnList insns) { + int s = insns.size(); + remove(); + insert(insns); + end = start+s; + } + + public void remove() { + while(end != start) + remove(0); + } + + public void setLast(AbstractInsnNode last) { + end = list.indexOf(last)+1; + } + + public void setFirst(AbstractInsnNode first) { + start = list.indexOf(first); + } + + public InsnListSection drop(int n) { + return slice(n, size()); + } + + public InsnListSection take(int n) { + return slice(0, n); + } + + public InsnListSection slice(int start, int end) { + return new InsnListSection(list, this.start+start, this.start+end); + } + + /** + * Removes leading and trailing labels and line number nodes that don't affect control flow + * @return this + */ + public InsnListSection trim(Set controlFlowLabels) { + while(start < end && !InsnComparator.insnImportant(getFirst(), controlFlowLabels)) + start++; + + while(start < end && !InsnComparator.insnImportant(getLast(), controlFlowLabels)) + end--; + + return this; + } + + public String toString() { + Textifier t = new Textifier(); + accept(new TraceMethodVisitor(t)); + StringWriter sw = new StringWriter(); + t.print(new PrintWriter(sw)); + return sw.toString(); + } + + public void println() { + System.out.println(toString()); + } + + public HashMap identityLabelMap() { + HashMap labelMap = new HashMap(); + for (AbstractInsnNode insn : this) + switch(insn.getType()) { + case LABEL: + labelMap.put((LabelNode) insn, (LabelNode) insn); + break; + case JUMP_INSN: + labelMap.put(((JumpInsnNode)insn).label, ((JumpInsnNode)insn).label); + break; + case LOOKUPSWITCH_INSN: + LookupSwitchInsnNode linsn = (LookupSwitchInsnNode)insn; + labelMap.put(linsn.dflt, linsn.dflt); + for(LabelNode label : linsn.labels) + labelMap.put(label, label); + break; + case TABLESWITCH_INSN: + TableSwitchInsnNode tinsn = (TableSwitchInsnNode)insn; + labelMap.put(tinsn.dflt, tinsn.dflt); + for(LabelNode label : tinsn.labels) + labelMap.put(label, label); + break; + case FRAME: + FrameNode fnode = (FrameNode)insn; + if(fnode.local != null) + for(Object o : fnode.local) + if(o instanceof LabelNode) + labelMap.put((LabelNode) o, (LabelNode) o); + if(fnode.stack != null) + for(Object o : fnode.stack) + if(o instanceof LabelNode) + labelMap.put((LabelNode) o, (LabelNode) o); + break; + } + + return labelMap; + } + + public Map cloneLabels() { + Map labelMap = identityLabelMap(); + for(Entry entry : labelMap.entrySet()) + entry.setValue(new LabelNode()); + + return labelMap; + } + + public InsnListSection copy() { + return copy(cloneLabels()); + } + + public InsnListSection copy(Map labelMap) { + InsnListSection copy = new InsnListSection(); + for(AbstractInsnNode insn : this) + copy.add(insn.clone(labelMap)); + + return copy; + } + + @Override + public Iterator iterator() { + return new InsnListSectionIterator(); + } +} \ No newline at end of file diff --git a/src/codechicken/lib/asm/InstructionComparator.java b/src/codechicken/lib/asm/InstructionComparator.java deleted file mode 100644 index 9e516b1..0000000 --- a/src/codechicken/lib/asm/InstructionComparator.java +++ /dev/null @@ -1,239 +0,0 @@ -package codechicken.lib.asm; - -import org.objectweb.asm.tree.*; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -public class InstructionComparator -{ - public static class InsnListSection - { - public InsnListSection(AbstractInsnNode first, AbstractInsnNode last) - { - this.first = first; - this.last = last; - } - - public InsnListSection(InsnList haystack, int start, int end) - { - this(haystack.get(start), haystack.get(end)); - } - - public AbstractInsnNode first; - public AbstractInsnNode last; - } - - public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2) - { - if(insn1.var == -1 || insn2.var == -1) - return true; - - return insn1.var == insn2.var; - } - - public static boolean methodInsnEqual(AbstractInsnNode absnode, int Opcode, ObfMapping method) - { - if(!(absnode instanceof MethodInsnNode) || absnode.getOpcode() != Opcode) - return false; - - return method.matches((MethodInsnNode)absnode); - } - - public static boolean methodInsnEqual(MethodInsnNode insn1, MethodInsnNode insn2) - { - return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc); - } - - public static boolean fieldInsnEqual(FieldInsnNode insn1, FieldInsnNode insn2) - { - return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc); - } - - public static boolean ldcInsnEqual(LdcInsnNode insn1, LdcInsnNode insn2) - { - if(insn1.cst.equals("~") || insn2.cst.equals("~")) - return true; - - return insn1.cst.equals(insn2.cst); - } - - public static boolean typeInsnEqual(TypeInsnNode insn1, TypeInsnNode insn2) - { - if(insn1.desc.equals("~") || insn2.desc.equals("~")) - return true; - - return insn1.desc.equals(insn2.desc); - } - - public static boolean iincInsnEqual(IincInsnNode node1, IincInsnNode node2) - { - return node1.var == node2.var && node1.incr == node2.incr; - } - - public static boolean intInsnEqual(IntInsnNode node1, IntInsnNode node2) - { - if(node1.operand == -1 || node2.operand == -1) - return true; - - return node1.operand == node2.operand; - } - - public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) - { - if(node1.getOpcode() != node2.getOpcode()) - return false; - - switch(node2.getType()) - { - case VAR_INSN: - return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2); - case TYPE_INSN: - return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2); - case FIELD_INSN: - return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2); - case METHOD_INSN: - return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2); - case LDC_INSN: - return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2); - case IINC_INSN: - return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2); - case INT_INSN: - return intInsnEqual((IntInsnNode)node1, (IntInsnNode)node2); - default: - return true; - } - } - - public static InsnList getImportantList(InsnList list) - { - if(list.size() == 0) - return list; - - HashMap labels = new HashMap(); - for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) - { - if(insn instanceof LabelNode) - labels.put((LabelNode)insn, (LabelNode)insn); - } - - InsnList importantNodeList = new InsnList(); - for(AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) - { - if(insn instanceof LabelNode || insn instanceof LineNumberNode) - continue; - - importantNodeList.add(insn.clone(labels)); - } - return importantNodeList; - } - - public static boolean insnListMatches(InsnList haystack, InsnList needle, int start) - { - if(haystack.size()-start < needle.size()) - return false; - - for(int i = 0; i < needle.size(); i++) - { - if(!insnEqual(haystack.get(i+start), needle.get(i))) - return false; - } - return true; - } - - public static List insnListFind(InsnList haystack, InsnList needle) - { - LinkedList list = new LinkedList(); - for(int start = 0; start <= haystack.size()-needle.size(); start++) - if(insnListMatches(haystack, needle, start)) - list.add(start); - - return list; - } - - public static List insnListFindStart(InsnList haystack, InsnList needle) - { - LinkedList callNodes = new LinkedList(); - for(int callPoint : insnListFind(haystack, needle)) - callNodes.add(haystack.get(callPoint)); - return callNodes; - } - - public static List insnListFindEnd(InsnList haystack, InsnList needle) - { - LinkedList callNodes = new LinkedList(); - for(int callPoint : insnListFind(haystack, needle)) - callNodes.add(haystack.get(callPoint+needle.size()-1)); - return callNodes; - } - - public static List insnListFindL(InsnList haystack, InsnList needle) - { - HashSet controlFlowLabels = new HashSet(); - - for(AbstractInsnNode insn = haystack.getFirst(); insn != null; insn = insn.getNext()) - { - switch(insn.getType()) - { - case 8: - case 15: - break; - case 7: - JumpInsnNode jinsn = (JumpInsnNode)insn; - controlFlowLabels.add(jinsn.label); - break; - case 11: - TableSwitchInsnNode tsinsn = (TableSwitchInsnNode)insn; - for(LabelNode label : tsinsn.labels) - controlFlowLabels.add(label); - break; - case 12: - LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode)insn; - for(LabelNode label : lsinsn.labels) - controlFlowLabels.add(label); - break; - } - } - - LinkedList list = new LinkedList(); - nextsection: for(int start = 0; start <= haystack.size()-needle.size(); start++) - { - InsnListSection section = insnListMatchesL(haystack, needle, start, controlFlowLabels); - if(section != null) - { - for(InsnListSection asection : list) - if(asection.last == section.last) - continue nextsection; - - list.add(section); - } - } - - return list; - } - - private static InsnListSection insnListMatchesL(InsnList haystack, InsnList needle, int start, HashSet controlFlowLabels) - { - int h = start, n = 0; - for(;h < haystack.size() && n < needle.size(); h++) - { - AbstractInsnNode insn = haystack.get(h); - if(insn.getType() == 15) - continue; - if(insn.getType() == 8 && !controlFlowLabels.contains(insn)) - continue; - - if(!insnEqual(haystack.get(h), needle.get(n))) - return null; - n++; - } - if(n != needle.size()) - return null; - - return new InsnListSection(haystack, start, h-1); - } -} diff --git a/src/codechicken/lib/asm/LocalVariablesSorterVisitor.java b/src/codechicken/lib/asm/LocalVariablesSorterVisitor.java new file mode 100644 index 0000000..e843da6 --- /dev/null +++ b/src/codechicken/lib/asm/LocalVariablesSorterVisitor.java @@ -0,0 +1,37 @@ +package codechicken.lib.asm; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.LocalVariablesSorter; + +import java.util.Set; + +public class LocalVariablesSorterVisitor extends ClassVisitor + { + public Set methods; + public String owner; + + public LocalVariablesSorterVisitor(Set methods, ClassVisitor cv) { + super(Opcodes.ASM4, cv); + this.methods = methods; + } + + public LocalVariablesSorterVisitor(ClassVisitor cv) { + this(null, cv); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + owner = name; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); + return methods == null || methods.contains(new ObfMapping(owner, name, desc)) ? new LocalVariablesSorter(access, desc, mv) : mv; + } + } + + \ No newline at end of file diff --git a/src/codechicken/lib/asm/ModularASMTransformer.java b/src/codechicken/lib/asm/ModularASMTransformer.java new file mode 100644 index 0000000..39e0d4c --- /dev/null +++ b/src/codechicken/lib/asm/ModularASMTransformer.java @@ -0,0 +1,285 @@ +package codechicken.lib.asm; + +import org.objectweb.asm.*; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.MethodNode; + +import java.io.File; +import java.util.*; + +import static codechicken.lib.asm.ASMHelper.*; + +public class ModularASMTransformer +{ + public static class ClassNodeTransformerList + { + List transformers = new LinkedList(); + HashSet methodsToSort = new HashSet(); + + public void add(ClassNodeTransformer t) { + transformers.add(t); + t.addMethodsToSort(methodsToSort); + } + + public byte[] transform(byte[] bytes) { + ClassNode cnode = new ClassNode(); + ClassReader reader = new ClassReader(bytes); + ClassVisitor cv = cnode; + if(!methodsToSort.isEmpty()) + cv = new LocalVariablesSorterVisitor(methodsToSort, cv); + reader.accept(cv, ClassReader.EXPAND_FRAMES); + + try { + int writeFlags = 0; + for(ClassNodeTransformer t : transformers) { + t.transform(cnode); + writeFlags|=t.writeFlags; + } + + bytes = createBytes(cnode, writeFlags); + if(config.getTag("dump_asm").getBooleanValue(true)) + dump(bytes, new File("asm/ccl_modular/"+cnode.name.replace('/', '#')+".txt"), false, false); + return bytes; + } catch (RuntimeException e) { + dump(bytes, new File("asm/ccl_modular/"+cnode.name.replace('/', '#')+".txt"), false, false); + throw e; + } + } + } + + public static abstract class ClassNodeTransformer + { + public int writeFlags; + public ClassNodeTransformer(int writeFlags) { + this.writeFlags = writeFlags; + } + + public ClassNodeTransformer() { + this(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + } + + public abstract String className(); + public abstract void transform(ClassNode cnode); + + public void addMethodsToSort(Set set) {} + } + + public static abstract class MethodTransformer extends ClassNodeTransformer + { + public final ObfMapping method; + + public MethodTransformer(ObfMapping method) { + this.method = method.toClassloading(); + } + + @Override + public String className() { + return method.javaClass(); + } + + @Override + public void transform(ClassNode cnode) { + MethodNode mv = findMethod(method, cnode); + if (mv == null) + throw new RuntimeException("Method not found: " + method); + + try { + transform(mv); + } catch (Exception e) { + throw new RuntimeException("Error transforming method: "+method, e); + } + } + + public abstract void transform(MethodNode mv); + } + + public static class MethodWriter extends ClassNodeTransformer + { + public final int access; + public final ObfMapping method; + public final String[] exceptions; + public InsnList list; + + public MethodWriter(int access, ObfMapping method) { + this(access, method, null, (InsnList)null); + } + + public MethodWriter(int access, ObfMapping method, InsnList list) { + this(access, method, null, list); + } + + public MethodWriter(int access, ObfMapping method, ASMBlock block) { + this(access, method, null, block); + } + + public MethodWriter(int access, ObfMapping method, String[] exceptions) { + this(access, method, exceptions, (InsnList)null); + } + + public MethodWriter(int access, ObfMapping method, String[] exceptions, InsnList list) { + this.access = access; + this.method = method.toClassloading(); + this.exceptions = exceptions; + this.list = list; + } + + public MethodWriter(int access, ObfMapping method, String[] exceptions, ASMBlock block) { + this(access, method, exceptions, block.rawListCopy()); + } + + @Override + public String className() { + return method.javaClass(); + } + + @Override + public void transform(ClassNode cnode) { + MethodNode mv = findMethod(method, cnode); + if(mv == null) + mv = (MethodNode) method.visitMethod(cnode, access, exceptions); + else { + mv.access = access; + mv.instructions.clear(); + if (mv.localVariables != null) + mv.localVariables.clear(); + if (mv.tryCatchBlocks != null) + mv.tryCatchBlocks.clear(); + } + + write(mv); + } + + public void write(MethodNode mv) { + logger.debug("Writing method "+method); + list.accept(mv); + } + } + + public static class MethodInjector extends MethodTransformer + { + public ASMBlock needle; + public ASMBlock injection; + public boolean before; + + public MethodInjector(ObfMapping method, ASMBlock needle, ASMBlock injection, boolean before) { + super(method); + this.needle = needle; + this.injection = injection; + this.before = before; + } + + public MethodInjector(ObfMapping method, ASMBlock injection, boolean before) { + this(method, null, injection, before); + } + + public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) { + this(method, new ASMBlock(needle), new ASMBlock(injection), before); + } + + public MethodInjector(ObfMapping method, InsnList injection, boolean before) { + this(method, null, new ASMBlock(injection), before); + } + + @Override + public void addMethodsToSort(Set set) { + set.add(method); + } + + @Override + public void transform(MethodNode mv) { + if(needle == null) { + logger.debug("Injecting "+(before ? "before" : "after")+" method "+method); + if (before) + mv.instructions.insert(injection.rawListCopy()); + else + mv.instructions.add(injection.rawListCopy()); + } + else { + for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) { + logger.debug("Injecting "+(before ? "before" : "after")+" method "+method+" @ "+key.start+" - "+key.end); + ASMBlock injectBlock = injection.copy().mergeLabels(needle.applyLabels(key)); + + if (before) + key.insertBefore(injectBlock.list.list); + else + key.insert(injectBlock.list.list); + } + } + } + } + + public static class MethodReplacer extends MethodTransformer + { + public ASMBlock needle; + public ASMBlock replacement; + + public MethodReplacer(ObfMapping method, ASMBlock needle, ASMBlock replacement) { + super(method); + this.needle = needle; + this.replacement = replacement; + } + + public MethodReplacer(ObfMapping method, InsnList needle, InsnList replacement) { + this(method, new ASMBlock(needle), new ASMBlock(replacement)); + } + + @Override + public void addMethodsToSort(Set set) { + set.add(method); + } + + @Override + public void transform(MethodNode mv) { + for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) { + logger.debug("Replacing method "+method+" @ "+key.start+" - "+key.end); + ASMBlock replaceBlock = replacement.copy().pullLabels(needle.applyLabels(key)); + key.insert(replaceBlock.list.list); + } + } + } + + public static class FieldWriter extends ClassNodeTransformer + { + public final ObfMapping field; + public final int access; + public final Object value; + + public FieldWriter(int access, ObfMapping field, Object value) { + this.field = field.toClassloading(); + this.access = access; + this.value = value; + } + + public FieldWriter(int access, ObfMapping field) { + this(access, field, null); + } + + @Override + public String className() { + return field.javaClass(); + } + + @Override + public void transform(ClassNode cnode) { + field.visitField(cnode, access, value); + } + } + + public HashMap transformers = new HashMap(); + + public void add(ClassNodeTransformer t) { + ClassNodeTransformerList list = transformers.get(t.className()); + if(list == null) + transformers.put(t.className(), list = new ClassNodeTransformerList()); + list.add(t); + } + + public byte[] transform(String name, byte[] bytes) { + if(bytes == null) + return null; + + ClassNodeTransformerList list = transformers.get(name); + return list == null ? bytes : list.transform(bytes); + } +} diff --git a/src/codechicken/lib/asm/ObfMapping.java b/src/codechicken/lib/asm/ObfMapping.java index 3f8d85d..c7c5579 100644 --- a/src/codechicken/lib/asm/ObfMapping.java +++ b/src/codechicken/lib/asm/ObfMapping.java @@ -1,6 +1,5 @@ package codechicken.lib.asm; -import codechicken.lib.config.ConfigFile; import codechicken.lib.config.ConfigTag; import com.google.common.base.Charsets; import com.google.common.base.Objects; @@ -9,6 +8,9 @@ import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.relauncher.FMLInjectionData; import net.minecraft.launchwrapper.Launch; +import net.minecraftforge.common.ForgeVersion; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.*; @@ -74,14 +76,9 @@ public String map(String typeName) { public static class MCPRemapper extends Remapper implements LineProcessor { - public static ConfigFile config; - public static File[] getConfFiles() { - if (config == null) - config = new ConfigFile(new File((File) FMLInjectionData.data()[6], "config/CodeChickenLib.cfg")).setComment("CodeChickenLib configuration file."); - - ConfigTag tag = config.getTag("dev.mappingDir").setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping"); - for (int i = 0; i < 6; i++) { + ConfigTag tag = ASMHelper.config.getTag("mappingDir").setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping"); + for (int i = 0; i < DIR_GUESSES+DIR_ASKS; i++) { File dir = confDirectoryGuess(i, tag); if (dir == null || dir.isFile()) continue; @@ -90,7 +87,7 @@ public static File[] getConfFiles() { try { mappings = parseConfDir(dir); } catch (Exception e) { - if (i >= 3) + if (i >= DIR_GUESSES) e.printStackTrace(); continue; } @@ -102,6 +99,8 @@ public static File[] getConfFiles() { throw new RuntimeException("Failed to select mappings directory, set it manually in the config"); } + private static final int DIR_GUESSES = 4; + private static final int DIR_ASKS = 3; public static File confDirectoryGuess(int i, ConfigTag tag) { File mcDir = (File) FMLInjectionData.data()[6]; switch (i) { @@ -111,6 +110,9 @@ public static File confDirectoryGuess(int i, ConfigTag tag) { return new File(mcDir, "../conf"); case 2: return new File(mcDir, "../build/unpacked/conf"); + case 3: + return new File(System.getProperty("user.home"), ".gradle/caches/minecraft/net/minecraftforge/forge/"+ + FMLInjectionData.data()[4]+"-"+ ForgeVersion.getVersion()+"/unpacked/conf"); default: JFileChooser fc = new JFileChooser(mcDir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -281,6 +283,14 @@ public void visitFieldInsn(MethodVisitor mv, int opcode) { mv.visitFieldInsn(opcode, s_owner, s_name, s_desc); } + public MethodVisitor visitMethod(ClassVisitor visitor, int access, String[] exceptions) { + return visitor.visitMethod(access, s_name, s_desc, null, exceptions); + } + + public FieldVisitor visitField(ClassVisitor visitor, int access, Object value) { + return visitor.visitField(access, s_name, s_desc, null, value); + } + public boolean isClass(String name) { return name.replace('.', '/').equals(s_owner); } diff --git a/src/codechicken/lib/config/ConfigFile.java b/src/codechicken/lib/config/ConfigFile.java index bddec27..b634dae 100644 --- a/src/codechicken/lib/config/ConfigFile.java +++ b/src/codechicken/lib/config/ConfigFile.java @@ -4,7 +4,19 @@ public class ConfigFile extends ConfigTagParent { + public static final byte[] crlf = new byte[]{0xD, 0xA}; + + public File file; + private boolean loading; + public ConfigFile(File file) { + newlinemode = 2; + load(file); + } + + protected ConfigFile() {} + + protected void load(File file) { try { if(!file.getParentFile().exists()) file.getParentFile().mkdirs(); @@ -14,11 +26,10 @@ public ConfigFile(File file) { throw new RuntimeException(e); } this.file = file; - newlinemode = 2; loadConfig(); } - private void loadConfig() { + protected void loadConfig() { loading = true; BufferedReader reader; try { @@ -66,22 +77,7 @@ public String getNameQualifier() { public static String readLine(BufferedReader reader) throws IOException { String line = reader.readLine(); - if (line != null) - return line.replace("\t", ""); - return line; - } - - public static String formatLine(String line) { - line = line.replace("\t", ""); - if (line.startsWith("#")) { - return line; - } else if (line.contains("=")) { - line = line.substring(0, line.indexOf("=")).replace(" ", "") + line.substring(line.indexOf("=")); - return line; - } else { - line = line.replace(" ", ""); - return line; - } + return line == null ? null : line.replace("\t", ""); } public static void writeLine(PrintWriter writer, String line, int tabs) { @@ -112,9 +108,4 @@ public void saveConfig() { public boolean isLoading() { return loading; } - - public File file; - private boolean loading; - - public static final byte[] lineend = new byte[]{0xD, 0xA}; } diff --git a/src/codechicken/lib/config/ConfigTagParent.java b/src/codechicken/lib/config/ConfigTagParent.java index d293ad9..55bc009 100644 --- a/src/codechicken/lib/config/ConfigTagParent.java +++ b/src/codechicken/lib/config/ConfigTagParent.java @@ -182,7 +182,7 @@ public void loadChildren(BufferedReader reader) break; if(line.startsWith("#")) { - if(comment == null || comment.equals("")) + if(comment.equals("")) comment = line.substring(1); else comment = comment+"\n"+line.substring(1); diff --git a/src/codechicken/lib/config/DefaultingConfigFile.java b/src/codechicken/lib/config/DefaultingConfigFile.java new file mode 100644 index 0000000..27a7ef7 --- /dev/null +++ b/src/codechicken/lib/config/DefaultingConfigFile.java @@ -0,0 +1,18 @@ +package codechicken.lib.config; + +import java.io.File; + +public class DefaultingConfigFile extends ConfigFile +{ + public DefaultingConfigFile(File file) { + super(); + if(file.exists()) + load(file); + } + + @Override + public void saveConfig() { + if(file != null) + super.saveConfig(); + } +} From 1f03959a9971974f1cf3a75ba8e9606f8025d866 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 29 Apr 2014 11:42:02 +1000 Subject: [PATCH 075/219] Fix ClassCircularityError with config package being used by asm package --- src/codechicken/lib/asm/ASMInit.java | 18 +++ .../lib/asm/ClassHeirachyManager.java | 141 ++++++++---------- 2 files changed, 77 insertions(+), 82 deletions(-) create mode 100644 src/codechicken/lib/asm/ASMInit.java diff --git a/src/codechicken/lib/asm/ASMInit.java b/src/codechicken/lib/asm/ASMInit.java new file mode 100644 index 0000000..ebc007f --- /dev/null +++ b/src/codechicken/lib/asm/ASMInit.java @@ -0,0 +1,18 @@ +package codechicken.lib.asm; + +import net.minecraft.launchwrapper.Launch; + +/** + * Initialisation class for using this package. Call this on coremod load + */ +public class ASMInit +{ + private static boolean initialised = false; + public static void init() { + if(!initialised) { + Launch.classLoader.addTransformerExclusion("codechicken.lib.asm"); + Launch.classLoader.addTransformerExclusion("codechicken.lib.config"); + initialised = true; + } + } +} diff --git a/src/codechicken/lib/asm/ClassHeirachyManager.java b/src/codechicken/lib/asm/ClassHeirachyManager.java index 7fd93e1..9f0acec 100644 --- a/src/codechicken/lib/asm/ClassHeirachyManager.java +++ b/src/codechicken/lib/asm/ClassHeirachyManager.java @@ -2,6 +2,7 @@ import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; import org.objectweb.asm.tree.ClassNode; @@ -19,22 +20,18 @@ public static class SuperCache String superclass; public HashSet parents = new HashSet(); private boolean flattened; - - public void add(String parent) - { + + public void add(String parent) { parents.add(parent); } - - public void flatten() - { - if(flattened) + + public void flatten() { + if (flattened) return; - - for(String s : new ArrayList(parents)) - { + + for (String s : new ArrayList(parents)) { SuperCache c = declareClass(s); - if(c != null) - { + if (c != null) { c.flatten(); parents.addAll(c.parents); } @@ -42,146 +39,126 @@ public void flatten() flattened = true; } } - + public static HashMap superclasses = new HashMap(); - private static LaunchClassLoader cl = (LaunchClassLoader)ClassHeirachyManager.class.getClassLoader(); - - static - { - cl.addTransformerExclusion("codechicken.lib.asm"); - } - - public static String toKey(String name) - { - if(ObfMapping.obfuscated) + private static LaunchClassLoader cl = Launch.classLoader; + + public static String toKey(String name) { + if (ObfMapping.obfuscated) name = FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.'); return name; } - - public static String unKey(String name) - { - if(ObfMapping.obfuscated) + + public static String unKey(String name) { + if (ObfMapping.obfuscated) name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); return name; } - + /** - * @param name The class in question + * @param name The class in question * @param superclass The class being extended * @return true if clazz extends, either directly or indirectly, superclass. */ - public static boolean classExtends(String name, String superclass) - { + public static boolean classExtends(String name, String superclass) { name = toKey(name); superclass = toKey(superclass); - - if(name.equals(superclass)) + + if (name.equals(superclass)) return true; - + SuperCache cache = declareClass(name); - if(cache == null)//just can't handle this + if (cache == null)//just can't handle this return false; - + cache.flatten(); return cache.parents.contains(superclass); } - private static SuperCache declareClass(String name) - { + private static SuperCache declareClass(String name) { name = toKey(name); SuperCache cache = superclasses.get(name); - - if(cache != null) + + if (cache != null) return cache; - - try - { + + try { byte[] bytes = cl.getClassBytes(unKey(name)); - if(bytes != null) + if (bytes != null) cache = declareASM(bytes); - } - catch(Exception e) - { + } catch (Exception e) { } - if(cache != null) + if (cache != null) return cache; - - try - { + + try { cache = declareReflection(name); + } catch (ClassNotFoundException e) { } - catch(ClassNotFoundException e) - { - } - + return cache; } - private static SuperCache declareReflection(String name) throws ClassNotFoundException - { + private static SuperCache declareReflection(String name) throws ClassNotFoundException { Class aclass = Class.forName(name); - + SuperCache cache = getOrCreateCache(name); - if(aclass.isInterface()) + if (aclass.isInterface()) cache.superclass = "java.lang.Object"; - else if(name.equals("java.lang.Object")) + else if (name.equals("java.lang.Object")) return cache; else cache.superclass = toKey(aclass.getSuperclass().getName()); - + cache.add(cache.superclass); - for(Class iclass : aclass.getInterfaces()) + for (Class iclass : aclass.getInterfaces()) cache.add(toKey(iclass.getName())); - + return cache; } - private static SuperCache declareASM(byte[] bytes) - { + private static SuperCache declareASM(byte[] bytes) { ClassNode node = ASMHelper.createClassNode(bytes); String name = toKey(node.name); - + SuperCache cache = getOrCreateCache(name); cache.superclass = toKey(node.superName.replace('/', '.')); cache.add(cache.superclass); - for(String iclass : node.interfaces) + for (String iclass : node.interfaces) cache.add(toKey(iclass.replace('/', '.'))); - + return cache; } @Override - public byte[] transform(String name, String tname, byte[] bytes) - { + public byte[] transform(String name, String tname, byte[] bytes) { if (bytes == null) return null; - - if(!superclasses.containsKey(tname)) + + if (!superclasses.containsKey(tname)) declareASM(bytes); - + return bytes; } - - public static SuperCache getOrCreateCache(String name) - { + + public static SuperCache getOrCreateCache(String name) { SuperCache cache = superclasses.get(name); - if(cache == null) + if (cache == null) superclasses.put(name, cache = new SuperCache()); return cache; } - public static String getSuperClass(String name, boolean runtime) - { + public static String getSuperClass(String name, boolean runtime) { name = toKey(name); SuperCache cache = declareClass(name); - if(cache == null) + if (cache == null) return "java.lang.Object"; - + cache.flatten(); String s = cache.superclass; - if(!runtime) + if (!runtime) s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s); return s; } From 66fd8ad103c6f47a9aa6c52ef9ab08250baaa860 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 29 Apr 2014 13:15:49 +1000 Subject: [PATCH 076/219] Reduce classloading remapping to minecraft classes. Everything else should be srg. --- src/codechicken/lib/asm/ClassHeirachyManager.java | 4 ++++ src/codechicken/lib/asm/ObfMapping.java | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/asm/ClassHeirachyManager.java b/src/codechicken/lib/asm/ClassHeirachyManager.java index 9f0acec..562bd9d 100644 --- a/src/codechicken/lib/asm/ClassHeirachyManager.java +++ b/src/codechicken/lib/asm/ClassHeirachyManager.java @@ -15,6 +15,10 @@ */ public class ClassHeirachyManager implements IClassTransformer { + static { + ASMInit.init(); + } + public static class SuperCache { String superclass; diff --git a/src/codechicken/lib/asm/ObfMapping.java b/src/codechicken/lib/asm/ObfMapping.java index c7c5579..07c237b 100644 --- a/src/codechicken/lib/asm/ObfMapping.java +++ b/src/codechicken/lib/asm/ObfMapping.java @@ -72,6 +72,10 @@ public String mapFieldName(String owner, String name, String desc) { public String map(String typeName) { return FMLDeobfuscatingRemapper.INSTANCE.unmap(typeName); } + + public boolean isObf(String typeName) { + return !map(typeName).equals(typeName); + } } public static class MCPRemapper extends Remapper implements LineProcessor @@ -379,7 +383,10 @@ public ObfMapping toRuntime() { } public ObfMapping toClassloading() { - map(obfuscated ? obfMapper : mcpMapper); + if(!obfuscated) + map(mcpMapper); + else if(obfMapper.isObf(s_owner)) + map(obfMapper); return this; } From 47d7c667de3f4ce6f04e404a63ce43916f1f6e9c Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 1 May 2014 00:24:23 +1000 Subject: [PATCH 077/219] Fix issue with double checking slots for fitting stacks in simulate mode --- src/codechicken/lib/inventory/InventoryUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/inventory/InventoryUtils.java b/src/codechicken/lib/inventory/InventoryUtils.java index 3f922e3..4c1c133 100644 --- a/src/codechicken/lib/inventory/InventoryUtils.java +++ b/src/codechicken/lib/inventory/InventoryUtils.java @@ -193,6 +193,8 @@ public static int insertItem(InventoryRange inv, ItemStack stack, boolean simula for (int pass = 0; pass < 2; pass++) { for (int slot : inv.slots) { ItemStack base = inv.inv.getStackInSlot(slot); + if((pass == 0) == (base == null)) + continue; int fit = fitStackInSlot(inv, slot, stack); if (fit == 0) continue; @@ -203,7 +205,7 @@ public static int insertItem(InventoryRange inv, ItemStack stack, boolean simula base.stackSize += fit; inv.inv.setInventorySlotContents(slot, base); } - } else if (pass == 1) { + } else { if (!simulate) inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); stack.stackSize -= fit; From f9fea33b5e426d47a0fa492544e86041955a3805 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 8 May 2014 14:04:37 +1000 Subject: [PATCH 078/219] Fix encoding inconsistency with writeString between PacketCustom and MCDataOutputStreamWrapper Refactored -> MCDataOutput -> MCDataOutputStream --- .../lib/data/MCDataOutputWrapper.java | 241 +++++++++++++++++ .../lib/data/MCOutputStreamWrapper.java | 253 ------------------ 2 files changed, 241 insertions(+), 253 deletions(-) create mode 100644 src/codechicken/lib/data/MCDataOutputWrapper.java delete mode 100644 src/codechicken/lib/data/MCOutputStreamWrapper.java diff --git a/src/codechicken/lib/data/MCDataOutputWrapper.java b/src/codechicken/lib/data/MCDataOutputWrapper.java new file mode 100644 index 0000000..f5f1203 --- /dev/null +++ b/src/codechicken/lib/data/MCDataOutputWrapper.java @@ -0,0 +1,241 @@ +package codechicken.lib.data; + +import codechicken.lib.vec.BlockCoord; +import com.google.common.base.Charsets; +import cpw.mods.fml.common.network.ByteBufUtils; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; +import org.apache.commons.lang3.Validate; + +import java.io.DataOutput; +import java.io.IOException; + +public class MCDataOutputWrapper implements MCDataOutput +{ + /** + * Mimics ByteBufUtils + * Write an integer using variable length encoding. + * + * @param to The buffer to write to + * @param i The integer to write + */ + public static void writeVarInt(DataOutput to, int i) throws IOException { + while ((i & 0x80) != 0) { + to.writeByte(i & 0x7F | 0x80); + i >>>= 7; + } + + to.writeByte(i); + } + + /** + * Mimics ByteBufUtils + * Write an extended short using a short and a byte if necessary + * + * @param to The buffer to write to + * @param s The short to write, less than 0x7FFFFF + */ + public static void writeVarShort(DataOutput to, int s) throws IOException { + int low = s & 0x7FFF; + int high = (s & 0x7F8000) >> 15; + if (high != 0) + low |= 0x8000; + to.writeShort(low); + if (high != 0) + to.writeByte(high); + } + + /** + * Mimics ByteBufUtils + * Write a String with UTF8 byte encoding to the buffer. + * It is encoded as [] + * @param to the data output to write to + * @param string The string to write + */ + public static void writeUTF8String(DataOutput to, String string) throws IOException { + byte[] utf8Bytes = string.getBytes(Charsets.UTF_8); + Validate.isTrue(ByteBufUtils.varIntByteCount(utf8Bytes.length) < 3, "The string is too long for this encoding."); + writeVarInt(to, utf8Bytes.length); + to.write(utf8Bytes); + } + + public DataOutput dataout; + + public MCDataOutputWrapper(DataOutput out) { + dataout = out; + } + + public MCDataOutputWrapper writeBoolean(boolean b) { + try { + dataout.writeBoolean(b); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeByte(int b) { + try { + dataout.writeByte(b); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeShort(int s) { + try { + dataout.writeShort(s); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeInt(int i) { + try { + dataout.writeInt(i); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeFloat(float f) { + try { + dataout.writeFloat(f); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeDouble(double d) { + try { + dataout.writeDouble(d); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeLong(long l) { + try { + dataout.writeLong(l); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + @Override + public MCDataOutputWrapper writeChar(char c) { + try { + dataout.writeChar(c); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + @Override + public MCDataOutput writeVarInt(int i) { + try { + writeVarInt(dataout, i); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + @Override + public MCDataOutput writeVarShort(int s) { + try { + writeVarShort(dataout, s); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeByteArray(byte[] barray) { + try { + dataout.write(barray); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeCoord(int x, int y, int z) { + writeInt(x); + writeInt(y); + writeInt(z); + return this; + } + + public MCDataOutputWrapper writeCoord(BlockCoord coord) { + writeInt(coord.x); + writeInt(coord.y); + writeInt(coord.z); + return this; + } + + public MCDataOutputWrapper writeString(String s) { + try { + writeUTF8String(dataout, s); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeItemStack(ItemStack stack) { + writeItemStack(stack, false); + return this; + } + + public MCDataOutputWrapper writeItemStack(ItemStack stack, boolean large) { + if (stack == null) { + writeShort(-1); + } else { + writeShort(Item.getIdFromItem(stack.getItem())); + if (large) + writeInt(stack.stackSize); + else + writeByte(stack.stackSize); + writeShort(stack.getItemDamage()); + writeNBTTagCompound(stack.stackTagCompound); + } + return this; + } + + public MCDataOutputWrapper writeNBTTagCompound(NBTTagCompound compound) { + try { + if (compound == null) { + writeShort(-1); + } else { + byte[] bytes = CompressedStreamTools.compress(compound); + writeShort((short) bytes.length); + writeByteArray(bytes); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public MCDataOutputWrapper writeFluidStack(FluidStack fluid) { + if (fluid == null) { + writeShort(-1); + } else { + writeShort(fluid.fluidID); + writeInt(fluid.amount); + writeNBTTagCompound(fluid.tag); + } + return this; + } +} diff --git a/src/codechicken/lib/data/MCOutputStreamWrapper.java b/src/codechicken/lib/data/MCOutputStreamWrapper.java deleted file mode 100644 index 49d4328..0000000 --- a/src/codechicken/lib/data/MCOutputStreamWrapper.java +++ /dev/null @@ -1,253 +0,0 @@ -package codechicken.lib.data; - -import codechicken.lib.vec.BlockCoord; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompressedStreamTools; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.fluids.FluidStack; - -import java.io.DataOutputStream; -import java.io.IOException; - -public class MCOutputStreamWrapper implements MCDataOutput -{ - public DataOutputStream dataout; - - public MCOutputStreamWrapper(DataOutputStream out) - { - dataout = out; - } - - public MCOutputStreamWrapper writeBoolean(boolean b) - { - try - { - dataout.writeBoolean(b); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeByte(int b) - { - try - { - dataout.writeByte(b); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeShort(int s) - { - try - { - dataout.writeShort(s); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeInt(int i) - { - try - { - dataout.writeInt(i); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeFloat(float f) - { - try - { - dataout.writeFloat(f); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeDouble(double d) - { - try - { - dataout.writeDouble(d); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeLong(long l) - { - try - { - dataout.writeLong(l); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - @Override - public MCOutputStreamWrapper writeChar(char c) - { - try - { - dataout.writeChar(c); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - @Override - public MCDataOutput writeVarInt(int i) { - while ((i & 0x80) != 0) - { - writeByte(i & 0x7F | 0x80); - i >>>= 7; - } - - writeByte(i); - return this; - } - - @Override - public MCDataOutput writeVarShort(int s) { - int low = s & 0x7FFF; - int high = (s & 0x7F8000) >> 15; - if (high != 0) - low |= 0x8000; - writeShort(low); - if (high != 0) - writeByte(high); - return this; - } - - public MCOutputStreamWrapper writeByteArray(byte[] barray) - { - try - { - dataout.write(barray); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeCoord(int x, int y, int z) - { - writeInt(x); - writeInt(y); - writeInt(z); - return this; - } - - public MCOutputStreamWrapper writeCoord(BlockCoord coord) - { - writeInt(coord.x); - writeInt(coord.y); - writeInt(coord.z); - return this; - } - - public MCOutputStreamWrapper writeString(String s) - { - try - { - if(s.length() > 65535) - throw new IOException("String length: "+s.length()+"too long."); - dataout.writeShort(s.length()); - dataout.writeChars(s); - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeItemStack(ItemStack stack) - { - writeItemStack(stack, false); - return this; - } - - public MCOutputStreamWrapper writeItemStack(ItemStack stack, boolean large) { - if (stack == null) { - writeShort(-1); - } else { - writeShort(Item.getIdFromItem(stack.getItem())); - if (large) - writeInt(stack.stackSize); - else - writeByte(stack.stackSize); - writeShort(stack.getItemDamage()); - writeNBTTagCompound(stack.stackTagCompound); - } - return this; - } - - public MCOutputStreamWrapper writeNBTTagCompound(NBTTagCompound compound) - { - try - { - if (compound == null) - { - writeShort(-1); - } - else - { - byte[] bytes = CompressedStreamTools.compress(compound); - writeShort((short)bytes.length); - writeByteArray(bytes); - } - } - catch(IOException e) - { - throw new RuntimeException(e); - } - return this; - } - - public MCOutputStreamWrapper writeFluidStack(FluidStack fluid) - { - if (fluid == null) - { - writeShort(-1); - } - else - { - writeShort(fluid.fluidID); - writeInt(fluid.amount); - writeNBTTagCompound(fluid.tag); - } - return this; - } -} From 408e45ef250629ffd34ca4e3a0cf118becedde75 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 8 May 2014 14:06:12 +1000 Subject: [PATCH 079/219] Bump patch version --- build/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build.properties b/build/build.properties index 8779295..55d5901 100644 --- a/build/build.properties +++ b/build/build.properties @@ -1,3 +1,3 @@ minecraft_version=1.7.2 forge_version=10.12.0.1054 -mod_version=1.1.0 +mod_version=1.1.1 From 215715f7c5702e5fe8df9638209f309e1e515657 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 9 May 2014 09:23:58 +1000 Subject: [PATCH 080/219] Added full block model and planar light matrix Added set function to Rectangle4i --- src/codechicken/lib/lighting/LightMatrix.java | 1 + .../lib/lighting/PlanarLightMatrix.java | 55 +++++++++++++++++++ src/codechicken/lib/render/BlockRenderer.java | 34 ++++++++++++ src/codechicken/lib/render/CCRenderState.java | 5 ++ src/codechicken/lib/vec/Rectangle4i.java | 7 +++ 5 files changed, 102 insertions(+) create mode 100644 src/codechicken/lib/lighting/PlanarLightMatrix.java diff --git a/src/codechicken/lib/lighting/LightMatrix.java b/src/codechicken/lib/lighting/LightMatrix.java index d35e420..5eb6fff 100644 --- a/src/codechicken/lib/lighting/LightMatrix.java +++ b/src/codechicken/lib/lighting/LightMatrix.java @@ -89,6 +89,7 @@ public void sample(int i) { Block b = access.getBlock(x, y, z); bSamples[i] = access.getLightBrightnessForSkyBlocks(x, y, z, b.getLightValue(access, x, y, z)); aSamples[i] = b.getAmbientOcclusionLightValue(); + sampled |= 1 << i; } } diff --git a/src/codechicken/lib/lighting/PlanarLightMatrix.java b/src/codechicken/lib/lighting/PlanarLightMatrix.java new file mode 100644 index 0000000..f557fe5 --- /dev/null +++ b/src/codechicken/lib/lighting/PlanarLightMatrix.java @@ -0,0 +1,55 @@ +package codechicken.lib.lighting; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.BlockCoord; +import net.minecraft.block.Block; +import net.minecraft.world.IBlockAccess; + +public class PlanarLightMatrix extends PlanarLightModel +{ + public static final int operationIndex = CCRenderState.registerOperation(); + public static PlanarLightMatrix instance = new PlanarLightMatrix(); + + public IBlockAccess access; + public BlockCoord pos = new BlockCoord(); + + private int sampled = 0; + public int[] brightness = new int[6]; + + public PlanarLightMatrix() { + super(PlanarLightModel.standardLightModel.colours); + } + + public PlanarLightMatrix locate(IBlockAccess a, int x, int y, int z) { + access = a; + pos.set(x, y, z); + sampled = 0; + return this; + } + + public int brightness(int side) { + if((sampled & 1 << side) == 0) { + Block b = access.getBlock(pos.x, pos.y, pos.z); + brightness[side] = access.getLightBrightnessForSkyBlocks(pos.x, pos.y, pos.z, b.getLightValue(access, pos.x, pos.y, pos.z)); + sampled |= 1 << side; + } + return brightness[side]; + } + + @Override + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + return true; + } + + @Override + public void operate() { + super.operate(); + CCRenderState.setBrightness(brightness(CCRenderState.side)); + } + + @Override + public int operationID() { + return operationIndex; + } +} diff --git a/src/codechicken/lib/render/BlockRenderer.java b/src/codechicken/lib/render/BlockRenderer.java index c222d2a..311b046 100644 --- a/src/codechicken/lib/render/BlockRenderer.java +++ b/src/codechicken/lib/render/BlockRenderer.java @@ -1,6 +1,7 @@ package codechicken.lib.render; import codechicken.lib.lighting.LC; +import codechicken.lib.render.CCRenderState.VertexAttribute; import codechicken.lib.vec.Cuboid6; public class BlockRenderer @@ -105,6 +106,39 @@ public BlockFace loadCuboidFace(Cuboid6 c, int side) { } } + public static class FullBlock implements CCRenderState.IVertexSource + { + public Vertex5[] verts = CCModel.quadModel(24).generateBlock(0, Cuboid6.full).verts; + public LC[] lightCoords = new LC[24]; + + public FullBlock() { + for(int i = 0; i < 24; i++) + lightCoords[i] = new LC().compute(verts[i].vec, i/4); + } + + @Override + public Vertex5[] getVertices() { + return verts; + } + + @Override + public T getAttributes(VertexAttribute attr) { + return attr == CCRenderState.lightCoordAttrib ? (T) lightCoords : null; + } + + @Override + public boolean hasAttribute(VertexAttribute attr) { + return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib; + } + + @Override + public void prepareVertex() { + CCRenderState.side = CCRenderState.vertexIndex>>2; + } + } + + public static FullBlock fullBlock = new FullBlock(); + private static BlockFace face = new BlockFace(); /** diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 835cbb7..b8c8244 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -3,6 +3,7 @@ import codechicken.lib.colour.ColourRGBA; import codechicken.lib.lighting.LC; import codechicken.lib.lighting.LightMatrix; +import codechicken.lib.lighting.PlanarLightMatrix; import codechicken.lib.util.Copyable; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Transformation; @@ -296,6 +297,10 @@ public static void setModel(IVertexSource source) { public static void setModel(IVertexSource source, int start, int end) { bindModel(source); + setVertexRange(start, end); + } + + public static void setVertexRange(int start, int end) { firstVertexIndex = start; lastVertexIndex = end; } diff --git a/src/codechicken/lib/vec/Rectangle4i.java b/src/codechicken/lib/vec/Rectangle4i.java index 0e29d35..49058c7 100644 --- a/src/codechicken/lib/vec/Rectangle4i.java +++ b/src/codechicken/lib/vec/Rectangle4i.java @@ -34,6 +34,13 @@ public int x2() { public int y2() { return y+h-1; } + + public void set(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } public Rectangle4i offset(int dx, int dy) { From f1153412c123e7926d97840ba18ef680831e655f Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 9 May 2014 09:25:47 +1000 Subject: [PATCH 081/219] Remove unused import --- src/codechicken/lib/render/CCRenderState.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index b8c8244..0695e5c 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -3,7 +3,6 @@ import codechicken.lib.colour.ColourRGBA; import codechicken.lib.lighting.LC; import codechicken.lib.lighting.LightMatrix; -import codechicken.lib.lighting.PlanarLightMatrix; import codechicken.lib.util.Copyable; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Transformation; From 8386a982a216823aacb18e19d17fdb3221c85468 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 23 May 2014 14:33:17 +1000 Subject: [PATCH 082/219] Fixed IndexOutOfBoundsException with CCRenderState.copyOf --- src/codechicken/lib/render/CCRenderState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 0695e5c..9a10081 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -102,7 +102,7 @@ public static void arrayCopy(Object src, int srcPos, Object dst, int destPos, in public static T copyOf(VertexAttribute attr, T src, int length) { T dst = attr.newArray(length); - arrayCopy(src, 0, dst, 0, length); + arrayCopy(src, 0, dst, 0, ((Object[])src).length); return dst; } From 6d19cc0079fa4b7147182f69a283611b65848d69 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:21:31 +1000 Subject: [PATCH 083/219] Fix colour not being set when a colour multiplier with white was added --- src/codechicken/lib/render/ColourMultiplier.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/render/ColourMultiplier.java b/src/codechicken/lib/render/ColourMultiplier.java index 8e30758..71e3228 100644 --- a/src/codechicken/lib/render/ColourMultiplier.java +++ b/src/codechicken/lib/render/ColourMultiplier.java @@ -20,8 +20,10 @@ public ColourMultiplier(int colour) { @Override public boolean load() { - if(colour == -1) + if(colour == -1) { + CCRenderState.setColour(-1); return false; + } CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; From 66015a13c56215ff8b8bc9587dd58e899221bbc4 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:21:50 +1000 Subject: [PATCH 084/219] Added toString to BlockCoord --- src/codechicken/lib/vec/BlockCoord.java | 37 ++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/codechicken/lib/vec/BlockCoord.java b/src/codechicken/lib/vec/BlockCoord.java index 318677f..b506eaf 100644 --- a/src/codechicken/lib/vec/BlockCoord.java +++ b/src/codechicken/lib/vec/BlockCoord.java @@ -9,19 +9,19 @@ public class BlockCoord implements Comparable, Copyable public int x; public int y; public int z; - + public BlockCoord(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } - + public BlockCoord(Vector3 v) { this(MathHelper.floor_double(v.x), MathHelper.floor_double(v.y), MathHelper.floor_double(v.z)); } - + public BlockCoord(TileEntity tile) { this(tile.xCoord, tile.yCoord, tile.zCoord); @@ -31,7 +31,7 @@ public BlockCoord(int[] ia) { this(ia[0], ia[1], ia[2]); } - + public BlockCoord() { } @@ -49,7 +49,7 @@ public boolean equals(Object obj) BlockCoord o2 = (BlockCoord)obj; return x == o2.x && y == o2.y && z == o2.z; } - + @Override public int hashCode() { @@ -81,7 +81,7 @@ public double mag() { return Math.sqrt(x*x+y*y+z*z); } - + public int mag2() { return x*x+y*y+z*z; @@ -96,7 +96,7 @@ public boolean isAxial() { return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); } - + public BlockCoord add(BlockCoord coord2) { x+=coord2.x; @@ -112,7 +112,7 @@ public BlockCoord add(int i, int j, int k) z+=k; return this; } - + public BlockCoord sub(BlockCoord coord2) { x-=coord2.x; @@ -128,7 +128,7 @@ public BlockCoord sub(int i, int j, int k) z-=k; return this; } - + public BlockCoord offset(int side) { return offset(side, 1); @@ -142,7 +142,7 @@ public BlockCoord offset(int side, int amount) z+=offset.z*amount; return this; } - + public BlockCoord inset(int side) { return inset(side, 1); @@ -182,7 +182,7 @@ public BlockCoord setSide(int s, int v) } return this; } - + public static final BlockCoord[] sideOffsets = new BlockCoord[]{ new BlockCoord( 0,-1, 0), new BlockCoord( 0, 1, 0), @@ -218,7 +218,7 @@ public BlockCoord set(int[] ia) { return set(ia[0], ia[1], ia[2]); } - + public int toSide() { if(!isAxial()) return -1; @@ -228,14 +228,19 @@ public int toSide() if(z > 0) return 3; if(x < 0) return 4; if(x > 0) return 5; - + return -1; } - + public int absSum() { - return (x < 0 ? -x : x) + - (y < 0 ? -y : y) + + return (x < 0 ? -x : x) + + (y < 0 ? -y : y) + (z < 0 ? -z : z); } + + public String toString() + { + return "("+x+", "+y+", "+z+")"; + } } From 307ca816944d1d860f715271086f52138c7dedcd Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:23:00 +1000 Subject: [PATCH 085/219] Add meaningful exception text to CustomGradient when resource not found --- src/codechicken/lib/colour/CustomGradient.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/codechicken/lib/colour/CustomGradient.java b/src/codechicken/lib/colour/CustomGradient.java index ba3270f..159bf4b 100644 --- a/src/codechicken/lib/colour/CustomGradient.java +++ b/src/codechicken/lib/colour/CustomGradient.java @@ -13,6 +13,9 @@ public class CustomGradient public CustomGradient(ResourceLocation textureFile) { BufferedImage img = TextureUtils.loadBufferedImage(textureFile); + if(img == null) + throw new RuntimeException("File not found: "+textureFile.toString()); + int[] data = new int[img.getWidth()]; img.getRGB(0, 0, img.getWidth(), 1, data, 0, img.getWidth()); gradient = new int[img.getWidth()]; From 5c54b184ea5af982e141cc4738246cfb89add425 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:23:40 +1000 Subject: [PATCH 086/219] Fix inconsistent use of var ints in fluid packets --- src/codechicken/lib/data/MCDataOutputWrapper.java | 2 +- src/codechicken/lib/packet/PacketCustom.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codechicken/lib/data/MCDataOutputWrapper.java b/src/codechicken/lib/data/MCDataOutputWrapper.java index f5f1203..48679d4 100644 --- a/src/codechicken/lib/data/MCDataOutputWrapper.java +++ b/src/codechicken/lib/data/MCDataOutputWrapper.java @@ -233,7 +233,7 @@ public MCDataOutputWrapper writeFluidStack(FluidStack fluid) { writeShort(-1); } else { writeShort(fluid.fluidID); - writeInt(fluid.amount); + writeVarInt(fluid.amount); writeNBTTagCompound(fluid.tag); } return this; diff --git a/src/codechicken/lib/packet/PacketCustom.java b/src/codechicken/lib/packet/PacketCustom.java index 6abbb60..715f011 100644 --- a/src/codechicken/lib/packet/PacketCustom.java +++ b/src/codechicken/lib/packet/PacketCustom.java @@ -465,7 +465,7 @@ public FluidStack readFluidStack() { short fluidID = readShort(); if (fluidID >= 0) - fluid = new FluidStack(fluidID, readInt(), readNBTTagCompound()); + fluid = new FluidStack(fluidID, readVarInt(), readNBTTagCompound()); return fluid; } From 3bde4ab9eeee723d7c10c39c145f6cb7536468ad Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:24:18 +1000 Subject: [PATCH 087/219] Remove broken render() function in CCModel, made CCRenderState.startDrawing(int) public again --- src/codechicken/lib/render/CCModel.java | 5 ----- src/codechicken/lib/render/CCRenderState.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/codechicken/lib/render/CCModel.java b/src/codechicken/lib/render/CCModel.java index 526119e..d6b2c8e 100644 --- a/src/codechicken/lib/render/CCModel.java +++ b/src/codechicken/lib/render/CCModel.java @@ -398,11 +398,6 @@ public CCModel expand(int extraVerts) return this; } - public void render() - { - render(0, verts.length, null, null, null); - } - public void render(double x, double y, double z, double u, double v) { render(new Vector3(x, y, z).translation(), new UVTranslation(u, v)); diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 9a10081..487605c 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -373,7 +373,7 @@ public static void startDrawing() { startDrawing(7); } - private static void startDrawing(int mode) { + public static void startDrawing(int mode) { Tessellator.instance.startDrawing(mode); if(hasColour) Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); From 0529baaf234ea14163270134a868280d990e213e Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:27:56 +1000 Subject: [PATCH 088/219] Add setBaseColour function for clarity --- src/codechicken/lib/render/CCRenderState.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 487605c..55a37c8 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -348,6 +348,11 @@ public static void setColour(int c) { colour = c; } + public static void setBaseColour(int c) { + hasColour = true; + baseColour = c; + } + public static void setBrightness(int b) { hasBrightness = true; brightness = b; From 29ef6904f07de676c1273aea0e2d2ec58190d587 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:43:20 +1000 Subject: [PATCH 089/219] Fix loophole with model colour attribute in CCRenderState --- src/codechicken/lib/render/CCRenderPipeline.java | 4 +--- src/codechicken/lib/render/CCRenderState.java | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/codechicken/lib/render/CCRenderPipeline.java b/src/codechicken/lib/render/CCRenderPipeline.java index b25141e..915cfc5 100644 --- a/src/codechicken/lib/render/CCRenderPipeline.java +++ b/src/codechicken/lib/render/CCRenderPipeline.java @@ -84,10 +84,8 @@ public void rebuild() { if(CCRenderState.useNormals) addAttribute(CCRenderState.normalAttrib); - if(CCRenderState.baseColour != -1 || CCRenderState.alphaOverride >= 0) + if(CCRenderState.hasColour) addAttribute(CCRenderState.colourAttrib); - else if(CCRenderState.hasColour) - CCRenderState.setColour(-1); for(int i = 0; i < ops.size(); i++) { IVertexOperation op = ops.get(i); diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 55a37c8..2c52fde 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -269,7 +269,8 @@ public void operate() { public static void reset() { model = null; pipeline.reset(); - hasNormal = hasColour = hasBrightness = false; + hasNormal = hasBrightness = false; + hasColour = true; baseColour = alphaOverride = -1; } From 97cb16586acbf5a6c8e8b14ac32568eb79104db4 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 00:47:00 +1000 Subject: [PATCH 090/219] Consistency :L --- src/codechicken/lib/render/CCRenderState.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 2c52fde..9234837 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -349,11 +349,6 @@ public static void setColour(int c) { colour = c; } - public static void setBaseColour(int c) { - hasColour = true; - baseColour = c; - } - public static void setBrightness(int b) { hasBrightness = true; brightness = b; From 09bf91715beaf08b4406ba8099f63f8ae12f163f Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 15 Jun 2014 02:07:20 +1000 Subject: [PATCH 091/219] Seperate colour and lighting a bit. Made baking colours easier and the distinction between dynamic and static rendering easier to manage. Fixed invalid u coords in generateBlock --- src/codechicken/lib/lighting/LightMatrix.java | 3 + src/codechicken/lib/lighting/LightModel.java | 3 + .../lib/lighting/PlanarLightModel.java | 3 + src/codechicken/lib/render/CCModel.java | 74 +++++++++---------- .../lib/render/CCRenderPipeline.java | 4 +- src/codechicken/lib/render/CCRenderState.java | 40 +++++++++- src/codechicken/lib/render/Vertex5.java | 7 +- 7 files changed, 93 insertions(+), 41 deletions(-) diff --git a/src/codechicken/lib/lighting/LightMatrix.java b/src/codechicken/lib/lighting/LightMatrix.java index 5eb6fff..1962eb0 100644 --- a/src/codechicken/lib/lighting/LightMatrix.java +++ b/src/codechicken/lib/lighting/LightMatrix.java @@ -139,6 +139,9 @@ public static int interpBrightness(int a, int b, int c, int d) { @Override public boolean load() { + if(!CCRenderState.computeLighting) + return false; + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); return true; diff --git a/src/codechicken/lib/lighting/LightModel.java b/src/codechicken/lib/lighting/LightModel.java index aa33a80..eca2f9d 100644 --- a/src/codechicken/lib/lighting/LightModel.java +++ b/src/codechicken/lib/lighting/LightModel.java @@ -82,6 +82,9 @@ public int apply(int colour, Vector3 normal) { @Override public boolean load() { + if(!CCRenderState.computeLighting) + return false; + CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; diff --git a/src/codechicken/lib/lighting/PlanarLightModel.java b/src/codechicken/lib/lighting/PlanarLightModel.java index 942521f..3923198 100644 --- a/src/codechicken/lib/lighting/PlanarLightModel.java +++ b/src/codechicken/lib/lighting/PlanarLightModel.java @@ -18,6 +18,9 @@ public PlanarLightModel(int[] colours) { @Override public boolean load() { + if(!CCRenderState.computeLighting) + return false; + CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; diff --git a/src/codechicken/lib/render/CCModel.java b/src/codechicken/lib/render/CCModel.java index d6b2c8e..09eb602 100644 --- a/src/codechicken/lib/render/CCModel.java +++ b/src/codechicken/lib/render/CCModel.java @@ -206,55 +206,55 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, if((mask&1) == 0) {//bottom face u1 = x1; v1 = z1; u2 = x2; v2 = z2; - verts[i++] = new Vertex5(x1, y1, z2, u1, v2); - verts[i++] = new Vertex5(x1, y1, z1, u1, v1); - verts[i++] = new Vertex5(x2, y1, z1, u2, v1); - verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + verts[i++] = new Vertex5(x1, y1, z2, u1, v2, 0); + verts[i++] = new Vertex5(x1, y1, z1, u1, v1, 0); + verts[i++] = new Vertex5(x2, y1, z1, u2, v1, 0); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2, 0); } if((mask&2) == 0) {//top face - u1 = x1+2; v1 = z1; - u2 = x2+2; v2 = z2; - verts[i++] = new Vertex5(x2, y2, z2, u2, v2); - verts[i++] = new Vertex5(x2, y2, z1, u2, v1); - verts[i++] = new Vertex5(x1, y2, z1, u1, v1); - verts[i++] = new Vertex5(x1, y2, z2, u1, v2); + u1 = x1; v1 = z1; + u2 = x2; v2 = z2; + verts[i++] = new Vertex5(x2, y2, z2, u2, v2, 1); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1, 1); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1, 1); + verts[i++] = new Vertex5(x1, y2, z2, u1, v2, 1); } if((mask&4) == 0) {//east face - u1 = 1-x1+4; v1 = 1-y2; - u2 = 1-x2+4; v2 = 1-y1; - verts[i++] = new Vertex5(x1, y1, z1, u1, v2); - verts[i++] = new Vertex5(x1, y2, z1, u1, v1); - verts[i++] = new Vertex5(x2, y2, z1, u2, v1); - verts[i++] = new Vertex5(x2, y1, z1, u2, v2); + u1 = 1-x1; v1 = 1-y2; + u2 = 1-x2; v2 = 1-y1; + verts[i++] = new Vertex5(x1, y1, z1, u1, v2, 2); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1, 2); + verts[i++] = new Vertex5(x2, y2, z1, u2, v1, 2); + verts[i++] = new Vertex5(x2, y1, z1, u2, v2, 2); } if((mask&8) == 0) {//west face - u1 = x1+6; v1 = 1-y2; - u2 = x2+6; v2 = 1-y1; - verts[i++] = new Vertex5(x2, y1, z2, u2, v2); - verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - verts[i++] = new Vertex5(x1, y2, z2, u1, v1); - verts[i++] = new Vertex5(x1, y1, z2, u1, v2); + u1 = x1; v1 = 1-y2; + u2 = x2; v2 = 1-y1; + verts[i++] = new Vertex5(x2, y1, z2, u2, v2, 3); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1, 3); + verts[i++] = new Vertex5(x1, y2, z2, u1, v1, 3); + verts[i++] = new Vertex5(x1, y1, z2, u1, v2, 3); } if((mask&0x10) == 0) {//north face - u1 = z1+8; v1 = 1-y2; - u2 = z2+8; v2 = 1-y1; - verts[i++] = new Vertex5(x1, y1, z2, u2, v2); - verts[i++] = new Vertex5(x1, y2, z2, u2, v1); - verts[i++] = new Vertex5(x1, y2, z1, u1, v1); - verts[i++] = new Vertex5(x1, y1, z1, u1, v2); + u1 = z1; v1 = 1-y2; + u2 = z2; v2 = 1-y1; + verts[i++] = new Vertex5(x1, y1, z2, u2, v2, 4); + verts[i++] = new Vertex5(x1, y2, z2, u2, v1, 4); + verts[i++] = new Vertex5(x1, y2, z1, u1, v1, 4); + verts[i++] = new Vertex5(x1, y1, z1, u1, v2, 4); } if((mask&0x20) == 0) {//south face - u1 = 1-z1+10; v1 = 1-y2; - u2 = 1-z2+10; v2 = 1-y1; - verts[i++] = new Vertex5(x2, y1, z1, u1, v2); - verts[i++] = new Vertex5(x2, y2, z1, u1, v1); - verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - verts[i++] = new Vertex5(x2, y1, z2, u2, v2); + u1 = 1-z1; v1 = 1-y2; + u2 = 1-z2; v2 = 1-y1; + verts[i++] = new Vertex5(x2, y1, z1, u1, v2, 5); + verts[i++] = new Vertex5(x2, y2, z1, u1, v1, 5); + verts[i++] = new Vertex5(x2, y2, z2, u2, v1, 5); + verts[i++] = new Vertex5(x2, y1, z2, u2, v2, 5); } return this; @@ -299,10 +299,10 @@ public CCModel computeNormals(int start, int length) public CCModel computeLighting(LightModel light) { Vector3[] normals = normals(); - int[] colours = getAttributes(CCRenderState.colourAttrib); + int[] colours = getAttributes(CCRenderState.lightingAttrib); if(colours == null) { - setColour(-1); - colours = getAttributes(CCRenderState.colourAttrib); + colours = getOrAllocate(CCRenderState.lightingAttrib); + Arrays.fill(colours, -1); } for(int k = 0; k < verts.length; k++) colours[k] = light.apply(colours[k], normals[k]); diff --git a/src/codechicken/lib/render/CCRenderPipeline.java b/src/codechicken/lib/render/CCRenderPipeline.java index 915cfc5..72fb2b3 100644 --- a/src/codechicken/lib/render/CCRenderPipeline.java +++ b/src/codechicken/lib/render/CCRenderPipeline.java @@ -84,8 +84,10 @@ public void rebuild() { if(CCRenderState.useNormals) addAttribute(CCRenderState.normalAttrib); - if(CCRenderState.hasColour) + if(CCRenderState.useColour) addAttribute(CCRenderState.colourAttrib); + if(CCRenderState.computeLighting) + addAttribute(CCRenderState.lightingAttrib); for(int i = 0; i < ops.size(); i++) { IVertexOperation op = ops.get(i); diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 9234837..624244d 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -180,6 +180,32 @@ public void operate() { setColour(baseColour); } }; + public static VertexAttribute lightingAttrib = new VertexAttribute() { + private int[] colourRef; + + @Override + public int[] newArray(int length) { + return new int[length]; + } + + @Override + public boolean load() { + if(!computeLighting || !hasColour || !model.hasAttribute(this)) + return false; + + colourRef = model.getAttributes(this); + if(colourRef != null) { + pipeline.addDependency(colourAttrib); + return true; + } + return false; + } + + @Override + public void operate() { + setColour(ColourRGBA.multiply(colour, colourRef[vertexIndex])); + } + }; public static VertexAttribute sideAttrib = new VertexAttribute() { private int[] sideRef; @@ -251,6 +277,8 @@ public void operate() { public static int baseColour; public static int alphaOverride; public static boolean useNormals; + public static boolean computeLighting; + public static boolean useColour; public static LightMatrix lightMatrix = new LightMatrix(); //vertex outputs @@ -269,8 +297,8 @@ public void operate() { public static void reset() { model = null; pipeline.reset(); - hasNormal = hasBrightness = false; - hasColour = true; + useNormals = hasNormal = hasBrightness = hasColour = false; + useColour = computeLighting = true; baseColour = alphaOverride = -1; } @@ -362,6 +390,14 @@ public static void pullLightmap() { setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX); } + /** + * Compact helper for setting dynamic rendering context. Uses normals and doesn't compute lighting + */ + public static void setDynamic() { + useNormals = true; + computeLighting = false; + } + public static void changeTexture(String texture) { changeTexture(new ResourceLocation(texture)); } diff --git a/src/codechicken/lib/render/Vertex5.java b/src/codechicken/lib/render/Vertex5.java index 358b1f8..0339a4f 100644 --- a/src/codechicken/lib/render/Vertex5.java +++ b/src/codechicken/lib/render/Vertex5.java @@ -30,8 +30,13 @@ public Vertex5(Vector3 vert, double u, double v) { this(vert, new UV(u, v)); } - + public Vertex5(double x, double y, double z, double u, double v) + { + this(x, y, z, u, v, 0); + } + + public Vertex5(double x, double y, double z, double u, double v, int tex) { this(new Vector3(x, y, z), new UV(u, v)); } From 1680d74d6d111ecc531d73cb9114df22ae968a68 Mon Sep 17 00:00:00 2001 From: MrTJP Date: Sun, 15 Jun 2014 11:26:19 -0400 Subject: [PATCH 092/219] Light attribute should not depend on colour Light attribute makes sure that we have color, but at the time of check, hasColour is false, because nothing has operated yet. We want to check the context flag instead. (We could just not check this color flag at all, and leave the two actually 'separate') --- src/codechicken/lib/render/CCRenderState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 624244d..70f9db1 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -190,7 +190,7 @@ public int[] newArray(int length) { @Override public boolean load() { - if(!computeLighting || !hasColour || !model.hasAttribute(this)) + if(!computeLighting || !useColour || !model.hasAttribute(this)) return false; colourRef = model.getAttributes(this); From 93b1e5dbf0682cc1dc6c9ad32f119a3a08c7ac90 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 27 Jun 2014 15:08:10 +1000 Subject: [PATCH 093/219] 1.7.10 --- build/build.properties | 4 ++-- src/codechicken/lib/gui/GuiDraw.java | 2 +- src/codechicken/lib/packet/PacketCustom.java | 2 +- src/codechicken/lib/render/CCModel.java | 4 +--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/build/build.properties b/build/build.properties index 55d5901..481366a 100644 --- a/build/build.properties +++ b/build/build.properties @@ -1,3 +1,3 @@ -minecraft_version=1.7.2 -forge_version=10.12.0.1054 +minecraft_version=1.7.10 +forge_version=10.13.0.1151 mod_version=1.1.1 diff --git a/src/codechicken/lib/gui/GuiDraw.java b/src/codechicken/lib/gui/GuiDraw.java index 59875ca..41d84cd 100644 --- a/src/codechicken/lib/gui/GuiDraw.java +++ b/src/codechicken/lib/gui/GuiDraw.java @@ -101,7 +101,7 @@ public static int getStringWidth(String s) { public static Dimension displaySize() { Minecraft mc = Minecraft.getMinecraft(); - ScaledResolution res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight); + ScaledResolution res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); return new Dimension(res.getScaledWidth(), res.getScaledHeight()); } diff --git a/src/codechicken/lib/packet/PacketCustom.java b/src/codechicken/lib/packet/PacketCustom.java index 715f011..7e238f2 100644 --- a/src/codechicken/lib/packet/PacketCustom.java +++ b/src/codechicken/lib/packet/PacketCustom.java @@ -538,7 +538,7 @@ public void sendToOps() { public static void sendToOps(Packet packet) { for (EntityPlayerMP player : (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) - if (MinecraftServer.getServer().getConfigurationManager().isPlayerOpped(player.getCommandSenderName())) + if (MinecraftServer.getServer().getConfigurationManager().func_152596_g(player.getGameProfile())) sendToPlayer(packet, player); } diff --git a/src/codechicken/lib/render/CCModel.java b/src/codechicken/lib/render/CCModel.java index 09eb602..8240f0c 100644 --- a/src/codechicken/lib/render/CCModel.java +++ b/src/codechicken/lib/render/CCModel.java @@ -790,9 +790,7 @@ public CCModel shrinkUVs(double d) */ public CCModel sidedCopy(int side1, int side2, Vector3 point) { - CCModel model = newModel(vertexMode, verts.length); - copy(this, 0, model, 0, model.verts.length); - return model.apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point)); + return copy().apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point)); } /** From ba15e4b116727ead2b71af36273587dd439605c2 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 29 Jun 2014 14:27:19 +1000 Subject: [PATCH 094/219] Added informative exception when attempting to register a channel using a modID > 20 characters --- src/codechicken/lib/packet/PacketCustom.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/codechicken/lib/packet/PacketCustom.java b/src/codechicken/lib/packet/PacketCustom.java index 7e238f2..bd4586b 100644 --- a/src/codechicken/lib/packet/PacketCustom.java +++ b/src/codechicken/lib/packet/PacketCustom.java @@ -145,8 +145,12 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exc public static String channelName(Object channelKey) { if (channelKey instanceof String) return (String) channelKey; - if (channelKey instanceof ModContainer) - return ((ModContainer) channelKey).getModId(); + if (channelKey instanceof ModContainer) { + String s = ((ModContainer) channelKey).getModId(); + if(s.length() > 20) + throw new IllegalArgumentException("Mod ID ("+s+") too long for use as channel (20 chars). Use a string identifier"); + return s; + } ModContainer mc = FMLCommonHandler.instance().findContainerFor(channelKey); if (mc != null) From e7c670b1d343bb5d4d8a18d03f9b27ed913933f5 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 29 Jun 2014 14:28:15 +1000 Subject: [PATCH 095/219] Bound tooltips to screen properly --- src/codechicken/lib/gui/GuiDraw.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/gui/GuiDraw.java b/src/codechicken/lib/gui/GuiDraw.java index 41d84cd..bb80828 100644 --- a/src/codechicken/lib/gui/GuiDraw.java +++ b/src/codechicken/lib/gui/GuiDraw.java @@ -177,7 +177,10 @@ public static void drawMultilineTip(int x, int y, List list) { } if (x < 8) x = 8; - else if (x > displaySize().width - w - 8) x -= 24 + w;//flip side of cursor + else if (x > displaySize().width - w - 8) { + x -= 24 + w;//flip side of cursor + if(x < 8) x = 8; + } y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h); gui.incZLevel(300); From 18461348e35cea661ede1458cf0ae021bc956088 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 3 Jul 2014 01:26:02 +1000 Subject: [PATCH 096/219] Fix crash with tool system when loading ASMHelper --- src/codechicken/lib/asm/ASMHelper.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/codechicken/lib/asm/ASMHelper.java b/src/codechicken/lib/asm/ASMHelper.java index 7fa1aa3..6c53a96 100644 --- a/src/codechicken/lib/asm/ASMHelper.java +++ b/src/codechicken/lib/asm/ASMHelper.java @@ -2,7 +2,6 @@ import codechicken.lib.config.ConfigFile; import codechicken.lib.config.DefaultingConfigFile; -import cpw.mods.fml.relauncher.FMLInjectionData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; @@ -25,11 +24,16 @@ public class ASMHelper public static Logger logger = LogManager.getLogger("CCL ASM"); private static ConfigFile loadConfig() { - File file = new File((File) FMLInjectionData.data()[6], "config/CodeChickenLib.cfg"); - if(ObfMapping.obfuscated) - return new DefaultingConfigFile(file); - else - return new ConfigFile(file).setComment("CodeChickenLib development configuration file."); + try {//weak reference for environments without FML + File mcDir = (File)((Object[])Class.forName("cpw.mods.fml.relauncher.FMLInjectionData").getMethod("data").invoke(null))[6]; + File file = new File(mcDir, "config/CodeChickenLib.cfg"); + if(ObfMapping.obfuscated) + return new DefaultingConfigFile(file); + else + return new ConfigFile(file).setComment("CodeChickenLib development configuration file."); + } catch (Exception ignored) { + return null;//no config for these systems + } } public static interface Acceptor From f753dcdeb8b5b3b3c3287197defc74961c578502 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 3 Jul 2014 01:38:09 +1000 Subject: [PATCH 097/219] Add log4j libs --- src/codechicken/lib/tool/LibDownloader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/tool/LibDownloader.java b/src/codechicken/lib/tool/LibDownloader.java index a36f026..c4107be 100644 --- a/src/codechicken/lib/tool/LibDownloader.java +++ b/src/codechicken/lib/tool/LibDownloader.java @@ -16,7 +16,9 @@ public class LibDownloader private static String[] libs = new String[] { "org/ow2/asm/asm-debug-all/4.1/asm-debug-all-4.1.jar", "com/google/guava/guava/14.0/guava-14.0.jar", - "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar"}; + "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", + "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", + "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar"}; private static File libDir = new File("lib"); private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); From 23a58af62ad1606f0ef242f6d0034fee1dbdf13a Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 3 Jul 2014 21:02:54 +1000 Subject: [PATCH 098/219] Fix isObfuscated check returning false on obf names as opposed to srg names --- src/codechicken/lib/asm/ObfMapping.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/asm/ObfMapping.java b/src/codechicken/lib/asm/ObfMapping.java index 07c237b..bd062ab 100644 --- a/src/codechicken/lib/asm/ObfMapping.java +++ b/src/codechicken/lib/asm/ObfMapping.java @@ -73,8 +73,12 @@ public String map(String typeName) { return FMLDeobfuscatingRemapper.INSTANCE.unmap(typeName); } + public String unmap(String typeName) { + return FMLDeobfuscatingRemapper.INSTANCE.map(typeName); + } + public boolean isObf(String typeName) { - return !map(typeName).equals(typeName); + return !map(typeName).equals(typeName) || !unmap(typeName).equals(typeName); } } From 4b16ef27769403b56516233622505b822f7572d5 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 10 Jul 2014 01:17:37 +1000 Subject: [PATCH 099/219] Fix texture not found exceptions in console when using placeholder texture --- .../lib/render/PlaceholderTexture.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/codechicken/lib/render/PlaceholderTexture.java b/src/codechicken/lib/render/PlaceholderTexture.java index 8ef54ee..b909375 100644 --- a/src/codechicken/lib/render/PlaceholderTexture.java +++ b/src/codechicken/lib/render/PlaceholderTexture.java @@ -6,14 +6,17 @@ public class PlaceholderTexture extends TextureAtlasSprite { - protected PlaceholderTexture(String par1) - { + protected PlaceholderTexture(String par1) { super(par1); } - + + @Override + public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) { + return true; + } + @Override - public boolean load(IResourceManager manager, ResourceLocation location) - { - return false; + public boolean load(IResourceManager manager, ResourceLocation location) { + return true; } } From 9411dd0808d1c6274a734ae2919093d8b1984d78 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 11 Jul 2014 15:18:05 +1000 Subject: [PATCH 100/219] Added SimpleBrightnessModel for rendering 'solid' blocks --- .../lib/lighting/SimpleBrightnessModel.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/codechicken/lib/lighting/SimpleBrightnessModel.java diff --git a/src/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/codechicken/lib/lighting/SimpleBrightnessModel.java new file mode 100644 index 0000000..942e1c3 --- /dev/null +++ b/src/codechicken/lib/lighting/SimpleBrightnessModel.java @@ -0,0 +1,54 @@ +package codechicken.lib.lighting; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.BlockCoord; +import net.minecraft.block.Block; +import net.minecraft.world.IBlockAccess; + +/** + * Faster precomputed version of LightModel that only works for axis planar sides + */ +public class SimpleBrightnessModel implements CCRenderState.IVertexOperation +{ + public static final int operationIndex = CCRenderState.registerOperation(); + public static SimpleBrightnessModel instance = new SimpleBrightnessModel(); + + public IBlockAccess access; + public BlockCoord pos = new BlockCoord(); + + private int sampled = 0; + private int[] samples = new int[6]; + private BlockCoord c = new BlockCoord(); + + public void locate(IBlockAccess a, int x, int y, int z) { + access = a; + pos.set(x, y, z); + sampled = 0; + } + + public int sample(int side) { + if ((sampled & 1 << side) == 0) { + c.set(pos).offset(side); + Block block = access.getBlock(c.x, c.y, c.z); + samples[side] = access.getLightBrightnessForSkyBlocks(c.x, c.y, c.z, block.getLightValue(access, c.x, c.y, c.z)); + sampled |= 1 << side; + } + return samples[side]; + } + + @Override + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + return true; + } + + @Override + public void operate() { + CCRenderState.setBrightness(sample(CCRenderState.side)); + } + + @Override + public int operationID() { + return operationIndex; + } +} From 0ba1132ff60877c1cab886201114700343a31d59 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 25 Jul 2014 00:32:36 +1000 Subject: [PATCH 101/219] Add parameterised mouse point rescaling helper for events --- src/codechicken/lib/gui/GuiDraw.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/codechicken/lib/gui/GuiDraw.java b/src/codechicken/lib/gui/GuiDraw.java index bb80828..7dd8169 100644 --- a/src/codechicken/lib/gui/GuiDraw.java +++ b/src/codechicken/lib/gui/GuiDraw.java @@ -110,10 +110,14 @@ public static Dimension displayRes() { return new Dimension(mc.displayWidth, mc.displayHeight); } - public static Point getMousePosition() { + public static Point getMousePosition(int eventX, int eventY) { Dimension size = displaySize(); Dimension res = displayRes(); - return new Point(Mouse.getX() * size.width / res.width, size.height - Mouse.getY() * size.height / res.height - 1); + return new Point(eventX * size.width / res.width, size.height - eventY * size.height / res.height - 1); + } + + public static Point getMousePosition() { + return getMousePosition(Mouse.getX(), Mouse.getY()); } public static void changeTexture(String s) { From 76a6c9e7d545681ca1de7a3a89e29378f4c64a20 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Sun, 27 Jul 2014 22:32:27 +1000 Subject: [PATCH 102/219] Add lang proxy --- src/codechicken/lib/util/LangProxy.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/codechicken/lib/util/LangProxy.java diff --git a/src/codechicken/lib/util/LangProxy.java b/src/codechicken/lib/util/LangProxy.java new file mode 100644 index 0000000..287b0a7 --- /dev/null +++ b/src/codechicken/lib/util/LangProxy.java @@ -0,0 +1,20 @@ +package codechicken.lib.util; + +import net.minecraft.util.StatCollector; + +public class LangProxy +{ + public final String namespace; + + public LangProxy(String namespace) { + this.namespace = namespace+"."; + } + + public String translate(String key) { + return StatCollector.translateToLocal(namespace+key); + } + + public String format(String key, Object... params) { + return StatCollector.translateToLocalFormatted(namespace+key, params); + } +} From 3b081ed3cd34be6e05bb4c3c4fb5aafaf1da1960 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 5 Aug 2014 18:00:41 +1000 Subject: [PATCH 103/219] Keep class references of config package within config so it can be used at the ASM level Add simple extensible config serialisation --- src/codechicken/lib/colour/Colour.java | 30 ++ src/codechicken/lib/config/ConfigTag.java | 323 +++++++----------- .../lib/config/ConfigTagParent.java | 195 +++++------ 3 files changed, 236 insertions(+), 312 deletions(-) diff --git a/src/codechicken/lib/colour/Colour.java b/src/codechicken/lib/colour/Colour.java index ea8a636..1bccdf3 100644 --- a/src/codechicken/lib/colour/Colour.java +++ b/src/codechicken/lib/colour/Colour.java @@ -1,13 +1,43 @@ package codechicken.lib.colour; +import codechicken.lib.config.ConfigTag.IConfigType; import codechicken.lib.math.MathHelper; import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import org.lwjgl.opengl.GL11; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public abstract class Colour implements Copyable { + public static IConfigType configRGB = new IConfigType() + { + @Override + public String configValue(Colour entry) { + String s = Long.toString(((long) entry.rgb()) << 32 >>> 32, 16); + while (s.length() < 6) + s = "0" + s; + return "0x" + s.toUpperCase(); + } + + private final Pattern patternRGB = Pattern.compile("(\\d+),(\\d+),(\\d+)"); + @Override + public Colour valueOf(String text) throws Exception { + Matcher matcherRGB = patternRGB.matcher(text.replaceAll("\\s", "")); + if(matcherRGB.matches()) + return new ColourRGBA( + Integer.parseInt(matcherRGB.group(1)), + Integer.parseInt(matcherRGB.group(2)), + Integer.parseInt(matcherRGB.group(3)), + 0xFF); + + int hex = (int) Long.parseLong(text.replace("0x", ""), 16); + return new ColourRGBA(hex<<8|0xFF); + } + }; + public byte r; public byte g; public byte b; diff --git a/src/codechicken/lib/config/ConfigTag.java b/src/codechicken/lib/config/ConfigTag.java index cd3b8ad..e0eebd5 100644 --- a/src/codechicken/lib/config/ConfigTag.java +++ b/src/codechicken/lib/config/ConfigTag.java @@ -1,299 +1,230 @@ package codechicken.lib.config; -import codechicken.lib.colour.Colour; -import codechicken.lib.colour.ColourRGBA; - import java.io.PrintWriter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class ConfigTag extends ConfigTagParent -{ - public ConfigTag(ConfigTagParent parent, String name) +{ + public interface IConfigType { + public String configValue(T entry); + + public T valueOf(String text) throws Exception; + } + + public ConfigTag(ConfigTagParent parent, String name) { this.parent = parent; this.name = name; - qualifiedname = parent.getNameQualifier()+name; + qualifiedname = parent.getNameQualifier() + name; newline = parent.newlinemode == 2; parent.addChild(this); } - + @Override - public String getNameQualifier() - { - return qualifiedname+"."; + public String getNameQualifier() { + return qualifiedname + "."; } - + @Override - public void saveConfig() - { + public void saveConfig() { parent.saveConfig(); } - + /** * Called when the tag is loaded from a config file as opposed to constructed by a mod + * * @return this */ - public ConfigTag onLoaded() - { + public ConfigTag onLoaded() { return this; } - - public void setValue(String value) - { + + public void setValue(String value) { this.value = value; saveConfig(); } - - public void setDefaultValue(String defaultvalue) - { - if(value == null) - { - value = defaultvalue; + + public void setDefaultValue(String defaultValue) { + if (value == null) { + value = defaultValue; saveConfig(); } } - - public void setIntValue(int i) - { + + public void setIntValue(int i) { setValue(Integer.toString(i)); } - - public void setBooleanValue(boolean b) - { + + public void setBooleanValue(boolean b) { setValue(Boolean.toString(b)); } - - public void setHexValue(int i) - { - setValue("0x"+Long.toString(((long)i) << 32 >>> 32, 16)); + + public void setHexValue(int i) { + setValue("0x" + Long.toString(((long) i) << 32 >>> 32, 16)); } - - public void setColourRGB(Colour c) - { - String s = Long.toString(((long)c.rgb()) << 32 >>> 32, 16); - while(s.length() < 6) - s = "0"+s; - setValue("0x"+s.toUpperCase()); + + public void set(IConfigType type, T entry) { + setValue(type.configValue(entry)); } - - public String getValue() - { + + public String getValue() { return value; } - - public String getValue(String defaultvalue) - { - setDefaultValue(defaultvalue); + + public String getValue(String defaultValue) { + setDefaultValue(defaultValue); return value; } - - public int getIntValue() - { + + public int getIntValue() { return Integer.parseInt(getValue()); } - - public int getIntValue(int defaultvalue) - { - if(value == null) - { - setIntValue(defaultvalue); - } - try - { - return getIntValue(); - } - catch(NumberFormatException nfe) - { - setIntValue(defaultvalue); - return getIntValue(); - } + + public int getIntValue(int defaultValue) { + try { + if (value != null) + return getIntValue(); + } catch (NumberFormatException ignored) {} + + setIntValue(defaultValue); + return defaultValue; } - - public boolean getBooleanValue() - { + + public boolean getBooleanValue() { String value = getValue(); - if(value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) - { + if (value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) return true; - } - else if(value != null && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) - { + else if (value != null && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) return false; - } - throw new NumberFormatException(qualifiedname+".value="+value); + + throw new NumberFormatException(qualifiedname + ".value=" + value); } - - public boolean getBooleanValue(boolean defaultvalue) - { - if(value == null) - { - setBooleanValue(defaultvalue); - } - try - { - return getBooleanValue(); - } - catch(NumberFormatException nfe) - { - setBooleanValue(defaultvalue); - return getBooleanValue(); - } + + public boolean getBooleanValue(boolean defaultValue) { + try { + if (value != null) + return getBooleanValue(); + } catch (NumberFormatException ignored) {} + + setBooleanValue(defaultValue); + return defaultValue; } - public int getHexValue() - { + public int getHexValue() { return (int) Long.parseLong(getValue().replace("0x", ""), 16); } - - public int getHexValue(int defaultvalue) - { - if(value == null) - { - setHexValue(defaultvalue); - } - try - { - return getHexValue(); - } - catch(NumberFormatException nfe) - { - setHexValue(defaultvalue); - return getHexValue(); - } + + public int getHexValue(int defaultValue) { + try { + if (value != null) + return getHexValue(); + } catch (NumberFormatException ignored) {} + + setHexValue(defaultValue); + return defaultValue; } - - private static final Pattern patternRGB = Pattern.compile("(\\d+),(\\d+),(\\d+)"); - public Colour getColourRGB() - { - Matcher matcherRGB = patternRGB.matcher(getValue().replaceAll("\\s", "")); - if(matcherRGB.matches()) - { - return new ColourRGBA( - Integer.parseInt(matcherRGB.group(1)), - Integer.parseInt(matcherRGB.group(2)), - Integer.parseInt(matcherRGB.group(3)), - 0xFF); + + public T get(IConfigType type) { + try { + return type.valueOf(getValue()); + } catch (Exception e) { + throw new RuntimeException(e); } - - return new ColourRGBA(getHexValue()<<8|0xFF); } - - public Colour getColourRGB(Colour defaultvalue) - { - if(value == null) - { - setColourRGB(defaultvalue); - } - try - { - return getColourRGB(); - } - catch(NumberFormatException nfe) - { - setColourRGB(defaultvalue); - return getColourRGB(); - } + + public T get(IConfigType type, T defaultValue) { + try { + if (value != null) + return get(type); + } catch (Exception ignored) {} + + set(type, defaultValue); + return defaultValue; } - public void save(PrintWriter writer, int tabs, String bracequalifier, boolean first) - { + public void save(PrintWriter writer, int tabs, String bracequalifier, boolean first) { String vname; - if(qualifiedname.contains(".") && bracequalifier.length() > 0) + if (qualifiedname.contains(".") && bracequalifier.length() > 0) vname = qualifiedname.substring(bracequalifier.length() + 1); else vname = qualifiedname; - - if(newline && !first) + + if (newline && !first) ConfigFile.writeLine(writer, "", tabs); - + writeComment(writer, tabs); - if(value != null) - ConfigFile.writeLine(writer, vname+"="+value, tabs); + if (value != null) + ConfigFile.writeLine(writer, vname + "=" + value, tabs); - if(!hasChildTags()) + if (!hasChildTags()) return; - - if(brace) - { - if(value == null) + + if (brace) { + if (value == null) ConfigFile.writeLine(writer, vname, tabs); ConfigFile.writeLine(writer, "{", tabs); - saveTagTree(writer, tabs+1, qualifiedname); + saveTagTree(writer, tabs + 1, qualifiedname); ConfigFile.writeLine(writer, "}", tabs); - } - else - { + } else { saveTagTree(writer, tabs, bracequalifier); } - } + } @Override - public ConfigTag setComment(String comment) - { + public ConfigTag setComment(String comment) { super.setComment(comment); return this; } - + @Override - public ConfigTag setSortMode(int mode) - { + public ConfigTag setSortMode(int mode) { super.setSortMode(mode); return this; } - - public ConfigTag setNewLine(boolean b) - { + + public ConfigTag setNewLine(boolean b) { newline = b; saveConfig(); return this; } - - public ConfigTag useBraces() - { + + public ConfigTag useBraces() { brace = true; - if(parent.newlinemode == 1) + if (parent.newlinemode == 1) newline = true; - + saveConfig(); return this; } - - public ConfigTag setPosition(int pos) - { + + public ConfigTag setPosition(int pos) { position = pos; saveConfig(); return this; } - - public boolean containsTag(String tagname) - { + + public boolean containsTag(String tagname) { return getTag(tagname, false) != null; } - - public int getId(String name, int defaultValue) - { + + public int getId(String name, int defaultValue) { return getTag(name).getIntValue(defaultValue); } - - public int getId(String name) - { + + public int getId(String name) { int ret = getId(name, IDBase); - IDBase = ret+1; + IDBase = ret + 1; return ret; } - - public int getAcheivementId(String name, int defaultValue) - { + + public int getAcheivementId(String name, int defaultValue) { return getTag(name).getIntValue(defaultValue); } - - public ConfigTag setBaseID(int i) - { + + public ConfigTag setBaseID(int i) { IDBase = i; return this; } - + public ConfigTagParent parent; public String name; public String qualifiedname; @@ -301,6 +232,6 @@ public ConfigTag setBaseID(int i) public boolean brace; public boolean newline; public int position = Integer.MAX_VALUE; - + private int IDBase; } diff --git a/src/codechicken/lib/config/ConfigTagParent.java b/src/codechicken/lib/config/ConfigTagParent.java index 55bc009..8eab85d 100644 --- a/src/codechicken/lib/config/ConfigTagParent.java +++ b/src/codechicken/lib/config/ConfigTagParent.java @@ -11,26 +11,23 @@ public abstract class ConfigTagParent public static class TagOrderComparator implements Comparator { int sortMode; - - public TagOrderComparator(int sortMode) - { + + public TagOrderComparator(int sortMode) { this.sortMode = sortMode; } - - public int compare(ConfigTag o1, ConfigTag o2) - { - if(o1.position != o2.position) + + public int compare(ConfigTag o1, ConfigTag o2) { + if (o1.position != o2.position) return compareInt(o1.position, o2.position); - if(o1.brace != o2.brace) + if (o1.brace != o2.brace) return o1.brace ? 1 : -1;//braced one goes after - switch(sortMode) - { + switch (sortMode) { case 1: - if(o1.value == o2.value) + if (o1.value == o2.value) return 0; - if(o1.value == null) + if (o1.value == null) return 1; - if(o2.value == null) + if (o2.value == null) return -1; return o1.value.compareTo(o2.value); default: @@ -38,12 +35,11 @@ public int compare(ConfigTag o1, ConfigTag o2) } } - private int compareInt(int a, int b) - { + private int compareInt(int a, int b) { return a == b ? 0 : a < b ? -1 : 1; } } - + private TreeMap childtags = new TreeMap(); public String comment; /** @@ -55,187 +51,154 @@ private int compareInt(int a, int b) * 0 = never, 1 = when braced, 2 = always */ public int newlinemode = 1; - + public abstract void saveConfig(); - + public abstract String getNameQualifier(); - - public ConfigTagParent setComment(String comment) - { + + public ConfigTagParent setComment(String comment) { this.comment = comment; saveConfig(); return this; } - - public ConfigTagParent setSortMode(int mode) - { + + public ConfigTagParent setSortMode(int mode) { sortMode = mode; saveConfig(); return this; } - - public ConfigTagParent setNewLineMode(int mode) - { + + public ConfigTagParent setNewLineMode(int mode) { newlinemode = mode; - for(Entry entry : childtags.entrySet()) - { + for (Entry entry : childtags.entrySet()) { ConfigTag tag = entry.getValue(); - if(newlinemode == 0) + if (newlinemode == 0) tag.newline = false; - else if(newlinemode == 1) + else if (newlinemode == 1) tag.newline = tag.brace; - else if(newlinemode == 2) + else if (newlinemode == 2) tag.newline = true; } saveConfig(); return this; } - - public Map childTagMap() - { + + public Map childTagMap() { return childtags; } - - public boolean hasChildTags() - { + + public boolean hasChildTags() { return !childtags.isEmpty(); } - - public boolean containsTag(String tagname) - { + + public boolean containsTag(String tagname) { return getTag(tagname, false) != null; } - - public ConfigTag getNewTag(String tagname) - { + + public ConfigTag getNewTag(String tagname) { return new ConfigTag(this, tagname); } - public ConfigTag getTag(String tagname, boolean create) - { + public ConfigTag getTag(String tagname, boolean create) { int dotpos = tagname.indexOf("."); String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos); ConfigTag basetag = childtags.get(basetagname); - if(basetag == null) - { - if(!create) + if (basetag == null) { + if (!create) return null; - + basetag = getNewTag(basetagname); saveConfig(); } - if(dotpos == -1) + if (dotpos == -1) return basetag; - - return basetag.getTag(tagname.substring(dotpos+1), create); + + return basetag.getTag(tagname.substring(dotpos + 1), create); } - - public ConfigTag getTag(String tagname) - { + + public ConfigTag getTag(String tagname) { return getTag(tagname, true); } - - public boolean removeTag(String tagname) - { + + public boolean removeTag(String tagname) { ConfigTag tag = getTag(tagname, false); - if(tag == null) + if (tag == null) return false; int dotpos = tagname.lastIndexOf("."); - String lastpart = dotpos == -1 ? tagname : tagname.substring(dotpos+1, tagname.length()); - if(tag.parent != null) - { + String lastpart = dotpos == -1 ? tagname : tagname.substring(dotpos + 1, tagname.length()); + if (tag.parent != null) { boolean ret = tag.parent.childtags.remove(lastpart) != null; - if(ret) + if (ret) saveConfig(); return ret; } - + return false; } - public void addChild(ConfigTag tag) - { + public void addChild(ConfigTag tag) { childtags.put(tag.name, tag); } - - public ArrayList getSortedTagList() - { + + public ArrayList getSortedTagList() { ArrayList taglist = new ArrayList(childtags.size()); - for(Entry tag : childtags.entrySet()) - taglist.add((T)tag.getValue()); - + for (Entry tag : childtags.entrySet()) + taglist.add((T) tag.getValue()); + Collections.sort(taglist, new TagOrderComparator(sortMode)); return taglist; } - - public void loadChildren(BufferedReader reader) - { + + public void loadChildren(BufferedReader reader) { String comment = ""; - String bracequalifier=""; - try - { - while(true) - { + String bracequalifier = ""; + try { + while (true) { String line = ConfigFile.readLine(reader); - if(line == null) + if (line == null) break; - if(line.startsWith("#")) - { - if(comment.equals("")) + if (line.startsWith("#")) { + if (comment.equals("")) comment = line.substring(1); else - comment = comment+"\n"+line.substring(1); - } - else if(line.contains("=")) - { + comment = comment + "\n" + line.substring(1); + } else if (line.contains("=")) { String qualifiedname = line.substring(0, line.indexOf("=")); getTag(qualifiedname) - .onLoaded() - .setComment(comment) - .setValue(line.substring(line.indexOf("=")+1)); + .onLoaded() + .setComment(comment) + .setValue(line.substring(line.indexOf("=") + 1)); comment = ""; bracequalifier = qualifiedname; - } - else if(line.equals("{")) - { + } else if (line.equals("{")) { getTag(bracequalifier).setComment(comment).useBraces().loadChildren(reader); comment = ""; bracequalifier = ""; - } - else if(line.equals("}")) - { + } else if (line.equals("}")) { break; - } - else - { + } else { bracequalifier = line; } } - } - catch(IOException e) - { + } catch (IOException e) { throw new RuntimeException(e); } } - - public void saveTagTree(PrintWriter writer, int tabs, String bracequalifier) - { + + public void saveTagTree(PrintWriter writer, int tabs, String bracequalifier) { boolean first = true; - for(ConfigTag tag : getSortedTagList()) - { + for (ConfigTag tag : getSortedTagList()) { tag.save(writer, tabs, bracequalifier, first); first = false; } } - - public void writeComment(PrintWriter writer, int tabs) - { - if(comment != null && !comment.equals("")) - { + + public void writeComment(PrintWriter writer, int tabs) { + if (comment != null && !comment.equals("")) { String[] comments = comment.split("\n"); - for(int i = 0; i < comments.length; i++) - ConfigFile.writeLine(writer, "#"+comments[i], tabs); + for (int i = 0; i < comments.length; i++) + ConfigFile.writeLine(writer, "#" + comments[i], tabs); } } } From f50b326d92b9afbaac320326cb245d89589ad92a Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 15 Aug 2014 14:48:15 +1000 Subject: [PATCH 104/219] Added lightmap push function to CCRenderState --- src/codechicken/lib/render/CCRenderState.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/codechicken/lib/render/CCRenderState.java index 70f9db1..952f01f 100644 --- a/src/codechicken/lib/render/CCRenderState.java +++ b/src/codechicken/lib/render/CCRenderState.java @@ -390,6 +390,10 @@ public static void pullLightmap() { setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX); } + public static void pushLightmap() { + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness & 0xFFFF, brightness >>> 16); + } + /** * Compact helper for setting dynamic rendering context. Uses normals and doesn't compute lighting */ From 71f3c55d9d70e80a4a351fc0f3212f91b965af4c Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 15 Aug 2014 16:40:29 +1000 Subject: [PATCH 105/219] Add mipmaps to animated TextureFX --- src/codechicken/lib/render/TextureSpecial.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/codechicken/lib/render/TextureSpecial.java b/src/codechicken/lib/render/TextureSpecial.java index 03eb55c..9a44498 100644 --- a/src/codechicken/lib/render/TextureSpecial.java +++ b/src/codechicken/lib/render/TextureSpecial.java @@ -24,6 +24,7 @@ public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis //textureFX fields private TextureFX textureFX; + private int mipmapLevels; private int blankSize = -1; private ArrayList baseTextures; @@ -64,11 +65,21 @@ public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY public void updateAnimation() { if (textureFX != null) { textureFX.update(); - if (textureFX.changed()) - TextureUtil.uploadTextureMipmap(new int[][]{textureFX.imageData}, width, height, originX, originY, false, false); + if (textureFX.changed()) { + int[][] mipmaps = new int[mipmapLevels + 1][]; + mipmaps[0] = textureFX.imageData; + mipmaps = TextureUtil.generateMipmapData(mipmapLevels, width, mipmaps); + TextureUtil.uploadTextureMipmap(mipmaps, width, height, originX, originY, false, false); + } } } + @Override + public void generateMipmaps(int p_147963_1_) { + super.generateMipmaps(p_147963_1_); + mipmapLevels = p_147963_1_; + } + @Override public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) { return true; From 38744413af5a303d599f88432cded1cce4d60407 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 15 Aug 2014 19:19:48 +1000 Subject: [PATCH 106/219] Fixed anisotropic filtering with TextureFX --- .../lib/render/SpriteSheetManager.java | 6 +- .../lib/render/TextureSpecial.java | 60 +++++++++++++------ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/codechicken/lib/render/SpriteSheetManager.java b/src/codechicken/lib/render/SpriteSheetManager.java index b64436a..2b6a4af 100644 --- a/src/codechicken/lib/render/SpriteSheetManager.java +++ b/src/codechicken/lib/render/SpriteSheetManager.java @@ -48,9 +48,9 @@ public void registerIcons(IIconRegister register) if(TextureUtils.refreshTexture(textureMap, resource.getResourcePath())) { reloadTexture(); - for(int i = 0; i < sprites.length; i++) - if(sprites[i] != null) - textureMap.setTextureEntry(sprites[i].getIconName(), sprites[i]); + for (TextureSpecial sprite : sprites) + if (sprite != null) + textureMap.setTextureEntry(sprite.getIconName(), sprite); } else { diff --git a/src/codechicken/lib/render/TextureSpecial.java b/src/codechicken/lib/render/TextureSpecial.java index 9a44498..841eff2 100644 --- a/src/codechicken/lib/render/TextureSpecial.java +++ b/src/codechicken/lib/render/TextureSpecial.java @@ -1,5 +1,6 @@ package codechicken.lib.render; +import codechicken.lib.asm.ObfMapping; import codechicken.lib.render.SpriteSheetManager.SpriteSheet; import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; @@ -10,10 +11,12 @@ import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.data.AnimationMetadataSection; import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; import java.awt.image.BufferedImage; +import java.lang.reflect.Method; import java.util.ArrayList; @SideOnly(Side.CLIENT) @@ -25,6 +28,8 @@ public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis //textureFX fields private TextureFX textureFX; private int mipmapLevels; + private int rawWidth; + private int rawHeight; private int blankSize = -1; private ArrayList baseTextures; @@ -32,6 +37,18 @@ public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis private boolean selfRegister; public int atlasIndex; + private static Method m_prepareAnisotropicFiltering; + static { + try { + m_prepareAnisotropicFiltering = TextureAtlasSprite.class.getMethod( + new ObfMapping("net/minecraft/client/renderer/texture", "func_147960_a", "([[III)[[I") + .toRuntime().s_name, int[][].class, int.class, int.class); + m_prepareAnisotropicFiltering.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + protected TextureSpecial(String par1) { super(par1); } @@ -58,7 +75,7 @@ public TextureSpecial addTextureFX(TextureFX fx) { public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) { super.initSprite(sheetWidth, sheetHeight, originX, originY, rotated); if (textureFX != null) - textureFX.onTextureDimensionsUpdate(width, height); + textureFX.onTextureDimensionsUpdate(rawWidth, rawHeight); } @Override @@ -68,12 +85,29 @@ public void updateAnimation() { if (textureFX.changed()) { int[][] mipmaps = new int[mipmapLevels + 1][]; mipmaps[0] = textureFX.imageData; + mipmaps = prepareAnisotropicFiltering(mipmaps); mipmaps = TextureUtil.generateMipmapData(mipmapLevels, width, mipmaps); TextureUtil.uploadTextureMipmap(mipmaps, width, height, originX, originY, false, false); } } } + + public int[][] prepareAnisotropicFiltering(int[][] mipmaps) { + try { + return (int[][]) m_prepareAnisotropicFiltering.invoke(this, mipmaps, rawWidth, rawHeight); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void loadSprite(BufferedImage[] images, AnimationMetadataSection animationMeta, boolean anisotropicFiltering) { + rawWidth = images[0].getWidth(); + rawHeight = images[0].getHeight(); + super.loadSprite(images, animationMeta, anisotropicFiltering); + } + @Override public void generateMipmaps(int p_147963_1_) { super.generateMipmaps(p_147963_1_); @@ -85,35 +119,27 @@ public boolean hasCustomLoader(IResourceManager manager, ResourceLocation locati return true; } - public void addFrame(int[] data) { + public void addFrame(int[] data, int width, int height) { GameSettings settings = Minecraft.getMinecraft().gameSettings; BufferedImage[] images = new BufferedImage[settings.mipmapLevels+1]; images[0] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); images[0].setRGB(0, 0, width, height, data, 0, width); - super.loadSprite(images, null, settings.anisotropicFiltering > 1); + loadSprite(images, null, settings.anisotropicFiltering > 1); } @Override public boolean load(IResourceManager manager, ResourceLocation location) { if (baseTextures != null) { - for (TextureDataHolder tex : baseTextures) { - width = tex.width; - height = tex.height; - addFrame(tex.data); - } + for (TextureDataHolder tex : baseTextures) + addFrame(tex.data, tex.width, tex.height); } - - if (spriteSheet != null) { + else if (spriteSheet != null) { TextureDataHolder tex = spriteSheet.createSprite(spriteIndex); - width = tex.width; - height = tex.height; - addFrame(tex.data); + addFrame(tex.data, tex.width, tex.height); } - - if (blankSize > 0) { - width = height = blankSize; - addFrame(new int[blankSize * blankSize]); + else if (blankSize > 0) { + addFrame(new int[blankSize * blankSize], blankSize, blankSize); } if (framesTextureData.isEmpty()) From f9287f696b7eef8589b43598c83579ca831a3662 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Tue, 19 Aug 2014 00:08:19 +1000 Subject: [PATCH 107/219] Replaced reflective invokation of private super method with copy of mojang code --- .../lib/render/TextureSpecial.java | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/codechicken/lib/render/TextureSpecial.java b/src/codechicken/lib/render/TextureSpecial.java index 841eff2..6f71410 100644 --- a/src/codechicken/lib/render/TextureSpecial.java +++ b/src/codechicken/lib/render/TextureSpecial.java @@ -16,7 +16,6 @@ import net.minecraft.util.ResourceLocation; import java.awt.image.BufferedImage; -import java.lang.reflect.Method; import java.util.ArrayList; @SideOnly(Side.CLIENT) @@ -37,18 +36,6 @@ public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis private boolean selfRegister; public int atlasIndex; - private static Method m_prepareAnisotropicFiltering; - static { - try { - m_prepareAnisotropicFiltering = TextureAtlasSprite.class.getMethod( - new ObfMapping("net/minecraft/client/renderer/texture", "func_147960_a", "([[III)[[I") - .toRuntime().s_name, int[][].class, int.class, int.class); - m_prepareAnisotropicFiltering.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - protected TextureSpecial(String par1) { super(par1); } @@ -93,11 +80,31 @@ public void updateAnimation() { } + /** + * Copy paste mojang code because it's private, and CCL can't have access transformers or reflection + */ public int[][] prepareAnisotropicFiltering(int[][] mipmaps) { - try { - return (int[][]) m_prepareAnisotropicFiltering.invoke(this, mipmaps, rawWidth, rawHeight); - } catch (Exception e) { - throw new RuntimeException(e); + if (Minecraft.getMinecraft().gameSettings.anisotropicFiltering <= 1) + { + return mipmaps; + } + else + { + int[][] aint1 = new int[mipmaps.length][]; + + for (int k = 0; k < mipmaps.length; ++k) + { + int[] aint2 = mipmaps[k]; + + if (aint2 != null) + { + int[] aint3 = new int[(rawWidth + 16 >> k) * (rawHeight + 16 >> k)]; + System.arraycopy(aint2, 0, aint3, 0, aint2.length); + aint1[k] = TextureUtil.prepareAnisotropicData(aint3, rawWidth >> k, rawHeight >> k, 8 >> k); + } + } + + return aint1; } } From 645919daa9831b079e075236842b64734306c165 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 29 Aug 2014 02:29:30 +1000 Subject: [PATCH 108/219] Added FullBlock side masked render function Fixed bug with Vertex5 constructor not passing tex to UV --- src/codechicken/lib/render/BlockRenderer.java | 21 ++++++-- src/codechicken/lib/render/Vertex5.java | 51 ++++++++----------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/codechicken/lib/render/BlockRenderer.java b/src/codechicken/lib/render/BlockRenderer.java index 311b046..a408e97 100644 --- a/src/codechicken/lib/render/BlockRenderer.java +++ b/src/codechicken/lib/render/BlockRenderer.java @@ -138,17 +138,32 @@ public void prepareVertex() { } public static FullBlock fullBlock = new FullBlock(); + public static void renderFullBlock(int sideMask) { + CCRenderState.setModel(fullBlock); + renderFaces(sideMask); + } - private static BlockFace face = new BlockFace(); + /** + * Renders faces of a block-like model based on a sideMask. Eg for side 2, verts 8-11 will be rendered + * @param sideMask A mask of faces not to render + */ + public static void renderFaces(int sideMask) { + if(sideMask == 0x3F) return; + for(int s = 0; s < 6; s++) + if((sideMask & 1< { public Vector3 vec; public UV uv; - - public Vertex5() - { + + public Vertex5() { this(new Vector3(), new UV()); } - - public Vertex5(Vector3 vert, UV uv) - { + + public Vertex5(Vector3 vert, UV uv) { this.vec = vert; this.uv = uv; } - - public Vertex5(Vector3 vert, double u, double v) - { + + public Vertex5(Vector3 vert, double u, double v) { this(vert, new UV(u, v)); } - public Vertex5(double x, double y, double z, double u, double v) - { + public Vertex5(double x, double y, double z, double u, double v) { this(x, y, z, u, v, 0); } - public Vertex5(double x, double y, double z, double u, double v, int tex) - { - this(new Vector3(x, y, z), new UV(u, v)); + public Vertex5(double x, double y, double z, double u, double v, int tex) { + this(new Vector3(x, y, z), new UV(u, v, tex)); } - public Vertex5 set(double x, double y, double z, double u, double v) - { + public Vertex5 set(double x, double y, double z, double u, double v) { vec.set(x, y, z); uv.set(u, v); return this; } - public Vertex5 set(double x, double y, double z, double u, double v, int tex) - { + public Vertex5 set(double x, double y, double z, double u, double v, int tex) { vec.set(x, y, z); uv.set(u, v, tex); return this; @@ -61,30 +54,26 @@ public Vertex5 set(Vertex5 vert) { return this; } - public Vertex5(Vertex5 vertex5) - { + public Vertex5(Vertex5 vertex5) { this(vertex5.vec.copy(), vertex5.uv.copy()); } - public Vertex5 copy() - { + public Vertex5 copy() { return new Vertex5(this); } - - public String toString() - { + + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Vertex: ("+new BigDecimal(vec.x, cont)+", "+new BigDecimal(vec.y, cont)+", "+new BigDecimal(vec.z, cont)+") ("+new BigDecimal(uv.u, cont)+", "+new BigDecimal(uv.v, cont)+")"; + return "Vertex: (" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ") " + + "(" + new BigDecimal(uv.u, cont) + ", " + new BigDecimal(uv.v, cont) + ") ("+uv.tex+")"; } - public Vertex5 apply(Transformation t) - { + public Vertex5 apply(Transformation t) { vec.apply(t); return this; } - - public Vertex5 apply(UVTransformation t) - { + + public Vertex5 apply(UVTransformation t) { uv.apply(t); return this; } From 05d1e187f841bcc551a71e80562cd9ba856c4db8 Mon Sep 17 00:00:00 2001 From: davboecki Date: Sat, 4 Oct 2014 13:00:55 +0200 Subject: [PATCH 109/219] Set ItemStack in the IInventory again after modifiing --- src/codechicken/lib/inventory/InventoryUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codechicken/lib/inventory/InventoryUtils.java b/src/codechicken/lib/inventory/InventoryUtils.java index 4c1c133..757a1f6 100644 --- a/src/codechicken/lib/inventory/InventoryUtils.java +++ b/src/codechicken/lib/inventory/InventoryUtils.java @@ -50,6 +50,8 @@ public static ItemStack decrStackSize(IInventory inv, int slot, int size) { ItemStack itemstack1 = item.splitStack(size); if (item.stackSize == 0) inv.setInventorySlotContents(slot, null); + else + inv.setInventorySlotContents(slot, item); inv.markDirty(); return itemstack1; From 4a40b215d5e92393e022a82e6fdb0e17f902af8f Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 7 Nov 2014 01:03:01 +1000 Subject: [PATCH 110/219] Update tool ASM to 5.0.3 Add set(TileEntity) method to BlockCoord Remove unused imports --- src/codechicken/lib/asm/ASMHelper.java | 10 ++++++++-- src/codechicken/lib/tool/LibDownloader.java | 2 +- src/codechicken/lib/vec/BlockCoord.java | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/codechicken/lib/asm/ASMHelper.java b/src/codechicken/lib/asm/ASMHelper.java index 6c53a96..85526db 100644 --- a/src/codechicken/lib/asm/ASMHelper.java +++ b/src/codechicken/lib/asm/ASMHelper.java @@ -8,6 +8,8 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.*; +import org.objectweb.asm.util.ASMifier; +import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceClassVisitor; import java.io.File; @@ -145,7 +147,7 @@ public static void replaceMethod(MethodNode original, MethodNode replacement) { replacement.accept(original); } - public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals) { + public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals, boolean textify) { try { if(!file.getParentFile().exists()) file.getParentFile().mkdirs(); @@ -153,7 +155,7 @@ public static void dump(Acceptor acceptor, File file, boolean filterImportant, b file.createNewFile(); PrintWriter pout = new PrintWriter(file); - ClassVisitor cv = new TraceClassVisitor(pout); + ClassVisitor cv = new TraceClassVisitor(null, textify ? new Textifier() : new ASMifier(), pout); if(filterImportant) cv = new ImportantInsnVisitor(cv); if(sortLocals) cv = new LocalVariablesSorterVisitor(cv); acceptor.accept(cv); @@ -163,6 +165,10 @@ public static void dump(Acceptor acceptor, File file, boolean filterImportant, b } } + public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals) { + dump(acceptor, file, filterImportant, sortLocals, config.getTag("textify").getBooleanValue(true)); + } + public static void dump(final byte[] bytes, File file, boolean filterImportant, boolean sortLocals) { dump(new Acceptor() { diff --git a/src/codechicken/lib/tool/LibDownloader.java b/src/codechicken/lib/tool/LibDownloader.java index c4107be..dc77c10 100644 --- a/src/codechicken/lib/tool/LibDownloader.java +++ b/src/codechicken/lib/tool/LibDownloader.java @@ -14,7 +14,7 @@ public class LibDownloader { private static String[] libs = new String[] { - "org/ow2/asm/asm-debug-all/4.1/asm-debug-all-4.1.jar", + "org/ow2/asm/asm-debug-all/5.0.3/asm-debug-all-5.0.3.jar", "com/google/guava/guava/14.0/guava-14.0.jar", "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", diff --git a/src/codechicken/lib/vec/BlockCoord.java b/src/codechicken/lib/vec/BlockCoord.java index b506eaf..4299400 100644 --- a/src/codechicken/lib/vec/BlockCoord.java +++ b/src/codechicken/lib/vec/BlockCoord.java @@ -219,6 +219,10 @@ public BlockCoord set(int[] ia) return set(ia[0], ia[1], ia[2]); } + public BlockCoord set(TileEntity tile) { + return set(tile.xCoord, tile.yCoord, tile.zCoord); + } + public int toSide() { if(!isAxial()) return -1; From feb8bfd02895ee4cd5bbf8d8a264450249b16234 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 7 Nov 2014 01:03:41 +1000 Subject: [PATCH 111/219] Workaround some mod interactions not calling the world load event before world tick --- src/codechicken/lib/world/WorldExtensionManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/world/WorldExtensionManager.java b/src/codechicken/lib/world/WorldExtensionManager.java index dd7f192..b8ec2b4 100644 --- a/src/codechicken/lib/world/WorldExtensionManager.java +++ b/src/codechicken/lib/world/WorldExtensionManager.java @@ -123,8 +123,11 @@ public void clientTick(TickEvent.ClientTickEvent event) } @SubscribeEvent - public void clientTick(TickEvent.WorldTickEvent event) + public void serverTick(TickEvent.WorldTickEvent event) { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + if(event.phase == TickEvent.Phase.START) preTick(event.world); else From 29e4eda53bec11e525cf8eed70d4923f93197f6e Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Wed, 17 Dec 2014 23:36:56 +1000 Subject: [PATCH 112/219] Added IChunkLoadTile --- src/codechicken/lib/world/IChunkLoadTile.java | 12 ++++++++++ .../lib/world/TileChunkLoadHook.java | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/codechicken/lib/world/IChunkLoadTile.java create mode 100644 src/codechicken/lib/world/TileChunkLoadHook.java diff --git a/src/codechicken/lib/world/IChunkLoadTile.java b/src/codechicken/lib/world/IChunkLoadTile.java new file mode 100644 index 0000000..5739102 --- /dev/null +++ b/src/codechicken/lib/world/IChunkLoadTile.java @@ -0,0 +1,12 @@ +package codechicken.lib.world; + +/** + * Provides a callback for tile entities when a chunk is loaded, as an alternative to validate when the chunk hasn't been added to the world. + * To hook all world join/seperate events. Use this, TileEntity.validate with a worldObj.blockExists check, TileEntity.onChunkUnload and TileEntity.invalidate + * Be sure to call TileChunkLoadHook.init() from your mod during initialisation + * You could easily implement this in your own mod, but providing it here reduces the number of times the chunkTileEntityMap needs to be iterated + */ +public interface IChunkLoadTile +{ + public void onChunkLoad(); +} diff --git a/src/codechicken/lib/world/TileChunkLoadHook.java b/src/codechicken/lib/world/TileChunkLoadHook.java new file mode 100644 index 0000000..718d45d --- /dev/null +++ b/src/codechicken/lib/world/TileChunkLoadHook.java @@ -0,0 +1,24 @@ +package codechicken.lib.world; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkEvent; + +public class TileChunkLoadHook +{ + private static boolean init; + public static void init() { + if(init) return; + init = true; + + MinecraftForge.EVENT_BUS.register(new TileChunkLoadHook()); + } + + @SubscribeEvent + public void onChunkLoad(ChunkEvent.Load event) { + for(TileEntity t : ((Iterable)event.getChunk().chunkTileEntityMap.values())) + if(t instanceof IChunkLoadTile) + ((IChunkLoadTile)t).onChunkLoad(); + } +} From ccc986f1d7d7d722fe97b0bfc2373ba2647ac9cc Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 19 Dec 2014 01:55:31 +1000 Subject: [PATCH 113/219] Fix ConcurrentModificationException in tile chunk load hook --- src/codechicken/lib/world/TileChunkLoadHook.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/world/TileChunkLoadHook.java b/src/codechicken/lib/world/TileChunkLoadHook.java index 718d45d..e080c2e 100644 --- a/src/codechicken/lib/world/TileChunkLoadHook.java +++ b/src/codechicken/lib/world/TileChunkLoadHook.java @@ -5,6 +5,9 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.ChunkEvent; +import java.util.ArrayList; +import java.util.List; + public class TileChunkLoadHook { private static boolean init; @@ -17,7 +20,8 @@ public static void init() { @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { - for(TileEntity t : ((Iterable)event.getChunk().chunkTileEntityMap.values())) + List list = new ArrayList(event.getChunk().chunkTileEntityMap.values()); + for(TileEntity t : list) if(t instanceof IChunkLoadTile) ((IChunkLoadTile)t).onChunkLoad(); } From d92b0a6a311e307ef52f930b3153a077d2cae29d Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 16 Jan 2015 18:33:29 +1000 Subject: [PATCH 114/219] Potentially breaking change to InventoryRange constructor Added some new methods to CuboidCoord Removed unused methods from RayTracer --- build/build.properties | 2 +- .../lib/inventory/InventoryRange.java | 4 +- src/codechicken/lib/raytracer/RayTracer.java | 41 -------- src/codechicken/lib/vec/CuboidCoord.java | 99 +++++++++---------- 4 files changed, 48 insertions(+), 98 deletions(-) diff --git a/build/build.properties b/build/build.properties index 481366a..27f3785 100644 --- a/build/build.properties +++ b/build/build.properties @@ -1,3 +1,3 @@ minecraft_version=1.7.10 forge_version=10.13.0.1151 -mod_version=1.1.1 +mod_version=1.1.3 diff --git a/src/codechicken/lib/inventory/InventoryRange.java b/src/codechicken/lib/inventory/InventoryRange.java index f3d8c2d..9622325 100644 --- a/src/codechicken/lib/inventory/InventoryRange.java +++ b/src/codechicken/lib/inventory/InventoryRange.java @@ -36,10 +36,10 @@ public InventoryRange(IInventory inv) this(inv, 0); } - public InventoryRange(IInventory inv, int fslot, int lslot) + public InventoryRange(IInventory inv, int fslot, int size) { this.inv = inv; - slots = new int[lslot-fslot]; + slots = new int[size]; for(int i = 0; i < slots.length; i++) slots[i] = fslot+i; } diff --git a/src/codechicken/lib/raytracer/RayTracer.java b/src/codechicken/lib/raytracer/RayTracer.java index 12d9d49..d648699 100644 --- a/src/codechicken/lib/raytracer/RayTracer.java +++ b/src/codechicken/lib/raytracer/RayTracer.java @@ -107,30 +107,6 @@ public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 c return mop; } - public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid, BlockCoord pos) - { - MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); - if(mop != null) - { - mop.typeOfHit = MovingObjectType.BLOCK; - mop.blockX = pos.x; - mop.blockY = pos.y; - mop.blockZ = pos.z; - } - return mop; - } - - public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid, Entity e) - { - MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); - if(mop != null) - { - mop.typeOfHit = MovingObjectType.ENTITY; - mop.entityHit = e; - } - return mop; - } - public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids) { double c_dist = Double.MAX_VALUE; @@ -166,23 +142,6 @@ public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids, BlockCoord pos, Block block, List hitList) - { - for(IndexedCuboid6 cuboid : cuboids) - { - MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); - if(mop != null) - { - ExtendedMOP emop = new ExtendedMOP(mop, cuboid.data, s_dist); - emop.typeOfHit = MovingObjectType.BLOCK; - emop.blockX = pos.x; - emop.blockY = pos.y; - emop.blockZ = pos.z; - hitList.add(emop); - } - } - } - public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) { Block block = world.getBlock(x, y, z); diff --git a/src/codechicken/lib/vec/CuboidCoord.java b/src/codechicken/lib/vec/CuboidCoord.java index a3c598a..ef05e75 100644 --- a/src/codechicken/lib/vec/CuboidCoord.java +++ b/src/codechicken/lib/vec/CuboidCoord.java @@ -10,30 +10,25 @@ public class CuboidCoord implements Iterable, Copyable public BlockCoord min; public BlockCoord max; - public CuboidCoord() - { + public CuboidCoord() { min = new BlockCoord(); max = new BlockCoord(); } - public CuboidCoord(BlockCoord min, BlockCoord max) - { + public CuboidCoord(BlockCoord min, BlockCoord max) { this.min = min; this.max = max; } - - public CuboidCoord(BlockCoord coord) - { + + public CuboidCoord(BlockCoord coord) { this(coord, coord.copy()); } - public CuboidCoord(int[] ia) - { + public CuboidCoord(int[] ia) { this(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); } - public CuboidCoord(int x1, int y1, int z1, int x2, int y2, int z2) - { + public CuboidCoord(int x1, int y1, int z1, int x2, int y2, int z2) { this(new BlockCoord(x1, y1, z1), new BlockCoord(x2, y2, z2)); } @@ -47,19 +42,28 @@ public CuboidCoord expand(int x, int y, int z) { return this; } - public CuboidCoord expand(int side, int amount) - { - if(side%2 == 0)//negative side + public CuboidCoord expand(int side, int amount) { + if (side % 2 == 0)//negative side min = min.offset(side, amount); else max = max.offset(side, amount); return this; } + + public CuboidCoord offset(BlockCoord b) { + min.add(b); + max.add(b); + return this; + } + + public CuboidCoord offset(int x, int y, int z) { + min.add(x, y, z); + max.add(x, y, z); + return this; + } - public int size(int s) - { - switch(s) - { + public int size(int s) { + switch(s) { case 0: case 1: return max.y - min.y+1; @@ -74,10 +78,8 @@ public int size(int s) } } - public int getSide(int s) - { - switch(s) - { + public int getSide(int s) { + switch(s) { case 0: return min.y; case 1: return max.y; case 2: return min.z; @@ -88,10 +90,8 @@ public int getSide(int s) throw new IndexOutOfBoundsException("Switch Falloff"); } - public CuboidCoord setSide(int s, int v) - { - switch(s) - { + public CuboidCoord setSide(int s, int v) { + switch(s) { case 0: min.y = v; break; case 1: max.y = v; break; case 2: min.z = v; break; @@ -103,75 +103,66 @@ public CuboidCoord setSide(int s, int v) return this; } - public int getVolume() - { + public int getVolume() { return (max.x-min.x+1)*(max.y-min.y+1)*(max.z-min.z+1); } - public Vector3 getCenterVec() - { + public Vector3 getCenterVec() { return new Vector3(min.x+(max.x-min.x+1)/2D, min.y+(max.y-min.y+1)/2D, min.z+(max.z-min.z+1)/2D); } - public BlockCoord getCenter(BlockCoord store) - { + public BlockCoord getCenter(BlockCoord store) { store.set(min.x+(max.x-min.x)/2, min.y+(max.y-min.y)/2, min.z+(max.z-min.z)/2); return store; } - public boolean contains(BlockCoord coord) - { + public boolean contains(BlockCoord coord) { return contains(coord.x, coord.y, coord.z); } - public boolean contains(int x, int y, int z) - { + public boolean contains(int x, int y, int z) { return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z; } - public int[] intArray() - { + public int[] intArray() { return new int[]{min.x, min.y, min.z, max.x, max.y, max.z}; } - public CuboidCoord copy() - { + public CuboidCoord copy() { return new CuboidCoord(min.copy(), max.copy()); } - public Cuboid6 bounds() - { - return new Cuboid6(min.x, min.y, min.z, max.x+1, max.y+1, max.z+1); + public Cuboid6 bounds() { + return new Cuboid6(min.x, min.y, min.z, max.x + 1, max.y + 1, max.z + 1); } - public AxisAlignedBB toAABB() - { + public AxisAlignedBB toAABB() { return bounds().toAABB(); } - public void set(BlockCoord min, BlockCoord max) - { + public CuboidCoord set(CuboidCoord c) { + return set(c.min, c.max); + } + + public CuboidCoord set(BlockCoord min, BlockCoord max) { this.min.set(min); this.max.set(max); + return this; } - public CuboidCoord set(int x1, int y1, int z1, int x2, int y2, int z2) - { + public CuboidCoord set(int x1, int y1, int z1, int x2, int y2, int z2) { min.set(x1, y1, z1); max.set(x2, y2, z2); return this; } public CuboidCoord set(BlockCoord coord) { - min.set(coord); - max.set(coord); - return this; + return set(coord, coord); } - public CuboidCoord set(int[] ia) - { + public CuboidCoord set(int[] ia) { return set(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); } From 6b5404f1c0c94a0188c78cf157203ea67891303f Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Thu, 29 Jan 2015 10:34:39 +1000 Subject: [PATCH 115/219] Add missing icon detection helper method --- src/codechicken/lib/render/TextureUtils.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/render/TextureUtils.java b/src/codechicken/lib/render/TextureUtils.java index 0c04353..0ccaa70 100644 --- a/src/codechicken/lib/render/TextureUtils.java +++ b/src/codechicken/lib/render/TextureUtils.java @@ -154,8 +154,16 @@ public static boolean refreshTexture(TextureMap map, String name) { public static IIcon safeIcon(IIcon icon) { if (icon == null) - icon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); + icon = ((TextureMap) engine().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); return icon; } + + public static boolean isMissing(IIcon icon, ResourceLocation atlas) { + if(icon == null) + return true; + + IIcon missing = ((TextureMap) engine().getTexture(atlas)).getAtlasSprite("missingno"); + return icon.getMinU() == missing.getMinU() && icon.getMinV() == missing.getMinV(); + } } From 65a89cc92c6c74f8287c72d3dd0a6eae782b33e6 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 17 Apr 2015 12:28:56 +1000 Subject: [PATCH 116/219] Fluid API update --- build/build.properties | 2 +- src/codechicken/lib/data/MCDataOutputWrapper.java | 2 +- src/codechicken/lib/packet/PacketCustom.java | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/build.properties b/build/build.properties index 27f3785..4c9f512 100644 --- a/build/build.properties +++ b/build/build.properties @@ -1,3 +1,3 @@ minecraft_version=1.7.10 -forge_version=10.13.0.1151 +forge_version=10.13.3.1373-1.7.10 mod_version=1.1.3 diff --git a/src/codechicken/lib/data/MCDataOutputWrapper.java b/src/codechicken/lib/data/MCDataOutputWrapper.java index 48679d4..89ea270 100644 --- a/src/codechicken/lib/data/MCDataOutputWrapper.java +++ b/src/codechicken/lib/data/MCDataOutputWrapper.java @@ -232,7 +232,7 @@ public MCDataOutputWrapper writeFluidStack(FluidStack fluid) { if (fluid == null) { writeShort(-1); } else { - writeShort(fluid.fluidID); + writeShort(fluid.getFluidID()); writeVarInt(fluid.amount); writeNBTTagCompound(fluid.tag); } diff --git a/src/codechicken/lib/packet/PacketCustom.java b/src/codechicken/lib/packet/PacketCustom.java index bd4586b..fe5d32e 100644 --- a/src/codechicken/lib/packet/PacketCustom.java +++ b/src/codechicken/lib/packet/PacketCustom.java @@ -34,6 +34,8 @@ import net.minecraft.server.management.PlayerManager; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import java.util.EnumMap; @@ -371,7 +373,7 @@ public PacketCustom writeFluidStack(FluidStack fluid) { if (fluid == null) { writeShort(-1); } else { - writeShort(fluid.fluidID); + writeShort(fluid.getFluidID()); writeVarInt(fluid.amount); writeNBTTagCompound(fluid.tag); } @@ -465,13 +467,11 @@ public NBTTagCompound readNBTTagCompound() { } public FluidStack readFluidStack() { - FluidStack fluid = null; - short fluidID = readShort(); + Fluid fluid = FluidRegistry.getFluid(readShort()); + if(fluid == null) + fluid = FluidRegistry.WATER; - if (fluidID >= 0) - fluid = new FluidStack(fluidID, readVarInt(), readNBTTagCompound()); - - return fluid; + return new FluidStack(fluid, readVarInt(), readNBTTagCompound()); } public FMLProxyPacket toPacket() { From 16f0b50920ea0133706eec87704071422bacc494 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 24 Apr 2015 17:53:39 +1000 Subject: [PATCH 117/219] Fix GuiDraw.getStringWidth with bold formatting --- src/codechicken/lib/gui/GuiDraw.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/codechicken/lib/gui/GuiDraw.java b/src/codechicken/lib/gui/GuiDraw.java index 7dd8169..fb0f2a3 100644 --- a/src/codechicken/lib/gui/GuiDraw.java +++ b/src/codechicken/lib/gui/GuiDraw.java @@ -92,11 +92,8 @@ public static void drawStringR(String text, int x, int y, int colour) { drawStringR(text, x, y, colour, true); } - public static int getStringWidth(String s) { - if (s == null || s.equals("")) - return 0; - return fontRenderer.getStringWidth(EnumChatFormatting.getTextWithoutFormattingCodes(s)); + return fontRenderer.getStringWidth(s); } public static Dimension displaySize() { From 42b022af2aac81935b9dd23cfb6c95f74700c995 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 24 Apr 2015 18:47:59 +1000 Subject: [PATCH 118/219] Add fontRenderer parameter to drawMultilineTip --- src/codechicken/lib/gui/GuiDraw.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/codechicken/lib/gui/GuiDraw.java b/src/codechicken/lib/gui/GuiDraw.java index fb0f2a3..bfb280d 100644 --- a/src/codechicken/lib/gui/GuiDraw.java +++ b/src/codechicken/lib/gui/GuiDraw.java @@ -158,6 +158,10 @@ public static ITooltipLineHandler getTipLine(String line) { } public static void drawMultilineTip(int x, int y, List list) { + drawMultilineTip(fontRenderer, x, y, list); + } + + public static void drawMultilineTip(FontRenderer font, int x, int y, List list) { if (list.isEmpty()) return; @@ -172,7 +176,7 @@ public static void drawMultilineTip(int x, int y, List list) { ITooltipLineHandler line = getTipLine(s); Dimension d = line != null ? line.getSize() : - new Dimension(getStringWidth(s), list.get(i).endsWith(TOOLTIP_LINESPACE) && i + 1 < list.size() ? 12 : 10); + new Dimension(font.getStringWidth(s), list.get(i).endsWith(TOOLTIP_LINESPACE) && i + 1 < list.size() ? 12 : 10); w = Math.max(w, d.width); h += d.height; } @@ -193,7 +197,7 @@ else if (x > displaySize().width - w - 8) { y += line.getSize().height; } else { - fontRenderer.drawStringWithShadow(s, x, y, -1); + font.drawStringWithShadow(s, x, y, -1); y += s.endsWith(TOOLTIP_LINESPACE) ? 12 : 10; } } From 05bd26eb87d873cad66abf762299c05633cc56b4 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 29 May 2015 17:32:27 +1000 Subject: [PATCH 119/219] Moved ExtendedContainer code from CCC --- .../lib/inventory/ContainerExtended.java | 297 ++++++++++++++++++ .../lib/inventory/ContainerSynchronised.java | 67 ++++ .../lib/inventory/GuiContainerWidget.java | 131 ++++++++ .../lib/inventory/IContainerSyncVar.java | 14 + .../lib/inventory/IntegerSync.java | 34 ++ src/codechicken/lib/inventory/SlotDummy.java | 72 +++++ .../lib/inventory/SlotDummyOutput.java | 19 ++ .../lib/inventory/SlotHandleClicks.java | 16 + src/codechicken/lib/packet/PacketCustom.java | 12 +- 9 files changed, 656 insertions(+), 6 deletions(-) create mode 100644 src/codechicken/lib/inventory/ContainerExtended.java create mode 100644 src/codechicken/lib/inventory/ContainerSynchronised.java create mode 100644 src/codechicken/lib/inventory/GuiContainerWidget.java create mode 100644 src/codechicken/lib/inventory/IContainerSyncVar.java create mode 100644 src/codechicken/lib/inventory/IntegerSync.java create mode 100644 src/codechicken/lib/inventory/SlotDummy.java create mode 100644 src/codechicken/lib/inventory/SlotDummyOutput.java create mode 100644 src/codechicken/lib/inventory/SlotHandleClicks.java diff --git a/src/codechicken/lib/inventory/ContainerExtended.java b/src/codechicken/lib/inventory/ContainerExtended.java new file mode 100644 index 0000000..7c7cb15 --- /dev/null +++ b/src/codechicken/lib/inventory/ContainerExtended.java @@ -0,0 +1,297 @@ +package codechicken.lib.inventory; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import codechicken.lib.packet.PacketCustom; +import codechicken.lib.packet.PacketCustom.IClientPacketHandler; +import codechicken.lib.packet.PacketCustom.IServerPacketHandler; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ICrafting; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.inventory.Slot; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.INetHandlerPlayServer; +import org.apache.logging.log4j.LogManager; + +/** + * Clean container implementation with a few extra features. + * Easy shift-click handling. + * Hooks for slot clicks, large stack sizes and some networking. + */ +public abstract class ContainerExtended extends Container implements ICrafting +{ + private static final String netChannel = "CCL:Container"; + private static int nextNetworkID = 0; + static { + PacketCustom.assignHandler(netChannel, new IClientPacketHandler() + { + @Override + public void handlePacket(PacketCustom packet, Minecraft mc, INetHandlerPlayClient handler) { + Container cont = mc.thePlayer.openContainer; + if(!(cont instanceof ContainerExtended)) + return; + + ContainerExtended c = (ContainerExtended)cont; + if(packet.getType() == 1) + c.netID = packet.readInt(); + else if(c.netID == packet.readInt()) + c.handleClientPacket(packet); + } + }); + PacketCustom.assignHandler(netChannel, new IServerPacketHandler() + { + @Override + public void handlePacket(PacketCustom packet, EntityPlayerMP sender, INetHandlerPlayServer handler) { + Container cont = sender.openContainer; + if(!(cont instanceof ContainerExtended)) + return; + + ContainerExtended c = (ContainerExtended)cont; + if(c.netID == packet.readInt()) + c.handleServerPacket(packet); + } + }); + } + + public LinkedList playerCrafters = new LinkedList(); + private int netID; + + public ContainerExtended() { + crafters.add(this); + if(FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) + netID = ++nextNetworkID; + } + + @Override + public void addCraftingToCrafters(ICrafting icrafting) { + if (icrafting instanceof EntityPlayerMP) { + playerCrafters.add((EntityPlayerMP) icrafting); + sendNetID((EntityPlayerMP) icrafting); + sendContainerAndContentsToPlayer(this, getInventory(), Arrays.asList((EntityPlayerMP) icrafting)); + detectAndSendChanges(); + } else + super.addCraftingToCrafters(icrafting); + } + + private void sendNetID(EntityPlayerMP player) { + if(netID == 0) + LogManager.getLogger("CodeChickenLib").error("Player added to container with 0 network ID"); + else + new PacketCustom(netChannel, 1).writeInt(netID).sendToPlayer(player); + } + + @Override + public void removeCraftingFromCrafters(ICrafting icrafting) { + if (icrafting instanceof EntityPlayerMP) + playerCrafters.remove(icrafting); + else + super.removeCraftingFromCrafters(icrafting); + } + + @Override + public void sendContainerAndContentsToPlayer(Container container, List list) { + sendContainerAndContentsToPlayer(container, list, playerCrafters); + } + + public void sendContainerAndContentsToPlayer(Container container, List list, List playerCrafters) { + LinkedList largeStacks = new LinkedList(); + for (int i = 0; i < list.size(); i++) { + ItemStack stack = list.get(i); + if (stack != null && stack.stackSize > Byte.MAX_VALUE) { + list.set(i, null); + largeStacks.add(stack); + } else + largeStacks.add(null); + } + + for (EntityPlayerMP player : playerCrafters) + player.sendContainerAndContentsToPlayer(container, list); + + for (int i = 0; i < largeStacks.size(); i++) { + ItemStack stack = largeStacks.get(i); + if (stack != null) + sendLargeStack(stack, i, playerCrafters); + } + } + + public void sendLargeStack(ItemStack stack, int slot, List players) { + } + + @Override + public void sendProgressBarUpdate(Container container, int i, int j) { + for (EntityPlayerMP player : playerCrafters) + player.sendProgressBarUpdate(container, i, j); + } + + @Override + public void sendSlotContents(Container container, int slot, ItemStack stack) { + if (stack != null && stack.stackSize > Byte.MAX_VALUE) + sendLargeStack(stack, slot, playerCrafters); + else + for (EntityPlayerMP player : playerCrafters) + player.sendSlotContents(container, slot, stack); + } + + @Override + public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer player) { + if (par1 >= 0 && par1 < inventorySlots.size()) { + Slot slot = getSlot(par1); + if (slot instanceof SlotHandleClicks) + return ((SlotHandleClicks) slot).slotClick(this, player, par2, par3); + } + return super.slotClick(par1, par2, par3, player); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int slotIndex) { + ItemStack transferredStack = null; + Slot slot = (Slot) inventorySlots.get(slotIndex); + + if (slot != null && slot.getHasStack()) { + ItemStack stack = slot.getStack(); + transferredStack = stack.copy(); + + if (!doMergeStackAreas(slotIndex, stack)) + return null; + + if (stack.stackSize == 0) + slot.putStack(null); + else + slot.onSlotChanged(); + } + + return transferredStack; + } + + @Override + public boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean reverse) { + boolean merged = false; + int slotIndex = reverse ? endIndex - 1 : startIndex; + + if (stack == null) + return false; + + if (stack.isStackable())//search for stacks to increase + { + while (stack.stackSize > 0 && (reverse ? slotIndex >= startIndex : slotIndex < endIndex)) { + Slot slot = (Slot) inventorySlots.get(slotIndex); + ItemStack slotStack = slot.getStack(); + + if (slotStack != null && slotStack.getItem() == stack.getItem() && + (!stack.getHasSubtypes() || stack.getItemDamage() == slotStack.getItemDamage()) && + ItemStack.areItemStackTagsEqual(stack, slotStack)) { + int totalStackSize = slotStack.stackSize + stack.stackSize; + int maxStackSize = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit()); + if (totalStackSize <= maxStackSize) { + stack.stackSize = 0; + slotStack.stackSize = totalStackSize; + slot.onSlotChanged(); + merged = true; + } else if (slotStack.stackSize < maxStackSize) { + stack.stackSize -= maxStackSize - slotStack.stackSize; + slotStack.stackSize = maxStackSize; + slot.onSlotChanged(); + merged = true; + } + } + + slotIndex += reverse ? -1 : 1; + } + } + + if (stack.stackSize > 0)//normal transfer :) + { + slotIndex = reverse ? endIndex - 1 : startIndex; + + while (stack.stackSize > 0 && (reverse ? slotIndex >= startIndex : slotIndex < endIndex)) { + Slot slot = (Slot) this.inventorySlots.get(slotIndex); + + if (!slot.getHasStack() && slot.isItemValid(stack)) { + int maxStackSize = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit()); + if (stack.stackSize <= maxStackSize) { + slot.putStack(stack.copy()); + slot.onSlotChanged(); + stack.stackSize = 0; + merged = true; + } else { + slot.putStack(stack.splitStack(maxStackSize)); + slot.onSlotChanged(); + merged = true; + } + } + + slotIndex += reverse ? -1 : 1; + } + } + + return merged; + } + + /** + * Called when slotIndex is shift clicked on. Recommended implementation is to call mergeItemStack based on slotIndex + * + * @param stack The stack in the clicked slot + * @return True if one or more items were moved from this slots into other slots + */ + public boolean doMergeStackAreas(int slotIndex, ItemStack stack) { + return false; + } + + protected void bindPlayerInventory(InventoryPlayer inventoryPlayer) { + bindPlayerInventory(inventoryPlayer, 8, 84); + } + + protected void bindPlayerInventory(InventoryPlayer inventoryPlayer, int x, int y) { + for (int row = 0; row < 3; row++) + for (int col = 0; col < 9; col++) + addSlotToContainer(new Slot(inventoryPlayer, col + row * 9 + 9, x + col * 18, y + row * 18)); + for (int slot = 0; slot < 9; slot++) + addSlotToContainer(new Slot(inventoryPlayer, slot, x + slot * 18, y + 58)); + } + + @Override + public boolean canInteractWith(EntityPlayer var1) { + return true; + } + + public void sendContainerPacket(PacketCustom packet) { + for (EntityPlayerMP player : playerCrafters) + packet.sendToPlayer(player); + } + + /** + * @param type An identifying number for the packet type between 2 and 0x79 inclusive. 1 is reserved for synchronising networkIDs + * @return A packet on the CCL inventory channel that will be recieved by this container on the other network side + */ + public PacketCustom getPacket(int type) { + if(netID == 0) + LogManager.getLogger("CodeChickenLib").error("Tried to get packet for container with 0 network ID"); + if(type == 1) + throw new IllegalArgumentException("Packet type 1 is reserved for network synchronisation in ContainerExtended"); + + return new PacketCustom(netChannel, type).writeInt(netID); + } + + /** + * Handle a packet from the server obtained by getPacket. + */ + public void handleClientPacket(PacketCustom packet) {} + + /** + * Handle a packet from the client obtained by getPacket. + */ + public void handleServerPacket(PacketCustom packet) {} + + public void sendProgressBarUpdate(int barID, int value) { + for (ICrafting crafting : (List) crafters) + crafting.sendProgressBarUpdate(this, barID, value); + } +} diff --git a/src/codechicken/lib/inventory/ContainerSynchronised.java b/src/codechicken/lib/inventory/ContainerSynchronised.java new file mode 100644 index 0000000..f2fee59 --- /dev/null +++ b/src/codechicken/lib/inventory/ContainerSynchronised.java @@ -0,0 +1,67 @@ +package codechicken.lib.inventory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; + +import codechicken.lib.packet.PacketCustom; + +public abstract class ContainerSynchronised extends ContainerExtended +{ + private ArrayList syncVars = new ArrayList(); + + /** + * Create a packet to be used to send a synced variable update. + * Calls getPacket. Can be overriden to add extra identifying data or change the type (default 2) + */ + public PacketCustom createSyncPacket() { + return getPacket(2); + } + + @Override + public final void detectAndSendChanges() { + super.detectAndSendChanges(); + + for (int i = 0; i < syncVars.size(); i++) { + IContainerSyncVar var = syncVars.get(i); + if (var.changed()) { + PacketCustom packet = createSyncPacket(); + packet.writeByte(i); + var.writeChange(packet); + sendContainerPacket(packet); + var.reset(); + } + } + } + + @Override + public void sendContainerAndContentsToPlayer(Container container, List list, List playerCrafters) { + super.sendContainerAndContentsToPlayer(container, list, playerCrafters); + for (int i = 0; i < syncVars.size(); i++) { + IContainerSyncVar var = syncVars.get(i); + PacketCustom packet = createSyncPacket(); + packet.writeByte(i); + var.writeChange(packet); + var.reset(); + for (EntityPlayerMP player : playerCrafters) + packet.sendToPlayer(player); + } + } + + public void addSyncVar(IContainerSyncVar var) { + syncVars.add(var); + } + + @Override + public final void handleClientPacket(PacketCustom packet) { + syncVars.get(packet.readUByte()).readChange(packet); + } + + public List getSyncedVars() { + return Collections.unmodifiableList(syncVars); + } +} diff --git a/src/codechicken/lib/inventory/GuiContainerWidget.java b/src/codechicken/lib/inventory/GuiContainerWidget.java new file mode 100644 index 0000000..eaf4226 --- /dev/null +++ b/src/codechicken/lib/inventory/GuiContainerWidget.java @@ -0,0 +1,131 @@ +package codechicken.lib.inventory; + +import java.awt.Point; +import java.util.ArrayList; + +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import codechicken.lib.gui.GuiDraw; +import codechicken.core.gui.GuiWidget; +import codechicken.core.gui.IGuiActionListener; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Container; + +public class GuiContainerWidget extends GuiContainer implements IGuiActionListener +{ + public ArrayList widgets = new ArrayList(); + + public GuiContainerWidget(Container inventorySlots) + { + this(inventorySlots, 176, 166); + } + + public GuiContainerWidget(Container inventorySlots, int xSize, int ySize) + { + super(inventorySlots); + this.xSize = xSize; + this.ySize = ySize; + } + + @Override + public void setWorldAndResolution(Minecraft mc, int i, int j) + { + super.setWorldAndResolution(mc, i, j); + if(widgets.isEmpty()) + addWidgets(); + } + + public void add(GuiWidget widget) + { + widgets.add(widget); + widget.onAdded(this); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey) + { + GL11.glTranslated(guiLeft, guiTop, 0); + drawBackground(); + for(GuiWidget widget : widgets) + widget.draw(mousex-guiLeft, mousey-guiTop, f); + + GL11.glTranslated(-guiLeft, -guiTop, 0); + } + + public void drawBackground() + { + } + + @Override + protected void mouseClicked(int x, int y, int button) + { + super.mouseClicked(x, y, button); + for(GuiWidget widget : widgets) + widget.mouseClicked(x-guiLeft, y-guiTop, button); + } + + @Override + protected void mouseMovedOrUp(int x, int y, int button) + { + super.mouseMovedOrUp(x, y, button); + for(GuiWidget widget : widgets) + widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button); + } + + @Override + protected void mouseClickMove(int x, int y, int button, long time) + { + super.mouseClickMove(x, y, button, time); + for(GuiWidget widget : widgets) + widget.mouseDragged(x-guiLeft, y-guiTop, button, time); + } + + @Override + public void updateScreen() + { + super.updateScreen(); + if(mc.currentScreen == this) + for(GuiWidget widget : widgets) + widget.update(); + } + + @Override + public void keyTyped(char c, int keycode) + { + super.keyTyped(c, keycode); + for(GuiWidget widget : widgets) + widget.keyTyped(c, keycode); + } + + @Override + public void handleMouseInput() + { + super.handleMouseInput(); + int i = Mouse.getEventDWheel(); + if(i != 0) + { + Point p = GuiDraw.getMousePosition(); + int scroll = i > 0 ? 1 : -1; + for(GuiWidget widget : widgets) + widget.mouseScrolled(p.x, p.y, scroll); + } + } + + @Override + public void actionPerformed(String ident, Object... params) + { + } + + public void addWidgets() + { + } + + @Override + public void onGuiClosed() { + super.onGuiClosed(); + widgets.clear(); + } +} diff --git a/src/codechicken/lib/inventory/IContainerSyncVar.java b/src/codechicken/lib/inventory/IContainerSyncVar.java new file mode 100644 index 0000000..dc3b01f --- /dev/null +++ b/src/codechicken/lib/inventory/IContainerSyncVar.java @@ -0,0 +1,14 @@ +package codechicken.lib.inventory; + +import codechicken.lib.packet.PacketCustom; + +public interface IContainerSyncVar +{ + public boolean changed(); + + public void reset(); + + public void writeChange(PacketCustom packet); + + public void readChange(PacketCustom packet); +} diff --git a/src/codechicken/lib/inventory/IntegerSync.java b/src/codechicken/lib/inventory/IntegerSync.java new file mode 100644 index 0000000..841e564 --- /dev/null +++ b/src/codechicken/lib/inventory/IntegerSync.java @@ -0,0 +1,34 @@ +package codechicken.lib.inventory; + +import codechicken.lib.packet.PacketCustom; + +public abstract class IntegerSync implements IContainerSyncVar +{ + public int c_value; + + @Override + public boolean changed() + { + return getValue() != c_value; + } + + @Override + public void reset() + { + c_value = getValue(); + } + + @Override + public void writeChange(PacketCustom packet) + { + packet.writeInt(getValue()); + } + + @Override + public void readChange(PacketCustom packet) + { + c_value = packet.readInt(); + } + + public abstract int getValue(); +} diff --git a/src/codechicken/lib/inventory/SlotDummy.java b/src/codechicken/lib/inventory/SlotDummy.java new file mode 100644 index 0000000..d72320c --- /dev/null +++ b/src/codechicken/lib/inventory/SlotDummy.java @@ -0,0 +1,72 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class SlotDummy extends SlotHandleClicks +{ + public final int stackLimit; + public SlotDummy(IInventory inv, int slot, int x, int y) + { + this(inv, slot, x, y, 64); + } + + public SlotDummy(IInventory inv, int slot, int x, int y, int limit) + { + super(inv, slot, x, y); + stackLimit = limit; + } + + @Override + public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) + { + ItemStack held = player.inventory.getItemStack(); + boolean shift = modifier == 1; + slotClick(held, button, shift); + return null; + } + + public void slotClick(ItemStack held, int button, boolean shift) + { + ItemStack tstack = getStack(); + if(held != null && (tstack == null || !InventoryUtils.canStack(held, tstack))) + { + int quantity = Math.min(held.stackSize, stackLimit); + if(shift) + quantity = Math.min(stackLimit, held.getMaxStackSize()*16); + if(button == 1) + quantity = 1; + putStack(InventoryUtils.copyStack(held, quantity)); + } + else if(tstack != null) + { + int inc; + if(held != null) + { + inc = button == 1 ? -held.stackSize : held.stackSize; + if(shift) + inc *= 16; + } + else + { + inc = button == 1 ? -1 : 1; + if(shift) + inc *= 16; + } + int quantity = tstack.stackSize+inc; + if(quantity <= 0) + putStack(null); + else + putStack(InventoryUtils.copyStack(tstack, quantity)); + } + } + + @Override + public void putStack(ItemStack stack) + { + if(stack != null && stack.stackSize > stackLimit) + stack = InventoryUtils.copyStack(stack, stackLimit); + super.putStack(stack); + } +} diff --git a/src/codechicken/lib/inventory/SlotDummyOutput.java b/src/codechicken/lib/inventory/SlotDummyOutput.java new file mode 100644 index 0000000..b8fab64 --- /dev/null +++ b/src/codechicken/lib/inventory/SlotDummyOutput.java @@ -0,0 +1,19 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class SlotDummyOutput extends SlotHandleClicks +{ + public SlotDummyOutput(IInventory inv, int slot, int x, int y) + { + super(inv, slot, x, y); + } + + @Override + public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) + { + return null; + } +} diff --git a/src/codechicken/lib/inventory/SlotHandleClicks.java b/src/codechicken/lib/inventory/SlotHandleClicks.java new file mode 100644 index 0000000..7e56ddd --- /dev/null +++ b/src/codechicken/lib/inventory/SlotHandleClicks.java @@ -0,0 +1,16 @@ +package codechicken.lib.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public abstract class SlotHandleClicks extends Slot +{ + public SlotHandleClicks(IInventory inv, int slot, int x, int y) + { + super(inv, slot, x, y); + } + + public abstract ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier); +} diff --git a/src/codechicken/lib/packet/PacketCustom.java b/src/codechicken/lib/packet/PacketCustom.java index fe5d32e..0d6bf2f 100644 --- a/src/codechicken/lib/packet/PacketCustom.java +++ b/src/codechicken/lib/packet/PacketCustom.java @@ -147,17 +147,17 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exc public static String channelName(Object channelKey) { if (channelKey instanceof String) return (String) channelKey; - if (channelKey instanceof ModContainer) { - String s = ((ModContainer) channelKey).getModId(); + + ModContainer mc = channelKey instanceof ModContainer ? + (ModContainer) channelKey : + FMLCommonHandler.instance().findContainerFor(channelKey); + if (mc != null) { + String s = mc.getModId(); if(s.length() > 20) throw new IllegalArgumentException("Mod ID ("+s+") too long for use as channel (20 chars). Use a string identifier"); return s; } - ModContainer mc = FMLCommonHandler.instance().findContainerFor(channelKey); - if (mc != null) - return mc.getModId(); - throw new IllegalArgumentException("Invalid channel: " + channelKey); } From e9f9253875db08f1e71398591335dde83db91c1b Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 29 May 2015 17:44:08 +1000 Subject: [PATCH 120/219] Moved 1 file too many --- .../lib/inventory/GuiContainerWidget.java | 131 ------------------ 1 file changed, 131 deletions(-) delete mode 100644 src/codechicken/lib/inventory/GuiContainerWidget.java diff --git a/src/codechicken/lib/inventory/GuiContainerWidget.java b/src/codechicken/lib/inventory/GuiContainerWidget.java deleted file mode 100644 index eaf4226..0000000 --- a/src/codechicken/lib/inventory/GuiContainerWidget.java +++ /dev/null @@ -1,131 +0,0 @@ -package codechicken.lib.inventory; - -import java.awt.Point; -import java.util.ArrayList; - -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - -import codechicken.lib.gui.GuiDraw; -import codechicken.core.gui.GuiWidget; -import codechicken.core.gui.IGuiActionListener; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.inventory.Container; - -public class GuiContainerWidget extends GuiContainer implements IGuiActionListener -{ - public ArrayList widgets = new ArrayList(); - - public GuiContainerWidget(Container inventorySlots) - { - this(inventorySlots, 176, 166); - } - - public GuiContainerWidget(Container inventorySlots, int xSize, int ySize) - { - super(inventorySlots); - this.xSize = xSize; - this.ySize = ySize; - } - - @Override - public void setWorldAndResolution(Minecraft mc, int i, int j) - { - super.setWorldAndResolution(mc, i, j); - if(widgets.isEmpty()) - addWidgets(); - } - - public void add(GuiWidget widget) - { - widgets.add(widget); - widget.onAdded(this); - } - - @Override - protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey) - { - GL11.glTranslated(guiLeft, guiTop, 0); - drawBackground(); - for(GuiWidget widget : widgets) - widget.draw(mousex-guiLeft, mousey-guiTop, f); - - GL11.glTranslated(-guiLeft, -guiTop, 0); - } - - public void drawBackground() - { - } - - @Override - protected void mouseClicked(int x, int y, int button) - { - super.mouseClicked(x, y, button); - for(GuiWidget widget : widgets) - widget.mouseClicked(x-guiLeft, y-guiTop, button); - } - - @Override - protected void mouseMovedOrUp(int x, int y, int button) - { - super.mouseMovedOrUp(x, y, button); - for(GuiWidget widget : widgets) - widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button); - } - - @Override - protected void mouseClickMove(int x, int y, int button, long time) - { - super.mouseClickMove(x, y, button, time); - for(GuiWidget widget : widgets) - widget.mouseDragged(x-guiLeft, y-guiTop, button, time); - } - - @Override - public void updateScreen() - { - super.updateScreen(); - if(mc.currentScreen == this) - for(GuiWidget widget : widgets) - widget.update(); - } - - @Override - public void keyTyped(char c, int keycode) - { - super.keyTyped(c, keycode); - for(GuiWidget widget : widgets) - widget.keyTyped(c, keycode); - } - - @Override - public void handleMouseInput() - { - super.handleMouseInput(); - int i = Mouse.getEventDWheel(); - if(i != 0) - { - Point p = GuiDraw.getMousePosition(); - int scroll = i > 0 ? 1 : -1; - for(GuiWidget widget : widgets) - widget.mouseScrolled(p.x, p.y, scroll); - } - } - - @Override - public void actionPerformed(String ident, Object... params) - { - } - - public void addWidgets() - { - } - - @Override - public void onGuiClosed() { - super.onGuiClosed(); - widgets.clear(); - } -} From 2987b36bad2db78a546fbef053b56ce8701316af Mon Sep 17 00:00:00 2001 From: planetguy Date: Tue, 14 Jul 2015 19:12:29 -0700 Subject: [PATCH 121/219] Fix for 1.7.10 with latest Forge versions. Forge now repeats the Minecraft version in the folder path. This commit adds another guess that checks that folder for deobfuscation data. --- src/codechicken/lib/asm/ObfMapping.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/codechicken/lib/asm/ObfMapping.java b/src/codechicken/lib/asm/ObfMapping.java index bd062ab..9861f25 100644 --- a/src/codechicken/lib/asm/ObfMapping.java +++ b/src/codechicken/lib/asm/ObfMapping.java @@ -107,7 +107,7 @@ public static File[] getConfFiles() { throw new RuntimeException("Failed to select mappings directory, set it manually in the config"); } - private static final int DIR_GUESSES = 4; + private static final int DIR_GUESSES = 5; private static final int DIR_ASKS = 3; public static File confDirectoryGuess(int i, ConfigTag tag) { File mcDir = (File) FMLInjectionData.data()[6]; @@ -121,6 +121,9 @@ public static File confDirectoryGuess(int i, ConfigTag tag) { case 3: return new File(System.getProperty("user.home"), ".gradle/caches/minecraft/net/minecraftforge/forge/"+ FMLInjectionData.data()[4]+"-"+ ForgeVersion.getVersion()+"/unpacked/conf"); + case 4: + return new File(System.getProperty("user.home"), ".gradle/caches/minecraft/net/minecraftforge/forge/"+ + FMLInjectionData.data()[4]+"-"+ ForgeVersion.getVersion()+"-"+FMLInjectionData.data()[4]+"/unpacked/conf"); default: JFileChooser fc = new JFileChooser(mcDir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); From 0ac4906338b9fb36e7992d1c642791d5134e0627 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 13:55:05 +0100 Subject: [PATCH 122/219] Updated to unified build script --- .github/workflows/pull-request.yml | 32 ++ .github/workflows/release.yml | 41 ++ .gitignore | 29 + build.gradle | 526 ++++++++++++++++++ build/build.gradle | 152 ----- build/build.properties | 3 - build/gradle/wrapper/gradle-wrapper.jar | Bin 51106 -> 0 bytes build/settings.gradle | 19 - dependencies.gradle | 5 + gradle.properties | 60 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55616 bytes .../wrapper/gradle-wrapper.properties | 3 +- build/gradlew => gradlew | 98 ++-- build/gradlew.bat => gradlew.bat | 30 +- jitpack.yml | 2 + repositories.gradle | 5 + src/codechicken/lib/world/ChunkExtension.java | 85 --- src/codechicken/lib/world/IChunkLoadTile.java | 12 - .../lib/world/TileChunkLoadHook.java | 28 - src/codechicken/lib/world/WorldExtension.java | 99 ---- .../lib/world/WorldExtensionInstantiator.java | 17 - .../lib/world/WorldExtensionManager.java | 201 ------- .../java}/codechicken/lib/asm/ASMBlock.java | 0 .../java}/codechicken/lib/asm/ASMHelper.java | 0 .../java}/codechicken/lib/asm/ASMInit.java | 0 .../java}/codechicken/lib/asm/ASMReader.java | 0 .../codechicken/lib/asm/CC_ClassWriter.java | 0 .../lib/asm/ClassHeirachyManager.java | 0 .../lib/asm/ImportantInsnVisitor.java | 0 .../codechicken/lib/asm/InsnComparator.java | 0 .../codechicken/lib/asm/InsnListSection.java | 0 .../lib/asm/LocalVariablesSorterVisitor.java | 0 .../lib/asm/ModularASMTransformer.java | 0 .../java}/codechicken/lib/asm/ObfMapping.java | 0 .../java}/codechicken/lib/colour/Colour.java | 0 .../codechicken/lib/colour/ColourARGB.java | 0 .../codechicken/lib/colour/ColourRGBA.java | 0 .../lib/colour/CustomGradient.java | 0 .../codechicken/lib/config/ConfigFile.java | 0 .../codechicken/lib/config/ConfigTag.java | 0 .../lib/config/ConfigTagParent.java | 0 .../lib/config/DefaultingConfigFile.java | 0 .../lib/config/SimpleProperties.java | 0 .../codechicken/lib/data/MCDataInput.java | 0 .../lib/data/MCDataInputStream.java | 0 .../codechicken/lib/data/MCDataOutput.java | 0 .../lib/data/MCDataOutputStream.java | 0 .../lib/data/MCDataOutputWrapper.java | 0 .../java}/codechicken/lib/gui/Canvas9Seg.java | 0 .../java}/codechicken/lib/gui/GuiDraw.java | 0 .../lib/inventory/ContainerExtended.java | 0 .../lib/inventory/ContainerSynchronised.java | 0 .../lib/inventory/IContainerSyncVar.java | 0 .../lib/inventory/IntegerSync.java | 0 .../lib/inventory/InventoryCopy.java | 0 .../lib/inventory/InventoryNBT.java | 0 .../lib/inventory/InventoryRange.java | 0 .../lib/inventory/InventorySimple.java | 0 .../lib/inventory/InventoryUtils.java | 0 .../codechicken/lib/inventory/ItemKey.java | 0 .../codechicken/lib/inventory/SlotDummy.java | 0 .../lib/inventory/SlotDummyOutput.java | 0 .../lib/inventory/SlotHandleClicks.java | 0 .../java}/codechicken/lib/lighting/LC.java | 0 .../codechicken/lib/lighting/LightMatrix.java | 0 .../codechicken/lib/lighting/LightModel.java | 0 .../lib/lighting/PlanarLightMatrix.java | 0 .../lib/lighting/PlanarLightModel.java | 0 .../lib/lighting/SimpleBrightnessModel.java | 0 .../codechicken/lib/math/MathHelper.java | 0 .../lib/packet/ICustomPacketTile.java | 0 .../codechicken/lib/packet/PacketCustom.java | 0 .../lib/raytracer/ExtendedMOP.java | 0 .../lib/raytracer/IndexedCuboid6.java | 0 .../codechicken/lib/raytracer/RayTracer.java | 0 .../codechicken/lib/render/BlockRenderer.java | 0 .../java}/codechicken/lib/render/CCModel.java | 0 .../lib/render/CCModelLibrary.java | 0 .../lib/render/CCRenderPipeline.java | 0 .../codechicken/lib/render/CCRenderState.java | 0 .../lib/render/ColourMultiplier.java | 0 .../lib/render/EntityDigIconFX.java | 0 .../codechicken/lib/render/FontUtils.java | 0 .../codechicken/lib/render/IFaceRenderer.java | 0 .../lib/render/ManagedTextureFX.java | 0 .../lib/render/PlaceholderTexture.java | 0 .../codechicken/lib/render/QBImporter.java | 0 .../codechicken/lib/render/RenderUtils.java | 0 .../codechicken/lib/render/ShaderProgram.java | 0 .../lib/render/SpriteSheetManager.java | 0 .../lib/render/TextureDataHolder.java | 0 .../codechicken/lib/render/TextureFX.java | 0 .../lib/render/TextureSpecial.java | 0 .../codechicken/lib/render/TextureUtils.java | 0 .../java}/codechicken/lib/render/Vertex5.java | 0 .../lib/render/uv/IconTransformation.java | 0 .../render/uv/MultiIconTransformation.java | 0 .../java}/codechicken/lib/render/uv/UV.java | 0 .../codechicken/lib/render/uv/UVRotation.java | 0 .../codechicken/lib/render/uv/UVScale.java | 0 .../lib/render/uv/UVTransformation.java | 0 .../lib/render/uv/UVTransformationList.java | 0 .../lib/render/uv/UVTranslation.java | 0 .../codechicken/lib/tool/LibDownloader.java | 0 .../lib/tool/MCStripTransformer.java | 0 .../java}/codechicken/lib/tool/Main.java | 0 .../lib/tool/StripClassLoader.java | 0 .../java}/codechicken/lib/tool/ToolMain.java | 0 .../lib/tool/module/JOptModule.java | 0 .../lib/tool/module/ModuleQBConverter.java | 0 .../java}/codechicken/lib/util/Copyable.java | 0 .../java}/codechicken/lib/util/LangProxy.java | 0 .../java}/codechicken/lib/vec/AxisCycle.java | 0 .../java}/codechicken/lib/vec/BlockCoord.java | 0 .../java}/codechicken/lib/vec/Cuboid6.java | 0 .../codechicken/lib/vec/CuboidCoord.java | 0 .../codechicken/lib/vec/ITransformation.java | 0 .../IrreversibleTransformationException.java | 0 .../java}/codechicken/lib/vec/Line3.java | 0 .../java}/codechicken/lib/vec/Matrix4.java | 0 .../java}/codechicken/lib/vec/Quat.java | 0 .../codechicken/lib/vec/Rectangle4i.java | 0 .../lib/vec/RedundantTransformation.java | 0 .../java}/codechicken/lib/vec/Rotation.java | 0 .../java}/codechicken/lib/vec/Scale.java | 0 .../java}/codechicken/lib/vec/SwapYZ.java | 0 .../codechicken/lib/vec/Transformation.java | 0 .../lib/vec/TransformationList.java | 0 .../codechicken/lib/vec/Translation.java | 0 .../lib/vec/VariableTransformation.java | 0 .../java}/codechicken/lib/vec/Vector3.java | 0 src/main/resources/mcmod.info | 16 + 132 files changed, 798 insertions(+), 665 deletions(-) create mode 100644 .github/workflows/pull-request.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 build.gradle delete mode 100644 build/build.gradle delete mode 100644 build/build.properties delete mode 100644 build/gradle/wrapper/gradle-wrapper.jar delete mode 100644 build/settings.gradle create mode 100644 dependencies.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar rename {build/gradle => gradle}/wrapper/gradle-wrapper.properties (53%) rename build/gradlew => gradlew (72%) rename build/gradlew.bat => gradlew.bat (73%) create mode 100644 jitpack.yml create mode 100644 repositories.gradle delete mode 100644 src/codechicken/lib/world/ChunkExtension.java delete mode 100644 src/codechicken/lib/world/IChunkLoadTile.java delete mode 100644 src/codechicken/lib/world/TileChunkLoadHook.java delete mode 100644 src/codechicken/lib/world/WorldExtension.java delete mode 100644 src/codechicken/lib/world/WorldExtensionInstantiator.java delete mode 100644 src/codechicken/lib/world/WorldExtensionManager.java rename src/{ => main/java}/codechicken/lib/asm/ASMBlock.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ASMHelper.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ASMInit.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ASMReader.java (100%) rename src/{ => main/java}/codechicken/lib/asm/CC_ClassWriter.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ClassHeirachyManager.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ImportantInsnVisitor.java (100%) rename src/{ => main/java}/codechicken/lib/asm/InsnComparator.java (100%) rename src/{ => main/java}/codechicken/lib/asm/InsnListSection.java (100%) rename src/{ => main/java}/codechicken/lib/asm/LocalVariablesSorterVisitor.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ModularASMTransformer.java (100%) rename src/{ => main/java}/codechicken/lib/asm/ObfMapping.java (100%) rename src/{ => main/java}/codechicken/lib/colour/Colour.java (100%) rename src/{ => main/java}/codechicken/lib/colour/ColourARGB.java (100%) rename src/{ => main/java}/codechicken/lib/colour/ColourRGBA.java (100%) rename src/{ => main/java}/codechicken/lib/colour/CustomGradient.java (100%) rename src/{ => main/java}/codechicken/lib/config/ConfigFile.java (100%) rename src/{ => main/java}/codechicken/lib/config/ConfigTag.java (100%) rename src/{ => main/java}/codechicken/lib/config/ConfigTagParent.java (100%) rename src/{ => main/java}/codechicken/lib/config/DefaultingConfigFile.java (100%) rename src/{ => main/java}/codechicken/lib/config/SimpleProperties.java (100%) rename src/{ => main/java}/codechicken/lib/data/MCDataInput.java (100%) rename src/{ => main/java}/codechicken/lib/data/MCDataInputStream.java (100%) rename src/{ => main/java}/codechicken/lib/data/MCDataOutput.java (100%) rename src/{ => main/java}/codechicken/lib/data/MCDataOutputStream.java (100%) rename src/{ => main/java}/codechicken/lib/data/MCDataOutputWrapper.java (100%) rename src/{ => main/java}/codechicken/lib/gui/Canvas9Seg.java (100%) rename src/{ => main/java}/codechicken/lib/gui/GuiDraw.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/ContainerExtended.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/ContainerSynchronised.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/IContainerSyncVar.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/IntegerSync.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/InventoryCopy.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/InventoryNBT.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/InventoryRange.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/InventorySimple.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/InventoryUtils.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/ItemKey.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/SlotDummy.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/SlotDummyOutput.java (100%) rename src/{ => main/java}/codechicken/lib/inventory/SlotHandleClicks.java (100%) rename src/{ => main/java}/codechicken/lib/lighting/LC.java (100%) rename src/{ => main/java}/codechicken/lib/lighting/LightMatrix.java (100%) rename src/{ => main/java}/codechicken/lib/lighting/LightModel.java (100%) rename src/{ => main/java}/codechicken/lib/lighting/PlanarLightMatrix.java (100%) rename src/{ => main/java}/codechicken/lib/lighting/PlanarLightModel.java (100%) rename src/{ => main/java}/codechicken/lib/lighting/SimpleBrightnessModel.java (100%) rename src/{ => main/java}/codechicken/lib/math/MathHelper.java (100%) rename src/{ => main/java}/codechicken/lib/packet/ICustomPacketTile.java (100%) rename src/{ => main/java}/codechicken/lib/packet/PacketCustom.java (100%) rename src/{ => main/java}/codechicken/lib/raytracer/ExtendedMOP.java (100%) rename src/{ => main/java}/codechicken/lib/raytracer/IndexedCuboid6.java (100%) rename src/{ => main/java}/codechicken/lib/raytracer/RayTracer.java (100%) rename src/{ => main/java}/codechicken/lib/render/BlockRenderer.java (100%) rename src/{ => main/java}/codechicken/lib/render/CCModel.java (100%) rename src/{ => main/java}/codechicken/lib/render/CCModelLibrary.java (100%) rename src/{ => main/java}/codechicken/lib/render/CCRenderPipeline.java (100%) rename src/{ => main/java}/codechicken/lib/render/CCRenderState.java (100%) rename src/{ => main/java}/codechicken/lib/render/ColourMultiplier.java (100%) rename src/{ => main/java}/codechicken/lib/render/EntityDigIconFX.java (100%) rename src/{ => main/java}/codechicken/lib/render/FontUtils.java (100%) rename src/{ => main/java}/codechicken/lib/render/IFaceRenderer.java (100%) rename src/{ => main/java}/codechicken/lib/render/ManagedTextureFX.java (100%) rename src/{ => main/java}/codechicken/lib/render/PlaceholderTexture.java (100%) rename src/{ => main/java}/codechicken/lib/render/QBImporter.java (100%) rename src/{ => main/java}/codechicken/lib/render/RenderUtils.java (100%) rename src/{ => main/java}/codechicken/lib/render/ShaderProgram.java (100%) rename src/{ => main/java}/codechicken/lib/render/SpriteSheetManager.java (100%) rename src/{ => main/java}/codechicken/lib/render/TextureDataHolder.java (100%) rename src/{ => main/java}/codechicken/lib/render/TextureFX.java (100%) rename src/{ => main/java}/codechicken/lib/render/TextureSpecial.java (100%) rename src/{ => main/java}/codechicken/lib/render/TextureUtils.java (100%) rename src/{ => main/java}/codechicken/lib/render/Vertex5.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/IconTransformation.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/MultiIconTransformation.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/UV.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/UVRotation.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/UVScale.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/UVTransformation.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/UVTransformationList.java (100%) rename src/{ => main/java}/codechicken/lib/render/uv/UVTranslation.java (100%) rename src/{ => main/java}/codechicken/lib/tool/LibDownloader.java (100%) rename src/{ => main/java}/codechicken/lib/tool/MCStripTransformer.java (100%) rename src/{ => main/java}/codechicken/lib/tool/Main.java (100%) rename src/{ => main/java}/codechicken/lib/tool/StripClassLoader.java (100%) rename src/{ => main/java}/codechicken/lib/tool/ToolMain.java (100%) rename src/{ => main/java}/codechicken/lib/tool/module/JOptModule.java (100%) rename src/{ => main/java}/codechicken/lib/tool/module/ModuleQBConverter.java (100%) rename src/{ => main/java}/codechicken/lib/util/Copyable.java (100%) rename src/{ => main/java}/codechicken/lib/util/LangProxy.java (100%) rename src/{ => main/java}/codechicken/lib/vec/AxisCycle.java (100%) rename src/{ => main/java}/codechicken/lib/vec/BlockCoord.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Cuboid6.java (100%) rename src/{ => main/java}/codechicken/lib/vec/CuboidCoord.java (100%) rename src/{ => main/java}/codechicken/lib/vec/ITransformation.java (100%) rename src/{ => main/java}/codechicken/lib/vec/IrreversibleTransformationException.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Line3.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Matrix4.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Quat.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Rectangle4i.java (100%) rename src/{ => main/java}/codechicken/lib/vec/RedundantTransformation.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Rotation.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Scale.java (100%) rename src/{ => main/java}/codechicken/lib/vec/SwapYZ.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Transformation.java (100%) rename src/{ => main/java}/codechicken/lib/vec/TransformationList.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Translation.java (100%) rename src/{ => main/java}/codechicken/lib/vec/VariableTransformation.java (100%) rename src/{ => main/java}/codechicken/lib/vec/Vector3.java (100%) create mode 100644 src/main/resources/mcmod.info diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..f4e30c1 --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,32 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Build pull request + +on: + pull_request: + branches: [ master, main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6a64794 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Build and release main branch + +on: + push: + branches: [ master, main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build + + - uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "latest" + prerelease: true + title: "Latest Development Build" + files: build/libs/*.jar + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4a0ea1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +.gradle +.settings +/.idea/ +/run/ +/build/ +/eclipse/ +.classpath +.project +/bin/ +/config/ +/crash-reports/ +/logs/ +options.txt +/saves/ +usernamecache.json +banned-ips.json +banned-players.json +eula.txt +ops.json +server.properties +servers.dat +usercache.json +whitelist.json +world/ +/out/ +*.iml +*.ipr +*.iws +src/main/resources/mixins.*.json diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..7fe18ad --- /dev/null +++ b/build.gradle @@ -0,0 +1,526 @@ +//version: 21647c763d3f6c90d59c900edae1248239c49dfb +/* +DO NOT CHANGE THIS FILE! + +Also, you may replace this file at any time if there is an update available. +Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates. + */ + + +import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation + +import java.util.concurrent.TimeUnit + +buildscript { + repositories { + maven { + name = "jitpack" + url = "https://jitpack.io" + } + maven { + name = "forge" + url = "https://maven.minecraftforge.net" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + maven { + name = "Scala CI dependencies" + url = "https://repo1.maven.org/maven2/" + } + } + dependencies { + classpath 'com.github.TheElan:ForgeGradle:1.2.2' + } +} + +plugins { + id("org.ajoberstar.grgit") version("3.1.1") + id("com.github.johnrengelman.shadow") version("4.0.4") + id("com.palantir.git-version") version("0.12.3") +} + +apply plugin: 'scala' +apply plugin: 'forge' +apply plugin: 'idea' + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } +} + +idea { + module { + inheritOutputDirs = true + downloadJavadoc = true + downloadSources = true + } +} + +checkPropertyExists("modName") +checkPropertyExists("modId") +checkPropertyExists("modGroup") +checkPropertyExists("autoUpdateBuildScript") +checkPropertyExists("minecraftVersion") +checkPropertyExists("forgeVersion") +checkPropertyExists("replaceGradleTokenInFile") +checkPropertyExists("gradleTokenModId") +checkPropertyExists("gradleTokenModName") +checkPropertyExists("gradleTokenVersion") +checkPropertyExists("gradleTokenGroupName") +checkPropertyExists("apiPackage") +checkPropertyExists("accessTransformersFile") +checkPropertyExists("usesMixins") +checkPropertyExists("mixinPlugin") +checkPropertyExists("mixinsPackage") +checkPropertyExists("coreModClass") +checkPropertyExists("containsMixinsAndOrCoreModOnly") +checkPropertyExists("usesShadowedDependencies") +checkPropertyExists("developmentEnvironmentUserName") + +def checkPropertyExists(String propertyName) { + if (project.hasProperty(propertyName) == false) { + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + } +} + + +String javaSourceDir = "src/main/java/" +String scalaSourceDir = "src/main/scala/" + +String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") +String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") +if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) +} + +if(apiPackage) { + targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + } +} + +if(accessTransformersFile) { + String targetFile = "src/main/resources/META-INF/" + accessTransformersFile + if(new File(targetFile).exists() == false) { + throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + } +} + +if(usesMixins.toBoolean()) { + if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { + throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!") + } + + targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + } + + String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" + String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" + if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + } +} + +if(coreModClass) { + String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" + String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" + if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + } +} + +configurations.all { + resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) + + // Make sure GregTech build won't time out + System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String) + System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String) +} + +// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version +'git config core.fileMode false'.execute() +// Pulls version from git tag +version = minecraftVersion + "-" + gitVersion() +group = modGroup +archivesBaseName = modId + +minecraft { + version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion + runDir = "run" + + if (replaceGradleTokenInFile) { + replaceIn replaceGradleTokenInFile + if(gradleTokenModId) { + replace gradleTokenModId, modId + } + if(gradleTokenModName) { + replace gradleTokenModName, modName + } + if(gradleTokenModName) { + replace gradleTokenVersion, versionDetails().lastTag + } + if(gradleTokenGroupName) { + replace gradleTokenGroupName, modGroup + } + } +} + +if(file("addon.gradle").exists()) { + apply from: "addon.gradle" +} + +apply from: 'repositories.gradle' + +configurations { + implementation.extendsFrom(shadowImplementation) +} + +repositories { + if(usesMixins.toBoolean()) { + maven { + name = "sponge" + url = "https://repo.spongepowered.org/repository/maven-public" + } + maven { + url = "https://jitpack.io" + } + } +} + +dependencies { + if(usesMixins.toBoolean()) { + annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3") + annotationProcessor("com.google.guava:guava:24.1.1-jre") + annotationProcessor("com.google.code.gson:gson:2.8.6") + annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") + // using 0.8 to workaround a issue in 0.7 which fails mixin application + compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + // Mixin includes a lot of dependencies that are too up-to-date + exclude module: "launchwrapper" + exclude module: "guava" + exclude module: "gson" + exclude module: "commons-io" + exclude module: "log4j-core" + } + compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev") + } +} + +apply from: 'dependencies.gradle' + +task relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} + +def mixinConfigJson = "mixins." + modId + ".json" +def mixingConfigRefMap = "mixins." + modId + ".refmap.json" +def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap +def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" + +task generateAssets { + if(usesMixins.toBoolean()) { + new File(projectDir.toString() + "/src/main/resources/", mixinConfigJson).text = """{ + "required": true, + "minVersion": "0.7.11", + "package": "${modGroup}.${mixinsPackage}", + "plugin": "${modGroup}.${mixinPlugin}", + "refmap": "${mixingConfigRefMap}", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8" +} + +""" + } +} + +shadowJar { + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } + + minimize() + configurations = [project.configurations.shadowImplementation] + dependsOn(relocateShadowJar) +} + +jar { + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } + + if(usesShadowedDependencies.toBoolean()) { + dependsOn(shadowJar) + enabled = false + } +} + +reobf { + if(usesMixins.toBoolean()) { + addExtraSrgFile mixinSrg + } +} + +afterEvaluate { + if(usesMixins.toBoolean()) { + tasks.compileJava { + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobf.srg}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" + ] + } + } +} + +runClient { + def arguments = [] + + if(usesMixins.toBoolean()) { + arguments += [ + "--mods=../build/libs/$modId-${version}.jar", + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + } + + if(developmentEnvironmentUserName) { + arguments += [ + "--username", + developmentEnvironmentUserName + ] + } + + args(arguments) +} + +runServer { + def arguments = [] + + if(usesMixins.toBoolean()) { + arguments += [ + "--mods=../build/libs/$modId-${version}.jar", + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + } + + args(arguments) +} + +processResources +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} + +task sourcesJar(type: Jar) { + from (sourceSets.main.allJava) + from (file("$projectDir/LICENSE")) + getArchiveClassifier().set('sources') + + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } +} + +task devJar(type: Jar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") + + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } +} + +task apiJar(type: Jar) { + from (sourceSets.main.allJava) { + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + } + + from (sourceSets.main.output) { + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + } + + from (sourceSets.main.resources.srcDirs) { + include("LICENSE") + } + + getArchiveClassifier().set('api') +} + +artifacts { + archives sourcesJar + archives devJar + if(apiPackage) { + archives apiJar + } +} + +// Updating +task updateBuildScript { + doLast { + if (updateBuildScript()) return + + print("Build script already up-to-date!") + } +} + +if (isNewBuildScriptVersionAvailable()) { + if (autoUpdateBuildScript.toBoolean()) { + updateBuildScript() + } else { + println("Build script update available! Run 'gradle updateBuildScript'") + } +} + +static URL availableBuildScriptUrl() { + new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") +} + +static boolean updateBuildScript() { + if (isNewBuildScriptVersionAvailable()) { + def buildscriptFile = new File("build.gradle") + availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } + print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + return true + } + return false +} + +static boolean isNewBuildScriptVersionAvailable() { + Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] + + String currentBuildScript = new File("build.gradle").getText() + String currentBuildScriptHash = getVersionHash(currentBuildScript) + String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() + String availableBuildScriptHash = getVersionHash(availableBuildScript) + + boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash + return !isUpToDate +} + +static String getVersionHash(String buildScriptContent) { + String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") + if(versionLine != null) { + return versionLine.split(": ").last() + } + return "" +} + +configure(updateBuildScript) { + group = 'forgegradle' + description = 'Updates the build script to the latest version' +} diff --git a/build/build.gradle b/build/build.gradle deleted file mode 100644 index 84ce131..0000000 --- a/build/build.gradle +++ /dev/null @@ -1,152 +0,0 @@ -// This sets us up for building a forge project - you need all of these -buildscript { - repositories { - mavenCentral() - maven { - name = "forge" - url = "http://files.minecraftforge.net/maven" - } - maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" - } - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' - } -} - -// Apply the forge plugin - this adds all the magic for automatically obfuscating, deobfuscating etc -apply plugin: 'forge' - -// This is our group -group = "codechicken" // http://maven.apache.org/guides/mini/guide-naming-conventions.html -// This is our actual project within the group. -archivesBaseName = "CodeChickenLib" - -// Define properties file -ext.configFile = file "build.properties" - -configFile.withReader { - // Load config. It shall from now be referenced as simply config or project.config - def prop = new Properties() - prop.load(it) - project.ext.config = new ConfigSlurper().parse prop -} - -version = "${project.config.mod_version}." + System.getenv("BUILD_NUMBER") ?: "1" - -println config.minecraft_version + "-" + config.forge_version -// Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here -minecraft { - version = config.minecraft_version + "-" + config.forge_version -} - - -// this sets our output jar to have a 'tag' of 'universal' on it -// It also adds the minecraft version in a custom version name -// The result is files named ---universal.jar -jar { - classifier = 'universal' - version = "${project.minecraft.version}-${project.version}" - manifest { - attributes 'Main-Class': 'codechicken.lib.tool.Main' - } - -} -sourceSets { - main { - java { - srcDir new File(project.projectDir.parentFile, "src") - } - } -} - -// Add in a source jar for people, should they desire to download such a thing -task sourceJar(type: Jar) { - from sourceSets.main.allSource - classifier = 'src' - version = "${project.minecraft.version}-${project.version}" -} - -// Add in an mcp named jar, for those who wish to run in a development environment (assuming mcp naming matches) -task deobfJar(type: Jar) { - from sourceSets.main.output - classifier = 'dev' - version = "${project.minecraft.version}-${project.version}" - manifest { - attributes 'Main-Class': 'codechicken.lib.tool.Main' - } - -} - -// Tell the artifact system about our extra jars -artifacts { - archives sourceJar, deobfJar -} - -// Configure an upload task. this is setup for uploading to files.minecraftforge.net. There are other examples around -uploadArchives { - dependsOn 'reobf' - repositories { - if (project.hasProperty("filesmaven")) { - logger.info('Publishing to files server') - - mavenDeployer { - configuration = configurations.deployJars - - repository(url: project.filesmaven.url) { - authentication(userName: project.filesmaven.username, privateKey: project.filesmaven.key) - } - - // This is just the pom data for the maven repo - pom { - groupId = project.group - // Force the maven upload to use the - syntax preferred at files - version = "${project.minecraft.version}-${project.version}" - artifactId = project.archivesBaseName - project { - name project.archivesBaseName - packaging 'jar' - description 'CodeChickenLib' - url 'https://github.com/Chicken-Bones/CodeChickenLib' - - scm { - url 'https://github.com/Chicken-Bones/CodeChickenLib' - connection 'scm:git:git://github.com/Chicken-Bones/CodeChickenLib.git' - developerConnection 'scm:git:git@github.com:Chicken-Bones/CodeChickenLib.git' - } - - issueManagement { - system 'github' - url 'https://github.com/Chicken-Bones/CodeChickenLib/issues' - } - - licenses { - license { - name 'GNU Lesser Public License (GPL), Version 2.1' - url 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt' - distribution 'repo' - } - } - - developers { - developer { - id 'chicken-bones' - name 'chicken-bones' - roles { role 'developer' } - } - } - } - } - } - } else { - logger.info('Publishing to repo folder') - - mavenDeployer { - pom.version = "${project.minecraft.version}-${project.version}" - repository(url: 'file://localhost/' + project.file('repo').getAbsolutePath()) - } - } - } -} \ No newline at end of file diff --git a/build/build.properties b/build/build.properties deleted file mode 100644 index 4c9f512..0000000 --- a/build/build.properties +++ /dev/null @@ -1,3 +0,0 @@ -minecraft_version=1.7.10 -forge_version=10.13.3.1373-1.7.10 -mod_version=1.1.3 diff --git a/build/gradle/wrapper/gradle-wrapper.jar b/build/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 3c7abdf12790879c06b07176de29647f77aa4129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51106 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

CflOl1i4(-2^1KXo)&I5QlgjRKFQgM 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 z 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%0DvTus6fLI&f~`9YxjD=W5pR41LBYQt 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 diff --git a/build/settings.gradle b/build/settings.gradle deleted file mode 100644 index 398e21f..0000000 --- a/build/settings.gradle +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This settings file was auto generated by the Gradle buildInit task - * by 'sunstrike' at '21/11/13 14:14' with Gradle 1.9 - * - * The settings file is used to specify which projects to include in your build. - * In a single project build this file can be empty or even removed. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html - */ - -/* -// To declare projects as part of a multi-project build use the 'include' method -include 'shared' -include 'api' -include 'services:webservice' -*/ - -rootProject.name = 'CodeChickenLib' diff --git a/dependencies.gradle b/dependencies.gradle new file mode 100644 index 0000000..b6456d0 --- /dev/null +++ b/dependencies.gradle @@ -0,0 +1,5 @@ +// Add your dependencies here + +dependencies { + +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..2e0a9a3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,60 @@ +modName = CodeChickenLib + +# This is a case-sensitive string to identify your mod. Convention is to use lower case. +modId = CodeChickenLib + +modGroup = codechicken + +# WHY is there no version field? +# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the +# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/ + +# Will update your build.gradle automatically whenever an update is available +autoUpdateBuildScript = false + +minecraftVersion = 1.7.10 +forgeVersion = 10.13.4.1614 + +# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name each time you +# restart Minecraft in development. Choose this dependent on your mod: +# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name +# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty +developmentEnvironmentUserName = "Developer" + +# Define a source file of your project with: +# public static final String VERSION = "GRADLETOKEN_VERSION"; +# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's +# version in @Mod([...], version = VERSION, [...]) +# Leave these properties empty to skip individual token replacements +replaceGradleTokenInFile = +gradleTokenModId = +gradleTokenModName = +gradleTokenVersion = +gradleTokenGroupName = + +# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can +# leave this property empty. +# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api +apiPackage = + +# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/ +# Example value: mymodid_at.cfg +accessTransformersFile = + +# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! +usesMixins = false +# Specify the location of your implementation of IMixinPlugin. Leave it empty otherwise. +mixinPlugin = +# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! +mixinsPackage = +# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! +# This parameter is for legacy compatability only +# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin +coreModClass = +# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class +# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! +containsMixinsAndOrCoreModOnly = false + +# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your +# responsibility check the licence and request permission for distribution, if required. +usesShadowedDependencies = false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c2d1cf016b3885f6930543d57b744ea8c220a1a GIT binary patch literal 55616 zcmafaW0WS*vSoFbZJS-TZP!<}ZQEV8ZQHihW!tvx>6!c9%-lQoy;&DmfdT@8fB*sl68LLCKtKQ283+jS?^Q-bNq|NIAW8=eB==8_)^)r*{C^$z z{u;{v?IMYnO`JhmPq7|LA_@Iz75S9h~8`iX>QrjrmMeu{>hn4U;+$dor zz+`T8Q0f}p^Ao)LsYq74!W*)&dTnv}E8;7H*Zetclpo2zf_f>9>HT8;`O^F8;M%l@ z57Z8dk34kG-~Wg7n48qF2xwPp;SOUpd1}9Moir5$VSyf4gF)Mp-?`wO3;2x9gYj59oFwG>?Leva43@e(z{mjm0b*@OAYLC`O9q|s+FQLOE z!+*Y;%_0(6Sr<(cxE0c=lS&-FGBFGWd_R<5$vwHRJG=tB&Mi8@hq_U7@IMyVyKkOo6wgR(<% zQw1O!nnQl3T9QJ)Vh=(`cZM{nsEKChjbJhx@UQH+G>6p z;beBQ1L!3Zl>^&*?cSZjy$B3(1=Zyn~>@`!j%5v7IBRt6X`O)yDpVLS^9EqmHxBcisVG$TRwiip#ViN|4( zYn!Av841_Z@Ys=T7w#>RT&iXvNgDq3*d?$N(SznG^wR`x{%w<6^qj&|g})La;iD?`M=p>99p><39r9+e z`dNhQ&tol5)P#;x8{tT47i*blMHaDKqJs8!Pi*F{#)9%USFxTVMfMOy{mp2ZrLR40 z2a9?TJgFyqgx~|j0eA6SegKVk@|Pd|_6P$HvwTrLTK)Re`~%kg8o9`EAE1oAiY5Jgo=H}0*D?tSCn^=SIN~fvv453Ia(<1|s07aTVVtsRxY6+tT3589iQdi^ zC92D$ewm9O6FA*u*{Fe_=b`%q`pmFvAz@hfF@OC_${IPmD#QMpPNo0mE9U=Ch;k0L zZteokPG-h7PUeRCPPYG%H!WswC?cp7M|w42pbtwj!m_&4%hB6MdLQe&}@5-h~! zkOt;w0BbDc0H!RBw;1UeVckHpJ@^|j%FBZlC} zsm?nFOT$`F_i#1_gh4|n$rDe>0md6HvA=B%hlX*3Z%y@a&W>Rq`Fe(8smIgxTGb#8 zZ`->%h!?QCk>v*~{!qp=w?a*};Y**1uH`)OX`Gi+L%-d6{rV?@}MU#qfCU(!hLz;kWH=0A%W7E^pA zD;A%Jg5SsRe!O*0TyYkAHe&O9z*Ij-YA$%-rR?sc`xz_v{>x%xY39!8g#!Z0#03H( z{O=drKfb0cbx1F*5%q81xvTDy#rfUGw(fesh1!xiS2XT;7_wBi(Rh4i(!rR^9=C+- z+**b9;icxfq@<7}Y!PW-0rTW+A^$o*#ZKenSkxLB$Qi$%gJSL>x!jc86`GmGGhai9 zOHq~hxh}KqQHJeN$2U{M>qd*t8_e&lyCs69{bm1?KGTYoj=c0`rTg>pS6G&J4&)xp zLEGIHSTEjC0-s-@+e6o&w=h1sEWWvJUvezID1&exb$)ahF9`(6`?3KLyVL$|c)CjS zx(bsy87~n8TQNOKle(BM^>1I!2-CZ^{x6zdA}qeDBIdrfd-(n@Vjl^9zO1(%2pP9@ zKBc~ozr$+4ZfjmzEIzoth(k?pbI87=d5OfjVZ`Bn)J|urr8yJq`ol^>_VAl^P)>2r)s+*3z5d<3rP+-fniCkjmk=2hTYRa@t zCQcSxF&w%mHmA?!vaXnj7ZA$)te}ds+n8$2lH{NeD4mwk$>xZCBFhRy$8PE>q$wS`}8pI%45Y;Mg;HH+}Dp=PL)m77nKF68FggQ-l3iXlVZuM2BDrR8AQbK;bn1%jzahl0; zqz0(mNe;f~h8(fPzPKKf2qRsG8`+Ca)>|<&lw>KEqM&Lpnvig>69%YQpK6fx=8YFj zHKrfzy>(7h2OhUVasdwKY`praH?>qU0326-kiSyOU_Qh>ytIs^htlBA62xU6xg?*l z)&REdn*f9U3?u4$j-@ndD#D3l!viAUtw}i5*Vgd0Y6`^hHF5R=No7j8G-*$NWl%?t z`7Nilf_Yre@Oe}QT3z+jOUVgYtT_Ym3PS5(D>kDLLas8~F+5kW%~ZYppSrf1C$gL* zCVy}fWpZ3s%2rPL-E63^tA|8OdqKsZ4TH5fny47ENs1#^C`_NLg~H^uf3&bAj#fGV zDe&#Ot%_Vhj$}yBrC3J1Xqj>Y%&k{B?lhxKrtYy;^E9DkyNHk5#6`4cuP&V7S8ce9 zTUF5PQIRO7TT4P2a*4;M&hk;Q7&{(83hJe5BSm=9qt~;U)NTf=4uKUcnxC`;iPJeI zW#~w?HIOM+0j3ptB0{UU{^6_#B*Q2gs;1x^YFey(%DJHNWz@e_NEL?$fv?CDxG`jk zH|52WFdVsZR;n!Up;K;4E$|w4h>ZIN+@Z}EwFXI{w_`?5x+SJFY_e4J@|f8U08%dd z#Qsa9JLdO$jv)?4F@&z_^{Q($tG`?|9bzt8ZfH9P`epY`soPYqi1`oC3x&|@m{hc6 zs0R!t$g>sR@#SPfNV6Pf`a^E?q3QIaY30IO%yKjx#Njj@gro1YH2Q(0+7D7mM~c>C zk&_?9Ye>B%*MA+77$Pa!?G~5tm`=p{NaZsUsOgm6Yzclr_P^2)r(7r%n(0?4B#$e7 z!fP;+l)$)0kPbMk#WOjm07+e?{E)(v)2|Ijo{o1+Z8#8ET#=kcT*OwM#K68fSNo%< zvZFdHrOrr;>`zq!_welWh!X}=oN5+V01WJn7=;z5uo6l_$7wSNkXuh=8Y>`TjDbO< z!yF}c42&QWYXl}XaRr0uL?BNPXlGw=QpDUMo`v8pXzzG(=!G;t+mfCsg8 zJb9v&a)E!zg8|%9#U?SJqW!|oBHMsOu}U2Uwq8}RnWeUBJ>FtHKAhP~;&T4mn(9pB zu9jPnnnH0`8ywm-4OWV91y1GY$!qiQCOB04DzfDDFlNy}S{$Vg9o^AY!XHMueN<{y zYPo$cJZ6f7``tmlR5h8WUGm;G*i}ff!h`}L#ypFyV7iuca!J+C-4m@7*Pmj9>m+jh zlpWbud)8j9zvQ`8-oQF#u=4!uK4kMFh>qS_pZciyq3NC(dQ{577lr-!+HD*QO_zB9 z_Rv<#qB{AAEF8Gbr7xQly%nMA%oR`a-i7nJw95F3iH&IX5hhy3CCV5y>mK4)&5aC*12 zI`{(g%MHq<(ocY5+@OK-Qn-$%!Nl%AGCgHl>e8ogTgepIKOf3)WoaOkuRJQt%MN8W z=N-kW+FLw=1^}yN@*-_c>;0N{-B!aXy#O}`%_~Nk?{e|O=JmU8@+92Q-Y6h)>@omP=9i~ zi`krLQK^!=@2BH?-R83DyFkejZkhHJqV%^} zUa&K22zwz7b*@CQV6BQ9X*RB177VCVa{Z!Lf?*c~PwS~V3K{id1TB^WZh=aMqiws5)qWylK#^SG9!tqg3-)p_o(ABJsC!0;0v36;0tC= z!zMQ_@se(*`KkTxJ~$nIx$7ez&_2EI+{4=uI~dwKD$deb5?mwLJ~ema_0Z z6A8Q$1~=tY&l5_EBZ?nAvn$3hIExWo_ZH2R)tYPjxTH5mAw#3n-*sOMVjpUrdnj1DBm4G!J+Ke}a|oQN9f?!p-TcYej+(6FNh_A? zJ3C%AOjc<8%9SPJ)U(md`W5_pzYpLEMwK<_jgeg-VXSX1Nk1oX-{yHz z-;CW!^2ds%PH{L{#12WonyeK5A=`O@s0Uc%s!@22etgSZW!K<%0(FHC+5(BxsXW@e zAvMWiO~XSkmcz%-@s{|F76uFaBJ8L5H>nq6QM-8FsX08ug_=E)r#DC>d_!6Nr+rXe zzUt30Du_d0oSfX~u>qOVR*BmrPBwL@WhF^5+dHjWRB;kB$`m8|46efLBXLkiF|*W= zg|Hd(W}ZnlJLotYZCYKoL7YsQdLXZ!F`rLqLf8n$OZOyAzK`uKcbC-n0qoH!5-rh&k-`VADETKHxrhK<5C zhF0BB4azs%j~_q_HA#fYPO0r;YTlaa-eb)Le+!IeP>4S{b8&STp|Y0if*`-A&DQ$^ z-%=i73HvEMf_V6zSEF?G>G-Eqn+|k`0=q?(^|ZcqWsuLlMF2!E*8dDAx%)}y=lyMa z$Nn0_f8YN8g<4D>8IL3)GPf#dJYU@|NZqIX$;Lco?Qj=?W6J;D@pa`T=Yh z-ybpFyFr*3^gRt!9NnbSJWs2R-S?Y4+s~J8vfrPd_&_*)HBQ{&rW(2X>P-_CZU8Y9 z-32><7|wL*K+3{ZXE5}nn~t@NNT#Bc0F6kKI4pVwLrpU@C#T-&f{Vm}0h1N3#89@d zgcx3QyS;Pb?V*XAq;3(W&rjLBazm69XX;%^n6r}0!CR2zTU1!x#TypCr`yrII%wk8 z+g)fyQ!&xIX(*>?T}HYL^>wGC2E}euj{DD_RYKK@w=yF+44367X17)GP8DCmBK!xS zE{WRfQ(WB-v>DAr!{F2-cQKHIjIUnLk^D}7XcTI#HyjSiEX)BO^GBI9NjxojYfQza zWsX@GkLc7EqtP8(UM^cq5zP~{?j~*2T^Bb={@PV)DTkrP<9&hxDwN2@hEq~8(ZiF! z3FuQH_iHyQ_s-#EmAC5~K$j_$cw{+!T>dm#8`t%CYA+->rWp09jvXY`AJQ-l%C{SJ z1c~@<5*7$`1%b}n7ivSo(1(j8k+*Gek(m^rQ!+LPvb=xA@co<|(XDK+(tb46xJ4) zcw7w<0p3=Idb_FjQ@ttoyDmF?cT4JRGrX5xl&|ViA@Lg!vRR}p#$A?0=Qe+1)Mizl zn;!zhm`B&9t0GA67GF09t_ceE(bGdJ0mbXYrUoV2iuc3c69e;!%)xNOGG*?x*@5k( zh)snvm0s&gRq^{yyeE)>hk~w8)nTN`8HJRtY0~1f`f9ue%RV4~V(K*B;jFfJY4dBb z*BGFK`9M-tpWzayiD>p_`U(29f$R|V-qEB;+_4T939BPb=XRw~8n2cGiRi`o$2qm~ zN&5N7JU{L*QGM@lO8VI)fUA0D7bPrhV(GjJ$+@=dcE5vAVyCy6r&R#4D=GyoEVOnu z8``8q`PN-pEy>xiA_@+EN?EJpY<#}BhrsUJC0afQFx7-pBeLXR9Mr+#w@!wSNR7vxHy@r`!9MFecB4O zh9jye3iSzL0@t3)OZ=OxFjjyK#KSF|zz@K}-+HaY6gW+O{T6%Zky@gD$6SW)Jq;V0 zt&LAG*YFO^+=ULohZZW*=3>7YgND-!$2}2)Mt~c>JO3j6QiPC-*ayH2xBF)2m7+}# z`@m#q{J9r~Dr^eBgrF(l^#sOjlVNFgDs5NR*Xp;V*wr~HqBx7?qBUZ8w)%vIbhhe) zt4(#1S~c$Cq7b_A%wpuah1Qn(X9#obljoY)VUoK%OiQZ#Fa|@ZvGD0_oxR=vz{>U* znC(W7HaUDTc5F!T77GswL-jj7e0#83DH2+lS-T@_^SaWfROz9btt*5zDGck${}*njAwf}3hLqKGLTeV&5(8FC+IP>s;p{L@a~RyCu)MIa zs~vA?_JQ1^2Xc&^cjDq02tT_Z0gkElR0Aa$v@VHi+5*)1(@&}gEXxP5Xon?lxE@is z9sxd|h#w2&P5uHJxWgmtVZJv5w>cl2ALzri;r57qg){6`urTu(2}EI?D?##g=!Sbh z*L*>c9xN1a3CH$u7C~u_!g81`W|xp=54oZl9CM)&V9~ATCC-Q!yfKD@vp#2EKh0(S zgt~aJ^oq-TM0IBol!w1S2j7tJ8H7;SR7yn4-H}iz&U^*zW95HrHiT!H&E|rSlnCYr z7Y1|V7xebn=TFbkH;>WIH6H>8;0?HS#b6lCke9rSsH%3AM1#2U-^*NVhXEIDSFtE^ z=jOo1>j!c__Bub(R*dHyGa)@3h?!ls1&M)d2{?W5#1|M@6|ENYYa`X=2EA_oJUw=I zjQ)K6;C!@>^i7vdf`pBOjH>Ts$97}B=lkb07<&;&?f#cy3I0p5{1=?O*#8m$C_5TE zh}&8lOWWF7I@|pRC$G2;Sm#IJfhKW@^jk=jfM1MdJP(v2fIrYTc{;e5;5gsp`}X8-!{9{S1{h+)<@?+D13s^B zq9(1Pu(Dfl#&z|~qJGuGSWDT&u{sq|huEsbJhiqMUae}K*g+R(vG7P$p6g}w*eYWn zQ7luPl1@{vX?PMK%-IBt+N7TMn~GB z!Ldy^(2Mp{fw_0;<$dgHAv1gZgyJAx%}dA?jR=NPW1K`FkoY zNDgag#YWI6-a2#&_E9NMIE~gQ+*)i<>0c)dSRUMHpg!+AL;a;^u|M1jp#0b<+#14z z+#LuQ1jCyV_GNj#lHWG3e9P@H34~n0VgP#(SBX=v|RSuOiY>L87 z#KA{JDDj2EOBX^{`a;xQxHtY1?q5^B5?up1akjEPhi1-KUsK|J9XEBAbt%^F`t0I- zjRYYKI4OB7Zq3FqJFBZwbI=RuT~J|4tA8x)(v2yB^^+TYYJS>Et`_&yge##PuQ%0I z^|X!Vtof}`UuIxPjoH8kofw4u1pT5h`Ip}d8;l>WcG^qTe>@x63s#zoJiGmDM@_h= zo;8IZR`@AJRLnBNtatipUvL^(1P_a;q8P%&voqy#R!0(bNBTlV&*W9QU?kRV1B*~I zWvI?SNo2cB<7bgVY{F_CF$7z!02Qxfw-Ew#p!8PC#! z1sRfOl`d-Y@&=)l(Sl4CS=>fVvor5lYm61C!!iF3NMocKQHUYr0%QM}a4v2>rzPfM zUO}YRDb7-NEqW+p_;e0{Zi%0C$&B3CKx6|4BW`@`AwsxE?Vu}@Jm<3%T5O&05z+Yq zkK!QF(vlN}Rm}m_J+*W4`8i~R&`P0&5!;^@S#>7qkfb9wxFv@(wN@$k%2*sEwen$a zQnWymf+#Uyv)0lQVd?L1gpS}jMQZ(NHHCKRyu zjK|Zai0|N_)5iv)67(zDBCK4Ktm#ygP|0(m5tU`*AzR&{TSeSY8W=v5^=Ic`ahxM-LBWO+uoL~wxZmgcSJMUF9q%<%>jsvh9Dnp^_e>J_V=ySx4p?SF0Y zg4ZpZt@!h>WR76~P3_YchYOak7oOzR|`t+h!BbN}?zd zq+vMTt0!duALNWDwWVIA$O=%{lWJEj;5(QD()huhFL5=6x_=1h|5ESMW&S|*oxgF# z-0GRIb ziolwI13hJ-Rl(4Rj@*^=&Zz3vD$RX8bFWvBM{niz(%?z0gWNh_vUvpBDoa>-N=P4c zbw-XEJ@txIbc<`wC883;&yE4ayVh>+N($SJ01m}fumz!#!aOg*;y4Hl{V{b;&ux3& zBEmSq2jQ7#IbVm3TPBw?2vVN z0wzj|Y6EBS(V%Pb+@OPkMvEKHW~%DZk#u|A18pZMmCrjWh%7J4Ph>vG61 zRBgJ6w^8dNRg2*=K$Wvh$t>$Q^SMaIX*UpBG)0bqcvY%*by=$EfZAy{ZOA#^tB(D( zh}T(SZgdTj?bG9u+G{Avs5Yr1x=f3k7%K|eJp^>BHK#~dsG<&+=`mM@>kQ-cAJ2k) zT+Ht5liXdc^(aMi9su~{pJUhe)!^U&qn%mV6PS%lye+Iw5F@Xv8E zdR4#?iz+R4--iiHDQmQWfNre=iofAbF~1oGTa1Ce?hId~W^kPuN(5vhNx++ZLkn?l zUA7L~{0x|qA%%%P=8+-Ck{&2$UHn#OQncFS@uUVuE39c9o~#hl)v#!$X(X*4ban2c z{buYr9!`H2;6n73n^W3Vg(!gdBV7$e#v3qubWALaUEAf@`ava{UTx%2~VVQbEE(*Q8_ zv#me9i+0=QnY)$IT+@3vP1l9Wrne+MlZNGO6|zUVG+v&lm7Xw3P*+gS6e#6mVx~(w zyuaXogGTw4!!&P3oZ1|4oc_sGEa&m3Jsqy^lzUdJ^y8RlvUjDmbC^NZ0AmO-c*&m( zSI%4P9f|s!B#073b>Eet`T@J;3qY!NrABuUaED6M^=s-Q^2oZS`jVzuA z>g&g$!Tc>`u-Q9PmKu0SLu-X(tZeZ<%7F+$j3qOOftaoXO5=4!+P!%Cx0rNU+@E~{ zxCclYb~G(Ci%o{}4PC(Bu>TyX9slm5A^2Yi$$kCq-M#Jl)a2W9L-bq5%@Pw^ zh*iuuAz`x6N_rJ1LZ7J^MU9~}RYh+EVIVP+-62u+7IC%1p@;xmmQ`dGCx$QpnIUtK z0`++;Ddz7{_R^~KDh%_yo8WM$IQhcNOALCIGC$3_PtUs?Y44@Osw;OZ()Lk=(H&Vc zXjkHt+^1@M|J%Q&?4>;%T-i%#h|Tb1u;pO5rKst8(Cv2!3U{TRXdm&>fWTJG)n*q&wQPjRzg%pS1RO9}U0*C6fhUi&f#qoV`1{U<&mWKS<$oVFW>{&*$6)r6Rx)F4W zdUL8Mm_qNk6ycFVkI5F?V+cYFUch$92|8O^-Z1JC94GU+Nuk zA#n3Z1q4<6zRiv%W5`NGk*Ym{#0E~IA6*)H-=RmfWIY%mEC0? zSih7uchi`9-WkF2@z1ev6J_N~u;d$QfSNLMgPVpHZoh9oH-8D*;EhoCr~*kJ<|-VD z_jklPveOxWZq40E!SV@0XXy+~Vfn!7nZ1GXsn~U$>#u0d*f?RL9!NMlz^qxYmz|xt zz6A&MUAV#eD%^GcP#@5}QH5e7AV`}(N2#(3xpc!7dDmgu7C3TpgX5Z|$%Vu8=&SQI zdxUk*XS-#C^-cM*O>k}WD5K81e2ayyRA)R&5>KT1QL!T!%@}fw{>BsF+-pzu>;7{g z^CCSWfH;YtJGT@+An0Ded#zM9>UEFOdR_Xq zS~!5R*{p1Whq62ynHo|n$4p7&d|bal{iGsxAY?opi3R${)Zt*8YyOU!$TWMYXF?|i zPXYr}wJp#EH;keSG5WYJ*(~oiu#GDR>C4%-HpIWr7v`W`lzQN-lb?*vpoit z8FqJ)`LC4w8fO8Fu}AYV`awF2NLMS4$f+?=KisU4P6@#+_t)5WDz@f*qE|NG0*hwO z&gv^k^kC6Fg;5>Gr`Q46C{6>3F(p0QukG6NM07rxa&?)_C*eyU(jtli>9Zh#eUb(y zt9NbC-bp0>^m?i`?$aJUyBmF`N0zQ% zvF_;vLVI{tq%Ji%u*8s2p4iBirv*uD(?t~PEz$CfxVa=@R z^HQu6-+I9w>a35kX!P)TfnJDD!)j8!%38(vWNe9vK0{k*`FS$ABZ`rdwfQe@IGDki zssfXnsa6teKXCZUTd^qhhhUZ}>GG_>F0~LG7*<*x;8e39nb-0Bka(l)%+QZ_IVy3q zcmm2uKO0p)9|HGxk*e_$mX2?->&-MXe`=Fz3FRTFfM!$_y}G?{F9jmNgD+L%R`jM1 zIP-kb=3Hlsb35Q&qo(%Ja(LwQj>~!GI|Hgq65J9^A!ibChYB3kxLn@&=#pr}BwON0Q=e5;#sF8GGGuzx6O}z%u3l?jlKF&8Y#lUA)Cs6ZiW8DgOk|q z=YBPAMsO7AoAhWgnSKae2I7%7*Xk>#AyLX-InyBO?OD_^2^nI4#;G|tBvg3C0ldO0 z*`$g(q^es4VqXH2t~0-u^m5cfK8eECh3Rb2h1kW%%^8A!+ya3OHLw$8kHorx4(vJO zAlVu$nC>D{7i?7xDg3116Y2e+)Zb4FPAdZaX}qA!WW{$d?u+sK(iIKqOE-YM zH7y^hkny24==(1;qEacfFU{W{xSXhffC&DJV&oqw`u~WAl@=HIel>KC-mLs2ggFld zsSm-03=Jd^XNDA4i$vKqJ|e|TBc19bglw{)QL${Q(xlN?E;lPumO~;4w_McND6d+R zsc2p*&uRWd`wTDszTcWKiii1mNBrF7n&LQp$2Z<}zkv=8k2s6-^+#siy_K1`5R+n( z++5VOU^LDo(kt3ok?@$3drI`<%+SWcF*`CUWqAJxl3PAq!X|q{al;8%HfgxxM#2Vb zeBS756iU|BzB>bN2NP=AX&!{uZXS;|F`LLd9F^97UTMnNks_t7EPnjZF`2ocD2*u+ z?oKP{xXrD*AKGYGkZtlnvCuazg6g16ZAF{Nu%w+LCZ+v_*`0R$NK)tOh_c#cze;o$ z)kY(eZ5Viv<5zl1XfL(#GO|2FlXL#w3T?hpj3BZ&OAl^L!7@ zy;+iJWYQYP?$(`li_!|bfn!h~k#=v-#XXyjTLd+_txOqZZETqSEp>m+O0ji7MxZ*W zSdq+yqEmafrsLErZG8&;kH2kbCwluSa<@1yU3^Q#5HmW(hYVR0E6!4ZvH;Cr<$`qf zSvqRc`Pq_9b+xrtN3qLmds9;d7HdtlR!2NV$rZPCh6>(7f7M}>C^LeM_5^b$B~mn| z#)?`E=zeo9(9?{O_ko>51~h|c?8{F=2=_-o(-eRc z9p)o51krhCmff^U2oUi#$AG2p-*wSq8DZ(i!Jmu1wzD*)#%J&r)yZTq`3e|v4>EI- z=c|^$Qhv}lEyG@!{G~@}Wbx~vxTxwKoe9zn%5_Z^H$F1?JG_Kadc(G8#|@yaf2-4< zM1bdQF$b5R!W1f`j(S>Id;CHMzfpyjYEC_95VQ*$U3y5piVy=9Rdwg7g&)%#6;U%b2W}_VVdh}qPnM4FY9zFP(5eR zWuCEFox6e;COjs$1RV}IbpE0EV;}5IP}Oq|zcb*77PEDIZU{;@_;8*22{~JRvG~1t zc+ln^I+)Q*+Ha>(@=ra&L&a-kD;l$WEN;YL0q^GE8+})U_A_StHjX_gO{)N>tx4&F zRK?99!6JqktfeS-IsD@74yuq*aFJoV{5&K(W`6Oa2Qy0O5JG>O`zZ-p7vBGh!MxS;}}h6(96Wp`dci3DY?|B@1p8fVsDf$|0S zfE{WL5g3<9&{~yygYyR?jK!>;eZ2L#tpL2)H#89*b zycE?VViXbH7M}m33{#tI69PUPD=r)EVPTBku={Qh{ zKi*pht1jJ+yRhVE)1=Y()iS9j`FesMo$bjLSqPMF-i<42Hxl6%y7{#vw5YT(C}x0? z$rJU7fFmoiR&%b|Y*pG?7O&+Jb#Z%S8&%o~fc?S9c`Dwdnc4BJC7njo7?3bp#Yonz zPC>y`DVK~nzN^n}jB5RhE4N>LzhCZD#WQseohYXvqp5^%Ns!q^B z&8zQN(jgPS(2ty~g2t9!x9;Dao~lYVujG-QEq{vZp<1Nlp;oj#kFVsBnJssU^p-4% zKF_A?5sRmA>d*~^og-I95z$>T*K*33TGBPzs{OMoV2i+(P6K|95UwSj$Zn<@Rt(g%|iY z$SkSjYVJ)I<@S(kMQ6md{HxAa8S`^lXGV?ktLX!ngTVI~%WW+p#A#XTWaFWeBAl%U z&rVhve#Yse*h4BC4nrq7A1n>Rlf^ErbOceJC`o#fyCu@H;y)`E#a#)w)3eg^{Hw&E7);N5*6V+z%olvLj zp^aJ4`h*4L4ij)K+uYvdpil(Z{EO@u{BcMI&}5{ephilI%zCkBhBMCvOQT#zp|!18 zuNl=idd81|{FpGkt%ty=$fnZnWXxem!t4x{ zat@68CPmac(xYaOIeF}@O1j8O?2jbR!KkMSuix;L8x?m01}|bS2=&gsjg^t2O|+0{ zlzfu5r5_l4)py8uPb5~NHPG>!lYVynw;;T-gk1Pl6PQ39Mwgd2O+iHDB397H)2grN zHwbd>8i%GY>Pfy7;y5X7AN>qGLZVH>N_ZuJZ-`z9UA> zfyb$nbmPqxyF2F;UW}7`Cu>SS%0W6h^Wq5e{PWAjxlh=#Fq+6SiPa-L*551SZKX&w zc9TkPv4eao?kqomkZ#X%tA{`UIvf|_=Y7p~mHZKqO>i_;q4PrwVtUDTk?M7NCssa?Y4uxYrsXj!+k@`Cxl;&{NLs*6!R<6k9$Bq z%grLhxJ#G_j~ytJpiND8neLfvD0+xu>wa$-%5v;4;RYYM66PUab)c9ruUm%d{^s{# zTBBY??@^foRv9H}iEf{w_J%rV<%T1wv^`)Jm#snLTIifjgRkX``x2wV(D6(=VTLL4 zI-o}&5WuwBl~(XSLIn5~{cGWorl#z+=(vXuBXC#lp}SdW=_)~8Z(Vv!#3h2@pdA3d z{cIPYK@Ojc9(ph=H3T7;aY>(S3~iuIn05Puh^32WObj%hVN(Y{Ty?n?Cm#!kGNZFa zW6Ybz!tq|@erhtMo4xAus|H8V_c+XfE5mu|lYe|{$V3mKnb1~fqoFim;&_ZHN_=?t zysQwC4qO}rTi}k8_f=R&i27RdBB)@bTeV9Wcd}Rysvod}7I%ujwYbTI*cN7Kbp_hO z=eU521!#cx$0O@k9b$;pnCTRtLIzv){nVW6Ux1<0@te6`S5%Ew3{Z^9=lbL5$NFvd4eUtK?%zgmB;_I&p`)YtpN`2Im(?jPN<(7Ua_ZWJRF(CChv`(gHfWodK%+joy>8Vaa;H1w zIJ?!kA|x7V;4U1BNr(UrhfvjPii7YENLIm`LtnL9Sx z5E9TYaILoB2nSwDe|BVmrpLT43*dJ8;T@1l zJE)4LEzIE{IN}+Nvpo3=ZtV!U#D;rB@9OXYw^4QH+(52&pQEcZq&~u9bTg63ikW9! z=!_RjN2xO=F+bk>fSPhsjQA;)%M1My#34T`I7tUf>Q_L>DRa=>Eo(sapm>}}LUsN% zVw!C~a)xcca`G#g*Xqo>_uCJTz>LoWGSKOwp-tv`yvfqw{17t`9Z}U4o+q2JGP^&9 z(m}|d13XhYSnEm$_8vH-Lq$A^>oWUz1)bnv|AVn_0FwM$vYu&8+qUg$+qP}nwrykD zwmIF?wr$()X@33oz1@B9zi+?Th^nZnsES)rb@O*K^JL~ZH|pRRk$i0+ohh?Il)y&~ zQaq{}9YxPt5~_2|+r#{k#~SUhO6yFq)uBGtYMMg4h1qddg!`TGHocYROyNFJtYjNe z3oezNpq6%TP5V1g(?^5DMeKV|i6vdBq)aGJ)BRv;K(EL0_q7$h@s?BV$)w31*c(jd z{@hDGl3QdXxS=#?0y3KmPd4JL(q(>0ikTk6nt98ptq$6_M|qrPi)N>HY>wKFbnCKY z%0`~`9p)MDESQJ#A`_>@iL7qOCmCJ(p^>f+zqaMuDRk!z01Nd2A_W^D%~M73jTqC* zKu8u$$r({vP~TE8rPk?8RSjlRvG*BLF}ye~Su%s~rivmjg2F z24dhh6-1EQF(c>Z1E8DWY)Jw#9U#wR<@6J)3hjA&2qN$X%piJ4s={|>d-|Gzl~RNu z##iR(m;9TN3|zh+>HgTI&82iR>$YVoOq$a(2%l*2mNP(AsV=lR^>=tIP-R9Tw!BYnZROx`PN*JiNH>8bG}&@h0_v$yOTk#@1;Mh;-={ZU7e@JE(~@@y0AuETvsqQV@7hbKe2wiWk@QvV=Kz`%@$rN z_0Hadkl?7oEdp5eaaMqBm;#Xj^`fxNO^GQ9S3|Fb#%{lN;1b`~yxLGEcy8~!cz{!! z=7tS!I)Qq%w(t9sTSMWNhoV#f=l5+a{a=}--?S!rA0w}QF!_Eq>V4NbmYKV&^OndM z4WiLbqeC5+P@g_!_rs01AY6HwF7)$~%Ok^(NPD9I@fn5I?f$(rcOQjP+z?_|V0DiN zb}l0fy*el9E3Q7fVRKw$EIlb&T0fG~fDJZL7Qn8*a5{)vUblM)*)NTLf1ll$ zpQ^(0pkSTol`|t~`Y4wzl;%NRn>689mpQrW=SJ*rB;7}w zVHB?&sVa2%-q@ANA~v)FXb`?Nz8M1rHKiZB4xC9<{Q3T!XaS#fEk=sXI4IFMnlRqG+yaFw< zF{}7tcMjV04!-_FFD8(FtuOZx+|CjF@-xl6-{qSFF!r7L3yD()=*Ss6fT?lDhy(h$ zt#%F575$U(3-e2LsJd>ksuUZZ%=c}2dWvu8f!V%>z3gajZ!Dlk zm=0|(wKY`c?r$|pX6XVo6padb9{EH}px)jIsdHoqG^(XH(7}r^bRa8BC(%M+wtcB? z6G2%tui|Tx6C3*#RFgNZi9emm*v~txI}~xV4C`Ns)qEoczZ>j*r zqQCa5k90Gntl?EX!{iWh=1t$~jVoXjs&*jKu0Ay`^k)hC^v_y0xU~brMZ6PPcmt5$ z@_h`f#qnI$6BD(`#IR0PrITIV^~O{uo=)+Bi$oHA$G* zH0a^PRoeYD3jU_k%!rTFh)v#@cq`P3_y=6D(M~GBud;4 zCk$LuxPgJ5=8OEDlnU!R^4QDM4jGni}~C zy;t2E%Qy;A^bz_5HSb5pq{x{g59U!ReE?6ULOw58DJcJy;H?g*ofr(X7+8wF;*3{rx>j&27Syl6A~{|w{pHb zeFgu0E>OC81~6a9(2F13r7NZDGdQxR8T68&t`-BK zE>ZV0*0Ba9HkF_(AwfAds-r=|dA&p`G&B_zn5f9Zfrz9n#Rvso`x%u~SwE4SzYj!G zVQ0@jrLwbYP=awX$21Aq!I%M{x?|C`narFWhp4n;=>Sj!0_J!k7|A0;N4!+z%Oqlk z1>l=MHhw3bi1vT}1!}zR=6JOIYSm==qEN#7_fVsht?7SFCj=*2+Ro}B4}HR=D%%)F z?eHy=I#Qx(vvx)@Fc3?MT_@D))w@oOCRR5zRw7614#?(-nC?RH`r(bb{Zzn+VV0bm zJ93!(bfrDH;^p=IZkCH73f*GR8nDKoBo|!}($3^s*hV$c45Zu>6QCV(JhBW=3(Tpf z=4PT6@|s1Uz+U=zJXil3K(N6;ePhAJhCIo`%XDJYW@x#7Za);~`ANTvi$N4(Fy!K- z?CQ3KeEK64F0@ykv$-0oWCWhYI-5ZC1pDqui@B|+LVJmU`WJ=&C|{I_))TlREOc4* zSd%N=pJ_5$G5d^3XK+yj2UZasg2) zXMLtMp<5XWWfh-o@ywb*nCnGdK{&S{YI54Wh2|h}yZ})+NCM;~i9H@1GMCgYf`d5n zwOR(*EEkE4-V#R2+Rc>@cAEho+GAS2L!tzisLl${42Y=A7v}h;#@71_Gh2MV=hPr0_a% z0!={Fcv5^GwuEU^5rD|sP;+y<%5o9;#m>ssbtVR2g<420(I-@fSqfBVMv z?`>61-^q;M(b3r2z{=QxSjyH=-%99fpvb}8z}d;%_8$$J$qJg1Sp3KzlO_!nCn|g8 zzg8skdHNsfgkf8A7PWs;YBz_S$S%!hWQ@G>guCgS--P!!Ui9#%GQ#Jh?s!U-4)7ozR?i>JXHU$| zg0^vuti{!=N|kWorZNFX`dJgdphgic#(8sOBHQdBkY}Qzp3V%T{DFb{nGPgS;QwnH9B9;-Xhy{? z(QVwtzkn9I)vHEmjY!T3ifk1l5B?%%TgP#;CqG-?16lTz;S_mHOzu#MY0w}XuF{lk z*dt`2?&plYn(B>FFXo+fd&CS3q^hquSLVEn6TMAZ6e*WC{Q2e&U7l|)*W;^4l~|Q= zt+yFlLVqPz!I40}NHv zE2t1meCuGH%<`5iJ(~8ji#VD{?uhP%F(TnG#uRZW-V}1=N%ev&+Gd4v!0(f`2Ar-Y z)GO6eYj7S{T_vxV?5^%l6TF{ygS_9e2DXT>9caP~xq*~oE<5KkngGtsv)sdCC zaQH#kSL%c*gLj6tV)zE6SGq|0iX*DPV|I`byc9kn_tNQkPU%y<`rj zMC}lD<93=Oj+D6Y2GNMZb|m$^)RVdi`&0*}mxNy0BW#0iq!GGN2BGx5I0LS>I|4op z(6^xWULBr=QRpbxIJDK~?h;K#>LwQI4N<8V?%3>9I5l+e*yG zFOZTIM0c3(q?y9f7qDHKX|%zsUF%2zN9jDa7%AK*qrI5@z~IruFP+IJy7!s~TE%V3 z_PSSxXlr!FU|Za>G_JL>DD3KVZ7u&}6VWbwWmSg?5;MabycEB)JT(eK8wg`^wvw!Q zH5h24_E$2cuib&9>Ue&@%Cly}6YZN-oO_ei5#33VvqV%L*~ZehqMe;)m;$9)$HBsM zfJ96Hk8GJyWwQ0$iiGjwhxGgQX$sN8ij%XJzW`pxqgwW=79hgMOMnC|0Q@ed%Y~=_ z?OnjUB|5rS+R$Q-p)vvM(eFS+Qr{_w$?#Y;0Iknw3u(+wA=2?gPyl~NyYa3me{-Su zhH#8;01jEm%r#5g5oy-f&F>VA5TE_9=a0aO4!|gJpu470WIrfGo~v}HkF91m6qEG2 zK4j=7C?wWUMG$kYbIp^+@)<#ArZ$3k^EQxraLk0qav9TynuE7T79%MsBxl3|nRn?L zD&8kt6*RJB6*a7=5c57wp!pg)p6O?WHQarI{o9@3a32zQ3FH8cK@P!DZ?CPN_LtmC6U4F zlv8T2?sau&+(i@EL6+tvP^&=|aq3@QgL4 zOu6S3wSWeYtgCnKqg*H4ifIQlR4hd^n{F+3>h3;u_q~qw-Sh;4dYtp^VYymX12$`? z;V2_NiRt82RC=yC+aG?=t&a81!gso$hQUb)LM2D4Z{)S zI1S9f020mSm(Dn$&Rlj0UX}H@ zv={G+fFC>Sad0~8yB%62V(NB4Z|b%6%Co8j!>D(VyAvjFBP%gB+`b*&KnJ zU8s}&F+?iFKE(AT913mq;57|)q?ZrA&8YD3Hw*$yhkm;p5G6PNiO3VdFlnH-&U#JH zEX+y>hB(4$R<6k|pt0?$?8l@zeWk&1Y5tlbgs3540F>A@@rfvY;KdnVncEh@N6Mfi zY)8tFRY~Z?Qw!{@{sE~vQy)0&fKsJpj?yR`Yj+H5SDO1PBId3~d!yjh>FcI#Ug|^M z7-%>aeyQhL8Zmj1!O0D7A2pZE-$>+-6m<#`QX8(n)Fg>}l404xFmPR~at%$(h$hYD zoTzbxo`O{S{E}s8Mv6WviXMP}(YPZoL11xfd>bggPx;#&pFd;*#Yx%TtN1cp)MuHf z+Z*5CG_AFPwk624V9@&aL0;=@Ql=2h6aJoqWx|hPQQzdF{e7|fe(m){0==hk_!$ou zI|p_?kzdO9&d^GBS1u+$>JE-6Ov*o{mu@MF-?$r9V>i%;>>Fo~U`ac2hD*X}-gx*v z1&;@ey`rA0qNcD9-5;3_K&jg|qvn@m^+t?8(GTF0l#|({Zwp^5Ywik@bW9mN+5`MU zJ#_Ju|jtsq{tv)xA zY$5SnHgHj}c%qlQG72VS_(OSv;H~1GLUAegygT3T-J{<#h}))pk$FjfRQ+Kr%`2ZiI)@$96Nivh82#K@t>ze^H?R8wHii6Pxy z0o#T(lh=V>ZD6EXf0U}sG~nQ1dFI`bx;vivBkYSVkxXn?yx1aGxbUiNBawMGad;6? zm{zp?xqAoogt=I2H0g@826=7z^DmTTLB11byYvAO;ir|O0xmNN3Ec0w%yHO({-%q(go%?_X{LP?=E1uXoQgrEGOfL1?~ zI%uPHC23dn-RC@UPs;mxq6cFr{UrgG@e3ONEL^SoxFm%kE^LBhe_D6+Ia+u0J=)BC zf8FB!0J$dYg33jb2SxfmkB|8qeN&De!%r5|@H@GiqReK(YEpnXC;-v~*o<#JmYuze zW}p-K=9?0=*fZyYTE7A}?QR6}m_vMPK!r~y*6%My)d;x4R?-=~MMLC_02KejX9q6= z4sUB4AD0+H4ulSYz4;6mL8uaD07eXFvpy*i5X@dmx--+9`ur@rcJ5<L#s%nq3MRi4Dpr;#28}dl36M{MkVs4+Fm3Pjo5qSV)h}i(2^$Ty|<7N z>*LiBzFKH30D!$@n^3B@HYI_V1?yM(G$2Ml{oZ}?frfPU+{i|dHQOP^M0N2#NN_$+ zs*E=MXUOd=$Z2F4jSA^XIW=?KN=w6{_vJ4f(ZYhLxvFtPozPJv9k%7+z!Zj+_0|HC zMU0(8`8c`Sa=%e$|Mu2+CT22Ifbac@7Vn*he`|6Bl81j`44IRcTu8aw_Y%;I$Hnyd zdWz~I!tkWuGZx4Yjof(?jM;exFlUsrj5qO=@2F;56&^gM9D^ZUQ!6TMMUw19zslEu zwB^^D&nG96Y+Qwbvgk?Zmkn9%d{+V;DGKmBE(yBWX6H#wbaAm&O1U^ zS4YS7j2!1LDC6|>cfdQa`}_^satOz6vc$BfFIG07LoU^IhVMS_u+N=|QCJao0{F>p z-^UkM)ODJW9#9*o;?LPCRV1y~k9B`&U)jbTdvuxG&2%!n_Z&udT=0mb@e;tZ$_l3bj6d0K2;Ya!&)q`A${SmdG_*4WfjubB)Mn+vaLV+)L5$yD zYSTGxpVok&fJDG9iS8#oMN{vQneO|W{Y_xL2Hhb%YhQJgq7j~X7?bcA|B||C?R=Eo z!z;=sSeKiw4mM$Qm>|aIP3nw36Tbh6Eml?hL#&PlR5xf9^vQGN6J8op1dpLfwFg}p zlqYx$610Zf?=vCbB_^~~(e4IMic7C}X(L6~AjDp^;|=d$`=!gd%iwCi5E9<6Y~z0! zX8p$qprEadiMgq>gZ_V~n$d~YUqqqsL#BE6t9ufXIUrs@DCTfGg^-Yh5Ms(wD1xAf zTX8g52V!jr9TlWLl+whcUDv?Rc~JmYs3haeG*UnV;4bI=;__i?OSk)bF3=c9;qTdP zeW1exJwD+;Q3yAw9j_42Zj9nuvs%qGF=6I@($2Ue(a9QGRMZTd4ZAlxbT5W~7(alP1u<^YY!c3B7QV z@jm$vn34XnA6Gh1I)NBgTmgmR=O1PKp#dT*mYDPRZ=}~X3B8}H*e_;;BHlr$FO}Eq zJ9oWk0y#h;N1~ho724x~d)A4Z-{V%F6#e5?Z^(`GGC}sYp5%DKnnB+i-NWxwL-CuF+^JWNl`t@VbXZ{K3#aIX+h9-{T*+t(b0BM&MymW9AA*{p^&-9 zWpWQ?*z(Yw!y%AoeoYS|E!(3IlLksr@?Z9Hqlig?Q4|cGe;0rg#FC}tXTmTNfpE}; z$sfUYEG@hLHUb$(K{A{R%~%6MQN|Bu949`f#H6YC*E(p3lBBKcx z-~Bsd6^QsKzB0)$FteBf*b3i7CN4hccSa-&lfQz4qHm>eC|_X!_E#?=`M(bZ{$cvU zZpMbr|4omp`s9mrgz@>4=Fk3~8Y7q$G{T@?oE0<(I91_t+U}xYlT{c&6}zPAE8ikT z3DP!l#>}i!A(eGT+@;fWdK#(~CTkwjs?*i4SJVBuNB2$6!bCRmcm6AnpHHvnN8G<| zuh4YCYC%5}Zo;BO1>L0hQ8p>}tRVx~O89!${_NXhT!HUoGj0}bLvL2)qRNt|g*q~B z7U&U7E+8Ixy1U`QT^&W@ZSRN|`_Ko$-Mk^^c%`YzhF(KY9l5))1jSyz$&>mWJHZzHt0Jje%BQFxEV}C00{|qo5_Hz7c!FlJ|T(JD^0*yjkDm zL}4S%JU(mBV|3G2jVWU>DX413;d+h0C3{g3v|U8cUj`tZL37Sf@1d*jpwt4^B)`bK zZdlwnPB6jfc7rIKsldW81$C$a9BukX%=V}yPnaBz|i6(h>S)+Bn44@i8RtBZf0XetH&kAb?iAL zD%Ge{>Jo3sy2hgrD?15PM}X_)(6$LV`&t*D`IP)m}bzM)+x-xRJ zavhA)>hu2cD;LUTvN38FEtB94ee|~lIvk~3MBPzmTsN|7V}Kzi!h&za#NyY zX^0BnB+lfBuW!oR#8G&S#Er2bCVtA@5FI`Q+a-e?G)LhzW_chWN-ZQmjtR

eWu-UOPu^G}|k=o=;ffg>8|Z*qev7qS&oqA7%Z{4Ezb!t$f3& z^NuT8CSNp`VHScyikB1YO{BgaBVJR&>dNIEEBwYkfOkWN;(I8CJ|vIfD}STN z{097)R9iC@6($s$#dsb*4BXBx7 zb{6S2O}QUk>upEfij9C2tjqWy7%%V@Xfpe)vo6}PG+hmuY1Tc}peynUJLLmm)8pshG zb}HWl^|sOPtYk)CD-7{L+l(=F zOp}fX8)|n{JDa&9uI!*@jh^^9qP&SbZ(xxDhR)y|bjnn|K3MeR3gl6xcvh9uqzb#K zYkVjnK$;lUky~??mcqN-)d5~mk{wXhrf^<)!Jjqc zG~hX0P_@KvOKwV=X9H&KR3GnP3U)DfqafBt$e10}iuVRFBXx@uBQ)sn0J%%c<;R+! zQz;ETTVa+ma>+VF%U43w?_F6s0=x@N2(oisjA7LUOM<$|6iE|$WcO67W|KY8JUV_# zg7P9K3Yo-c*;EmbsqT!M4(WT`%9uk+s9Em-yB0bE{B%F4X<8fT!%4??vezaJ(wJhj zfOb%wKfkY3RU}7^FRq`UEbB-#A-%7)NJQwQd1As=!$u#~2vQ*CE~qp`u=_kL<`{OL zk>753UqJVx1-4~+d@(pnX-i zV4&=eRWbJ)9YEGMV53poXpv$vd@^yd05z$$@i5J7%>gYKBx?mR2qGv&BPn!tE-_aW zg*C!Z&!B zH>3J16dTJC(@M0*kIc}Jn}jf=f*agba|!HVm|^@+7A?V>Woo!$SJko*Jv1mu>;d}z z^vF{3u5Mvo_94`4kq2&R2`32oyoWc2lJco3`Ls0Ew4E7*AdiMbn^LCV%7%mU)hr4S3UVJjDLUoIKRQ)gm?^{1Z}OYzd$1?a~tEY ztjXmIM*2_qC|OC{7V%430T?RsY?ZLN$w!bkDOQ0}wiq69){Kdu3SqW?NMC))S}zq^ zu)w!>E1!;OrXO!RmT?m&PA;YKUjJy5-Seu=@o;m4*Vp$0OipBl4~Ub)1xBdWkZ47=UkJd$`Z}O8ZbpGN$i_WtY^00`S8=EHG#Ff{&MU1L(^wYjTchB zMTK%1LZ(eLLP($0UR2JVLaL|C2~IFbWirNjp|^=Fl48~Sp9zNOCZ@t&;;^avfN(NpNfq}~VYA{q%yjHo4D>JB>XEv(~Z!`1~SoY=9v zTq;hrjObE_h)cmHXLJ>LC_&XQ2BgGfV}e#v}ZF}iF97bG`Nog&O+SA`2zsn%bbB309}I$ zYi;vW$k@fC^muYBL?XB#CBuhC&^H)F4E&vw(5Q^PF{7~}(b&lF4^%DQzL0(BVk?lM zTHXTo4?Ps|dRICEiux#y77_RF8?5!1D-*h5UY&gRY`WO|V`xxB{f{DHzBwvt1W==r zdfAUyd({^*>Y7lObr;_fO zxDDw7X^dO`n!PLqHZ`by0h#BJ-@bAFPs{yJQ~Ylj^M5zWsxO_WFHG}8hH>OK{Q)9` zSRP94d{AM(q-2x0yhK@aNMv!qGA5@~2tB;X?l{Pf?DM5Y*QK`{mGA? zjx;gwnR~#Nep12dFk<^@-U{`&`P1Z}Z3T2~m8^J&7y}GaMElsTXg|GqfF3>E#HG=j zMt;6hfbfjHSQ&pN9(AT8q$FLKXo`N(WNHDY!K6;JrHZCO&ISBdX`g8sXvIf?|8 zX$-W^ut!FhBxY|+R49o44IgWHt}$1BuE|6|kvn1OR#zhyrw}4H*~cpmFk%K(CTGYc zNkJ8L$eS;UYDa=ZHWZy`rO`!w0oIcgZnK&xC|93#nHvfb^n1xgxf{$LB`H1ao+OGb zKG_}>N-RHSqL(RBdlc7J-Z$Gaay`wEGJ_u-lo88{`aQ*+T~+x(H5j?Q{uRA~>2R+} zB+{wM2m?$->unwg8-GaFrG%ZmoHEceOj{W21)Mi2lAfT)EQuNVo+Do%nHPuq7Ttt7 z%^6J5Yo64dH671tOUrA7I2hL@HKZq;S#Ejxt;*m-l*pPj?=i`=E~FAXAb#QH+a}-% z#3u^pFlg%p{hGiIp>05T$RiE*V7bPXtkz(G<+^E}Risi6F!R~Mbf(Qz*<@2&F#vDr zaL#!8!&ughWxjA(o9xtK{BzzYwm_z2t*c>2jI)c0-xo8ahnEqZ&K;8uF*!Hg0?Gd* z=eJK`FkAr>7$_i$;kq3Ks5NNJkNBnw|1f-&Ys56c9Y@tdM3VTTuXOCbWqye9va6+ZSeF0eh} zYb^ct&4lQTfNZ3M3(9?{;s><(zq%hza7zcxlZ+`F8J*>%4wq8s$cC6Z=F@ zhbvdv;n$%vEI$B~B)Q&LkTse!8Vt};7Szv2@YB!_Ztp@JA>rc(#R1`EZcIdE+JiI% zC2!hgYt+~@%xU?;ir+g92W`*j z3`@S;I6@2rO28zqj&SWO^CvA5MeNEhBF+8-U0O0Q1Co=I^WvPl%#}UFDMBVl z5iXV@d|`QTa$>iw;m$^}6JeuW zjr;{)S2TfK0Q%xgHvONSJb#NA|LOmg{U=k;R?&1tQbylMEY4<1*9mJh&(qo`G#9{X zYRs)#*PtEHnO;PV0G~6G`ca%tpKgb6<@)xc^SQY58lTo*S$*sv5w7bG+8YLKYU`8{ zNBVlvgaDu7icvyf;N&%42z2L4(rR<*Jd48X8Jnw zN>!R$%MZ@~Xu9jH?$2Se&I|ZcW>!26BJP?H7og0hT(S`nXh6{sR36O^7%v=31T+eL z)~BeC)15v>1m#(LN>OEwYFG?TE0_z)MrT%3SkMBBjvCd6!uD+03Jz#!s#Y~b1jf>S z&Rz5&8rbLj5!Y;(Hx|UY(2aw~W(8!3q3D}LRE%XX(@h5TnP@PhDoLVQx;6|r^+Bvs zaR55cR%Db9hZ<<|I%dDkone+8Sq7dqPOMnGoHk~-R*#a8w$c)`>4U`k+o?2|E>Sd4 zZ0ZVT{95pY$qKJ54K}3JB!(WcES>F+x56oJBRg))tMJ^#Qc(2rVcd5add=Us6vpBNkIg9b#ulk%!XBU zV^fH1uY(rGIAiFew|z#MM!qsVv%ZNb#why9%9In4Kj-hDYtMdirWLFzn~de!nnH(V zv0>I3;X#N)bo1$dFzqo(tzmvqNUKraAz~?)OSv42MeM!OYu;2VKn2-s7#fucX`|l~ zplxtG1Pgk#(;V=`P_PZ`MV{Bt4$a7;aLvG@KQo%E=;7ZO&Ws-r@XL+AhnPn>PAKc7 zQ_iQ4mXa-a4)QS>cJzt_j;AjuVCp8g^|dIV=DI0>v-f_|w5YWAX61lNBjZEZax3aV znher(j)f+a9_s8n#|u=kj0(unR1P-*L7`{F28xv054|#DMh}q=@rs@-fbyf(2+52L zN>hn3v!I~%jfOV=j(@xLOsl$Jv-+yR5{3pX)$rIdDarl7(C3)})P`QoHN|y<<2n;` zJ0UrF=Zv}d=F(Uj}~Yv9(@1pqUSRa5_bB*AvQ|Z-6YZ*N%p(U z<;Bpqr9iEBe^LFF!t{1UnRtaH-9=@p35fMQJ~1^&)(2D|^&z?m z855r&diVS6}jmt2)A7LZDiv;&Ys6@W5P{JHY!!n7W zvj3(2{1R9Y=TJ|{^2DK&be*ZaMiRHw>WVI^701fC) zAp1?8?oiU%Faj?Qhou6S^d11_7@tEK-XQ~%q!!7hha-Im^>NcRF7OH7s{IO7arZQ{ zE8n?2><7*!*lH}~usWPWZ}2&M+)VQo7C!AWJSQc>8g_r-P`N&uybK5)p$5_o;+58Q z-Ux2l<3i|hxqqur*qAfHq=)?GDchq}ShV#m6&w|mi~ar~`EO_S=fb~<}66U>5i7$H#m~wR;L~4yHL2R&;L*u7-SPdHxLS&Iy76q$2j#Pe)$WulRiCICG*t+ zeehM8`!{**KRL{Q{8WCEFLXu3+`-XF(b?c1Z~wg?c0lD!21y?NLq?O$STk3NzmrHM zsCgQS5I+nxDH0iyU;KKjzS24GJmG?{D`08|N-v+Egy92lBku)fnAM<}tELA_U`)xKYb=pq|hejMCT1-rg0Edt6(*E9l9WCKI1a=@c99swp2t6Tx zFHy`8Hb#iXS(8c>F~({`NV@F4w0lu5X;MH6I$&|h*qfx{~DJ*h5e|61t1QP}tZEIcjC%!Fa)omJTfpX%aI+OD*Y(l|xc0$1Zip;4rx; zV=qI!5tSuXG7h?jLR)pBEx!B15HCoVycD&Z2dlqN*MFQDb!|yi0j~JciNC!>){~ zQQgmZvc}0l$XB0VIWdg&ShDTbTkArryp3x)T8%ulR;Z?6APx{JZyUm=LC-ACkFm`6 z(x7zm5ULIU-xGi*V6x|eF~CN`PUM%`!4S;Uv_J>b#&OT9IT=jx5#nydC4=0htcDme zDUH*Hk-`Jsa>&Z<7zJ{K4AZE1BVW%zk&MZ^lHyj8mWmk|Pq8WwHROz0Kwj-AFqvR)H2gDN*6dzVk>R3@_CV zw3Z@6s^73xW)XY->AFwUlk^4Q=hXE;ckW=|RcZFchyOM0vqBW{2l*QR#v^SZNnT6j zZv|?ZO1-C_wLWVuYORQryj29JA; zS4BsxfVl@X!W{!2GkG9fL4}58Srv{$-GYngg>JuHz!7ZPQbfIQr4@6ZC4T$`;Vr@t zD#-uJ8A!kSM*gA&^6yWi|F}&59^*Rx{qn3z{(JYxrzg!X2b#uGd>&O0e=0k_2*N?3 zYXV{v={ONL{rW~z_FtFj7kSSJZ?s);LL@W&aND7blR8rlvkAb48RwJZlOHA~t~RfC zOD%ZcOzhYEV&s9%qns0&ste5U!^MFWYn`Od()5RwIz6%@Ek+Pn`s79unJY-$7n-Uf z&eUYvtd)f7h7zG_hDiFC!psCg#q&0c=GHKOik~$$>$Fw*k z;G)HS$IR)Cu72HH|JjeeauX;U6IgZ_IfxFCE_bGPAU25$!j8Etsl0Rk@R`$jXuHo8 z3Hhj-rTR$Gq(x)4Tu6;6rHQhoCvL4Q+h0Y+@Zdt=KTb0~wj7-(Z9G%J+aQu05@k6JHeCC|YRFWGdDCV}ja;-yl^9<`>f=AwOqML1a~* z9@cQYb?!+Fmkf}9VQrL8$uyq8k(r8)#;##xG9lJ-B)Fg@15&To(@xgk9SP*bkHlxiy8I*wJQylh(+9X~H-Is!g&C!q*eIYuhl&fS&|w)dAzXBdGJ&Mp$+8D| zZaD<+RtjI90QT{R0YLk6_dm=GfCg>7;$ zlyLsNYf@MfLH<}ott5)t2CXiQos zFLt^`%ygB2Vy^I$W3J_Rt4olRn~Gh}AW(`F@LsUN{d$sR%bU&3;rsD=2KCL+4c`zv zlI%D>9-)U&R3;>d1Vdd5b{DeR!HXDm44Vq*u?`wziLLsFUEp4El;*S0;I~D#TgG0s zBXYZS{o|Hy0A?LVNS)V4c_CFwyYj-E#)4SQq9yaf`Y2Yhk7yHSdos~|fImZG5_3~~o<@jTOH@Mc7`*xn-aO5F zyFT-|LBsm(NbWkL^oB-Nd31djBaYebhIGXhsJyn~`SQ6_4>{fqIjRp#Vb|~+Qi}Mdz!Zsw= zz?5L%F{c{;Cv3Q8ab>dsHp)z`DEKHf%e9sT(aE6$az?A}3P`Lm(~W$8Jr=;d8#?dm_cmv>2673NqAOenze z=&QW`?TQAu5~LzFLJvaJ zaBU3mQFtl5z?4XQDBWNPaH4y)McRpX#$(3o5Nx@hVoOYOL&-P+gqS1cQ~J;~1roGH zVzi46?FaI@w-MJ0Y7BuAg*3;D%?<_OGsB3)c|^s3A{UoAOLP8scn`!5?MFa|^cTvq z#%bYG3m3UO9(sH@LyK9-LSnlVcm#5^NRs9BXFtRN9kBY2mPO|@b7K#IH{B{=0W06) zl|s#cIYcreZ5p3j>@Ly@35wr-q8z5f9=R42IsII=->1stLo@Q%VooDvg@*K(H@*5g zUPS&cM~k4oqp`S+qp^*nxzm^0mg3h8ppEHQ@cXyQ=YKV-6)FB*$KCa{POe2^EHr{J zOxcVd)s3Mzs8m`iV?MSp=qV59blW9$+$P+2;PZDRUD~sr*CQUr&EDiCSfH@wuHez+ z`d5p(r;I7D@8>nbZ&DVhT6qe+accH;<}q$8Nzz|d1twqW?UV%FMP4Y@NQ`3(+5*i8 zP9*yIMP7frrneG3M9 zf>GsjA!O#Bifr5np-H~9lR(>#9vhE6W-r`EjjeQ_wdWp+rt{{L5t5t(Ho|4O24@}4 z_^=_CkbI`3;~sXTnnsv=^b3J}`;IYyvb1gM>#J9{$l#Zd*W!;meMn&yXO7x`Epx_Y zm-1wlu~@Ii_7D}>%tzlXW;zQT=uQXSG@t$<#6-W*^vy7Vr2TCpnix@7!_|aNXEnN<-m?Oq;DpN*x6f>w za1Wa5entFEDtA0SD%iZv#3{wl-S`0{{i3a9cmgNW`!TH{J*~{@|5f%CKy@uk*8~af zt_d34U4y&3y9IZ5cXxLQ?(XjH5?q3Z0KxK~y!-CUyWG6{<)5lkhbox0HnV&7^zNBn zjc|?X!Y=63(Vg>#&Wx%=LUr5{i@~OdzT#?P8xu#P*I_?Jl7xM4dq)4vi}3Wj_c=XI zSbc)@Q2Et4=(nBDU{aD(F&*%Ix!53_^0`+nOFk)}*34#b0Egffld|t_RV91}S0m)0 zap{cQDWzW$geKzYMcDZDAw480!1e1!1Onpv9fK9Ov~sfi!~OeXb(FW)wKx335nNY! za6*~K{k~=pw`~3z!Uq%?MMzSl#s%rZM{gzB7nB*A83XIGyNbi|H8X>a5i?}Rs+z^; z2iXrmK4|eDOu@{MdS+?@(!-Ar4P4?H_yjTEMqm7`rbV4P275(-#TW##v#Dt14Yn9UB-Sg3`WmL0+H~N;iC`Mg%pBl?1AAOfZ&e; z*G=dR>=h_Mz@i;lrGpIOQwezI=S=R8#);d*;G8I(39ZZGIpWU)y?qew(t!j23B9fD z?Uo?-Gx3}6r8u1fUy!u)7LthD2(}boE#uhO&mKBau8W8`XV7vO>zb^ZVWiH-DOjl2 zf~^o1CYVU8eBdmpAB=T%i(=y}!@3N%G-*{BT_|f=egqtucEtjRJJhSf)tiBhpPDpgzOpG12UgvOFnab&16Zn^2ZHjs)pbd&W1jpx%%EXmE^ zdn#R73^BHp3w%&v!0~azw(Fg*TT*~5#dJw%-UdxX&^^(~V&C4hBpc+bPcLRZizWlc zjR;$4X3Sw*Rp4-o+a4$cUmrz05RucTNoXRINYG*DPpzM&;d1GNHFiyl(_x#wspacQ zL)wVFXz2Rh0k5i>?Ao5zEVzT)R(4Pjmjv5pzPrav{T(bgr|CM4jH1wDp6z*_jnN{V ziN56m1T)PBp1%`OCFYcJJ+T09`=&=Y$Z#!0l0J2sIuGQtAr>dLfq5S;{XGJzNk@a^ zk^eHlC4Gch`t+ue3RviiOlhz81CD9z~d|n5;A>AGtkZMUQ#f>5M14f2d}2 z8<*LNZvYVob!p9lbmb!0jt)xn6O&JS)`}7v}j+csS3e;&Awj zoNyjnqLzC(QQ;!jvEYUTy73t_%16p)qMb?ihbU{y$i?=a7@JJoXS!#CE#y}PGMK~3 zeeqqmo7G-W_S97s2eed^erB2qeh4P25)RO1>MH7ai5cZJTEevogLNii=oKG)0(&f` z&hh8cO{of0;6KiNWZ6q$cO(1)9r{`}Q&%p*O0W7N--sw3Us;)EJgB)6iSOg(9p_mc zRw{M^qf|?rs2wGPtjVKTOMAfQ+ZNNkb$Ok0;Pe=dNc7__TPCzw^H$5J0l4D z%p(_0w(oLmn0)YDwrcFsc*8q)J@ORBRoZ54GkJpxSvnagp|8H5sxB|ZKirp%_mQt_ z81+*Y8{0Oy!r8Gmih48VuRPwoO$dDW@h53$C)duL4_(osryhwZSj%~KsZ?2n?b`Z* z#C8aMdZxYmCWSM{mFNw1ov*W}Dl=%GQpp90qgZ{(T}GOS8#>sbiEU;zYvA?=wbD5g+ahbd1#s`=| zV6&f#ofJC261~Ua6>0M$w?V1j##jh-lBJ2vQ%&z`7pO%frhLP-1l)wMs=3Q&?oth1 zefkPr@3Z(&OL@~|<0X-)?!AdK)ShtFJ;84G2(izo3cCuKc{>`+aDoziL z6gLTL(=RYeD7x^FYA%sPXswOKhVa4i(S4>h&mLvS##6-H?w8q!B<8Alk>nQEwUG)SFXK zETfcTwi=R3!ck|hSM`|-^N3NWLav&UTO{a9=&Tuz-Kq963;XaRFq#-1R18fi^Gb-; zVO>Q{Oe<^b0WA!hkBi9iJp3`kGwacXX2CVQ0xQn@Y2OhrM%e4)Ea7Y*Df$dY2BpbL zv$kX}*#`R1uNA(7lk_FAk~{~9Z*Si5xd(WKQdD&I?8Y^cK|9H&huMU1I(251D7(LL z+){kRc=ALmD;#SH#YJ+|7EJL6e~w!D7_IrK5Q=1DCulUcN(3j`+D_a|GP}?KYx}V+ zx_vLTYCLb0C?h;e<{K0`)-|-qfM16y{mnfX(GGs2H-;-lRMXyb@kiY^D;i1haxoEk zsQ7C_o2wv?;3KS_0w^G5#Qgf*>u)3bT<3kGQL-z#YiN9QH7<(oDdNlSdeHD zQJN-U*_wJM_cU}1YOH=m>DW~{%MAPxL;gLdU6S5xLb$gJt#4c2KYaEaL8ORWf=^(l z-2`8^J;&YG@vb9em%s~QpU)gG@24BQD69;*y&-#0NBkxumqg#YYomd2tyo0NGCr8N z5<5-E%utH?Ixt!(Y4x>zIz4R^9SABVMpLl(>oXnBNWs8w&xygh_e4*I$y_cVm?W-^ ze!9mPy^vTLRclXRGf$>g%Y{(#Bbm2xxr_Mrsvd7ci|X|`qGe5=54Zt2Tb)N zlykxE&re1ny+O7g#`6e_zyjVjRi5!DeTvSJ9^BJqQ*ovJ%?dkaQl!8r{F`@KuDEJB3#ho5 zmT$A&L=?}gF+!YACb=%Y@}8{SnhaGCHRmmuAh{LxAn0sg#R6P_^cJ-9)+-{YU@<^- zlYnH&^;mLVYE+tyjFj4gaAPCD4CnwP75BBXA`O*H(ULnYD!7K14C!kGL_&hak)udZ zkQN8)EAh&9I|TY~F{Z6mBv7sz3?<^o(#(NXGL898S3yZPTaT|CzZpZ~pK~*9Zcf2F zgwuG)jy^OTZD`|wf&bEdq4Vt$ir-+qM7BosXvu`>W1;iFN7yTvcpN_#at)Q4n+(Jh zYX1A-24l9H5jgY?wdEbW{(6U1=Kc?Utren80bP`K?J0+v@{-RDA7Y8yJYafdI<7-I z_XA!xeh#R4N7>rJ_?(VECa6iWhMJ$qdK0Ms27xG&$gLAy(|SO7_M|AH`fIY)1FGDp zlsLwIDshDU;*n`dF@8vV;B4~jRFpiHrJhQ6TcEm%OjWTi+KmE7+X{19 z>e!sg0--lE2(S0tK}zD&ov-{6bMUc%dNFIn{2^vjXWlt>+uxw#d)T6HNk6MjsfN~4 zDlq#Jjp_!wn}$wfs!f8NX3Rk#9)Q6-jD;D9D=1{$`3?o~caZjXU*U32^JkJ$ZzJ_% zQWNfcImxb!AV1DRBq`-qTV@g1#BT>TlvktYOBviCY!13Bv?_hGYDK}MINVi;pg)V- z($Bx1Tj`c?1I3pYg+i_cvFtcQ$SV9%%9QBPg&8R~Ig$eL+xKZY!C=;M1|r)$&9J2x z;l^a*Ph+isNl*%y1T4SviuK1Nco_spQ25v5-}7u?T9zHB5~{-+W*y3p{yjn{1obqf zYL`J^Uz8zZZN8c4Dxy~)k3Ws)E5eYi+V2C!+7Sm0uu{xq)S8o{9uszFTnE>lPhY=5 zdke-B8_*KwWOd%tQs_zf0x9+YixHp+Qi_V$aYVc$P-1mg?2|_{BUr$6WtLdIX2FaF zGmPRTrdIz)DNE)j*_>b9E}sp*(1-16}u za`dgT`KtA3;+e~9{KV48RT=CGPaVt;>-35}%nlFUMK0y7nOjoYds7&Ft~#>0$^ciZ zM}!J5Mz{&|&lyG^bnmh?YtR z*Z5EfDxkrI{QS#Iq752aiA~V)DRlC*2jlA|nCU!@CJwxO#<=j6ssn;muv zhBT9~35VtwsoSLf*(7vl&{u7d_K_CSBMbzr zzyjt&V5O#8VswCRK3AvVbS7U5(KvTPyUc0BhQ}wy0z3LjcdqH8`6F3!`)b3(mOSxL z>i4f8xor(#V+&#ph~ycJMcj#qeehjxt=~Na>dx#Tcq6Xi4?BnDeu5WBBxt603*BY& zZ#;o1kv?qpZjwK-E{8r4v1@g*lwb|8w@oR3BTDcbiGKs)a>Fpxfzh&b ziQANuJ_tNHdx;a*JeCo^RkGC$(TXS;jnxk=dx++D8|dmPP<0@ z$wh#ZYI%Rx$NKe-)BlJzB*bot0ras3I%`#HTMDthGtM_G6u-(tSroGp1Lz+W1Y`$@ zP`9NK^|IHbBrJ#AL3!X*g3{arc@)nuqa{=*2y+DvSwE=f*{>z1HX(>V zNE$>bbc}_yAu4OVn;8LG^naq5HZY zh{Hec==MD+kJhy6t=Nro&+V)RqORK&ssAxioc7-L#UQuPi#3V2pzfh6Ar400@iuV5 z@r>+{-yOZ%XQhsSfw%;|a4}XHaloW#uGluLKux0II9S1W4w=X9J=(k&8KU()m}b{H zFtoD$u5JlGfpX^&SXHlp$J~wk|DL^YVNh2w(oZ~1*W156YRmenU;g=mI zw({B(QVo2JpJ?pJqu9vijk$Cn+%PSw&b4c@uU6vw)DjGm2WJKt!X}uZ43XYlDIz%& z=~RlgZpU-tu_rD`5!t?289PTyQ zZgAEp=zMK>RW9^~gyc*x%vG;l+c-V?}Bm;^{RpgbEnt_B!FqvnvSy)T=R zGa!5GACDk{9801o@j>L8IbKp#!*Td5@vgFKI4w!5?R{>@^hd8ax{l=vQnd2RDHopo zwA+qb2cu4Rx9^Bu1WNYT`a(g}=&&vT`&Sqn-irxzX_j1=tIE#li`Hn=ht4KQXp zzZj`JO+wojs0dRA#(bXBOFn**o+7rPY{bM9m<+UBF{orv$#yF8)AiOWfuas5Fo`CJ zqa;jAZU^!bh8sjE7fsoPn%Tw11+vufr;NMm3*zC=;jB{R49e~BDeMR+H6MGzDlcA^ zKg>JEL~6_6iaR4i`tSfUhkgPaLXZ<@L7poRF?dw_DzodYG{Gp7#24<}=18PBT}aY` z{)rrt`g}930jr3^RBQNA$j!vzTh#Mo1VL`QCA&US?;<2`P+xy8b9D_Hz>FGHC2r$m zW>S9ywTSdQI5hh%7^e`#r#2906T?))i59O(V^Rpxw42rCAu-+I3y#Pg6cm#&AX%dy ze=hv0cUMxxxh1NQEIYXR{IBM&Bk8FK3NZI3z+M>r@A$ocd*e%x-?W;M0pv50p+MVt zugo<@_ij*6RZ;IPtT_sOf2Zv}-3R_1=sW37GgaF9Ti(>V z1L4ju8RzM%&(B}JpnHSVSs2LH#_&@`4Kg1)>*)^i`9-^JiPE@=4l$+?NbAP?44hX&XAZy&?}1;=8c(e0#-3bltVWg6h=k!(mCx=6DqOJ-I!-(g;*f~DDe={{JGtH7=UY|0F zNk(YyXsGi;g%hB8x)QLpp;;`~4rx>zr3?A|W$>xj>^D~%CyzRctVqtiIz7O3pc@r@JdGJiH@%XR_9vaYoV?J3K1cT%g1xOYqhXfSa`fg=bCLy% zWG74UTdouXiH$?H()lyx6QXt}AS)cOa~3IdBxddcQp;(H-O}btpXR-iwZ5E)di9Jf zfToEu%bOR11xf=Knw7JovRJJ#xZDgAvhBDF<8mDu+Q|!}Z?m_=Oy%Ur4p<71cD@0OGZW+{-1QT?U%_PJJ8T!0d2*a9I2;%|A z9LrfBU!r9qh4=3Mm3nR_~X-EyNc<;?m`?dKUNetCnS)}_-%QcWuOpw zAdZF`4c_24z&m{H9-LIL`=Hrx%{IjrNZ~U<7k6p{_wRkR84g>`eUBOQd3x5 zT^kISYq)gGw?IB8(lu1=$#Vl?iZdrx$H0%NxW)?MO$MhRHn8$F^&mzfMCu>|`{)FL z`ZgOt`z%W~^&kzMAuWy9=q~$ldBftH0}T#(K5e8;j~!x$JjyspJ1IISI?ON5OIPB$ z-5_|YUMb+QUsiv3R%Ys4tVYW+x$}dg;hw%EdoH%SXMp`)v?cxR4wic{X9pVBH>=`#`Kcj!}x4 zV!`6tj|*q?jZdG(CSevn(}4Ogij5 z-kp;sZs}7oNu0x+NHs~(aWaKGV@l~TBkmW&mPj==N!f|1e1SndS6(rPxsn7dz$q_{ zL0jSrihO)1t?gh8N zosMjR3n#YC()CVKv zos2TbnL&)lHEIiYdz|%6N^vAUvTs6?s|~kwI4uXjc9fim`KCqW3D838Xu{48p$2?I zOeEqQe1}JUZECrZSO_m=2<$^rB#B6?nrFXFpi8jw)NmoKV^*Utg6i8aEW|^QNJuW& z4cbXpHSp4|7~TW(%JP%q9W2~@&@5Y5%cXL#fMhV59AGj<3$Hhtfa>24DLk{7GZUtr z5ql**-e58|mbz%5Kk~|f!;g+Ze^b);F+5~^jdoq#m+s?Y*+=d5ruym%-Tnn8htCV; zDyyUrWydgDNM&bI{yp<_wd-q&?Ig+BN-^JjWo6Zu3%Eov^Ja>%eKqrk&7kUqeM8PL zs5D}lTe_Yx;e=K`TDya!-u%y$)r*Cr4bSfN*eZk$XT(Lv2Y}qj&_UaiTevxs_=HXjnOuBpmT> zBg|ty8?|1rD1~Ev^6=C$L9%+RkmBSQxlnj3j$XN?%QBstXdx+Vl!N$f2Ey`i3p@!f zzqhI3jC(TZUx|sP%yValu^nzEV96o%*CljO>I_YKa8wMfc3$_L()k4PB6kglP@IT#wBd*3RITYADL}g+hlzLYxFmCt=_XWS}=jg8`RgJefB57z(2n&&q>m ze&F(YMmoRZW7sQ;cZgd(!A9>7mQ2d#!-?$%G8IQ0`p1|*L&P$GnU0i0^(S;Rua4v8 z_7Qhmv#@+kjS-M|($c*ZOo?V2PgT;GKJyP1REABlZhPyf!kR(0UA7Bww~R<7_u6#t z{XNbiKT&tjne(&=UDZ+gNxf&@9EV|fblS^gxNhI-DH;|`1!YNlMcC{d7I{u_E~cJOalFEzDY|I?S3kHtbrN&}R3k zK(Ph_Ty}*L3Et6$cUW`0}**BY@44KtwEy(jW@pAt`>g> z&8>-TmJiDwc;H%Ae%k6$ndZlfKruu1GocgZrLN=sYI52}_I%d)~ z6z40!%W4I6ch$CE2m>Dl3iwWIbcm27QNY#J!}3hqc&~(F8K{^gIT6E&L!APVaQhj^ zjTJEO&?**pivl^xqfD(rpLu;`Tm1MV+Wtd4u>X6u5V{Yp%)xH$k410o{pGoKdtY0t@GgqFN zO=!hTcYoa^dEPKvPX4ukgUTmR#q840gRMMi%{3kvh9gt(wK;Fniqu9A%BMsq?U&B5DFXC8t8FBN1&UIwS#=S zF(6^Eyn8T}p)4)yRvs2rCXZ{L?N6{hgE_dkH_HA#L3a0$@UMoBw6RE9h|k_rx~%rB zUqeEPL|!Pbp|up2Q=8AcUxflck(fPNJYP1OM_4I(bc24a**Qnd-@;Bkb^2z8Xv?;3yZp*| zoy9KhLo=;8n0rPdQ}yAoS8eb zAtG5QYB|~z@Z(Fxdu`LmoO>f&(JzsO|v0V?1HYsfMvF!3| zka=}6U13(l@$9&=1!CLTCMS~L01CMs@Abl4^Q^YgVgizWaJa%{7t)2sVcZg0mh7>d z(tN=$5$r?s={yA@IX~2ot9`ZGjUgVlul$IU4N}{ zIFBzY3O0;g$BZ#X|VjuTPKyw*|IJ+&pQ` z(NpzU`o=D86kZ3E5#!3Ry$#0AW!6wZe)_xZ8EPidvJ0f+MQJZ6|ZJ$CEV6;Yt{OJnL`dewc1k>AGbkK9Gf5BbB-fg? zgC4#CPYX+9%LLHg@=c;_Vai_~#ksI~)5|9k(W()g6ylc(wP2uSeJ$QLATtq%e#zpT zp^6Y)bV+e_pqIE7#-hURQhfQvIZpMUzD8&-t$esrKJ}4`ZhT|woYi>rP~y~LRf`*2!6 z6prDzJ~1VOlYhYAuBHcu9m>k_F>;N3rpLg>pr;{EDkeQPHfPv~woj$?UTF=txmaZy z?RrVthxVcqUM;X*(=UNg4(L|0d250Xk)6GF&DKD@r6{aZo;(}dnO5@CP7pMmdsI)- zeYH*@#+|)L8x7)@GNBu0Npyyh6r z^~!3$x&w8N)T;|LVgnwx1jHmZn{b2V zO|8s#F0NZhvux?0W9NH5;qZ?P_JtPW86)4J>AS{0F1S0d}=L2`{F z_y;o;17%{j4I)znptnB z%No1W>o}H2%?~CFo~0j?pzWk?dV4ayb!s{#>Yj`ZJ!H)xn}*Z_gFHy~JDis)?9-P=z4iOQg{26~n?dTms7)+F}? zcXvnHHnnbNTzc!$t+V}=<2L<7l(84v1I3b;-)F*Q?cwLNlgg{zi#iS)*rQ5AFWe&~ zWHPPGy{8wEC9JSL?qNVY76=es`bA{vUr~L7f9G@mP}2MNF0Qhv6Sgs`r_k!qRbSXK zv16Qqq`rFM9!4zCrCeiVS~P2e{Pw^A8I?p?NSVR{XfwlQo*wj|Ctqz4X-j+dU7eGkC(2y`(P?FM?P4gKki3Msw#fM6paBq#VNc>T2@``L{DlnnA-_*i10Kre&@-H!Z7gzn9pRF61?^^ z8dJ5kEeVKb%Bly}6NLV}<0(*eZM$QTLcH#+@iWS^>$Of_@Mu1JwM!>&3evymgY6>C_)sK+n|A5G6(3RJz0k>(z2uLdzXeTw)e4*g!h} zn*UvIx-Ozx<3rCF#C`khSv`Y-b&R4gX>d5osr$6jlq^8vi!M$QGx05pJZoY#RGr*J zsJmOhfodAzYQxv-MoU?m_|h^aEwgEHt5h_HMkHwtE+OA03(7{hm1V?AlYAS7G$u5n zO+6?51qo@aQK5#l6pM`kD5OmI28g!J2Z{5kNlSuKl=Yj3QZ|bvVHU}FlM+{QV=<=) z+b|%Q!R)FE z@ycDMSKV2?*XfcAc5@IOrSI&3&aR$|oAD8WNA6O;p~q-J@ll{x`jP<*eEpIYOYnT zer_t=dYw6a0avjQtKN&#n&(KJ5Kr$RXPOp1@Fq#0Of zTXQkq4qQxKWR>x#d{Hyh?6Y)U07;Q$?BTl7mx2bSPY_juXub1 z%-$)NKXzE<%}q>RX25*oeMVjiz&r_z;BrQV-(u>!U>C*OisXNU*UftsrH6vAhTEm@ zoKA`?fZL1sdd!+G@*NNvZa>}37u^x8^T>VH0_6Bx{3@x5NAg&55{2jUE-w3zCJNJi z^IlU=+DJz-9K&4c@7iKj(zlj@%V}27?vYmxo*;!jZVXJMeDg;5T!4Y1rxNV-e$WAu zkk6^Xao8HC=w2hpLvM(!xwo|~$eG6jJj39zyQHf)E+NPJlfspUhzRv&_qr8+Z1`DA zz`EV=A)d=;2&J;eypNx~q&Ir_7e_^xXg(L9>k=X4pxZ3y#-ch$^TN}i>X&uwF%75c(9cjO6`E5 z16vbMYb!lEIM?jxn)^+Ld8*hmEXR4a8TSfqwBg1(@^8$p&#@?iyGd}uhWTVS`Mlpa zGc+kV)K7DJwd46aco@=?iASsx?sDjbHoDVU9=+^tk46|Fxxey1u)_}c1j z^(`5~PU%og1LdSBE5x4N&5&%Nh$sy0oANXwUcGa>@CCMqP`4W$ZPSaykK|giiuMIw zu#j)&VRKWP55I(5K1^cog|iXgaK1Z%wm%T;;M3X`-`TTWaI}NtIZj;CS)S%S(h}qq zRFQ#{m4Qk$7;1i*0PC^|X1@a1pcMq1aiRSCHq+mnfj^FS{oxWs0McCN-lK4>SDp#` z7=Duh)kXC;lr1g3dqogzBBDg6>et<<>m>KO^|bI5X{+eMd^-$2xfoP*&e$vdQc7J% zmFO~OHf7aqlIvg%P`Gu|3n;lKjtRd@;;x#$>_xU(HpZos7?ShZlQSU)bY?qyQM3cHh5twS6^bF8NBKDnJgXHa)? zBYv=GjsZuYC2QFS+jc#uCsaEPEzLSJCL=}SIk9!*2Eo(V*SAUqKw#?um$mUIbqQQb zF1Nn(y?7;gP#@ws$W76>TuGcG=U_f6q2uJq?j#mv7g;llvqu{Yk~Mo>id)jMD7;T> zSB$1!g)QpIf*f}IgmV;!B+3u(ifW%xrD=`RKt*PDC?M5KI)DO`VXw(7X-OMLd3iVU z0CihUN(eNrY;m?vwK{55MU`p1;JDF=6ITN$+!q8W#`iIsN8;W7H?`htf%RS9Lh+KQ z_p_4?qO4#*`t+8l-N|kAKDcOt zoHsqz_oO&n?@4^Mr*4YrkDX44BeS*0zaA1j@*c}{$;jUxRXx1rq7z^*NX6d`DcQ}L z6*cN7e%`2#_J4z8=^GM6>%*i>>X^_0u9qn%0JTUo)c0zIz|7a`%_UnB)-I1cc+ z0}jAK0}jBl|6-2VT759oxBnf%-;7vs>7Mr}0h3^$0`5FAy}2h{ps5%RJA|^~6uCqg zxBMK5bQVD{Aduh1lu4)`Up*&( zCJQ>nafDb#MuhSZ5>YmD@|TcrNv~Q%!tca;tyy8Iy2vu2CeA+AsV^q*Wohg%69XYq zP0ppEDEYJ9>Se&X(v=U#ibxg()m=83pLc*|otbG;`CYZ z*YgsakGO$E$E_$|3bns7`m9ARe%myU3$DE;RoQ<6hR8e;%`pxO1{GXb$cCZl9lVnJ$(c` z``G?|PhXaz`>)rb7jm2#v7=(W?@ zjUhrNndRFMQ}%^^(-nmD&J>}9w@)>l;mhRr@$}|4ueOd?U9ZfO-oi%^n4{#V`i}#f zqh<@f^%~(MnS?Z0xsQI|Fghrby<&{FA+e4a>c(yxFL!Pi#?DW!!YI{OmR{xEC7T7k zS_g*9VWI}d0IvIXx*d5<7$5Vs=2^=ews4qZGmAVyC^9e;wxJ%BmB(F5*&!yyABCtLVGL@`qW>X9K zpv=W~+EszGef=am3LG+#yIq5oLXMnZ_dxSLQ_&bwjC^0e8qN@v!p?7mg02H<9`uaJ zy0GKA&YQV2CxynI3T&J*m!rf4@J*eo235*!cB1zEMQZ%h5>GBF;8r37K0h?@|E*0A zIHUg0y7zm(rFKvJS48W7RJwl!i~<6X2Zw+Fbm9ekev0M;#MS=Y5P(kq^(#q11zsvq zDIppe@xOMnsOIK+5BTFB=cWLalK#{3eE>&7fd11>l2=MpNKjsZT2kmG!jCQh`~Fu0 z9P0ab`$3!r`1yz8>_7DYsO|h$kIsMh__s*^KXv?Z1O8|~sEz?Y{+GDzze^GPjk$E$ zXbA-1gd77#=tn)YKU=;JE?}De0)WrT%H9s3`fn|%YibEdyZov3|MJ>QWS>290eCZj z58i<*>dC9=kz?s$sP_9kK1p>nV3qvbleExyq56|o+oQsb{ZVmuu1n~JG z0sUvo_i4fSM>xRs8rvG$*+~GZof}&ISxn(2JU*K{L<3+b{bBw{68H&Uiup@;fWWl5 zgB?IWMab0LkXK(Hz#yq>scZbd2%=B?DO~^q9tarlzZysN+g}n0+v);JhbjUT8AYrt z3?;0r%p9zLJv1r$%q&HKF@;3~0wVwO!U5m;J`Mm|`Nc^80sZd+Wj}21*SPoF82hCF zoK?Vw;4ioafdAkZxT1er-LLVi-*0`@2Ur&*!b?0U>R;no+S%)xoBuBxRw$?weN-u~tKE}8xb@7Gs%(aC;e1-LIlSfXDK(faFW)mnHdrLc3`F z6ZBsT^u0uVS&il=>YVX^*5`k!P4g1)2LQmz{?&dgf`7JrA4ZeE0sikL`k!Eb6r=g0 z{aCy_0I>fxSAXQYz3lw5G|ivg^L@(x-uch!AphH+d;E4`175`R0#b^)Zp>EM1Ks=zx6_261>!7 z{7F#a{Tl@Tpw9S`>7_i|PbScS-(dPJv9_0-FBP_aa@Gg^2IoKNZM~#=sW$SH3MJ|{ zsQy8F43lX7hYx<{v^Q9`2QsMzeen3cGpiTgzVp- z`aj3&Wv0(he1qKI!2jpGpO-i0Wpcz%vdn`2o9x&3;^nsZPt3c \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# 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"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +75,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +105,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -110,10 +125,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +170,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/build/gradlew.bat b/gradlew.bat similarity index 73% rename from build/gradlew.bat rename to gradlew.bat index 8a0b282..9618d8d 100644 --- a/build/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@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 @@ -8,14 +24,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@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= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@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 @@ -46,10 +62,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +75,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..09bbb51 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,2 @@ +before_install: + - ./gradlew setupCIWorkspace \ No newline at end of file diff --git a/repositories.gradle b/repositories.gradle new file mode 100644 index 0000000..f7d641b --- /dev/null +++ b/repositories.gradle @@ -0,0 +1,5 @@ +// Add any additional repositiroes for your dependencies here + +repositories { + +} diff --git a/src/codechicken/lib/world/ChunkExtension.java b/src/codechicken/lib/world/ChunkExtension.java deleted file mode 100644 index c3f17b7..0000000 --- a/src/codechicken/lib/world/ChunkExtension.java +++ /dev/null @@ -1,85 +0,0 @@ -package codechicken.lib.world; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.Packet; -import net.minecraft.world.ChunkCoordIntPair; -import net.minecraft.world.chunk.Chunk; - -import java.util.HashSet; - -public abstract class ChunkExtension -{ - public final Chunk chunk; - public final ChunkCoordIntPair coord; - public final WorldExtension world; - public HashSet watchedPlayers; - - public ChunkExtension(Chunk chunk, WorldExtension world) - { - this.chunk = chunk; - coord = chunk.getChunkCoordIntPair(); - this.world = world; - watchedPlayers = new HashSet(); - } - - public void loadData(NBTTagCompound tag) - { - } - - public void saveData(NBTTagCompound tag) - { - } - - public void load() - { - } - - public void unload() - { - } - - public final void sendPacketToPlayers(Packet packet) - { - for(EntityPlayerMP player : watchedPlayers) - player.playerNetServerHandler.sendPacket(packet); - } - - public final void watchPlayer(EntityPlayerMP player) - { - watchedPlayers.add(player); - onWatchPlayer(player); - } - - public void onWatchPlayer(EntityPlayerMP player) - { - } - - public final void unwatchPlayer(EntityPlayerMP player) - { - watchedPlayers.remove(player); - onUnWatchPlayer(player); - } - - public void onUnWatchPlayer(EntityPlayerMP player) - { - } - - public void sendUpdatePackets() - { - } - - @Override - public int hashCode() - { - return coord.chunkXPos ^ coord.chunkZPos; - } - - @Override - public boolean equals(Object o) - { - return (o instanceof ChunkExtension && ((ChunkExtension)o).coord.equals(coord)) || - (o instanceof ChunkCoordIntPair && coord.equals(o)) || - (o instanceof Long && (Long)o == (((long)coord.chunkXPos)<<32 | coord.chunkZPos)); - } -} diff --git a/src/codechicken/lib/world/IChunkLoadTile.java b/src/codechicken/lib/world/IChunkLoadTile.java deleted file mode 100644 index 5739102..0000000 --- a/src/codechicken/lib/world/IChunkLoadTile.java +++ /dev/null @@ -1,12 +0,0 @@ -package codechicken.lib.world; - -/** - * Provides a callback for tile entities when a chunk is loaded, as an alternative to validate when the chunk hasn't been added to the world. - * To hook all world join/seperate events. Use this, TileEntity.validate with a worldObj.blockExists check, TileEntity.onChunkUnload and TileEntity.invalidate - * Be sure to call TileChunkLoadHook.init() from your mod during initialisation - * You could easily implement this in your own mod, but providing it here reduces the number of times the chunkTileEntityMap needs to be iterated - */ -public interface IChunkLoadTile -{ - public void onChunkLoad(); -} diff --git a/src/codechicken/lib/world/TileChunkLoadHook.java b/src/codechicken/lib/world/TileChunkLoadHook.java deleted file mode 100644 index e080c2e..0000000 --- a/src/codechicken/lib/world/TileChunkLoadHook.java +++ /dev/null @@ -1,28 +0,0 @@ -package codechicken.lib.world; - -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import net.minecraft.tileentity.TileEntity; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.ChunkEvent; - -import java.util.ArrayList; -import java.util.List; - -public class TileChunkLoadHook -{ - private static boolean init; - public static void init() { - if(init) return; - init = true; - - MinecraftForge.EVENT_BUS.register(new TileChunkLoadHook()); - } - - @SubscribeEvent - public void onChunkLoad(ChunkEvent.Load event) { - List list = new ArrayList(event.getChunk().chunkTileEntityMap.values()); - for(TileEntity t : list) - if(t instanceof IChunkLoadTile) - ((IChunkLoadTile)t).onChunkLoad(); - } -} diff --git a/src/codechicken/lib/world/WorldExtension.java b/src/codechicken/lib/world/WorldExtension.java deleted file mode 100644 index 3015f93..0000000 --- a/src/codechicken/lib/world/WorldExtension.java +++ /dev/null @@ -1,99 +0,0 @@ -package codechicken.lib.world; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; - -import java.util.HashMap; - -public abstract class WorldExtension -{ - public final World world; - public HashMap chunkMap = new HashMap(); - - public WorldExtension(World world) - { - this.world = world; - } - - public void load() - { - } - - public void unload() - { - } - - public void save() - { - } - - public void preTick() - { - } - - public void postTick() - { - } - - protected final void addChunk(ChunkExtension extension) - { - chunkMap.put(extension.chunk, extension); - } - - protected final void loadChunk(Chunk chunk) - { - chunkMap.get(chunk).load(); - } - - protected final void unloadChunk(Chunk chunk) - { - chunkMap.get(chunk).unload(); - } - - protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) - { - chunkMap.get(chunk).loadData(tag); - } - - protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) - { - chunkMap.get(chunk).saveData(tag); - } - - protected final void remChunk(Chunk chunk) - { - chunkMap.remove(chunk); - } - - protected final void watchChunk(Chunk chunk, EntityPlayerMP player) - { - chunkMap.get(chunk).watchPlayer(player); - } - - protected final void unwatchChunk(Chunk chunk, EntityPlayerMP player) - { - ChunkExtension extension = chunkMap.get(chunk); - if(extension != null) - extension.unwatchPlayer(player); - } - - protected final void sendChunkUpdates(Chunk chunk) - { - chunkMap.get(chunk).sendUpdatePackets(); - } - - public boolean containsChunk(Chunk chunk) - { - return chunkMap.containsKey(chunk); - } - - public ChunkExtension getChunkExtension(int chunkXPos, int chunkZPos) - { - if(!world.blockExists(chunkXPos<<4, 128, chunkZPos<<4)) - return null; - - return chunkMap.get(world.getChunkFromChunkCoords(chunkXPos, chunkZPos)); - } -} diff --git a/src/codechicken/lib/world/WorldExtensionInstantiator.java b/src/codechicken/lib/world/WorldExtensionInstantiator.java deleted file mode 100644 index 23431b0..0000000 --- a/src/codechicken/lib/world/WorldExtensionInstantiator.java +++ /dev/null @@ -1,17 +0,0 @@ -package codechicken.lib.world; - -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; - -public abstract class WorldExtensionInstantiator -{ - public int instantiatorID; - - public abstract WorldExtension createWorldExtension(World world); - public abstract ChunkExtension createChunkExtension(Chunk chunk, WorldExtension world); - - public WorldExtension getExtension(World world) - { - return WorldExtensionManager.getWorldExtension(world, instantiatorID); - } -} diff --git a/src/codechicken/lib/world/WorldExtensionManager.java b/src/codechicken/lib/world/WorldExtensionManager.java deleted file mode 100644 index b8ec2b4..0000000 --- a/src/codechicken/lib/world/WorldExtensionManager.java +++ /dev/null @@ -1,201 +0,0 @@ -package codechicken.lib.world; - -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.TickEvent; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.Minecraft; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.EmptyChunk; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.world.ChunkDataEvent; -import net.minecraftforge.event.world.ChunkEvent; -import net.minecraftforge.event.world.ChunkWatchEvent.UnWatch; -import net.minecraftforge.event.world.ChunkWatchEvent.Watch; -import net.minecraftforge.event.world.WorldEvent; - -import java.util.ArrayList; -import java.util.HashMap; - -public class WorldExtensionManager -{ - public static class WorldExtensionEventHandler - { - @SubscribeEvent - public void onChunkDataLoad(ChunkDataEvent.Load event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - - createChunkExtension(event.world, event.getChunk()); - - for(WorldExtension extension : worldMap.get(event.world)) - extension.loadChunkData(event.getChunk(), event.getData()); - } - - @SubscribeEvent - public void onChunkDataSave(ChunkDataEvent.Save event) - { - for(WorldExtension extension : worldMap.get(event.world)) - extension.saveChunkData(event.getChunk(), event.getData()); - - if(!event.getChunk().isChunkLoaded) - removeChunk(event.world, event.getChunk()); - } - - @SubscribeEvent - public void onChunkLoad(ChunkEvent.Load event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - - createChunkExtension(event.world, event.getChunk()); - - for(WorldExtension extension : worldMap.get(event.world)) - extension.loadChunk(event.getChunk()); - } - - @SubscribeEvent - public void onChunkUnLoad(ChunkEvent.Unload event) - { - if(event.getChunk() instanceof EmptyChunk) - return; - - for(WorldExtension extension : worldMap.get(event.world)) - extension.unloadChunk(event.getChunk()); - - if(event.world.isRemote) - removeChunk(event.world, event.getChunk()); - } - - @SubscribeEvent - public void onWorldSave(WorldEvent.Save event) - { - if(worldMap.containsKey(event.world)) - for(WorldExtension extension : worldMap.get(event.world)) - extension.save(); - } - - @SubscribeEvent - public void onWorldLoad(WorldEvent.Load event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - } - - @SubscribeEvent - public void onWorldUnLoad(WorldEvent.Unload event) - { - if(worldMap.containsKey(event.world))//because force closing unloads a world twice - for(WorldExtension extension : worldMap.remove(event.world)) - extension.unload(); - } - - @SubscribeEvent - public void onChunkWatch(Watch event) - { - Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); - for(WorldExtension extension : worldMap.get(event.player.worldObj)) - extension.watchChunk(chunk, event.player); - } - - @SubscribeEvent - @SideOnly(Side.CLIENT) - public void onChunkUnWatch(UnWatch event) - { - Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); - for(WorldExtension extension : worldMap.get(event.player.worldObj)) - extension.unwatchChunk(chunk, event.player); - } - - @SubscribeEvent - @SideOnly(Side.CLIENT) - public void clientTick(TickEvent.ClientTickEvent event) - { - World world = Minecraft.getMinecraft().theWorld; - if (worldMap.containsKey(world)) - if (event.phase == TickEvent.Phase.START) - preTick(world); - else - postTick(world); - } - - @SubscribeEvent - public void serverTick(TickEvent.WorldTickEvent event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - - if(event.phase == TickEvent.Phase.START) - preTick(event.world); - else - postTick(event.world); - } - } - - private static boolean initialised; - private static ArrayList extensionIntialisers = new ArrayList(); - - public static void registerWorldExtension(WorldExtensionInstantiator init) - { - if(!initialised) - init(); - - init.instantiatorID = extensionIntialisers.size(); - extensionIntialisers.add(init); - } - - private static void init() - { - initialised = true; - MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); - FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); - } - - private static HashMap worldMap = new HashMap(); - - private static void onWorldLoad(World world) - { - WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()]; - for(int i = 0; i < extensions.length; i++) - extensions[i] = extensionIntialisers.get(i).createWorldExtension(world); - - worldMap.put(world, extensions); - - for(WorldExtension extension : extensions) - extension.load(); - } - - private static void createChunkExtension(World world, Chunk chunk) - { - WorldExtension[] extensions = worldMap.get(world); - for(int i = 0; i < extensionIntialisers.size(); i++) - if(!extensions[i].containsChunk(chunk)) - extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); - } - - private static void removeChunk(World world, Chunk chunk) - { - for(WorldExtension extension : worldMap.get(world)) - extension.remChunk(chunk); - } - - private static void preTick(World world) - { - for(WorldExtension extension : worldMap.get(world)) - extension.preTick(); - } - - private static void postTick(World world) - { - for(WorldExtension extension : worldMap.get(world)) - extension.postTick(); - } - - public static WorldExtension getWorldExtension(World world, int instantiatorID) - { - return worldMap.get(world)[instantiatorID]; - } -} diff --git a/src/codechicken/lib/asm/ASMBlock.java b/src/main/java/codechicken/lib/asm/ASMBlock.java similarity index 100% rename from src/codechicken/lib/asm/ASMBlock.java rename to src/main/java/codechicken/lib/asm/ASMBlock.java diff --git a/src/codechicken/lib/asm/ASMHelper.java b/src/main/java/codechicken/lib/asm/ASMHelper.java similarity index 100% rename from src/codechicken/lib/asm/ASMHelper.java rename to src/main/java/codechicken/lib/asm/ASMHelper.java diff --git a/src/codechicken/lib/asm/ASMInit.java b/src/main/java/codechicken/lib/asm/ASMInit.java similarity index 100% rename from src/codechicken/lib/asm/ASMInit.java rename to src/main/java/codechicken/lib/asm/ASMInit.java diff --git a/src/codechicken/lib/asm/ASMReader.java b/src/main/java/codechicken/lib/asm/ASMReader.java similarity index 100% rename from src/codechicken/lib/asm/ASMReader.java rename to src/main/java/codechicken/lib/asm/ASMReader.java diff --git a/src/codechicken/lib/asm/CC_ClassWriter.java b/src/main/java/codechicken/lib/asm/CC_ClassWriter.java similarity index 100% rename from src/codechicken/lib/asm/CC_ClassWriter.java rename to src/main/java/codechicken/lib/asm/CC_ClassWriter.java diff --git a/src/codechicken/lib/asm/ClassHeirachyManager.java b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java similarity index 100% rename from src/codechicken/lib/asm/ClassHeirachyManager.java rename to src/main/java/codechicken/lib/asm/ClassHeirachyManager.java diff --git a/src/codechicken/lib/asm/ImportantInsnVisitor.java b/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java similarity index 100% rename from src/codechicken/lib/asm/ImportantInsnVisitor.java rename to src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java diff --git a/src/codechicken/lib/asm/InsnComparator.java b/src/main/java/codechicken/lib/asm/InsnComparator.java similarity index 100% rename from src/codechicken/lib/asm/InsnComparator.java rename to src/main/java/codechicken/lib/asm/InsnComparator.java diff --git a/src/codechicken/lib/asm/InsnListSection.java b/src/main/java/codechicken/lib/asm/InsnListSection.java similarity index 100% rename from src/codechicken/lib/asm/InsnListSection.java rename to src/main/java/codechicken/lib/asm/InsnListSection.java diff --git a/src/codechicken/lib/asm/LocalVariablesSorterVisitor.java b/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java similarity index 100% rename from src/codechicken/lib/asm/LocalVariablesSorterVisitor.java rename to src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java diff --git a/src/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java similarity index 100% rename from src/codechicken/lib/asm/ModularASMTransformer.java rename to src/main/java/codechicken/lib/asm/ModularASMTransformer.java diff --git a/src/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java similarity index 100% rename from src/codechicken/lib/asm/ObfMapping.java rename to src/main/java/codechicken/lib/asm/ObfMapping.java diff --git a/src/codechicken/lib/colour/Colour.java b/src/main/java/codechicken/lib/colour/Colour.java similarity index 100% rename from src/codechicken/lib/colour/Colour.java rename to src/main/java/codechicken/lib/colour/Colour.java diff --git a/src/codechicken/lib/colour/ColourARGB.java b/src/main/java/codechicken/lib/colour/ColourARGB.java similarity index 100% rename from src/codechicken/lib/colour/ColourARGB.java rename to src/main/java/codechicken/lib/colour/ColourARGB.java diff --git a/src/codechicken/lib/colour/ColourRGBA.java b/src/main/java/codechicken/lib/colour/ColourRGBA.java similarity index 100% rename from src/codechicken/lib/colour/ColourRGBA.java rename to src/main/java/codechicken/lib/colour/ColourRGBA.java diff --git a/src/codechicken/lib/colour/CustomGradient.java b/src/main/java/codechicken/lib/colour/CustomGradient.java similarity index 100% rename from src/codechicken/lib/colour/CustomGradient.java rename to src/main/java/codechicken/lib/colour/CustomGradient.java diff --git a/src/codechicken/lib/config/ConfigFile.java b/src/main/java/codechicken/lib/config/ConfigFile.java similarity index 100% rename from src/codechicken/lib/config/ConfigFile.java rename to src/main/java/codechicken/lib/config/ConfigFile.java diff --git a/src/codechicken/lib/config/ConfigTag.java b/src/main/java/codechicken/lib/config/ConfigTag.java similarity index 100% rename from src/codechicken/lib/config/ConfigTag.java rename to src/main/java/codechicken/lib/config/ConfigTag.java diff --git a/src/codechicken/lib/config/ConfigTagParent.java b/src/main/java/codechicken/lib/config/ConfigTagParent.java similarity index 100% rename from src/codechicken/lib/config/ConfigTagParent.java rename to src/main/java/codechicken/lib/config/ConfigTagParent.java diff --git a/src/codechicken/lib/config/DefaultingConfigFile.java b/src/main/java/codechicken/lib/config/DefaultingConfigFile.java similarity index 100% rename from src/codechicken/lib/config/DefaultingConfigFile.java rename to src/main/java/codechicken/lib/config/DefaultingConfigFile.java diff --git a/src/codechicken/lib/config/SimpleProperties.java b/src/main/java/codechicken/lib/config/SimpleProperties.java similarity index 100% rename from src/codechicken/lib/config/SimpleProperties.java rename to src/main/java/codechicken/lib/config/SimpleProperties.java diff --git a/src/codechicken/lib/data/MCDataInput.java b/src/main/java/codechicken/lib/data/MCDataInput.java similarity index 100% rename from src/codechicken/lib/data/MCDataInput.java rename to src/main/java/codechicken/lib/data/MCDataInput.java diff --git a/src/codechicken/lib/data/MCDataInputStream.java b/src/main/java/codechicken/lib/data/MCDataInputStream.java similarity index 100% rename from src/codechicken/lib/data/MCDataInputStream.java rename to src/main/java/codechicken/lib/data/MCDataInputStream.java diff --git a/src/codechicken/lib/data/MCDataOutput.java b/src/main/java/codechicken/lib/data/MCDataOutput.java similarity index 100% rename from src/codechicken/lib/data/MCDataOutput.java rename to src/main/java/codechicken/lib/data/MCDataOutput.java diff --git a/src/codechicken/lib/data/MCDataOutputStream.java b/src/main/java/codechicken/lib/data/MCDataOutputStream.java similarity index 100% rename from src/codechicken/lib/data/MCDataOutputStream.java rename to src/main/java/codechicken/lib/data/MCDataOutputStream.java diff --git a/src/codechicken/lib/data/MCDataOutputWrapper.java b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java similarity index 100% rename from src/codechicken/lib/data/MCDataOutputWrapper.java rename to src/main/java/codechicken/lib/data/MCDataOutputWrapper.java diff --git a/src/codechicken/lib/gui/Canvas9Seg.java b/src/main/java/codechicken/lib/gui/Canvas9Seg.java similarity index 100% rename from src/codechicken/lib/gui/Canvas9Seg.java rename to src/main/java/codechicken/lib/gui/Canvas9Seg.java diff --git a/src/codechicken/lib/gui/GuiDraw.java b/src/main/java/codechicken/lib/gui/GuiDraw.java similarity index 100% rename from src/codechicken/lib/gui/GuiDraw.java rename to src/main/java/codechicken/lib/gui/GuiDraw.java diff --git a/src/codechicken/lib/inventory/ContainerExtended.java b/src/main/java/codechicken/lib/inventory/ContainerExtended.java similarity index 100% rename from src/codechicken/lib/inventory/ContainerExtended.java rename to src/main/java/codechicken/lib/inventory/ContainerExtended.java diff --git a/src/codechicken/lib/inventory/ContainerSynchronised.java b/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java similarity index 100% rename from src/codechicken/lib/inventory/ContainerSynchronised.java rename to src/main/java/codechicken/lib/inventory/ContainerSynchronised.java diff --git a/src/codechicken/lib/inventory/IContainerSyncVar.java b/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java similarity index 100% rename from src/codechicken/lib/inventory/IContainerSyncVar.java rename to src/main/java/codechicken/lib/inventory/IContainerSyncVar.java diff --git a/src/codechicken/lib/inventory/IntegerSync.java b/src/main/java/codechicken/lib/inventory/IntegerSync.java similarity index 100% rename from src/codechicken/lib/inventory/IntegerSync.java rename to src/main/java/codechicken/lib/inventory/IntegerSync.java diff --git a/src/codechicken/lib/inventory/InventoryCopy.java b/src/main/java/codechicken/lib/inventory/InventoryCopy.java similarity index 100% rename from src/codechicken/lib/inventory/InventoryCopy.java rename to src/main/java/codechicken/lib/inventory/InventoryCopy.java diff --git a/src/codechicken/lib/inventory/InventoryNBT.java b/src/main/java/codechicken/lib/inventory/InventoryNBT.java similarity index 100% rename from src/codechicken/lib/inventory/InventoryNBT.java rename to src/main/java/codechicken/lib/inventory/InventoryNBT.java diff --git a/src/codechicken/lib/inventory/InventoryRange.java b/src/main/java/codechicken/lib/inventory/InventoryRange.java similarity index 100% rename from src/codechicken/lib/inventory/InventoryRange.java rename to src/main/java/codechicken/lib/inventory/InventoryRange.java diff --git a/src/codechicken/lib/inventory/InventorySimple.java b/src/main/java/codechicken/lib/inventory/InventorySimple.java similarity index 100% rename from src/codechicken/lib/inventory/InventorySimple.java rename to src/main/java/codechicken/lib/inventory/InventorySimple.java diff --git a/src/codechicken/lib/inventory/InventoryUtils.java b/src/main/java/codechicken/lib/inventory/InventoryUtils.java similarity index 100% rename from src/codechicken/lib/inventory/InventoryUtils.java rename to src/main/java/codechicken/lib/inventory/InventoryUtils.java diff --git a/src/codechicken/lib/inventory/ItemKey.java b/src/main/java/codechicken/lib/inventory/ItemKey.java similarity index 100% rename from src/codechicken/lib/inventory/ItemKey.java rename to src/main/java/codechicken/lib/inventory/ItemKey.java diff --git a/src/codechicken/lib/inventory/SlotDummy.java b/src/main/java/codechicken/lib/inventory/SlotDummy.java similarity index 100% rename from src/codechicken/lib/inventory/SlotDummy.java rename to src/main/java/codechicken/lib/inventory/SlotDummy.java diff --git a/src/codechicken/lib/inventory/SlotDummyOutput.java b/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java similarity index 100% rename from src/codechicken/lib/inventory/SlotDummyOutput.java rename to src/main/java/codechicken/lib/inventory/SlotDummyOutput.java diff --git a/src/codechicken/lib/inventory/SlotHandleClicks.java b/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java similarity index 100% rename from src/codechicken/lib/inventory/SlotHandleClicks.java rename to src/main/java/codechicken/lib/inventory/SlotHandleClicks.java diff --git a/src/codechicken/lib/lighting/LC.java b/src/main/java/codechicken/lib/lighting/LC.java similarity index 100% rename from src/codechicken/lib/lighting/LC.java rename to src/main/java/codechicken/lib/lighting/LC.java diff --git a/src/codechicken/lib/lighting/LightMatrix.java b/src/main/java/codechicken/lib/lighting/LightMatrix.java similarity index 100% rename from src/codechicken/lib/lighting/LightMatrix.java rename to src/main/java/codechicken/lib/lighting/LightMatrix.java diff --git a/src/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java similarity index 100% rename from src/codechicken/lib/lighting/LightModel.java rename to src/main/java/codechicken/lib/lighting/LightModel.java diff --git a/src/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java similarity index 100% rename from src/codechicken/lib/lighting/PlanarLightMatrix.java rename to src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java diff --git a/src/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java similarity index 100% rename from src/codechicken/lib/lighting/PlanarLightModel.java rename to src/main/java/codechicken/lib/lighting/PlanarLightModel.java diff --git a/src/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java similarity index 100% rename from src/codechicken/lib/lighting/SimpleBrightnessModel.java rename to src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java diff --git a/src/codechicken/lib/math/MathHelper.java b/src/main/java/codechicken/lib/math/MathHelper.java similarity index 100% rename from src/codechicken/lib/math/MathHelper.java rename to src/main/java/codechicken/lib/math/MathHelper.java diff --git a/src/codechicken/lib/packet/ICustomPacketTile.java b/src/main/java/codechicken/lib/packet/ICustomPacketTile.java similarity index 100% rename from src/codechicken/lib/packet/ICustomPacketTile.java rename to src/main/java/codechicken/lib/packet/ICustomPacketTile.java diff --git a/src/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java similarity index 100% rename from src/codechicken/lib/packet/PacketCustom.java rename to src/main/java/codechicken/lib/packet/PacketCustom.java diff --git a/src/codechicken/lib/raytracer/ExtendedMOP.java b/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java similarity index 100% rename from src/codechicken/lib/raytracer/ExtendedMOP.java rename to src/main/java/codechicken/lib/raytracer/ExtendedMOP.java diff --git a/src/codechicken/lib/raytracer/IndexedCuboid6.java b/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java similarity index 100% rename from src/codechicken/lib/raytracer/IndexedCuboid6.java rename to src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java diff --git a/src/codechicken/lib/raytracer/RayTracer.java b/src/main/java/codechicken/lib/raytracer/RayTracer.java similarity index 100% rename from src/codechicken/lib/raytracer/RayTracer.java rename to src/main/java/codechicken/lib/raytracer/RayTracer.java diff --git a/src/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java similarity index 100% rename from src/codechicken/lib/render/BlockRenderer.java rename to src/main/java/codechicken/lib/render/BlockRenderer.java diff --git a/src/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java similarity index 100% rename from src/codechicken/lib/render/CCModel.java rename to src/main/java/codechicken/lib/render/CCModel.java diff --git a/src/codechicken/lib/render/CCModelLibrary.java b/src/main/java/codechicken/lib/render/CCModelLibrary.java similarity index 100% rename from src/codechicken/lib/render/CCModelLibrary.java rename to src/main/java/codechicken/lib/render/CCModelLibrary.java diff --git a/src/codechicken/lib/render/CCRenderPipeline.java b/src/main/java/codechicken/lib/render/CCRenderPipeline.java similarity index 100% rename from src/codechicken/lib/render/CCRenderPipeline.java rename to src/main/java/codechicken/lib/render/CCRenderPipeline.java diff --git a/src/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java similarity index 100% rename from src/codechicken/lib/render/CCRenderState.java rename to src/main/java/codechicken/lib/render/CCRenderState.java diff --git a/src/codechicken/lib/render/ColourMultiplier.java b/src/main/java/codechicken/lib/render/ColourMultiplier.java similarity index 100% rename from src/codechicken/lib/render/ColourMultiplier.java rename to src/main/java/codechicken/lib/render/ColourMultiplier.java diff --git a/src/codechicken/lib/render/EntityDigIconFX.java b/src/main/java/codechicken/lib/render/EntityDigIconFX.java similarity index 100% rename from src/codechicken/lib/render/EntityDigIconFX.java rename to src/main/java/codechicken/lib/render/EntityDigIconFX.java diff --git a/src/codechicken/lib/render/FontUtils.java b/src/main/java/codechicken/lib/render/FontUtils.java similarity index 100% rename from src/codechicken/lib/render/FontUtils.java rename to src/main/java/codechicken/lib/render/FontUtils.java diff --git a/src/codechicken/lib/render/IFaceRenderer.java b/src/main/java/codechicken/lib/render/IFaceRenderer.java similarity index 100% rename from src/codechicken/lib/render/IFaceRenderer.java rename to src/main/java/codechicken/lib/render/IFaceRenderer.java diff --git a/src/codechicken/lib/render/ManagedTextureFX.java b/src/main/java/codechicken/lib/render/ManagedTextureFX.java similarity index 100% rename from src/codechicken/lib/render/ManagedTextureFX.java rename to src/main/java/codechicken/lib/render/ManagedTextureFX.java diff --git a/src/codechicken/lib/render/PlaceholderTexture.java b/src/main/java/codechicken/lib/render/PlaceholderTexture.java similarity index 100% rename from src/codechicken/lib/render/PlaceholderTexture.java rename to src/main/java/codechicken/lib/render/PlaceholderTexture.java diff --git a/src/codechicken/lib/render/QBImporter.java b/src/main/java/codechicken/lib/render/QBImporter.java similarity index 100% rename from src/codechicken/lib/render/QBImporter.java rename to src/main/java/codechicken/lib/render/QBImporter.java diff --git a/src/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java similarity index 100% rename from src/codechicken/lib/render/RenderUtils.java rename to src/main/java/codechicken/lib/render/RenderUtils.java diff --git a/src/codechicken/lib/render/ShaderProgram.java b/src/main/java/codechicken/lib/render/ShaderProgram.java similarity index 100% rename from src/codechicken/lib/render/ShaderProgram.java rename to src/main/java/codechicken/lib/render/ShaderProgram.java diff --git a/src/codechicken/lib/render/SpriteSheetManager.java b/src/main/java/codechicken/lib/render/SpriteSheetManager.java similarity index 100% rename from src/codechicken/lib/render/SpriteSheetManager.java rename to src/main/java/codechicken/lib/render/SpriteSheetManager.java diff --git a/src/codechicken/lib/render/TextureDataHolder.java b/src/main/java/codechicken/lib/render/TextureDataHolder.java similarity index 100% rename from src/codechicken/lib/render/TextureDataHolder.java rename to src/main/java/codechicken/lib/render/TextureDataHolder.java diff --git a/src/codechicken/lib/render/TextureFX.java b/src/main/java/codechicken/lib/render/TextureFX.java similarity index 100% rename from src/codechicken/lib/render/TextureFX.java rename to src/main/java/codechicken/lib/render/TextureFX.java diff --git a/src/codechicken/lib/render/TextureSpecial.java b/src/main/java/codechicken/lib/render/TextureSpecial.java similarity index 100% rename from src/codechicken/lib/render/TextureSpecial.java rename to src/main/java/codechicken/lib/render/TextureSpecial.java diff --git a/src/codechicken/lib/render/TextureUtils.java b/src/main/java/codechicken/lib/render/TextureUtils.java similarity index 100% rename from src/codechicken/lib/render/TextureUtils.java rename to src/main/java/codechicken/lib/render/TextureUtils.java diff --git a/src/codechicken/lib/render/Vertex5.java b/src/main/java/codechicken/lib/render/Vertex5.java similarity index 100% rename from src/codechicken/lib/render/Vertex5.java rename to src/main/java/codechicken/lib/render/Vertex5.java diff --git a/src/codechicken/lib/render/uv/IconTransformation.java b/src/main/java/codechicken/lib/render/uv/IconTransformation.java similarity index 100% rename from src/codechicken/lib/render/uv/IconTransformation.java rename to src/main/java/codechicken/lib/render/uv/IconTransformation.java diff --git a/src/codechicken/lib/render/uv/MultiIconTransformation.java b/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java similarity index 100% rename from src/codechicken/lib/render/uv/MultiIconTransformation.java rename to src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java diff --git a/src/codechicken/lib/render/uv/UV.java b/src/main/java/codechicken/lib/render/uv/UV.java similarity index 100% rename from src/codechicken/lib/render/uv/UV.java rename to src/main/java/codechicken/lib/render/uv/UV.java diff --git a/src/codechicken/lib/render/uv/UVRotation.java b/src/main/java/codechicken/lib/render/uv/UVRotation.java similarity index 100% rename from src/codechicken/lib/render/uv/UVRotation.java rename to src/main/java/codechicken/lib/render/uv/UVRotation.java diff --git a/src/codechicken/lib/render/uv/UVScale.java b/src/main/java/codechicken/lib/render/uv/UVScale.java similarity index 100% rename from src/codechicken/lib/render/uv/UVScale.java rename to src/main/java/codechicken/lib/render/uv/UVScale.java diff --git a/src/codechicken/lib/render/uv/UVTransformation.java b/src/main/java/codechicken/lib/render/uv/UVTransformation.java similarity index 100% rename from src/codechicken/lib/render/uv/UVTransformation.java rename to src/main/java/codechicken/lib/render/uv/UVTransformation.java diff --git a/src/codechicken/lib/render/uv/UVTransformationList.java b/src/main/java/codechicken/lib/render/uv/UVTransformationList.java similarity index 100% rename from src/codechicken/lib/render/uv/UVTransformationList.java rename to src/main/java/codechicken/lib/render/uv/UVTransformationList.java diff --git a/src/codechicken/lib/render/uv/UVTranslation.java b/src/main/java/codechicken/lib/render/uv/UVTranslation.java similarity index 100% rename from src/codechicken/lib/render/uv/UVTranslation.java rename to src/main/java/codechicken/lib/render/uv/UVTranslation.java diff --git a/src/codechicken/lib/tool/LibDownloader.java b/src/main/java/codechicken/lib/tool/LibDownloader.java similarity index 100% rename from src/codechicken/lib/tool/LibDownloader.java rename to src/main/java/codechicken/lib/tool/LibDownloader.java diff --git a/src/codechicken/lib/tool/MCStripTransformer.java b/src/main/java/codechicken/lib/tool/MCStripTransformer.java similarity index 100% rename from src/codechicken/lib/tool/MCStripTransformer.java rename to src/main/java/codechicken/lib/tool/MCStripTransformer.java diff --git a/src/codechicken/lib/tool/Main.java b/src/main/java/codechicken/lib/tool/Main.java similarity index 100% rename from src/codechicken/lib/tool/Main.java rename to src/main/java/codechicken/lib/tool/Main.java diff --git a/src/codechicken/lib/tool/StripClassLoader.java b/src/main/java/codechicken/lib/tool/StripClassLoader.java similarity index 100% rename from src/codechicken/lib/tool/StripClassLoader.java rename to src/main/java/codechicken/lib/tool/StripClassLoader.java diff --git a/src/codechicken/lib/tool/ToolMain.java b/src/main/java/codechicken/lib/tool/ToolMain.java similarity index 100% rename from src/codechicken/lib/tool/ToolMain.java rename to src/main/java/codechicken/lib/tool/ToolMain.java diff --git a/src/codechicken/lib/tool/module/JOptModule.java b/src/main/java/codechicken/lib/tool/module/JOptModule.java similarity index 100% rename from src/codechicken/lib/tool/module/JOptModule.java rename to src/main/java/codechicken/lib/tool/module/JOptModule.java diff --git a/src/codechicken/lib/tool/module/ModuleQBConverter.java b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java similarity index 100% rename from src/codechicken/lib/tool/module/ModuleQBConverter.java rename to src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java diff --git a/src/codechicken/lib/util/Copyable.java b/src/main/java/codechicken/lib/util/Copyable.java similarity index 100% rename from src/codechicken/lib/util/Copyable.java rename to src/main/java/codechicken/lib/util/Copyable.java diff --git a/src/codechicken/lib/util/LangProxy.java b/src/main/java/codechicken/lib/util/LangProxy.java similarity index 100% rename from src/codechicken/lib/util/LangProxy.java rename to src/main/java/codechicken/lib/util/LangProxy.java diff --git a/src/codechicken/lib/vec/AxisCycle.java b/src/main/java/codechicken/lib/vec/AxisCycle.java similarity index 100% rename from src/codechicken/lib/vec/AxisCycle.java rename to src/main/java/codechicken/lib/vec/AxisCycle.java diff --git a/src/codechicken/lib/vec/BlockCoord.java b/src/main/java/codechicken/lib/vec/BlockCoord.java similarity index 100% rename from src/codechicken/lib/vec/BlockCoord.java rename to src/main/java/codechicken/lib/vec/BlockCoord.java diff --git a/src/codechicken/lib/vec/Cuboid6.java b/src/main/java/codechicken/lib/vec/Cuboid6.java similarity index 100% rename from src/codechicken/lib/vec/Cuboid6.java rename to src/main/java/codechicken/lib/vec/Cuboid6.java diff --git a/src/codechicken/lib/vec/CuboidCoord.java b/src/main/java/codechicken/lib/vec/CuboidCoord.java similarity index 100% rename from src/codechicken/lib/vec/CuboidCoord.java rename to src/main/java/codechicken/lib/vec/CuboidCoord.java diff --git a/src/codechicken/lib/vec/ITransformation.java b/src/main/java/codechicken/lib/vec/ITransformation.java similarity index 100% rename from src/codechicken/lib/vec/ITransformation.java rename to src/main/java/codechicken/lib/vec/ITransformation.java diff --git a/src/codechicken/lib/vec/IrreversibleTransformationException.java b/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java similarity index 100% rename from src/codechicken/lib/vec/IrreversibleTransformationException.java rename to src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java diff --git a/src/codechicken/lib/vec/Line3.java b/src/main/java/codechicken/lib/vec/Line3.java similarity index 100% rename from src/codechicken/lib/vec/Line3.java rename to src/main/java/codechicken/lib/vec/Line3.java diff --git a/src/codechicken/lib/vec/Matrix4.java b/src/main/java/codechicken/lib/vec/Matrix4.java similarity index 100% rename from src/codechicken/lib/vec/Matrix4.java rename to src/main/java/codechicken/lib/vec/Matrix4.java diff --git a/src/codechicken/lib/vec/Quat.java b/src/main/java/codechicken/lib/vec/Quat.java similarity index 100% rename from src/codechicken/lib/vec/Quat.java rename to src/main/java/codechicken/lib/vec/Quat.java diff --git a/src/codechicken/lib/vec/Rectangle4i.java b/src/main/java/codechicken/lib/vec/Rectangle4i.java similarity index 100% rename from src/codechicken/lib/vec/Rectangle4i.java rename to src/main/java/codechicken/lib/vec/Rectangle4i.java diff --git a/src/codechicken/lib/vec/RedundantTransformation.java b/src/main/java/codechicken/lib/vec/RedundantTransformation.java similarity index 100% rename from src/codechicken/lib/vec/RedundantTransformation.java rename to src/main/java/codechicken/lib/vec/RedundantTransformation.java diff --git a/src/codechicken/lib/vec/Rotation.java b/src/main/java/codechicken/lib/vec/Rotation.java similarity index 100% rename from src/codechicken/lib/vec/Rotation.java rename to src/main/java/codechicken/lib/vec/Rotation.java diff --git a/src/codechicken/lib/vec/Scale.java b/src/main/java/codechicken/lib/vec/Scale.java similarity index 100% rename from src/codechicken/lib/vec/Scale.java rename to src/main/java/codechicken/lib/vec/Scale.java diff --git a/src/codechicken/lib/vec/SwapYZ.java b/src/main/java/codechicken/lib/vec/SwapYZ.java similarity index 100% rename from src/codechicken/lib/vec/SwapYZ.java rename to src/main/java/codechicken/lib/vec/SwapYZ.java diff --git a/src/codechicken/lib/vec/Transformation.java b/src/main/java/codechicken/lib/vec/Transformation.java similarity index 100% rename from src/codechicken/lib/vec/Transformation.java rename to src/main/java/codechicken/lib/vec/Transformation.java diff --git a/src/codechicken/lib/vec/TransformationList.java b/src/main/java/codechicken/lib/vec/TransformationList.java similarity index 100% rename from src/codechicken/lib/vec/TransformationList.java rename to src/main/java/codechicken/lib/vec/TransformationList.java diff --git a/src/codechicken/lib/vec/Translation.java b/src/main/java/codechicken/lib/vec/Translation.java similarity index 100% rename from src/codechicken/lib/vec/Translation.java rename to src/main/java/codechicken/lib/vec/Translation.java diff --git a/src/codechicken/lib/vec/VariableTransformation.java b/src/main/java/codechicken/lib/vec/VariableTransformation.java similarity index 100% rename from src/codechicken/lib/vec/VariableTransformation.java rename to src/main/java/codechicken/lib/vec/VariableTransformation.java diff --git a/src/codechicken/lib/vec/Vector3.java b/src/main/java/codechicken/lib/vec/Vector3.java similarity index 100% rename from src/codechicken/lib/vec/Vector3.java rename to src/main/java/codechicken/lib/vec/Vector3.java diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..0942acd --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ + { + "modid": "${modId}", + "name": "${modName}", + "description": "This is a library of systems to help make various aspects of minecraft modding easier. It contains libraries for 3D math and transformations, model rendering, packets, config, colours, asm and a few other things.", + "version": "${modVersion}", + "mcversion": "${minecraftVersion}", + "url": "https://github.com/GTNewHorizons/CodeChickenLib", + "updateUrl": "", + "authorList": [ "Chicken-Bones", "GTNH-Team" ], + "credits": "", + "logoFile": "galacticraft_logo.png", + "screenshots": [], + "parent":"" + }, +] From 8fe333ed86042fae09a9417c33a503f61d499712 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 14:05:10 +0100 Subject: [PATCH 123/219] Fix gitignore --- .gitignore | 1 - .../codechicken/lib/world/ChunkExtension.java | 85 ++++++++ .../codechicken/lib/world/IChunkLoadTile.java | 12 ++ .../lib/world/TileChunkLoadHook.java | 28 +++ .../codechicken/lib/world/WorldExtension.java | 99 +++++++++ .../lib/world/WorldExtensionInstantiator.java | 17 ++ .../lib/world/WorldExtensionManager.java | 201 ++++++++++++++++++ 7 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 src/main/java/codechicken/lib/world/ChunkExtension.java create mode 100644 src/main/java/codechicken/lib/world/IChunkLoadTile.java create mode 100644 src/main/java/codechicken/lib/world/TileChunkLoadHook.java create mode 100644 src/main/java/codechicken/lib/world/WorldExtension.java create mode 100644 src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java create mode 100644 src/main/java/codechicken/lib/world/WorldExtensionManager.java diff --git a/.gitignore b/.gitignore index 4a0ea1e..558ad12 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ server.properties servers.dat usercache.json whitelist.json -world/ /out/ *.iml *.ipr diff --git a/src/main/java/codechicken/lib/world/ChunkExtension.java b/src/main/java/codechicken/lib/world/ChunkExtension.java new file mode 100644 index 0000000..c3f17b7 --- /dev/null +++ b/src/main/java/codechicken/lib/world/ChunkExtension.java @@ -0,0 +1,85 @@ +package codechicken.lib.world; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.Packet; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.chunk.Chunk; + +import java.util.HashSet; + +public abstract class ChunkExtension +{ + public final Chunk chunk; + public final ChunkCoordIntPair coord; + public final WorldExtension world; + public HashSet watchedPlayers; + + public ChunkExtension(Chunk chunk, WorldExtension world) + { + this.chunk = chunk; + coord = chunk.getChunkCoordIntPair(); + this.world = world; + watchedPlayers = new HashSet(); + } + + public void loadData(NBTTagCompound tag) + { + } + + public void saveData(NBTTagCompound tag) + { + } + + public void load() + { + } + + public void unload() + { + } + + public final void sendPacketToPlayers(Packet packet) + { + for(EntityPlayerMP player : watchedPlayers) + player.playerNetServerHandler.sendPacket(packet); + } + + public final void watchPlayer(EntityPlayerMP player) + { + watchedPlayers.add(player); + onWatchPlayer(player); + } + + public void onWatchPlayer(EntityPlayerMP player) + { + } + + public final void unwatchPlayer(EntityPlayerMP player) + { + watchedPlayers.remove(player); + onUnWatchPlayer(player); + } + + public void onUnWatchPlayer(EntityPlayerMP player) + { + } + + public void sendUpdatePackets() + { + } + + @Override + public int hashCode() + { + return coord.chunkXPos ^ coord.chunkZPos; + } + + @Override + public boolean equals(Object o) + { + return (o instanceof ChunkExtension && ((ChunkExtension)o).coord.equals(coord)) || + (o instanceof ChunkCoordIntPair && coord.equals(o)) || + (o instanceof Long && (Long)o == (((long)coord.chunkXPos)<<32 | coord.chunkZPos)); + } +} diff --git a/src/main/java/codechicken/lib/world/IChunkLoadTile.java b/src/main/java/codechicken/lib/world/IChunkLoadTile.java new file mode 100644 index 0000000..5739102 --- /dev/null +++ b/src/main/java/codechicken/lib/world/IChunkLoadTile.java @@ -0,0 +1,12 @@ +package codechicken.lib.world; + +/** + * Provides a callback for tile entities when a chunk is loaded, as an alternative to validate when the chunk hasn't been added to the world. + * To hook all world join/seperate events. Use this, TileEntity.validate with a worldObj.blockExists check, TileEntity.onChunkUnload and TileEntity.invalidate + * Be sure to call TileChunkLoadHook.init() from your mod during initialisation + * You could easily implement this in your own mod, but providing it here reduces the number of times the chunkTileEntityMap needs to be iterated + */ +public interface IChunkLoadTile +{ + public void onChunkLoad(); +} diff --git a/src/main/java/codechicken/lib/world/TileChunkLoadHook.java b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java new file mode 100644 index 0000000..e080c2e --- /dev/null +++ b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java @@ -0,0 +1,28 @@ +package codechicken.lib.world; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkEvent; + +import java.util.ArrayList; +import java.util.List; + +public class TileChunkLoadHook +{ + private static boolean init; + public static void init() { + if(init) return; + init = true; + + MinecraftForge.EVENT_BUS.register(new TileChunkLoadHook()); + } + + @SubscribeEvent + public void onChunkLoad(ChunkEvent.Load event) { + List list = new ArrayList(event.getChunk().chunkTileEntityMap.values()); + for(TileEntity t : list) + if(t instanceof IChunkLoadTile) + ((IChunkLoadTile)t).onChunkLoad(); + } +} diff --git a/src/main/java/codechicken/lib/world/WorldExtension.java b/src/main/java/codechicken/lib/world/WorldExtension.java new file mode 100644 index 0000000..3015f93 --- /dev/null +++ b/src/main/java/codechicken/lib/world/WorldExtension.java @@ -0,0 +1,99 @@ +package codechicken.lib.world; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +import java.util.HashMap; + +public abstract class WorldExtension +{ + public final World world; + public HashMap chunkMap = new HashMap(); + + public WorldExtension(World world) + { + this.world = world; + } + + public void load() + { + } + + public void unload() + { + } + + public void save() + { + } + + public void preTick() + { + } + + public void postTick() + { + } + + protected final void addChunk(ChunkExtension extension) + { + chunkMap.put(extension.chunk, extension); + } + + protected final void loadChunk(Chunk chunk) + { + chunkMap.get(chunk).load(); + } + + protected final void unloadChunk(Chunk chunk) + { + chunkMap.get(chunk).unload(); + } + + protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) + { + chunkMap.get(chunk).loadData(tag); + } + + protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) + { + chunkMap.get(chunk).saveData(tag); + } + + protected final void remChunk(Chunk chunk) + { + chunkMap.remove(chunk); + } + + protected final void watchChunk(Chunk chunk, EntityPlayerMP player) + { + chunkMap.get(chunk).watchPlayer(player); + } + + protected final void unwatchChunk(Chunk chunk, EntityPlayerMP player) + { + ChunkExtension extension = chunkMap.get(chunk); + if(extension != null) + extension.unwatchPlayer(player); + } + + protected final void sendChunkUpdates(Chunk chunk) + { + chunkMap.get(chunk).sendUpdatePackets(); + } + + public boolean containsChunk(Chunk chunk) + { + return chunkMap.containsKey(chunk); + } + + public ChunkExtension getChunkExtension(int chunkXPos, int chunkZPos) + { + if(!world.blockExists(chunkXPos<<4, 128, chunkZPos<<4)) + return null; + + return chunkMap.get(world.getChunkFromChunkCoords(chunkXPos, chunkZPos)); + } +} diff --git a/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java new file mode 100644 index 0000000..23431b0 --- /dev/null +++ b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java @@ -0,0 +1,17 @@ +package codechicken.lib.world; + +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +public abstract class WorldExtensionInstantiator +{ + public int instantiatorID; + + public abstract WorldExtension createWorldExtension(World world); + public abstract ChunkExtension createChunkExtension(Chunk chunk, WorldExtension world); + + public WorldExtension getExtension(World world) + { + return WorldExtensionManager.getWorldExtension(world, instantiatorID); + } +} diff --git a/src/main/java/codechicken/lib/world/WorldExtensionManager.java b/src/main/java/codechicken/lib/world/WorldExtensionManager.java new file mode 100644 index 0000000..b8ec2b4 --- /dev/null +++ b/src/main/java/codechicken/lib/world/WorldExtensionManager.java @@ -0,0 +1,201 @@ +package codechicken.lib.world; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.EmptyChunk; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.ChunkWatchEvent.UnWatch; +import net.minecraftforge.event.world.ChunkWatchEvent.Watch; +import net.minecraftforge.event.world.WorldEvent; + +import java.util.ArrayList; +import java.util.HashMap; + +public class WorldExtensionManager +{ + public static class WorldExtensionEventHandler + { + @SubscribeEvent + public void onChunkDataLoad(ChunkDataEvent.Load event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + + createChunkExtension(event.world, event.getChunk()); + + for(WorldExtension extension : worldMap.get(event.world)) + extension.loadChunkData(event.getChunk(), event.getData()); + } + + @SubscribeEvent + public void onChunkDataSave(ChunkDataEvent.Save event) + { + for(WorldExtension extension : worldMap.get(event.world)) + extension.saveChunkData(event.getChunk(), event.getData()); + + if(!event.getChunk().isChunkLoaded) + removeChunk(event.world, event.getChunk()); + } + + @SubscribeEvent + public void onChunkLoad(ChunkEvent.Load event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + + createChunkExtension(event.world, event.getChunk()); + + for(WorldExtension extension : worldMap.get(event.world)) + extension.loadChunk(event.getChunk()); + } + + @SubscribeEvent + public void onChunkUnLoad(ChunkEvent.Unload event) + { + if(event.getChunk() instanceof EmptyChunk) + return; + + for(WorldExtension extension : worldMap.get(event.world)) + extension.unloadChunk(event.getChunk()); + + if(event.world.isRemote) + removeChunk(event.world, event.getChunk()); + } + + @SubscribeEvent + public void onWorldSave(WorldEvent.Save event) + { + if(worldMap.containsKey(event.world)) + for(WorldExtension extension : worldMap.get(event.world)) + extension.save(); + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + } + + @SubscribeEvent + public void onWorldUnLoad(WorldEvent.Unload event) + { + if(worldMap.containsKey(event.world))//because force closing unloads a world twice + for(WorldExtension extension : worldMap.remove(event.world)) + extension.unload(); + } + + @SubscribeEvent + public void onChunkWatch(Watch event) + { + Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); + for(WorldExtension extension : worldMap.get(event.player.worldObj)) + extension.watchChunk(chunk, event.player); + } + + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void onChunkUnWatch(UnWatch event) + { + Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); + for(WorldExtension extension : worldMap.get(event.player.worldObj)) + extension.unwatchChunk(chunk, event.player); + } + + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void clientTick(TickEvent.ClientTickEvent event) + { + World world = Minecraft.getMinecraft().theWorld; + if (worldMap.containsKey(world)) + if (event.phase == TickEvent.Phase.START) + preTick(world); + else + postTick(world); + } + + @SubscribeEvent + public void serverTick(TickEvent.WorldTickEvent event) + { + if(!worldMap.containsKey(event.world)) + WorldExtensionManager.onWorldLoad(event.world); + + if(event.phase == TickEvent.Phase.START) + preTick(event.world); + else + postTick(event.world); + } + } + + private static boolean initialised; + private static ArrayList extensionIntialisers = new ArrayList(); + + public static void registerWorldExtension(WorldExtensionInstantiator init) + { + if(!initialised) + init(); + + init.instantiatorID = extensionIntialisers.size(); + extensionIntialisers.add(init); + } + + private static void init() + { + initialised = true; + MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); + FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); + } + + private static HashMap worldMap = new HashMap(); + + private static void onWorldLoad(World world) + { + WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()]; + for(int i = 0; i < extensions.length; i++) + extensions[i] = extensionIntialisers.get(i).createWorldExtension(world); + + worldMap.put(world, extensions); + + for(WorldExtension extension : extensions) + extension.load(); + } + + private static void createChunkExtension(World world, Chunk chunk) + { + WorldExtension[] extensions = worldMap.get(world); + for(int i = 0; i < extensionIntialisers.size(); i++) + if(!extensions[i].containsChunk(chunk)) + extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); + } + + private static void removeChunk(World world, Chunk chunk) + { + for(WorldExtension extension : worldMap.get(world)) + extension.remChunk(chunk); + } + + private static void preTick(World world) + { + for(WorldExtension extension : worldMap.get(world)) + extension.preTick(); + } + + private static void postTick(World world) + { + for(WorldExtension extension : worldMap.get(world)) + extension.postTick(); + } + + public static WorldExtension getWorldExtension(World world, int instantiatorID) + { + return worldMap.get(world)[instantiatorID]; + } +} From 81b0e9f0fdfd39ea14102c628e055cdc2c63ea0a Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 17:32:51 +0100 Subject: [PATCH 124/219] Move to unified build script --- .github/scripts/update-version.sh | 10 + .github/workflows/buildscript-maintenance.yml | 24 + .github/workflows/package-release.yml | 71 +++ .github/workflows/pull-request.yml | 32 ++ .github/workflows/release.yml | 41 ++ .gitignore | 30 +- build.gradle | 526 ++++++++++++++++++ build/build.gradle | 113 ---- build/build.properties | 4 - build/gradle/wrapper/gradle-wrapper.jar | Bin 51106 -> 0 bytes build/settings.gradle | 19 - dependencies.gradle | 5 + gradle.properties | 60 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55616 bytes .../wrapper/gradle-wrapper.properties | 3 +- build/gradlew => gradlew | 98 ++-- build/gradlew.bat => gradlew.bat | 30 +- jitpack.yml | 2 + repositories.gradle | 7 + .../codechicken/core/CCUpdateChecker.java | 0 .../codechicken/core/ClassDiscoverer.java | 0 .../java}/codechicken/core/ClientUtils.java | 0 .../java}/codechicken/core/CommonUtils.java | 0 .../codechicken/core/GuiModListScroll.java | 0 .../codechicken/core/IGuiPacketSender.java | 0 .../codechicken/core/IStringMatcher.java | 0 .../java}/codechicken/core/ProfileTimer.java | 0 .../codechicken/core/ReflectionManager.java | 0 .../java}/codechicken/core/ServerUtils.java | 0 .../java}/codechicken/core/TaskProfiler.java | 0 .../asm/CodeChickenAccessTransformer.java | 0 .../core/asm/CodeChickenCoreModContainer.java | 0 .../asm/DefaultImplementationTransformer.java | 0 .../core/asm/DelegatedTransformer.java | 0 .../core/asm/DependancyLister.java | 0 .../core/asm/InterfaceDependancies.java | 0 .../asm/InterfaceDependancyTransformer.java | 0 .../core/asm/MCPDeobfuscationTransformer.java | 0 .../codechicken/core/asm/MethodASMifier.java | 0 .../core/asm/TweakTransformer.java | 0 .../core/commands/CoreCommand.java | 0 .../core/commands/PlayerCommand.java | 0 .../core/commands/ServerCommand.java | 0 .../core/featurehack/EntityRenderHook.java | 0 .../core/featurehack/EntityUpdateHook.java | 0 .../core/featurehack/FeatureHack.java | 0 .../core/featurehack/GameDataManipulator.java | 0 .../core/featurehack/LiquidTextures.java | 0 .../featurehack/RenderEntityRenderHook.java | 0 .../core/featurehack/RenderNull.java | 0 .../featurehack/TweakTransformerHelper.java | 0 .../core/featurehack/mc/TextureLavaFX.java | 0 .../featurehack/mc/TextureLavaFlowFX.java | 0 .../core/featurehack/mc/TextureWaterFX.java | 0 .../featurehack/mc/TextureWaterFlowFX.java | 0 .../core/fluid/ExtendedFluidTank.java | 0 .../codechicken/core/fluid/FluidUtils.java | 0 .../codechicken/core/fluid/TankAccess.java | 0 .../codechicken/core/gui/ClickCounter.java | 0 .../codechicken/core/gui/GuiCCButton.java | 0 .../codechicken/core/gui/GuiCCTextField.java | 0 .../codechicken/core/gui/GuiScreenWidget.java | 0 .../codechicken/core/gui/GuiScrollPane.java | 0 .../codechicken/core/gui/GuiScrollSlot.java | 0 .../java}/codechicken/core/gui/GuiWidget.java | 0 .../core/gui/IGuiActionListener.java | 0 .../core/internal/CCCEventHandler.java | 0 .../core/inventory/GuiContainerWidget.java | 0 .../core/launch/CodeChickenCorePlugin.java | 0 .../codechicken/core/launch/DepLoader.java | 0 .../obfuscator/ConstantObfuscator.java | 0 .../obfuscator/DummyOutputStream.java | 0 .../obfuscator/IHeirachyEvaluator.java | 0 .../codechicken/obfuscator/ILogStreams.java | 0 .../codechicken/obfuscator/ObfDirection.java | 0 .../codechicken/obfuscator/ObfRemapper.java | 0 .../obfuscator/ObfuscationMap.java | 0 .../obfuscator/ObfuscationRun.java | 0 .../obfuscator/SystemLogStreams.java | 0 .../assets/codechickencore/asm/tweaks.asm | 0 .../assets/codechickencore/lang/de_DE.lang | 0 .../assets/codechickencore/lang/en_US.lang | 0 .../assets/codechickencore/lang/it_IT.lang | 0 .../assets/codechickencore/lang/ru_RU.lang | 0 {resources => src/main/resources}/cccmod.info | 0 .../main/resources}/dependencies.info | 0 86 files changed, 888 insertions(+), 187 deletions(-) create mode 100644 .github/scripts/update-version.sh create mode 100644 .github/workflows/buildscript-maintenance.yml create mode 100644 .github/workflows/package-release.yml create mode 100644 .github/workflows/pull-request.yml create mode 100644 .github/workflows/release.yml create mode 100644 build.gradle delete mode 100644 build/build.gradle delete mode 100644 build/build.properties delete mode 100644 build/gradle/wrapper/gradle-wrapper.jar delete mode 100644 build/settings.gradle create mode 100644 dependencies.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar rename {build/gradle => gradle}/wrapper/gradle-wrapper.properties (53%) rename build/gradlew => gradlew (72%) rename build/gradlew.bat => gradlew.bat (73%) create mode 100644 jitpack.yml create mode 100644 repositories.gradle rename src/{ => main/java}/codechicken/core/CCUpdateChecker.java (100%) rename src/{ => main/java}/codechicken/core/ClassDiscoverer.java (100%) rename src/{ => main/java}/codechicken/core/ClientUtils.java (100%) rename src/{ => main/java}/codechicken/core/CommonUtils.java (100%) rename src/{ => main/java}/codechicken/core/GuiModListScroll.java (100%) rename src/{ => main/java}/codechicken/core/IGuiPacketSender.java (100%) rename src/{ => main/java}/codechicken/core/IStringMatcher.java (100%) rename src/{ => main/java}/codechicken/core/ProfileTimer.java (100%) rename src/{ => main/java}/codechicken/core/ReflectionManager.java (100%) rename src/{ => main/java}/codechicken/core/ServerUtils.java (100%) rename src/{ => main/java}/codechicken/core/TaskProfiler.java (100%) rename src/{ => main/java}/codechicken/core/asm/CodeChickenAccessTransformer.java (100%) rename src/{ => main/java}/codechicken/core/asm/CodeChickenCoreModContainer.java (100%) rename src/{ => main/java}/codechicken/core/asm/DefaultImplementationTransformer.java (100%) rename src/{ => main/java}/codechicken/core/asm/DelegatedTransformer.java (100%) rename src/{ => main/java}/codechicken/core/asm/DependancyLister.java (100%) rename src/{ => main/java}/codechicken/core/asm/InterfaceDependancies.java (100%) rename src/{ => main/java}/codechicken/core/asm/InterfaceDependancyTransformer.java (100%) rename src/{ => main/java}/codechicken/core/asm/MCPDeobfuscationTransformer.java (100%) rename src/{ => main/java}/codechicken/core/asm/MethodASMifier.java (100%) rename src/{ => main/java}/codechicken/core/asm/TweakTransformer.java (100%) rename src/{ => main/java}/codechicken/core/commands/CoreCommand.java (100%) rename src/{ => main/java}/codechicken/core/commands/PlayerCommand.java (100%) rename src/{ => main/java}/codechicken/core/commands/ServerCommand.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/EntityRenderHook.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/EntityUpdateHook.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/FeatureHack.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/GameDataManipulator.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/LiquidTextures.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/RenderEntityRenderHook.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/RenderNull.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/TweakTransformerHelper.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/mc/TextureLavaFX.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/mc/TextureLavaFlowFX.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/mc/TextureWaterFX.java (100%) rename src/{ => main/java}/codechicken/core/featurehack/mc/TextureWaterFlowFX.java (100%) rename src/{ => main/java}/codechicken/core/fluid/ExtendedFluidTank.java (100%) rename src/{ => main/java}/codechicken/core/fluid/FluidUtils.java (100%) rename src/{ => main/java}/codechicken/core/fluid/TankAccess.java (100%) rename src/{ => main/java}/codechicken/core/gui/ClickCounter.java (100%) rename src/{ => main/java}/codechicken/core/gui/GuiCCButton.java (100%) rename src/{ => main/java}/codechicken/core/gui/GuiCCTextField.java (100%) rename src/{ => main/java}/codechicken/core/gui/GuiScreenWidget.java (100%) rename src/{ => main/java}/codechicken/core/gui/GuiScrollPane.java (100%) rename src/{ => main/java}/codechicken/core/gui/GuiScrollSlot.java (100%) rename src/{ => main/java}/codechicken/core/gui/GuiWidget.java (100%) rename src/{ => main/java}/codechicken/core/gui/IGuiActionListener.java (100%) rename src/{ => main/java}/codechicken/core/internal/CCCEventHandler.java (100%) rename src/{ => main/java}/codechicken/core/inventory/GuiContainerWidget.java (100%) rename src/{ => main/java}/codechicken/core/launch/CodeChickenCorePlugin.java (100%) rename src/{ => main/java}/codechicken/core/launch/DepLoader.java (100%) rename src/{ => main/java}/codechicken/obfuscator/ConstantObfuscator.java (100%) rename src/{ => main/java}/codechicken/obfuscator/DummyOutputStream.java (100%) rename src/{ => main/java}/codechicken/obfuscator/IHeirachyEvaluator.java (100%) rename src/{ => main/java}/codechicken/obfuscator/ILogStreams.java (100%) rename src/{ => main/java}/codechicken/obfuscator/ObfDirection.java (100%) rename src/{ => main/java}/codechicken/obfuscator/ObfRemapper.java (100%) rename src/{ => main/java}/codechicken/obfuscator/ObfuscationMap.java (100%) rename src/{ => main/java}/codechicken/obfuscator/ObfuscationRun.java (100%) rename src/{ => main/java}/codechicken/obfuscator/SystemLogStreams.java (100%) rename {resources => src/main/resources}/assets/codechickencore/asm/tweaks.asm (100%) rename {resources => src/main/resources}/assets/codechickencore/lang/de_DE.lang (100%) rename {resources => src/main/resources}/assets/codechickencore/lang/en_US.lang (100%) rename {resources => src/main/resources}/assets/codechickencore/lang/it_IT.lang (100%) rename {resources => src/main/resources}/assets/codechickencore/lang/ru_RU.lang (100%) rename {resources => src/main/resources}/cccmod.info (100%) rename {resources => src/main/resources}/dependencies.info (100%) diff --git a/.github/scripts/update-version.sh b/.github/scripts/update-version.sh new file mode 100644 index 0000000..6ab1b17 --- /dev/null +++ b/.github/scripts/update-version.sh @@ -0,0 +1,10 @@ +if [ ! -z $(git diff --name-only HEAD HEAD~1 | grep build.gradle) ]; then + new_version="$(git log -n1 --format=format:"%H")" + sed --in-place "s!^//version:.*!//version: $new_version!g" build.gradle + git add build.gradle + git commit -m "[ci skip] update build script version to $new_version" + git push + echo "Updated buildscript version to $new_version"; +else + echo "Ignored buildscript version update: no changes detected" +fi diff --git a/.github/workflows/buildscript-maintenance.yml b/.github/workflows/buildscript-maintenance.yml new file mode 100644 index 0000000..f5128e3 --- /dev/null +++ b/.github/workflows/buildscript-maintenance.yml @@ -0,0 +1,24 @@ +# This workflow only meant for the source mod you shouldn't bring it into your own project + +name: Buildscript maintenance + +on: + push: + branches: [ master, main ] + +jobs: + buildscript-maintenance: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 2 + + - name: setup git config + run: | + git config user.name "GitHub CI Bot" + git config user.email "<>" + + - name: Ensure build script version is up to date + run: .github/scripts/update-version.sh diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml new file mode 100644 index 0000000..363028e --- /dev/null +++ b/.github/workflows/package-release.yml @@ -0,0 +1,71 @@ +# This workflow only meant for the source mod you shouldn't bring it into your own project + +name: Release packages + +on: + push: + branches: [ master, main ] + +jobs: + zip-packages: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Zip starter + uses: montudor/action-zip@v1 + with: + args: > + zip -r starter.zip . \ + \ + -x "*.git/*" \ + \ + -x ".github/scripts/update-version.sh" \ + -x ".github/workflows/buildscript-maintenance.yml" \ + -x ".github/workflows/package-release.yml" \ + \ + -x "*docs/*" \ + -x "README.md" \ + -x "LICENSE" \ + \ + -x "starter.zip" \ + -x "migration.zip" + + - name: Publish starter package + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "latest-stater" + prerelease: true + title: "Latest starter package" + files: "starter.zip" + + - name: Zip migration + uses: montudor/action-zip@v1 + with: + args: > + zip -r migration.zip . \ + \ + -x "*.git/*" \ + \ + -x ".github/scripts/update-version.sh" \ + -x ".github/workflows/buildscript-maintenance.yml" \ + -x ".github/workflows/package-release.yml" \ + \ + -x "*docs/*" \ + -x "*src/*" \ + -x "LICENSE" \ + -x "README.md" \ + \ + -x "starter.zip" \ + -x "migration.zip" + + - name: Publish migration package + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "latest-migration" + prerelease: true + title: "Latest migration package" + files: "migration.zip" diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..f4e30c1 --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,32 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Build pull request + +on: + pull_request: + branches: [ master, main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6a64794 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Build and release main branch + +on: + push: + branches: [ master, main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build + + - uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "latest" + prerelease: true + title: "Latest Development Build" + files: build/libs/*.jar + diff --git a/.gitignore b/.gitignore index ccc5e8b..558ad12 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,28 @@ -/build/build -/build/.gradle +.gradle +.settings +/.idea/ +/run/ +/build/ +/eclipse/ +.classpath +.project +/bin/ +/config/ +/crash-reports/ +/logs/ +options.txt +/saves/ +usernamecache.json +banned-ips.json +banned-players.json +eula.txt +ops.json +server.properties +servers.dat +usercache.json +whitelist.json +/out/ +*.iml +*.ipr +*.iws +src/main/resources/mixins.*.json diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..7fe18ad --- /dev/null +++ b/build.gradle @@ -0,0 +1,526 @@ +//version: 21647c763d3f6c90d59c900edae1248239c49dfb +/* +DO NOT CHANGE THIS FILE! + +Also, you may replace this file at any time if there is an update available. +Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates. + */ + + +import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation + +import java.util.concurrent.TimeUnit + +buildscript { + repositories { + maven { + name = "jitpack" + url = "https://jitpack.io" + } + maven { + name = "forge" + url = "https://maven.minecraftforge.net" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + maven { + name = "Scala CI dependencies" + url = "https://repo1.maven.org/maven2/" + } + } + dependencies { + classpath 'com.github.TheElan:ForgeGradle:1.2.2' + } +} + +plugins { + id("org.ajoberstar.grgit") version("3.1.1") + id("com.github.johnrengelman.shadow") version("4.0.4") + id("com.palantir.git-version") version("0.12.3") +} + +apply plugin: 'scala' +apply plugin: 'forge' +apply plugin: 'idea' + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } +} + +idea { + module { + inheritOutputDirs = true + downloadJavadoc = true + downloadSources = true + } +} + +checkPropertyExists("modName") +checkPropertyExists("modId") +checkPropertyExists("modGroup") +checkPropertyExists("autoUpdateBuildScript") +checkPropertyExists("minecraftVersion") +checkPropertyExists("forgeVersion") +checkPropertyExists("replaceGradleTokenInFile") +checkPropertyExists("gradleTokenModId") +checkPropertyExists("gradleTokenModName") +checkPropertyExists("gradleTokenVersion") +checkPropertyExists("gradleTokenGroupName") +checkPropertyExists("apiPackage") +checkPropertyExists("accessTransformersFile") +checkPropertyExists("usesMixins") +checkPropertyExists("mixinPlugin") +checkPropertyExists("mixinsPackage") +checkPropertyExists("coreModClass") +checkPropertyExists("containsMixinsAndOrCoreModOnly") +checkPropertyExists("usesShadowedDependencies") +checkPropertyExists("developmentEnvironmentUserName") + +def checkPropertyExists(String propertyName) { + if (project.hasProperty(propertyName) == false) { + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + } +} + + +String javaSourceDir = "src/main/java/" +String scalaSourceDir = "src/main/scala/" + +String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") +String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") +if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) +} + +if(apiPackage) { + targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + } +} + +if(accessTransformersFile) { + String targetFile = "src/main/resources/META-INF/" + accessTransformersFile + if(new File(targetFile).exists() == false) { + throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + } +} + +if(usesMixins.toBoolean()) { + if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { + throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!") + } + + targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + } + + String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" + String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" + if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + } +} + +if(coreModClass) { + String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" + String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" + if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + } +} + +configurations.all { + resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) + + // Make sure GregTech build won't time out + System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String) + System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String) +} + +// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version +'git config core.fileMode false'.execute() +// Pulls version from git tag +version = minecraftVersion + "-" + gitVersion() +group = modGroup +archivesBaseName = modId + +minecraft { + version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion + runDir = "run" + + if (replaceGradleTokenInFile) { + replaceIn replaceGradleTokenInFile + if(gradleTokenModId) { + replace gradleTokenModId, modId + } + if(gradleTokenModName) { + replace gradleTokenModName, modName + } + if(gradleTokenModName) { + replace gradleTokenVersion, versionDetails().lastTag + } + if(gradleTokenGroupName) { + replace gradleTokenGroupName, modGroup + } + } +} + +if(file("addon.gradle").exists()) { + apply from: "addon.gradle" +} + +apply from: 'repositories.gradle' + +configurations { + implementation.extendsFrom(shadowImplementation) +} + +repositories { + if(usesMixins.toBoolean()) { + maven { + name = "sponge" + url = "https://repo.spongepowered.org/repository/maven-public" + } + maven { + url = "https://jitpack.io" + } + } +} + +dependencies { + if(usesMixins.toBoolean()) { + annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3") + annotationProcessor("com.google.guava:guava:24.1.1-jre") + annotationProcessor("com.google.code.gson:gson:2.8.6") + annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") + // using 0.8 to workaround a issue in 0.7 which fails mixin application + compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + // Mixin includes a lot of dependencies that are too up-to-date + exclude module: "launchwrapper" + exclude module: "guava" + exclude module: "gson" + exclude module: "commons-io" + exclude module: "log4j-core" + } + compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev") + } +} + +apply from: 'dependencies.gradle' + +task relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} + +def mixinConfigJson = "mixins." + modId + ".json" +def mixingConfigRefMap = "mixins." + modId + ".refmap.json" +def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap +def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" + +task generateAssets { + if(usesMixins.toBoolean()) { + new File(projectDir.toString() + "/src/main/resources/", mixinConfigJson).text = """{ + "required": true, + "minVersion": "0.7.11", + "package": "${modGroup}.${mixinsPackage}", + "plugin": "${modGroup}.${mixinPlugin}", + "refmap": "${mixingConfigRefMap}", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8" +} + +""" + } +} + +shadowJar { + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } + + minimize() + configurations = [project.configurations.shadowImplementation] + dependsOn(relocateShadowJar) +} + +jar { + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } + + if(usesShadowedDependencies.toBoolean()) { + dependsOn(shadowJar) + enabled = false + } +} + +reobf { + if(usesMixins.toBoolean()) { + addExtraSrgFile mixinSrg + } +} + +afterEvaluate { + if(usesMixins.toBoolean()) { + tasks.compileJava { + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobf.srg}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" + ] + } + } +} + +runClient { + def arguments = [] + + if(usesMixins.toBoolean()) { + arguments += [ + "--mods=../build/libs/$modId-${version}.jar", + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + } + + if(developmentEnvironmentUserName) { + arguments += [ + "--username", + developmentEnvironmentUserName + ] + } + + args(arguments) +} + +runServer { + def arguments = [] + + if(usesMixins.toBoolean()) { + arguments += [ + "--mods=../build/libs/$modId-${version}.jar", + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + } + + args(arguments) +} + +processResources +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} + +task sourcesJar(type: Jar) { + from (sourceSets.main.allJava) + from (file("$projectDir/LICENSE")) + getArchiveClassifier().set('sources') + + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } +} + +task devJar(type: Jar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") + + def manifestAttributes = [:] + if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + } + + if(accessTransformersFile) { + manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + } + + if(coreModClass) { + manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] + } + + if(usesMixins.toBoolean()) { + from refMap + manifestAttributes += [ + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : mixinConfigJson, + "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + ] + } + manifest { + attributes(manifestAttributes) + } +} + +task apiJar(type: Jar) { + from (sourceSets.main.allJava) { + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + } + + from (sourceSets.main.output) { + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + } + + from (sourceSets.main.resources.srcDirs) { + include("LICENSE") + } + + getArchiveClassifier().set('api') +} + +artifacts { + archives sourcesJar + archives devJar + if(apiPackage) { + archives apiJar + } +} + +// Updating +task updateBuildScript { + doLast { + if (updateBuildScript()) return + + print("Build script already up-to-date!") + } +} + +if (isNewBuildScriptVersionAvailable()) { + if (autoUpdateBuildScript.toBoolean()) { + updateBuildScript() + } else { + println("Build script update available! Run 'gradle updateBuildScript'") + } +} + +static URL availableBuildScriptUrl() { + new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") +} + +static boolean updateBuildScript() { + if (isNewBuildScriptVersionAvailable()) { + def buildscriptFile = new File("build.gradle") + availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } + print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + return true + } + return false +} + +static boolean isNewBuildScriptVersionAvailable() { + Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] + + String currentBuildScript = new File("build.gradle").getText() + String currentBuildScriptHash = getVersionHash(currentBuildScript) + String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() + String availableBuildScriptHash = getVersionHash(availableBuildScript) + + boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash + return !isUpToDate +} + +static String getVersionHash(String buildScriptContent) { + String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") + if(versionLine != null) { + return versionLine.split(": ").last() + } + return "" +} + +configure(updateBuildScript) { + group = 'forgegradle' + description = 'Updates the build script to the latest version' +} diff --git a/build/build.gradle b/build/build.gradle deleted file mode 100644 index cb4be9e..0000000 --- a/build/build.gradle +++ /dev/null @@ -1,113 +0,0 @@ -buildscript { - repositories { - mavenCentral() - maven { - name = "forge" - url = "http://files.minecraftforge.net/maven" - } - maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" - } - } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' - } -} - -apply plugin: 'forge' - -group = "codechicken" // http://maven.apache.org/guides/mini/guide-naming-conventions.html -archivesBaseName = "CodeChickenCore" - -// Define properties file -ext.configFile = file "build.properties" - -configFile.withReader { - // Load config. It shall from now be referenced as simply config or project.config - def prop = new Properties() - prop.load(it) - project.ext.config = new ConfigSlurper().parse prop -} - -dependencies { - compile "codechicken:CodeChickenLib:${config.mc_version}-${config.ccl_version}:dev" -} - -version = "${project.config.mod_version}." + System.getenv("BUILD_NUMBER") ?: "1" - -println config.mc_version + "-" + config.forge_version -// Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here -minecraft { - version = config.mc_version + "-" + config.forge_version - replace '${mod_version}', project.config.mod_version -} - -sourceSets { - main { - def root = project.projectDir.parentFile - java { - srcDir new File(root, "src") - } - resources { - srcDir new File(root, "resources") - } - } -} - -processResources { - //redo task if any of these properties change - inputs.property "version", project.version - inputs.property "mc_version", config.mc_version - inputs.property "ccl_version", config.ccl_version - - // Replace properties in info files - from(sourceSets.main.resources.srcDirs) { - include '*.info' - expand 'version':project.version,'mc_version':config.mc_version,'ccl_version':config.ccl_version - } - // Copy everything else - from(sourceSets.main.resources.srcDirs) { - include 'assets/**/*.*' - } -} - -version = "${project.minecraft.version}-${project.version}" -def commonManifest = { - attributes 'FMLCorePlugin': 'codechicken.core.launch.CodeChickenCorePlugin' -} - -jar { - classifier = 'universal' - manifest commonManifest -} - -task sourceJar(type: Jar) { - from sourceSets.main.java - classifier = 'src' -} - -task devJar(type: Jar) { - from sourceSets.main.output - classifier = 'dev' - manifest commonManifest -} - -// Tell the artifact system about our extra jars -artifacts { - archives sourceJar, devJar -} - -// Configure an upload task. -uploadArchives { - dependsOn 'reobf' - if (project.hasProperty("local_maven")) { - repositories { - logger.info('Publishing to local maven repo') - - mavenDeployer { - repository(url: "file://${local_maven}") - } - } - } -} \ No newline at end of file diff --git a/build/build.properties b/build/build.properties deleted file mode 100644 index 9abbab6..0000000 --- a/build/build.properties +++ /dev/null @@ -1,4 +0,0 @@ -mc_version=1.7.10 -forge_version=10.13.3.1373-1.7.10 -ccl_version=1.1.3.138 -mod_version=1.0.7 diff --git a/build/gradle/wrapper/gradle-wrapper.jar b/build/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 3c7abdf12790879c06b07176de29647f77aa4129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51106 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

CflOl1i4(-2^1KXo)&I5QlgjRKFQgM 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 z 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%0DvTus6fLI&f~`9YxjD=W5pR41LBYQt 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 diff --git a/build/settings.gradle b/build/settings.gradle deleted file mode 100644 index 25615e7..0000000 --- a/build/settings.gradle +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This settings file was auto generated by the Gradle buildInit task - * by 'sunstrike' at '21/11/13 14:14' with Gradle 1.9 - * - * The settings file is used to specify which projects to include in your build. - * In a single project build this file can be empty or even removed. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html - */ - -/* -// To declare projects as part of a multi-project build use the 'include' method -include 'shared' -include 'api' -include 'services:webservice' -*/ - -rootProject.name = 'CodeChickenCore' diff --git a/dependencies.gradle b/dependencies.gradle new file mode 100644 index 0000000..2ace0e6 --- /dev/null +++ b/dependencies.gradle @@ -0,0 +1,5 @@ +// Add your dependencies here + +dependencies { + compile("com.github.GTNewHorizons:CodeChickenLib:master-SNAPSHOT:dev") +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..cf07ab4 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,60 @@ +modName = CodeChickenCore + +# This is a case-sensitive string to identify your mod. Convention is to use lower case. +modId = CodeChickenCore + +modGroup = codechicken + +# WHY is there no version field? +# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the +# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/ + +# Will update your build.gradle automatically whenever an update is available +autoUpdateBuildScript = false + +minecraftVersion = 1.7.10 +forgeVersion = 10.13.4.1614 + +# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name each time you +# restart Minecraft in development. Choose this dependent on your mod: +# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name +# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty +developmentEnvironmentUserName = "Developer" + +# Define a source file of your project with: +# public static final String VERSION = "GRADLETOKEN_VERSION"; +# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's +# version in @Mod([...], version = VERSION, [...]) +# Leave these properties empty to skip individual token replacements +replaceGradleTokenInFile = +gradleTokenModId = +gradleTokenModName = +gradleTokenVersion = +gradleTokenGroupName = + +# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can +# leave this property empty. +# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api +apiPackage = + +# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/ +# Example value: mymodid_at.cfg +accessTransformersFile = + +# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! +usesMixins = false +# Specify the location of your implementation of IMixinPlugin. Leave it empty otherwise. +mixinPlugin = +# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! +mixinsPackage = +# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! +# This parameter is for legacy compatability only +# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin +coreModClass = core.launch.CodeChickenCorePlugin +# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class +# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! +containsMixinsAndOrCoreModOnly = false + +# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your +# responsibility check the licence and request permission for distribution, if required. +usesShadowedDependencies = false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c2d1cf016b3885f6930543d57b744ea8c220a1a GIT binary patch literal 55616 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# 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"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +75,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +105,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -110,10 +125,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +170,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/build/gradlew.bat b/gradlew.bat similarity index 73% rename from build/gradlew.bat rename to gradlew.bat index 8a0b282..9618d8d 100644 --- a/build/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@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 @@ -8,14 +24,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@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= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@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 @@ -46,10 +62,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +75,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..09bbb51 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,2 @@ +before_install: + - ./gradlew setupCIWorkspace \ No newline at end of file diff --git a/repositories.gradle b/repositories.gradle new file mode 100644 index 0000000..7d02b58 --- /dev/null +++ b/repositories.gradle @@ -0,0 +1,7 @@ +// Add any additional repositiroes for your dependencies here + +repositories { + maven { + url = "https://jitpack.io" + } +} diff --git a/src/codechicken/core/CCUpdateChecker.java b/src/main/java/codechicken/core/CCUpdateChecker.java similarity index 100% rename from src/codechicken/core/CCUpdateChecker.java rename to src/main/java/codechicken/core/CCUpdateChecker.java diff --git a/src/codechicken/core/ClassDiscoverer.java b/src/main/java/codechicken/core/ClassDiscoverer.java similarity index 100% rename from src/codechicken/core/ClassDiscoverer.java rename to src/main/java/codechicken/core/ClassDiscoverer.java diff --git a/src/codechicken/core/ClientUtils.java b/src/main/java/codechicken/core/ClientUtils.java similarity index 100% rename from src/codechicken/core/ClientUtils.java rename to src/main/java/codechicken/core/ClientUtils.java diff --git a/src/codechicken/core/CommonUtils.java b/src/main/java/codechicken/core/CommonUtils.java similarity index 100% rename from src/codechicken/core/CommonUtils.java rename to src/main/java/codechicken/core/CommonUtils.java diff --git a/src/codechicken/core/GuiModListScroll.java b/src/main/java/codechicken/core/GuiModListScroll.java similarity index 100% rename from src/codechicken/core/GuiModListScroll.java rename to src/main/java/codechicken/core/GuiModListScroll.java diff --git a/src/codechicken/core/IGuiPacketSender.java b/src/main/java/codechicken/core/IGuiPacketSender.java similarity index 100% rename from src/codechicken/core/IGuiPacketSender.java rename to src/main/java/codechicken/core/IGuiPacketSender.java diff --git a/src/codechicken/core/IStringMatcher.java b/src/main/java/codechicken/core/IStringMatcher.java similarity index 100% rename from src/codechicken/core/IStringMatcher.java rename to src/main/java/codechicken/core/IStringMatcher.java diff --git a/src/codechicken/core/ProfileTimer.java b/src/main/java/codechicken/core/ProfileTimer.java similarity index 100% rename from src/codechicken/core/ProfileTimer.java rename to src/main/java/codechicken/core/ProfileTimer.java diff --git a/src/codechicken/core/ReflectionManager.java b/src/main/java/codechicken/core/ReflectionManager.java similarity index 100% rename from src/codechicken/core/ReflectionManager.java rename to src/main/java/codechicken/core/ReflectionManager.java diff --git a/src/codechicken/core/ServerUtils.java b/src/main/java/codechicken/core/ServerUtils.java similarity index 100% rename from src/codechicken/core/ServerUtils.java rename to src/main/java/codechicken/core/ServerUtils.java diff --git a/src/codechicken/core/TaskProfiler.java b/src/main/java/codechicken/core/TaskProfiler.java similarity index 100% rename from src/codechicken/core/TaskProfiler.java rename to src/main/java/codechicken/core/TaskProfiler.java diff --git a/src/codechicken/core/asm/CodeChickenAccessTransformer.java b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java similarity index 100% rename from src/codechicken/core/asm/CodeChickenAccessTransformer.java rename to src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java diff --git a/src/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java similarity index 100% rename from src/codechicken/core/asm/CodeChickenCoreModContainer.java rename to src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java diff --git a/src/codechicken/core/asm/DefaultImplementationTransformer.java b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java similarity index 100% rename from src/codechicken/core/asm/DefaultImplementationTransformer.java rename to src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java diff --git a/src/codechicken/core/asm/DelegatedTransformer.java b/src/main/java/codechicken/core/asm/DelegatedTransformer.java similarity index 100% rename from src/codechicken/core/asm/DelegatedTransformer.java rename to src/main/java/codechicken/core/asm/DelegatedTransformer.java diff --git a/src/codechicken/core/asm/DependancyLister.java b/src/main/java/codechicken/core/asm/DependancyLister.java similarity index 100% rename from src/codechicken/core/asm/DependancyLister.java rename to src/main/java/codechicken/core/asm/DependancyLister.java diff --git a/src/codechicken/core/asm/InterfaceDependancies.java b/src/main/java/codechicken/core/asm/InterfaceDependancies.java similarity index 100% rename from src/codechicken/core/asm/InterfaceDependancies.java rename to src/main/java/codechicken/core/asm/InterfaceDependancies.java diff --git a/src/codechicken/core/asm/InterfaceDependancyTransformer.java b/src/main/java/codechicken/core/asm/InterfaceDependancyTransformer.java similarity index 100% rename from src/codechicken/core/asm/InterfaceDependancyTransformer.java rename to src/main/java/codechicken/core/asm/InterfaceDependancyTransformer.java diff --git a/src/codechicken/core/asm/MCPDeobfuscationTransformer.java b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java similarity index 100% rename from src/codechicken/core/asm/MCPDeobfuscationTransformer.java rename to src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java diff --git a/src/codechicken/core/asm/MethodASMifier.java b/src/main/java/codechicken/core/asm/MethodASMifier.java similarity index 100% rename from src/codechicken/core/asm/MethodASMifier.java rename to src/main/java/codechicken/core/asm/MethodASMifier.java diff --git a/src/codechicken/core/asm/TweakTransformer.java b/src/main/java/codechicken/core/asm/TweakTransformer.java similarity index 100% rename from src/codechicken/core/asm/TweakTransformer.java rename to src/main/java/codechicken/core/asm/TweakTransformer.java diff --git a/src/codechicken/core/commands/CoreCommand.java b/src/main/java/codechicken/core/commands/CoreCommand.java similarity index 100% rename from src/codechicken/core/commands/CoreCommand.java rename to src/main/java/codechicken/core/commands/CoreCommand.java diff --git a/src/codechicken/core/commands/PlayerCommand.java b/src/main/java/codechicken/core/commands/PlayerCommand.java similarity index 100% rename from src/codechicken/core/commands/PlayerCommand.java rename to src/main/java/codechicken/core/commands/PlayerCommand.java diff --git a/src/codechicken/core/commands/ServerCommand.java b/src/main/java/codechicken/core/commands/ServerCommand.java similarity index 100% rename from src/codechicken/core/commands/ServerCommand.java rename to src/main/java/codechicken/core/commands/ServerCommand.java diff --git a/src/codechicken/core/featurehack/EntityRenderHook.java b/src/main/java/codechicken/core/featurehack/EntityRenderHook.java similarity index 100% rename from src/codechicken/core/featurehack/EntityRenderHook.java rename to src/main/java/codechicken/core/featurehack/EntityRenderHook.java diff --git a/src/codechicken/core/featurehack/EntityUpdateHook.java b/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java similarity index 100% rename from src/codechicken/core/featurehack/EntityUpdateHook.java rename to src/main/java/codechicken/core/featurehack/EntityUpdateHook.java diff --git a/src/codechicken/core/featurehack/FeatureHack.java b/src/main/java/codechicken/core/featurehack/FeatureHack.java similarity index 100% rename from src/codechicken/core/featurehack/FeatureHack.java rename to src/main/java/codechicken/core/featurehack/FeatureHack.java diff --git a/src/codechicken/core/featurehack/GameDataManipulator.java b/src/main/java/codechicken/core/featurehack/GameDataManipulator.java similarity index 100% rename from src/codechicken/core/featurehack/GameDataManipulator.java rename to src/main/java/codechicken/core/featurehack/GameDataManipulator.java diff --git a/src/codechicken/core/featurehack/LiquidTextures.java b/src/main/java/codechicken/core/featurehack/LiquidTextures.java similarity index 100% rename from src/codechicken/core/featurehack/LiquidTextures.java rename to src/main/java/codechicken/core/featurehack/LiquidTextures.java diff --git a/src/codechicken/core/featurehack/RenderEntityRenderHook.java b/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java similarity index 100% rename from src/codechicken/core/featurehack/RenderEntityRenderHook.java rename to src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java diff --git a/src/codechicken/core/featurehack/RenderNull.java b/src/main/java/codechicken/core/featurehack/RenderNull.java similarity index 100% rename from src/codechicken/core/featurehack/RenderNull.java rename to src/main/java/codechicken/core/featurehack/RenderNull.java diff --git a/src/codechicken/core/featurehack/TweakTransformerHelper.java b/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java similarity index 100% rename from src/codechicken/core/featurehack/TweakTransformerHelper.java rename to src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java diff --git a/src/codechicken/core/featurehack/mc/TextureLavaFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java similarity index 100% rename from src/codechicken/core/featurehack/mc/TextureLavaFX.java rename to src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java diff --git a/src/codechicken/core/featurehack/mc/TextureLavaFlowFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java similarity index 100% rename from src/codechicken/core/featurehack/mc/TextureLavaFlowFX.java rename to src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java diff --git a/src/codechicken/core/featurehack/mc/TextureWaterFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java similarity index 100% rename from src/codechicken/core/featurehack/mc/TextureWaterFX.java rename to src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java diff --git a/src/codechicken/core/featurehack/mc/TextureWaterFlowFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java similarity index 100% rename from src/codechicken/core/featurehack/mc/TextureWaterFlowFX.java rename to src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java diff --git a/src/codechicken/core/fluid/ExtendedFluidTank.java b/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java similarity index 100% rename from src/codechicken/core/fluid/ExtendedFluidTank.java rename to src/main/java/codechicken/core/fluid/ExtendedFluidTank.java diff --git a/src/codechicken/core/fluid/FluidUtils.java b/src/main/java/codechicken/core/fluid/FluidUtils.java similarity index 100% rename from src/codechicken/core/fluid/FluidUtils.java rename to src/main/java/codechicken/core/fluid/FluidUtils.java diff --git a/src/codechicken/core/fluid/TankAccess.java b/src/main/java/codechicken/core/fluid/TankAccess.java similarity index 100% rename from src/codechicken/core/fluid/TankAccess.java rename to src/main/java/codechicken/core/fluid/TankAccess.java diff --git a/src/codechicken/core/gui/ClickCounter.java b/src/main/java/codechicken/core/gui/ClickCounter.java similarity index 100% rename from src/codechicken/core/gui/ClickCounter.java rename to src/main/java/codechicken/core/gui/ClickCounter.java diff --git a/src/codechicken/core/gui/GuiCCButton.java b/src/main/java/codechicken/core/gui/GuiCCButton.java similarity index 100% rename from src/codechicken/core/gui/GuiCCButton.java rename to src/main/java/codechicken/core/gui/GuiCCButton.java diff --git a/src/codechicken/core/gui/GuiCCTextField.java b/src/main/java/codechicken/core/gui/GuiCCTextField.java similarity index 100% rename from src/codechicken/core/gui/GuiCCTextField.java rename to src/main/java/codechicken/core/gui/GuiCCTextField.java diff --git a/src/codechicken/core/gui/GuiScreenWidget.java b/src/main/java/codechicken/core/gui/GuiScreenWidget.java similarity index 100% rename from src/codechicken/core/gui/GuiScreenWidget.java rename to src/main/java/codechicken/core/gui/GuiScreenWidget.java diff --git a/src/codechicken/core/gui/GuiScrollPane.java b/src/main/java/codechicken/core/gui/GuiScrollPane.java similarity index 100% rename from src/codechicken/core/gui/GuiScrollPane.java rename to src/main/java/codechicken/core/gui/GuiScrollPane.java diff --git a/src/codechicken/core/gui/GuiScrollSlot.java b/src/main/java/codechicken/core/gui/GuiScrollSlot.java similarity index 100% rename from src/codechicken/core/gui/GuiScrollSlot.java rename to src/main/java/codechicken/core/gui/GuiScrollSlot.java diff --git a/src/codechicken/core/gui/GuiWidget.java b/src/main/java/codechicken/core/gui/GuiWidget.java similarity index 100% rename from src/codechicken/core/gui/GuiWidget.java rename to src/main/java/codechicken/core/gui/GuiWidget.java diff --git a/src/codechicken/core/gui/IGuiActionListener.java b/src/main/java/codechicken/core/gui/IGuiActionListener.java similarity index 100% rename from src/codechicken/core/gui/IGuiActionListener.java rename to src/main/java/codechicken/core/gui/IGuiActionListener.java diff --git a/src/codechicken/core/internal/CCCEventHandler.java b/src/main/java/codechicken/core/internal/CCCEventHandler.java similarity index 100% rename from src/codechicken/core/internal/CCCEventHandler.java rename to src/main/java/codechicken/core/internal/CCCEventHandler.java diff --git a/src/codechicken/core/inventory/GuiContainerWidget.java b/src/main/java/codechicken/core/inventory/GuiContainerWidget.java similarity index 100% rename from src/codechicken/core/inventory/GuiContainerWidget.java rename to src/main/java/codechicken/core/inventory/GuiContainerWidget.java diff --git a/src/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java similarity index 100% rename from src/codechicken/core/launch/CodeChickenCorePlugin.java rename to src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java diff --git a/src/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java similarity index 100% rename from src/codechicken/core/launch/DepLoader.java rename to src/main/java/codechicken/core/launch/DepLoader.java diff --git a/src/codechicken/obfuscator/ConstantObfuscator.java b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java similarity index 100% rename from src/codechicken/obfuscator/ConstantObfuscator.java rename to src/main/java/codechicken/obfuscator/ConstantObfuscator.java diff --git a/src/codechicken/obfuscator/DummyOutputStream.java b/src/main/java/codechicken/obfuscator/DummyOutputStream.java similarity index 100% rename from src/codechicken/obfuscator/DummyOutputStream.java rename to src/main/java/codechicken/obfuscator/DummyOutputStream.java diff --git a/src/codechicken/obfuscator/IHeirachyEvaluator.java b/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java similarity index 100% rename from src/codechicken/obfuscator/IHeirachyEvaluator.java rename to src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java diff --git a/src/codechicken/obfuscator/ILogStreams.java b/src/main/java/codechicken/obfuscator/ILogStreams.java similarity index 100% rename from src/codechicken/obfuscator/ILogStreams.java rename to src/main/java/codechicken/obfuscator/ILogStreams.java diff --git a/src/codechicken/obfuscator/ObfDirection.java b/src/main/java/codechicken/obfuscator/ObfDirection.java similarity index 100% rename from src/codechicken/obfuscator/ObfDirection.java rename to src/main/java/codechicken/obfuscator/ObfDirection.java diff --git a/src/codechicken/obfuscator/ObfRemapper.java b/src/main/java/codechicken/obfuscator/ObfRemapper.java similarity index 100% rename from src/codechicken/obfuscator/ObfRemapper.java rename to src/main/java/codechicken/obfuscator/ObfRemapper.java diff --git a/src/codechicken/obfuscator/ObfuscationMap.java b/src/main/java/codechicken/obfuscator/ObfuscationMap.java similarity index 100% rename from src/codechicken/obfuscator/ObfuscationMap.java rename to src/main/java/codechicken/obfuscator/ObfuscationMap.java diff --git a/src/codechicken/obfuscator/ObfuscationRun.java b/src/main/java/codechicken/obfuscator/ObfuscationRun.java similarity index 100% rename from src/codechicken/obfuscator/ObfuscationRun.java rename to src/main/java/codechicken/obfuscator/ObfuscationRun.java diff --git a/src/codechicken/obfuscator/SystemLogStreams.java b/src/main/java/codechicken/obfuscator/SystemLogStreams.java similarity index 100% rename from src/codechicken/obfuscator/SystemLogStreams.java rename to src/main/java/codechicken/obfuscator/SystemLogStreams.java diff --git a/resources/assets/codechickencore/asm/tweaks.asm b/src/main/resources/assets/codechickencore/asm/tweaks.asm similarity index 100% rename from resources/assets/codechickencore/asm/tweaks.asm rename to src/main/resources/assets/codechickencore/asm/tweaks.asm diff --git a/resources/assets/codechickencore/lang/de_DE.lang b/src/main/resources/assets/codechickencore/lang/de_DE.lang similarity index 100% rename from resources/assets/codechickencore/lang/de_DE.lang rename to src/main/resources/assets/codechickencore/lang/de_DE.lang diff --git a/resources/assets/codechickencore/lang/en_US.lang b/src/main/resources/assets/codechickencore/lang/en_US.lang similarity index 100% rename from resources/assets/codechickencore/lang/en_US.lang rename to src/main/resources/assets/codechickencore/lang/en_US.lang diff --git a/resources/assets/codechickencore/lang/it_IT.lang b/src/main/resources/assets/codechickencore/lang/it_IT.lang similarity index 100% rename from resources/assets/codechickencore/lang/it_IT.lang rename to src/main/resources/assets/codechickencore/lang/it_IT.lang diff --git a/resources/assets/codechickencore/lang/ru_RU.lang b/src/main/resources/assets/codechickencore/lang/ru_RU.lang similarity index 100% rename from resources/assets/codechickencore/lang/ru_RU.lang rename to src/main/resources/assets/codechickencore/lang/ru_RU.lang diff --git a/resources/cccmod.info b/src/main/resources/cccmod.info similarity index 100% rename from resources/cccmod.info rename to src/main/resources/cccmod.info diff --git a/resources/dependencies.info b/src/main/resources/dependencies.info similarity index 100% rename from resources/dependencies.info rename to src/main/resources/dependencies.info From cae5e55cf5a3091270a87927292176e3179c89ac Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 17:49:07 +0100 Subject: [PATCH 125/219] Tweak build script --- gradle.properties | 6 +++--- .../codechicken/core/asm/CodeChickenCoreModContainer.java | 2 +- .../codechicken/core/launch/CodeChickenCorePlugin.java | 2 +- src/main/resources/dependencies.info | 6 +++--- src/main/resources/{cccmod.info => mcmod.info} | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/main/resources/{cccmod.info => mcmod.info} (60%) diff --git a/gradle.properties b/gradle.properties index cf07ab4..5da4b16 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -modName = CodeChickenCore +modName = CodeChicken Core # This is a case-sensitive string to identify your mod. Convention is to use lower case. modId = CodeChickenCore @@ -26,7 +26,7 @@ developmentEnvironmentUserName = "Developer" # The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's # version in @Mod([...], version = VERSION, [...]) # Leave these properties empty to skip individual token replacements -replaceGradleTokenInFile = +replaceGradleTokenInFile = CodeChickenCorePlugin.java gradleTokenModId = gradleTokenModName = gradleTokenVersion = @@ -53,7 +53,7 @@ mixinsPackage = coreModClass = core.launch.CodeChickenCorePlugin # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! -containsMixinsAndOrCoreModOnly = false +containsMixinsAndOrCoreModOnly = true # If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your # responsibility check the licence and request permission for distribution, if required. diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index ef5f457..dbe05f7 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -32,7 +32,7 @@ public static void loadConfig() { } public CodeChickenCoreModContainer() { - super(MetadataCollection.from(MetadataCollection.class.getResourceAsStream("/cccmod.info"), "CodeChickenCore").getMetadataForId("CodeChickenCore", null)); + super(MetadataCollection.from(MetadataCollection.class.getResourceAsStream("/mcmod.info"), "CodeChickenCore").getMetadataForId("CodeChickenCore", null)); } @Override diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 61aeb82..5ff5ebf 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -31,7 +31,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; - public static final String version = "${mod_version}"; + public static final String version = "GRADLETOKEN_VERSION"; public static File minecraftDir; public static String currentMcVersion; diff --git a/src/main/resources/dependencies.info b/src/main/resources/dependencies.info index c40cb0a..aff2dba 100644 --- a/src/main/resources/dependencies.info +++ b/src/main/resources/dependencies.info @@ -1,7 +1,7 @@ { - "repo": "http://files.minecraftforge.net/maven/codechicken/CodeChickenLib/${mc_version}-${ccl_version}/", - "file": "CodeChickenLib-${mc_version}-${ccl_version}-universal.jar", - "dev": "CodeChickenLib-${mc_version}-${ccl_version}-dev.jar", + "repo": "http://files.minecraftforge.net/maven/codechicken/CodeChickenLib/1.7.10-1.1.3.138/", + "file": "CodeChickenLib-1.7.10-1.1.3.138-universal.jar", + "dev": "CodeChickenLib-1.7.10-1.1.3.138-dev.jar", "class": "codechicken.lib.asm.ASMHelper", "coreLib": true } \ No newline at end of file diff --git a/src/main/resources/cccmod.info b/src/main/resources/mcmod.info similarity index 60% rename from src/main/resources/cccmod.info rename to src/main/resources/mcmod.info index aedcd8d..3c0ca94 100644 --- a/src/main/resources/cccmod.info +++ b/src/main/resources/mcmod.info @@ -1,12 +1,12 @@ [ { - "modid": "CodeChickenCore", - "name": "CodeChicken Core", + "modid": "${modId}", + "name": "${modName}", "description": "Base common code for all chickenbones mods. Supporters: JBoyJr", - "version": "${version}", - "mcversion": "${mc_version}", + "version": "${modVersion}", + "mcversion": "${minecraftVersion}", "url": "http://www.minecraftforum.net/topic/909223", "authorList": [ "ChickenBones" ] } From dc24e5480e1ec429e427a230ee685600a34f20bb Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 18:00:06 +0100 Subject: [PATCH 126/219] Remove wrong build script --- .github/scripts/update-version.sh | 10 --- .github/workflows/buildscript-maintenance.yml | 24 ------- .github/workflows/package-release.yml | 71 ------------------- 3 files changed, 105 deletions(-) delete mode 100644 .github/scripts/update-version.sh delete mode 100644 .github/workflows/buildscript-maintenance.yml delete mode 100644 .github/workflows/package-release.yml diff --git a/.github/scripts/update-version.sh b/.github/scripts/update-version.sh deleted file mode 100644 index 6ab1b17..0000000 --- a/.github/scripts/update-version.sh +++ /dev/null @@ -1,10 +0,0 @@ -if [ ! -z $(git diff --name-only HEAD HEAD~1 | grep build.gradle) ]; then - new_version="$(git log -n1 --format=format:"%H")" - sed --in-place "s!^//version:.*!//version: $new_version!g" build.gradle - git add build.gradle - git commit -m "[ci skip] update build script version to $new_version" - git push - echo "Updated buildscript version to $new_version"; -else - echo "Ignored buildscript version update: no changes detected" -fi diff --git a/.github/workflows/buildscript-maintenance.yml b/.github/workflows/buildscript-maintenance.yml deleted file mode 100644 index f5128e3..0000000 --- a/.github/workflows/buildscript-maintenance.yml +++ /dev/null @@ -1,24 +0,0 @@ -# This workflow only meant for the source mod you shouldn't bring it into your own project - -name: Buildscript maintenance - -on: - push: - branches: [ master, main ] - -jobs: - buildscript-maintenance: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - - name: setup git config - run: | - git config user.name "GitHub CI Bot" - git config user.email "<>" - - - name: Ensure build script version is up to date - run: .github/scripts/update-version.sh diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml deleted file mode 100644 index 363028e..0000000 --- a/.github/workflows/package-release.yml +++ /dev/null @@ -1,71 +0,0 @@ -# This workflow only meant for the source mod you shouldn't bring it into your own project - -name: Release packages - -on: - push: - branches: [ master, main ] - -jobs: - zip-packages: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Zip starter - uses: montudor/action-zip@v1 - with: - args: > - zip -r starter.zip . \ - \ - -x "*.git/*" \ - \ - -x ".github/scripts/update-version.sh" \ - -x ".github/workflows/buildscript-maintenance.yml" \ - -x ".github/workflows/package-release.yml" \ - \ - -x "*docs/*" \ - -x "README.md" \ - -x "LICENSE" \ - \ - -x "starter.zip" \ - -x "migration.zip" - - - name: Publish starter package - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "latest-stater" - prerelease: true - title: "Latest starter package" - files: "starter.zip" - - - name: Zip migration - uses: montudor/action-zip@v1 - with: - args: > - zip -r migration.zip . \ - \ - -x "*.git/*" \ - \ - -x ".github/scripts/update-version.sh" \ - -x ".github/workflows/buildscript-maintenance.yml" \ - -x ".github/workflows/package-release.yml" \ - \ - -x "*docs/*" \ - -x "*src/*" \ - -x "LICENSE" \ - -x "README.md" \ - \ - -x "starter.zip" \ - -x "migration.zip" - - - name: Publish migration package - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "latest-migration" - prerelease: true - title: "Latest migration package" - files: "migration.zip" From 247a72789e527d2a1ace9dce38a86b6e6e5b0cdc Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 18:10:29 +0100 Subject: [PATCH 127/219] Fix mod loading --- gradle.properties | 8 ++++---- .../core/asm/CodeChickenCoreModContainer.java | 10 +++++++++- .../core/launch/CodeChickenCorePlugin.java | 1 - src/main/resources/mcmod.info | 14 +++++++------- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5da4b16..6f45dd6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,10 +26,10 @@ developmentEnvironmentUserName = "Developer" # The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's # version in @Mod([...], version = VERSION, [...]) # Leave these properties empty to skip individual token replacements -replaceGradleTokenInFile = CodeChickenCorePlugin.java -gradleTokenModId = -gradleTokenModName = -gradleTokenVersion = +replaceGradleTokenInFile = CodeChickenCoreModContainer.java +gradleTokenModId = GRADLETOKEN_MODID +gradleTokenModName = GRADLETOKEN_MODNAME +gradleTokenVersion = GRADLETOKEN_VERSION gradleTokenGroupName = # In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index dbe05f7..da49e93 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -32,7 +32,15 @@ public static void loadConfig() { } public CodeChickenCoreModContainer() { - super(MetadataCollection.from(MetadataCollection.class.getResourceAsStream("/mcmod.info"), "CodeChickenCore").getMetadataForId("CodeChickenCore", null)); + super(getModMetadata()); + } + + private static ModMetadata getModMetadata() { + final ModMetadata modMetadata = new ModMetadata(); + modMetadata.name = "GRADLETOKEN_MODNAME"; + modMetadata.modId = "GRADLETOKEN_MODID"; + modMetadata.version = "GRADLETOKEN_VERSION"; + return modMetadata; } @Override diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 5ff5ebf..c7f6183 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -31,7 +31,6 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; - public static final String version = "GRADLETOKEN_VERSION"; public static File minecraftDir; public static String currentMcVersion; diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 3c0ca94..29f8f00 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -1,13 +1,13 @@ [ { - "modid": "${modId}", - "name": "${modName}", - "description": "Base common code for all chickenbones mods. +"modid": "${modId}", +"name": "${modName}", +"description": "Base common code for all chickenbones mods. Supporters: JBoyJr", - "version": "${modVersion}", - "mcversion": "${minecraftVersion}", - "url": "http://www.minecraftforum.net/topic/909223", - "authorList": [ "ChickenBones" ] +"version": "${modVersion}", +"mcversion": "${minecraftVersion}", +"url": "http://www.minecraftforum.net/topic/909223", +"authorList": [ "ChickenBones" ] } ] \ No newline at end of file From e2954edacfd17af25820cfa7583eae4f33b5eb66 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sat, 20 Nov 2021 18:24:43 +0100 Subject: [PATCH 128/219] Add version replacement in second file --- addon.gradle | 8 ++++++++ .../codechicken/core/launch/CodeChickenCorePlugin.java | 1 + 2 files changed, 9 insertions(+) create mode 100644 addon.gradle diff --git a/addon.gradle b/addon.gradle new file mode 100644 index 0000000..321d20b --- /dev/null +++ b/addon.gradle @@ -0,0 +1,8 @@ +minecraft { + if (replaceGradleTokenInFile) { + replaceIn "CodeChickenCorePlugin.java" + if(gradleTokenVersion) { + replace gradleTokenVersion, versionDetails().lastTag + } + } +} \ No newline at end of file diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index c7f6183..5ff5ebf 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -31,6 +31,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; + public static final String version = "GRADLETOKEN_VERSION"; public static File minecraftDir; public static String currentMcVersion; From 94630e0b2b282ebe8f6a109a12031851c6447e53 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sun, 21 Nov 2021 13:04:32 +0100 Subject: [PATCH 129/219] Add missing core mod --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2e0a9a3..59ff02f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,10 +50,10 @@ mixinsPackage = # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! # This parameter is for legacy compatability only # Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin -coreModClass = +coreModClass = lib.tool.Main # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! -containsMixinsAndOrCoreModOnly = false +containsMixinsAndOrCoreModOnly = true # If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your # responsibility check the licence and request permission for distribution, if required. From 263864ab82a4d61c10353ea3494295daa0346f4a Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Tue, 23 Nov 2021 19:02:11 +0100 Subject: [PATCH 130/219] Remove wrong logo entry --- src/main/resources/mcmod.info | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 0942acd..a4b40b0 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -9,7 +9,7 @@ "updateUrl": "", "authorList": [ "Chicken-Bones", "GTNH-Team" ], "credits": "", - "logoFile": "galacticraft_logo.png", + "logoFile": "", "screenshots": [], "parent":"" }, From 0e53357ab8449a06b9318f29fbc71b53497c0bfe Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Tue, 30 Nov 2021 10:00:15 +0100 Subject: [PATCH 131/219] Update buildscript and CI --- .github/scripts/test-no-crash-reports.sh | 9 + .../{pull-request.yml => build-and-test.yml} | 17 +- .github/workflows/release-tags.yml | 45 ++++ .github/workflows/release.yml | 41 ---- build.gradle | 219 +++++++++--------- 5 files changed, 174 insertions(+), 157 deletions(-) create mode 100644 .github/scripts/test-no-crash-reports.sh rename .github/workflows/{pull-request.yml => build-and-test.yml} (66%) create mode 100644 .github/workflows/release-tags.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/scripts/test-no-crash-reports.sh b/.github/scripts/test-no-crash-reports.sh new file mode 100644 index 0000000..c67e342 --- /dev/null +++ b/.github/scripts/test-no-crash-reports.sh @@ -0,0 +1,9 @@ +directory="run/crash-reports" +if [ -d $directory ]; then + echo "Crash reports detected:" + cat $directory/* + exit 1 +else + echo "No crash reports detected" + exit 0 +fi diff --git a/.github/workflows/pull-request.yml b/.github/workflows/build-and-test.yml similarity index 66% rename from .github/workflows/pull-request.yml rename to .github/workflows/build-and-test.yml index f4e30c1..6c9b3cb 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/build-and-test.yml @@ -1,14 +1,16 @@ # This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle -name: Build pull request +name: Build and test on: pull_request: branches: [ master, main ] + push: + branches: [ master, main ] jobs: - build: + build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -30,3 +32,14 @@ jobs: - name: Build the mod run: ./gradlew build + + - name: Run server for 1 minute + run: | + mkdir run + echo "eula=true" > run/eula.txt + timeout 10 ./gradlew runServer || true + + - name: Test no crashes happend + run: | + chmod +x .github/scripts/test-no-crash-reports.sh + .github/scripts/test-no-crash-reports.sh diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml new file mode 100644 index 0000000..25c354b --- /dev/null +++ b/.github/workflows/release-tags.yml @@ -0,0 +1,45 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Release tagged build + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set release version + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build + + - name: Release under current tag + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "${{ env.RELEASE_VERSION }}" + prerelease: false + title: "${{ env.RELEASE_VERSION }}" + files: build/libs/*.jar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 6a64794..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,41 +0,0 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle - -name: Build and release main branch - -on: - push: - branches: [ master, main ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "latest" - prerelease: true - title: "Latest Development Build" - files: build/libs/*.jar - diff --git a/build.gradle b/build.gradle index 7fe18ad..a380f6c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 21647c763d3f6c90d59c900edae1248239c49dfb +//version: ffe7b130f98fdfa1ac7c6ba4bd34722a55ab28d4 /* DO NOT CHANGE THIS FILE! @@ -8,15 +8,12 @@ Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradl import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import java.util.concurrent.TimeUnit buildscript { repositories { - maven { - name = "jitpack" - url = "https://jitpack.io" - } maven { name = "forge" url = "https://maven.minecraftforge.net" @@ -29,25 +26,31 @@ buildscript { name = "Scala CI dependencies" url = "https://repo1.maven.org/maven2/" } + maven { + name = "jitpack" + url = "https://jitpack.io" + } } dependencies { - classpath 'com.github.TheElan:ForgeGradle:1.2.2' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4' } } plugins { + id 'idea' + id 'scala' id("org.ajoberstar.grgit") version("3.1.1") id("com.github.johnrengelman.shadow") version("4.0.4") id("com.palantir.git-version") version("0.12.3") } -apply plugin: 'scala' apply plugin: 'forge' -apply plugin: 'idea' + +def projectJavaVersion = JavaLanguageVersion.of(8) java { toolchain { - languageVersion.set(JavaLanguageVersion.of(8)) + languageVersion.set(projectJavaVersion) } } @@ -59,6 +62,10 @@ idea { } } +if(JavaVersion.current() != JavaVersion.VERSION_1_8) { + throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) +} + checkPropertyExists("modName") checkPropertyExists("modId") checkPropertyExists("modGroup") @@ -150,7 +157,12 @@ configurations.all { // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version 'git config core.fileMode false'.execute() // Pulls version from git tag -version = minecraftVersion + "-" + gitVersion() +try { + version = minecraftVersion + "-" + gitVersion() +} +catch (Exception e) { + throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); +} group = modGroup archivesBaseName = modId @@ -166,7 +178,7 @@ minecraft { if(gradleTokenModName) { replace gradleTokenModName, modName } - if(gradleTokenModName) { + if(gradleTokenVersion) { replace gradleTokenVersion, versionDetails().lastTag } if(gradleTokenGroupName) { @@ -186,6 +198,10 @@ configurations { } repositories { + maven { + name = "Overmind forge repo mirror" + url = "https://gregtech.overminddl1.com/" + } if(usesMixins.toBoolean()) { maven { name = "sponge" @@ -218,19 +234,13 @@ dependencies { apply from: 'dependencies.gradle' -task relocateShadowJar(type: ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" -} - -def mixinConfigJson = "mixins." + modId + ".json" def mixingConfigRefMap = "mixins." + modId + ".refmap.json" def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if(usesMixins.toBoolean()) { - new File(projectDir.toString() + "/src/main/resources/", mixinConfigJson).text = """{ + new File(projectDir.toString() + "/src/main/resources/", "mixins." + modId + ".json").text = """{ "required": true, "minVersion": "0.7.11", "package": "${modGroup}.${mixinsPackage}", @@ -244,61 +254,24 @@ task generateAssets { } } -shadowJar { - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } - - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] - } - - if(coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } +task relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} - if(usesMixins.toBoolean()) { - from refMap - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false - ] - } +shadowJar { manifest { - attributes(manifestAttributes) + attributes(getManifestAttributes()) } - minimize() + minimize() // This will only allow shading for actually used classes configurations = [project.configurations.shadowImplementation] dependsOn(relocateShadowJar) } jar { - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } - - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] - } - - if(coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } - - if(usesMixins.toBoolean()) { - from refMap - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false - ] - } manifest { - attributes(manifestAttributes) + attributes(getManifestAttributes()) } if(usesShadowedDependencies.toBoolean()) { @@ -351,7 +324,7 @@ runClient { runServer { def arguments = [] - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { arguments += [ "--mods=../build/libs/$modId-${version}.jar", "--tweakClass org.spongepowered.asm.launch.MixinTweaker" @@ -361,36 +334,44 @@ runServer { args(arguments) } -processResources -{ - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version - - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - - // replace version and mcversion - expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName - } - - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } +tasks.withType(JavaExec).configureEach { + javaLauncher.set( + javaToolchains.launcherFor { + languageVersion = projectJavaVersion + } + ) } -task sourcesJar(type: Jar) { - from (sourceSets.main.allJava) - from (file("$projectDir/LICENSE")) - getArchiveClassifier().set('sources') +processResources + { + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + if(usesMixins.toBoolean()) { + from refMap + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } + } +def getManifestAttributes() { def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } @@ -403,45 +384,55 @@ task sourcesJar(type: Jar) { } if(usesMixins.toBoolean()) { - from refMap manifestAttributes += [ "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, + "MixinConfigs" : "mixins." + modId + ".json", "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false ] } - manifest { - attributes(manifestAttributes) - } + return manifestAttributes } -task devJar(type: Jar) { +task sourcesJar(type: Jar) { + from (sourceSets.main.allJava) + from (file("$projectDir/LICENSE")) + getArchiveClassifier().set('sources') +} + +task shadowDevJar(type: ShadowJar) { from sourceSets.main.output getArchiveClassifier().set("dev") - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + manifest { + attributes(getManifestAttributes()) } - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] - } + minimize() // This will only allow shading for actually used classes + configurations = [project.configurations.shadowImplementation] +} - if(coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } +task relocateShadowDevJar(type: ConfigureShadowRelocation) { + target = tasks.shadowDevJar + prefix = modGroup + ".shadow" +} + +task circularResolverJar(type: Jar) { + dependsOn(relocateShadowDevJar) + dependsOn(shadowDevJar) + enabled = false +} + +task devJar(type: Jar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") - if(usesMixins.toBoolean()) { - from refMap - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false - ] - } manifest { - attributes(manifestAttributes) + attributes(getManifestAttributes()) + } + + if(usesShadowedDependencies.toBoolean()) { + dependsOn(circularResolverJar) + enabled = false } } From 19dc5075993adc55921df66b0bc133a46f875ef3 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Tue, 30 Nov 2021 10:01:34 +0100 Subject: [PATCH 132/219] Update build script and CI --- .github/scripts/test-no-crash-reports.sh | 9 + .../{pull-request.yml => build-and-test.yml} | 17 +- .github/workflows/release-tags.yml | 45 ++++ .github/workflows/release.yml | 41 ---- build.gradle | 219 +++++++++--------- 5 files changed, 174 insertions(+), 157 deletions(-) create mode 100644 .github/scripts/test-no-crash-reports.sh rename .github/workflows/{pull-request.yml => build-and-test.yml} (66%) create mode 100644 .github/workflows/release-tags.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/scripts/test-no-crash-reports.sh b/.github/scripts/test-no-crash-reports.sh new file mode 100644 index 0000000..c67e342 --- /dev/null +++ b/.github/scripts/test-no-crash-reports.sh @@ -0,0 +1,9 @@ +directory="run/crash-reports" +if [ -d $directory ]; then + echo "Crash reports detected:" + cat $directory/* + exit 1 +else + echo "No crash reports detected" + exit 0 +fi diff --git a/.github/workflows/pull-request.yml b/.github/workflows/build-and-test.yml similarity index 66% rename from .github/workflows/pull-request.yml rename to .github/workflows/build-and-test.yml index f4e30c1..6c9b3cb 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/build-and-test.yml @@ -1,14 +1,16 @@ # This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle -name: Build pull request +name: Build and test on: pull_request: branches: [ master, main ] + push: + branches: [ master, main ] jobs: - build: + build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -30,3 +32,14 @@ jobs: - name: Build the mod run: ./gradlew build + + - name: Run server for 1 minute + run: | + mkdir run + echo "eula=true" > run/eula.txt + timeout 10 ./gradlew runServer || true + + - name: Test no crashes happend + run: | + chmod +x .github/scripts/test-no-crash-reports.sh + .github/scripts/test-no-crash-reports.sh diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml new file mode 100644 index 0000000..25c354b --- /dev/null +++ b/.github/workflows/release-tags.yml @@ -0,0 +1,45 @@ +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Release tagged build + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set release version + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup the workspace + run: ./gradlew setupCIWorkspace + + - name: Build the mod + run: ./gradlew build + + - name: Release under current tag + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: "${{ env.RELEASE_VERSION }}" + prerelease: false + title: "${{ env.RELEASE_VERSION }}" + files: build/libs/*.jar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 6a64794..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,41 +0,0 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle - -name: Build and release main branch - -on: - push: - branches: [ master, main ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "latest" - prerelease: true - title: "Latest Development Build" - files: build/libs/*.jar - diff --git a/build.gradle b/build.gradle index 7fe18ad..a380f6c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 21647c763d3f6c90d59c900edae1248239c49dfb +//version: ffe7b130f98fdfa1ac7c6ba4bd34722a55ab28d4 /* DO NOT CHANGE THIS FILE! @@ -8,15 +8,12 @@ Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradl import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import java.util.concurrent.TimeUnit buildscript { repositories { - maven { - name = "jitpack" - url = "https://jitpack.io" - } maven { name = "forge" url = "https://maven.minecraftforge.net" @@ -29,25 +26,31 @@ buildscript { name = "Scala CI dependencies" url = "https://repo1.maven.org/maven2/" } + maven { + name = "jitpack" + url = "https://jitpack.io" + } } dependencies { - classpath 'com.github.TheElan:ForgeGradle:1.2.2' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4' } } plugins { + id 'idea' + id 'scala' id("org.ajoberstar.grgit") version("3.1.1") id("com.github.johnrengelman.shadow") version("4.0.4") id("com.palantir.git-version") version("0.12.3") } -apply plugin: 'scala' apply plugin: 'forge' -apply plugin: 'idea' + +def projectJavaVersion = JavaLanguageVersion.of(8) java { toolchain { - languageVersion.set(JavaLanguageVersion.of(8)) + languageVersion.set(projectJavaVersion) } } @@ -59,6 +62,10 @@ idea { } } +if(JavaVersion.current() != JavaVersion.VERSION_1_8) { + throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) +} + checkPropertyExists("modName") checkPropertyExists("modId") checkPropertyExists("modGroup") @@ -150,7 +157,12 @@ configurations.all { // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version 'git config core.fileMode false'.execute() // Pulls version from git tag -version = minecraftVersion + "-" + gitVersion() +try { + version = minecraftVersion + "-" + gitVersion() +} +catch (Exception e) { + throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); +} group = modGroup archivesBaseName = modId @@ -166,7 +178,7 @@ minecraft { if(gradleTokenModName) { replace gradleTokenModName, modName } - if(gradleTokenModName) { + if(gradleTokenVersion) { replace gradleTokenVersion, versionDetails().lastTag } if(gradleTokenGroupName) { @@ -186,6 +198,10 @@ configurations { } repositories { + maven { + name = "Overmind forge repo mirror" + url = "https://gregtech.overminddl1.com/" + } if(usesMixins.toBoolean()) { maven { name = "sponge" @@ -218,19 +234,13 @@ dependencies { apply from: 'dependencies.gradle' -task relocateShadowJar(type: ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" -} - -def mixinConfigJson = "mixins." + modId + ".json" def mixingConfigRefMap = "mixins." + modId + ".refmap.json" def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if(usesMixins.toBoolean()) { - new File(projectDir.toString() + "/src/main/resources/", mixinConfigJson).text = """{ + new File(projectDir.toString() + "/src/main/resources/", "mixins." + modId + ".json").text = """{ "required": true, "minVersion": "0.7.11", "package": "${modGroup}.${mixinsPackage}", @@ -244,61 +254,24 @@ task generateAssets { } } -shadowJar { - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } - - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] - } - - if(coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } +task relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} - if(usesMixins.toBoolean()) { - from refMap - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false - ] - } +shadowJar { manifest { - attributes(manifestAttributes) + attributes(getManifestAttributes()) } - minimize() + minimize() // This will only allow shading for actually used classes configurations = [project.configurations.shadowImplementation] dependsOn(relocateShadowJar) } jar { - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } - - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] - } - - if(coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } - - if(usesMixins.toBoolean()) { - from refMap - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false - ] - } manifest { - attributes(manifestAttributes) + attributes(getManifestAttributes()) } if(usesShadowedDependencies.toBoolean()) { @@ -351,7 +324,7 @@ runClient { runServer { def arguments = [] - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { arguments += [ "--mods=../build/libs/$modId-${version}.jar", "--tweakClass org.spongepowered.asm.launch.MixinTweaker" @@ -361,36 +334,44 @@ runServer { args(arguments) } -processResources -{ - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version - - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - - // replace version and mcversion - expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName - } - - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } +tasks.withType(JavaExec).configureEach { + javaLauncher.set( + javaToolchains.launcherFor { + languageVersion = projectJavaVersion + } + ) } -task sourcesJar(type: Jar) { - from (sourceSets.main.allJava) - from (file("$projectDir/LICENSE")) - getArchiveClassifier().set('sources') +processResources + { + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + if(usesMixins.toBoolean()) { + from refMap + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } + } +def getManifestAttributes() { def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { + if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } @@ -403,45 +384,55 @@ task sourcesJar(type: Jar) { } if(usesMixins.toBoolean()) { - from refMap manifestAttributes += [ "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, + "MixinConfigs" : "mixins." + modId + ".json", "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false ] } - manifest { - attributes(manifestAttributes) - } + return manifestAttributes } -task devJar(type: Jar) { +task sourcesJar(type: Jar) { + from (sourceSets.main.allJava) + from (file("$projectDir/LICENSE")) + getArchiveClassifier().set('sources') +} + +task shadowDevJar(type: ShadowJar) { from sourceSets.main.output getArchiveClassifier().set("dev") - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] + manifest { + attributes(getManifestAttributes()) } - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] - } + minimize() // This will only allow shading for actually used classes + configurations = [project.configurations.shadowImplementation] +} - if(coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } +task relocateShadowDevJar(type: ConfigureShadowRelocation) { + target = tasks.shadowDevJar + prefix = modGroup + ".shadow" +} + +task circularResolverJar(type: Jar) { + dependsOn(relocateShadowDevJar) + dependsOn(shadowDevJar) + enabled = false +} + +task devJar(type: Jar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") - if(usesMixins.toBoolean()) { - from refMap - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : mixinConfigJson, - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false - ] - } manifest { - attributes(manifestAttributes) + attributes(getManifestAttributes()) + } + + if(usesShadowedDependencies.toBoolean()) { + dependsOn(circularResolverJar) + enabled = false } } From 35e8b9a9563d2364a06d2f328d6bdd75df9c4124 Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Fri, 3 Dec 2021 13:56:09 +0800 Subject: [PATCH 133/219] this is not a mod but a lib --- src/main/resources/mcmod.info | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 src/main/resources/mcmod.info diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info deleted file mode 100644 index a4b40b0..0000000 --- a/src/main/resources/mcmod.info +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "modid": "${modId}", - "name": "${modName}", - "description": "This is a library of systems to help make various aspects of minecraft modding easier. It contains libraries for 3D math and transformations, model rendering, packets, config, colours, asm and a few other things.", - "version": "${modVersion}", - "mcversion": "${minecraftVersion}", - "url": "https://github.com/GTNewHorizons/CodeChickenLib", - "updateUrl": "", - "authorList": [ "Chicken-Bones", "GTNH-Team" ], - "credits": "", - "logoFile": "", - "screenshots": [], - "parent":"" - }, -] From 8933d4cf78db58e73a38453e92bd72c5a33f2bbb Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Fri, 3 Dec 2021 21:12:30 +0800 Subject: [PATCH 134/219] why main class is now a coremod wtf --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 59ff02f..70da5a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,10 +50,10 @@ mixinsPackage = # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! # This parameter is for legacy compatability only # Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin -coreModClass = lib.tool.Main +coreModClass = # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! -containsMixinsAndOrCoreModOnly = true +containsMixinsAndOrCoreModOnly = # If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your # responsibility check the licence and request permission for distribution, if required. From 220b7c556360ff31e5e08861474187cea730e756 Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 14 Dec 2021 12:29:07 -0600 Subject: [PATCH 135/219] buildscript --- build.gradle | 62 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/build.gradle b/build.gradle index a380f6c..18fedd3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: ffe7b130f98fdfa1ac7c6ba4bd34722a55ab28d4 +//version: 928ecf7feb33a1149538b0e2cd17e3bc5f281428 /* DO NOT CHANGE THIS FILE! @@ -87,33 +87,27 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -def checkPropertyExists(String propertyName) { - if (project.hasProperty(propertyName) == false) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") - } -} - String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") -if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { +if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } if(apiPackage) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } } if(accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(new File(targetFile).exists() == false) { + if(getFile(targetFile).exists() == false) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } @@ -125,14 +119,14 @@ if(usesMixins.toBoolean()) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) } } @@ -141,7 +135,7 @@ if(coreModClass) { String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) } } @@ -163,8 +157,14 @@ try { catch (Exception e) { throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); } + group = modGroup -archivesBaseName = modId +if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { + archivesBaseName = customArchiveBaseName +} +else { + archivesBaseName = modId +} minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion @@ -240,7 +240,7 @@ def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if(usesMixins.toBoolean()) { - new File(projectDir.toString() + "/src/main/resources/", "mixins." + modId + ".json").text = """{ + getFile("/src/main/resources/mixins." + modId + ".json").text = """{ "required": true, "minVersion": "0.7.11", "package": "${modGroup}.${mixinsPackage}", @@ -438,11 +438,11 @@ task devJar(type: Jar) { task apiJar(type: Jar) { from (sourceSets.main.allJava) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } from (sourceSets.main.output) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } from (sourceSets.main.resources.srcDirs) { @@ -463,15 +463,15 @@ artifacts { // Updating task updateBuildScript { doLast { - if (updateBuildScript()) return + if (performBuildScriptUpdate(projectDir.toString())) return print("Build script already up-to-date!") } } -if (isNewBuildScriptVersionAvailable()) { +if (isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { - updateBuildScript() + performBuildScriptUpdate(projectDir.toString()) } else { println("Build script update available! Run 'gradle updateBuildScript'") } @@ -481,9 +481,9 @@ static URL availableBuildScriptUrl() { new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") } -static boolean updateBuildScript() { - if (isNewBuildScriptVersionAvailable()) { - def buildscriptFile = new File("build.gradle") +boolean performBuildScriptUpdate(String projectDir) { + if (isNewBuildScriptVersionAvailable(projectDir)) { + def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } print("Build script updated. Please REIMPORT the project or RESTART your IDE!") return true @@ -491,10 +491,10 @@ static boolean updateBuildScript() { return false } -static boolean isNewBuildScriptVersionAvailable() { +boolean isNewBuildScriptVersionAvailable(String projectDir) { Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] - String currentBuildScript = new File("build.gradle").getText() + String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() String availableBuildScriptHash = getVersionHash(availableBuildScript) @@ -515,3 +515,15 @@ configure(updateBuildScript) { group = 'forgegradle' description = 'Updates the build script to the latest version' } + +// Helper methods + +def checkPropertyExists(String propertyName) { + if (project.hasProperty(propertyName) == false) { + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + } +} + +def getFile(String relativePath) { + return new File(projectDir, relativePath) +} From ec6541e17fd9311550911432beb5cb2c9fdc119b Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 14 Dec 2021 13:13:23 -0600 Subject: [PATCH 136/219] remove outdated dependencies.info and traceback on failed parse --- src/main/java/codechicken/core/launch/DepLoader.java | 1 - src/main/resources/dependencies.info | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 src/main/resources/dependencies.info diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index 0032ed5..3b29ace 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -508,7 +508,6 @@ private void scanDepInfo(File file) { zip.close(); } catch (Exception e) { System.err.println("Failed to load dependencies.info from " + file.getName() + " as JSON"); - e.printStackTrace(); } } diff --git a/src/main/resources/dependencies.info b/src/main/resources/dependencies.info deleted file mode 100644 index aff2dba..0000000 --- a/src/main/resources/dependencies.info +++ /dev/null @@ -1,7 +0,0 @@ -{ - "repo": "http://files.minecraftforge.net/maven/codechicken/CodeChickenLib/1.7.10-1.1.3.138/", - "file": "CodeChickenLib-1.7.10-1.1.3.138-universal.jar", - "dev": "CodeChickenLib-1.7.10-1.1.3.138-dev.jar", - "class": "codechicken.lib.asm.ASMHelper", - "coreLib": true -} \ No newline at end of file From 878fdbe1dd7712364f9613082632f367aa1b4b1f Mon Sep 17 00:00:00 2001 From: bombcar Date: Wed, 15 Dec 2021 07:04:30 -0600 Subject: [PATCH 137/219] Add back traceback --- src/main/java/codechicken/core/launch/DepLoader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index 3b29ace..0032ed5 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -508,6 +508,7 @@ private void scanDepInfo(File file) { zip.close(); } catch (Exception e) { System.err.println("Failed to load dependencies.info from " + file.getName() + " as JSON"); + e.printStackTrace(); } } From 2e1fc1ece0ef93cf6e3e00a122946e349f8e4e45 Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 21 Dec 2021 08:23:33 -0600 Subject: [PATCH 138/219] update buildscript --- build.gradle | 173 ++++++++++++++++++++++++++++++++++++--------------- gradlew | 0 2 files changed, 122 insertions(+), 51 deletions(-) mode change 100644 => 100755 gradlew diff --git a/build.gradle b/build.gradle index a380f6c..43dfa37 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: ffe7b130f98fdfa1ac7c6ba4bd34722a55ab28d4 +//version: 8fa7883b6196c1765266f4e6ddf3118d5043aafb /* DO NOT CHANGE THIS FILE! @@ -42,6 +42,7 @@ plugins { id("org.ajoberstar.grgit") version("3.1.1") id("com.github.johnrengelman.shadow") version("4.0.4") id("com.palantir.git-version") version("0.12.3") + id("maven-publish") } apply plugin: 'forge' @@ -87,33 +88,27 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -def checkPropertyExists(String propertyName) { - if (project.hasProperty(propertyName) == false) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") - } -} - String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") -if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { +if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } if(apiPackage) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } } if(accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(new File(targetFile).exists() == false) { + if(getFile(targetFile).exists() == false) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } @@ -125,14 +120,14 @@ if(usesMixins.toBoolean()) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) } } @@ -141,7 +136,7 @@ if(coreModClass) { String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) } } @@ -163,8 +158,14 @@ try { catch (Exception e) { throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); } + group = modGroup -archivesBaseName = modId +if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { + archivesBaseName = customArchiveBaseName +} +else { + archivesBaseName = modId +} minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion @@ -194,7 +195,9 @@ if(file("addon.gradle").exists()) { apply from: 'repositories.gradle' configurations { - implementation.extendsFrom(shadowImplementation) + implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored + implementation.extendsFrom(shadowCompile) + implementation.extendsFrom(shadeCompile) } repositories { @@ -240,7 +243,7 @@ def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if(usesMixins.toBoolean()) { - new File(projectDir.toString() + "/src/main/resources/", "mixins." + modId + ".json").text = """{ + getFile("/src/main/resources/mixins." + modId + ".json").text = """{ "required": true, "minVersion": "0.7.11", "package": "${modGroup}.${mixinsPackage}", @@ -260,16 +263,28 @@ task relocateShadowJar(type: ConfigureShadowRelocation) { } shadowJar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + manifest { attributes(getManifestAttributes()) } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation] + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] dependsOn(relocateShadowJar) } jar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + manifest { attributes(getManifestAttributes()) } @@ -343,31 +358,31 @@ tasks.withType(JavaExec).configureEach { } processResources - { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version - - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - - // replace version and mcversion - expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName - } +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version - if(usesMixins.toBoolean()) { - from refMap - } + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } - } + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + if(usesMixins.toBoolean()) { + from refMap + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} def getManifestAttributes() { def manifestAttributes = [:] @@ -400,6 +415,12 @@ task sourcesJar(type: Jar) { } task shadowDevJar(type: ShadowJar) { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + from sourceSets.main.output getArchiveClassifier().set("dev") @@ -408,7 +429,7 @@ task shadowDevJar(type: ShadowJar) { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation] + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { @@ -423,6 +444,12 @@ task circularResolverJar(type: Jar) { } task devJar(type: Jar) { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + from sourceSets.main.output getArchiveClassifier().set("dev") @@ -438,11 +465,11 @@ task devJar(type: Jar) { task apiJar(type: Jar) { from (sourceSets.main.allJava) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } from (sourceSets.main.output) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } from (sourceSets.main.resources.srcDirs) { @@ -460,18 +487,50 @@ artifacts { } } +// publishing +publishing { + publications { + maven(MavenPublication) { + artifact source: jar + artifact source: sourcesJar, classifier: "src" + artifact source: devJar, classifier: "dev" + if (apiPackage) { + artifact source: apiJar, classifier: "api" + } + + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + artifactId = System.getenv("ARTIFACT_ID") ?: project.name + version = System.getenv("ARTIFACT_VERSION") ?: project.version + } + } + + repositories { + maven { + String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" + String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" + String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" + name = "GitHubPackages" + url = githubRepositoryUrl + credentials { + username = System.getenv("GITHUB_ACTOR") ?: "NONE" + password = System.getenv("GITHUB_TOKEN") ?: "NONE" + } + } + } +} + // Updating task updateBuildScript { doLast { - if (updateBuildScript()) return + if (performBuildScriptUpdate(projectDir.toString())) return print("Build script already up-to-date!") } } -if (isNewBuildScriptVersionAvailable()) { +if (isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { - updateBuildScript() + performBuildScriptUpdate(projectDir.toString()) } else { println("Build script update available! Run 'gradle updateBuildScript'") } @@ -481,9 +540,9 @@ static URL availableBuildScriptUrl() { new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") } -static boolean updateBuildScript() { - if (isNewBuildScriptVersionAvailable()) { - def buildscriptFile = new File("build.gradle") +boolean performBuildScriptUpdate(String projectDir) { + if (isNewBuildScriptVersionAvailable(projectDir)) { + def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } print("Build script updated. Please REIMPORT the project or RESTART your IDE!") return true @@ -491,10 +550,10 @@ static boolean updateBuildScript() { return false } -static boolean isNewBuildScriptVersionAvailable() { +boolean isNewBuildScriptVersionAvailable(String projectDir) { Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] - String currentBuildScript = new File("build.gradle").getText() + String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() String availableBuildScriptHash = getVersionHash(availableBuildScript) @@ -515,3 +574,15 @@ configure(updateBuildScript) { group = 'forgegradle' description = 'Updates the build script to the latest version' } + +// Helper methods + +def checkPropertyExists(String propertyName) { + if (project.hasProperty(propertyName) == false) { + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + } +} + +def getFile(String relativePath) { + return new File(projectDir, relativePath) +} diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From f9d880164463493593cc890d7afbc3abd681b91d Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 21 Dec 2021 09:28:19 -0600 Subject: [PATCH 139/219] fixbuild --- build.gradle | 113 +++++++++++++++++++++++++++++++++++++++------------ gradlew | 0 2 files changed, 86 insertions(+), 27 deletions(-) mode change 100644 => 100755 gradlew diff --git a/build.gradle b/build.gradle index 18fedd3..43dfa37 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 928ecf7feb33a1149538b0e2cd17e3bc5f281428 +//version: 8fa7883b6196c1765266f4e6ddf3118d5043aafb /* DO NOT CHANGE THIS FILE! @@ -42,6 +42,7 @@ plugins { id("org.ajoberstar.grgit") version("3.1.1") id("com.github.johnrengelman.shadow") version("4.0.4") id("com.palantir.git-version") version("0.12.3") + id("maven-publish") } apply plugin: 'forge' @@ -194,7 +195,9 @@ if(file("addon.gradle").exists()) { apply from: 'repositories.gradle' configurations { - implementation.extendsFrom(shadowImplementation) + implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored + implementation.extendsFrom(shadowCompile) + implementation.extendsFrom(shadeCompile) } repositories { @@ -260,16 +263,28 @@ task relocateShadowJar(type: ConfigureShadowRelocation) { } shadowJar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + manifest { attributes(getManifestAttributes()) } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation] + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] dependsOn(relocateShadowJar) } jar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + manifest { attributes(getManifestAttributes()) } @@ -343,31 +358,31 @@ tasks.withType(JavaExec).configureEach { } processResources - { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version - - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - - // replace version and mcversion - expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName - } +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version - if(usesMixins.toBoolean()) { - from refMap - } + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } - } + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } + + if(usesMixins.toBoolean()) { + from refMap + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} def getManifestAttributes() { def manifestAttributes = [:] @@ -400,6 +415,12 @@ task sourcesJar(type: Jar) { } task shadowDevJar(type: ShadowJar) { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + from sourceSets.main.output getArchiveClassifier().set("dev") @@ -408,7 +429,7 @@ task shadowDevJar(type: ShadowJar) { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation] + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { @@ -423,6 +444,12 @@ task circularResolverJar(type: Jar) { } task devJar(type: Jar) { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + from sourceSets.main.output getArchiveClassifier().set("dev") @@ -460,6 +487,38 @@ artifacts { } } +// publishing +publishing { + publications { + maven(MavenPublication) { + artifact source: jar + artifact source: sourcesJar, classifier: "src" + artifact source: devJar, classifier: "dev" + if (apiPackage) { + artifact source: apiJar, classifier: "api" + } + + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + artifactId = System.getenv("ARTIFACT_ID") ?: project.name + version = System.getenv("ARTIFACT_VERSION") ?: project.version + } + } + + repositories { + maven { + String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" + String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" + String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" + name = "GitHubPackages" + url = githubRepositoryUrl + credentials { + username = System.getenv("GITHUB_ACTOR") ?: "NONE" + password = System.getenv("GITHUB_TOKEN") ?: "NONE" + } + } + } +} + // Updating task updateBuildScript { doLast { diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 From 0d678abc10672f77ce36743a7d9165dc7ccabcb2 Mon Sep 17 00:00:00 2001 From: bombcar Date: Wed, 22 Dec 2021 07:46:39 -0600 Subject: [PATCH 140/219] developer --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 70da5a8..76af7f9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ forgeVersion = 10.13.4.1614 # restart Minecraft in development. Choose this dependent on your mod: # Do you need consistent player progressing (for example Thaumcraft)? -> Select a name # Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty -developmentEnvironmentUserName = "Developer" +developmentEnvironmentUserName = Developer # Define a source file of your project with: # public static final String VERSION = "GRADLETOKEN_VERSION"; From 23a1fd92366c02cb6967e66e3e8da2e7ff74903a Mon Sep 17 00:00:00 2001 From: bombcar Date: Thu, 23 Dec 2021 11:38:40 -0600 Subject: [PATCH 141/219] logger --- .../codechicken/core/launch/DepLoader.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index 0032ed5..c4f46b5 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -12,6 +12,8 @@ import sun.misc.URLClassPath; import sun.net.util.URLUtil; +import codechicken.core.launch.CodeChickenCorePlugin; + import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; @@ -318,9 +320,9 @@ private void deleteMod(File mod) { if (!mod.delete()) { mod.deleteOnExit(); String msg = owner + " was unable to delete file " + mod.getPath() + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; - System.err.println(msg); + CodeChickenCorePlugin.logger.error(msg); if (!GraphicsEnvironment.isHeadless()) - JOptionPane.showMessageDialog(null, msg, "An update error has occured", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, msg, "An update error has occurred", JOptionPane.ERROR_MESSAGE); System.exit(1); } @@ -332,7 +334,7 @@ private void download(Dependency dep) { try { URL libDownload = new URL(dep.url + '/' + dep.file.filename); downloadMonitor.updateProgressString("Downloading file %s", libDownload.toString()); - System.out.format("Downloading file %s\n", libDownload.toString()); + CodeChickenCorePlugin.logger.debug("Downloading file " + libDownload); URLConnection connection = libDownload.openConnection(); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); @@ -340,13 +342,13 @@ private void download(Dependency dep) { int sizeGuess = connection.getContentLength(); download(connection.getInputStream(), sizeGuess, libFile); downloadMonitor.updateProgressString("Download complete"); - System.out.println("Download complete"); + CodeChickenCorePlugin.logger.trace("Download complete"); scanDepInfo(libFile); } catch (Exception e) { libFile.delete(); if (downloadMonitor.shouldStopIt()) { - System.err.println("You have stopped the downloading operation before it could complete"); + CodeChickenCorePlugin.logger.error("You have stopped the downloading operation before it could complete"); System.exit(1); return; } @@ -428,12 +430,12 @@ private String checkExisting(Dependency dep) { int cmp = vfile.version.compareTo(dep.file.version); if (cmp < 0) { - System.out.println("Deleted old version " + f.getName()); + CodeChickenCorePlugin.logger.warn("Deleted old version " + f.getName()); deleteMod(f); return null; } if (cmp > 0) { - System.err.println("Warning: version of " + dep.file.name + ", " + vfile.version + " is newer than request " + dep.file.version); + CodeChickenCorePlugin.logger.warn("Warning: version of " + dep.file.name + ", " + vfile.version + " is newer than request " + dep.file.version); return f.getName(); } return f.getName();//found dependency @@ -507,7 +509,7 @@ private void scanDepInfo(File file) { loadJSon(zip.getInputStream(e)); zip.close(); } catch (Exception e) { - System.err.println("Failed to load dependencies.info from " + file.getName() + " as JSON"); + CodeChickenCorePlugin.logger.error("Failed to load dependencies.info from " + file.getName() + " as JSON"); e.printStackTrace(); } } @@ -547,7 +549,7 @@ private void loadJson(JsonObject node) throws IOException { if(node.has("pattern")) pattern = Pattern.compile(node.get("pattern").getAsString()); } catch (PatternSyntaxException e) { - System.err.println("Invalid filename pattern: "+node.get("pattern")); + CodeChickenCorePlugin.logger.error("Invalid filename pattern: " + node.get("pattern")); e.printStackTrace(); } if(pattern == null) From 1cca8bba346c98e5f213b78bce962671f36e2928 Mon Sep 17 00:00:00 2001 From: bombcar Date: Thu, 23 Dec 2021 11:46:31 -0600 Subject: [PATCH 142/219] another System.out --- src/main/java/codechicken/core/ProfileTimer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/codechicken/core/ProfileTimer.java b/src/main/java/codechicken/core/ProfileTimer.java index 86b4d8a..627ac65 100644 --- a/src/main/java/codechicken/core/ProfileTimer.java +++ b/src/main/java/codechicken/core/ProfileTimer.java @@ -1,5 +1,7 @@ package codechicken.core; +import codechicken.core.launch.CodeChickenCorePlugin; + public class ProfileTimer { public double decay; @@ -33,7 +35,6 @@ public void end() { scanCount++; if(logScans > 0 && scanCount % logScans == 0) - System.out.println("Profiled " + logName + " " + nanoTime + "ns"); - + CodeChickenCorePlugin.logger.info("Profiled " + logName + " " + nanoTime + "ns"); } } From bd177ae0bc18717899d5be245521b9f9866eb471 Mon Sep 17 00:00:00 2001 From: bombcar Date: Fri, 31 Dec 2021 22:37:18 -0600 Subject: [PATCH 143/219] add an early low memory error to GTNH --- gradle.properties | 10 +-- .../core/launch/CodeChickenCorePlugin.java | 65 ++++++++++++++++++- .../codechicken/core/launch/DepLoader.java | 2 +- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index 6f45dd6..55f3a6d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,15 +15,15 @@ autoUpdateBuildScript = false minecraftVersion = 1.7.10 forgeVersion = 10.13.4.1614 -# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name each time you +# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you # restart Minecraft in development. Choose this dependent on your mod: # Do you need consistent player progressing (for example Thaumcraft)? -> Select a name # Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty -developmentEnvironmentUserName = "Developer" +developmentEnvironmentUserName = Developer # Define a source file of your project with: # public static final String VERSION = "GRADLETOKEN_VERSION"; -# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's +# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's # version in @Mod([...], version = VERSION, [...]) # Leave these properties empty to skip individual token replacements replaceGradleTokenInFile = CodeChickenCoreModContainer.java @@ -32,7 +32,7 @@ gradleTokenModName = GRADLETOKEN_MODNAME gradleTokenVersion = GRADLETOKEN_VERSION gradleTokenGroupName = -# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can +# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can # leave this property empty. # Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api apiPackage = @@ -48,7 +48,7 @@ mixinPlugin = # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! mixinsPackage = # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! -# This parameter is for legacy compatability only +# This parameter is for legacy compatibility only # Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin coreModClass = core.launch.CodeChickenCorePlugin # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 5ff5ebf..d572898 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -1,9 +1,12 @@ package codechicken.core.launch; -import java.awt.Desktop; +import java.awt.*; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.text.CharacterIterator; +import java.text.NumberFormat; +import java.text.StringCharacterIterator; import java.util.List; import java.util.Map; import java.util.jar.Attributes; @@ -16,6 +19,7 @@ import javax.swing.event.HyperlinkListener; import codechicken.core.asm.*; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.CoreModManager; import cpw.mods.fml.common.versioning.DefaultArtifactVersion; @@ -91,6 +95,64 @@ public void hyperlinkUpdate(HyperlinkEvent event) { } } + public static long parseSize(String text) { + double d = Double.parseDouble(text.replaceAll("[GMK]B?$", "")); + long l = Math.round(d * 1024 * 1024 * 1024L); + switch (text.replaceAll("\\d?","").toUpperCase().charAt(0)) { + default: l /= 1024; + case 'K': l /= 1024; + case 'M': l /= 1024; + case 'G': return l; + } + } + + public static String humanReadableByteCountBin(long bytes) { + long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes); + if (absB < 1024) { + return bytes + " B"; + } + long value = absB; + CharacterIterator ci = new StringCharacterIterator("KMGTPE"); + for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) { + value >>= 10; + ci.next(); + } + value *= Long.signum(bytes); + return String.format("%.1f %ciB", value / 1024.0, ci.current()); + } + + public static void systemCheck(String minRAM) { + long minBytes = parseSize(minRAM); + if (Runtime.getRuntime().maxMemory() < minBytes) { + String err = "You should have at least " + minRAM + "of RAM but you have only allocated " + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; + logger.error(err); + + JEditorPane ep = new JEditorPane("text/html", + "" + + err + + "
GTNH seriously won't run without enough RAM. See
the Wiki for details." + + "
Recommended values are between 4GB and 6GB. Check your launcher's JVM arguments." + + ""); + + ep.setEditable(false); + ep.setOpaque(false); + ep.addHyperlinkListener(new HyperlinkListener() + { + @Override + public void hyperlinkUpdate(HyperlinkEvent event) { + try { + if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) + Desktop.getDesktop().browse(event.getURL().toURI()); + } catch (Exception ignored) {} + } + }); + + if (!GraphicsEnvironment.isHeadless()) + JOptionPane.showMessageDialog(null, ep, "lol nope", JOptionPane.ERROR_MESSAGE); + FMLCommonHandler.instance().exitJava(-99, true); + } + } + @Override public String[] getASMTransformerClass() { versionCheck(mcVersion, "CodeChickenCore"); @@ -124,6 +186,7 @@ public void injectData(Map data) { @Override public Void call() { CodeChickenCoreModContainer.loadConfig(); + systemCheck(CodeChickenCoreModContainer.config.getTag("minRAM").getValue("3GB")); TweakTransformer.load(); scanCodeChickenMods(); diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index c4f46b5..bf4e7d7 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -186,7 +186,7 @@ public void hyperlinkUpdate(HyperlinkEvent event) { } }); - JOptionPane.showMessageDialog(null, ep, "A download error has occured", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, ep, "A download error has occurred", JOptionPane.ERROR_MESSAGE); } } From 6aa549db9ac6b567cb7e4f36a9ca8622ec088155 Mon Sep 17 00:00:00 2001 From: bombcar Date: Fri, 31 Dec 2021 22:41:20 -0600 Subject: [PATCH 144/219] typo --- .../java/codechicken/core/launch/CodeChickenCorePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index d572898..00bd76d 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -124,7 +124,7 @@ public static String humanReadableByteCountBin(long bytes) { public static void systemCheck(String minRAM) { long minBytes = parseSize(minRAM); if (Runtime.getRuntime().maxMemory() < minBytes) { - String err = "You should have at least " + minRAM + "of RAM but you have only allocated " + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; + String err = "You should have at least " + minRAM + " of RAM but you have only allocated " + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; logger.error(err); JEditorPane ep = new JEditorPane("text/html", From 3adeff110faf6b353829901f9ea07cfa974f6537 Mon Sep 17 00:00:00 2001 From: bombcar Date: Sat, 1 Jan 2022 01:37:59 -0600 Subject: [PATCH 145/219] update exit code --- .../java/codechicken/core/launch/CodeChickenCorePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 00bd76d..4dc82e5 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -149,7 +149,7 @@ public void hyperlinkUpdate(HyperlinkEvent event) { if (!GraphicsEnvironment.isHeadless()) JOptionPane.showMessageDialog(null, ep, "lol nope", JOptionPane.ERROR_MESSAGE); - FMLCommonHandler.instance().exitJava(-99, true); + FMLCommonHandler.instance().exitJava(-98, true); } } From 352301c8eaad5144175147e78333afec8f9363bd Mon Sep 17 00:00:00 2001 From: bombcar Date: Sat, 1 Jan 2022 01:49:42 -0600 Subject: [PATCH 146/219] use GB instead of GiB --- .../java/codechicken/core/launch/CodeChickenCorePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 4dc82e5..40d7c1e 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -118,7 +118,7 @@ public static String humanReadableByteCountBin(long bytes) { ci.next(); } value *= Long.signum(bytes); - return String.format("%.1f %ciB", value / 1024.0, ci.current()); + return String.format("%.1f %cB", value / 1024.0, ci.current()); } public static void systemCheck(String minRAM) { From 0fc1466f9c4e3d10f6572a22bd1d51737992d9b9 Mon Sep 17 00:00:00 2001 From: bombcar Date: Sat, 1 Jan 2022 01:50:58 -0600 Subject: [PATCH 147/219] remove unused import --- src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 40d7c1e..284b84d 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -5,7 +5,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.text.CharacterIterator; -import java.text.NumberFormat; import java.text.StringCharacterIterator; import java.util.List; import java.util.Map; From cfd00f33c8daabfaebebac4f78c717a693eec48d Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 17 Jan 2022 19:20:12 -0800 Subject: [PATCH 148/219] maven publish buildscript update --- .github/workflows/release-tags.yml | 6 +++++ CODEOWNERS | 3 +++ build.gradle | 41 +++++++++++++++--------------- 3 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 CODEOWNERS diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml index 25c354b..c86d888 100644 --- a/.github/workflows/release-tags.yml +++ b/.github/workflows/release-tags.yml @@ -43,3 +43,9 @@ jobs: prerelease: false title: "${{ env.RELEASE_VERSION }}" files: build/libs/*.jar + + - name: Publish to Maven + run: ./gradlew publish + env: + MAVEN_USER: ${{ secrets.MAVEN_USER }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..a6b5f68 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +# Any Github changes require admin approval +/.github/** @GTNewHorizons/admin + diff --git a/build.gradle b/build.gradle index 43dfa37..cd021ef 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,9 @@ -//version: 8fa7883b6196c1765266f4e6ddf3118d5043aafb +//version: 1642464427 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. -Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates. +Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. */ @@ -32,7 +32,7 @@ buildscript { } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' } } @@ -151,12 +151,16 @@ configurations.all { // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version 'git config core.fileMode false'.execute() -// Pulls version from git tag + +// Pulls version first from the VERSION env and then git tag +String identifiedVersion try { - version = minecraftVersion + "-" + gitVersion() + String versionOverride = System.getenv("VERSION") ?: null + identifiedVersion = versionOverride == null ? gitVersion() : versionOverride + version = minecraftVersion + "-" + identifiedVersion } catch (Exception e) { - throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); + throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag, or the VERSION override must be set!"); } group = modGroup @@ -223,7 +227,7 @@ dependencies { annotationProcessor("com.google.code.gson:gson:2.8.6") annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") // using 0.8 to workaround a issue in 0.7 which fails mixin application - compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + compile("com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH") { // Mixin includes a lot of dependencies that are too up-to-date exclude module: "launchwrapper" exclude module: "guava" @@ -231,7 +235,7 @@ dependencies { exclude module: "commons-io" exclude module: "log4j-core" } - compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev") + compile("com.github.GTNewHorizons:SpongeMixins:1.5.0") } } @@ -498,22 +502,19 @@ publishing { artifact source: apiJar, classifier: "api" } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" artifactId = System.getenv("ARTIFACT_ID") ?: project.name - version = System.getenv("ARTIFACT_VERSION") ?: project.version + // Using the identified version, not project.version as it has the prepended 1.7.10 + version = System.getenv("RELEASE_VERSION") ?: identifiedVersion } } - + repositories { maven { - String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" - String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" - String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" - name = "GitHubPackages" - url = githubRepositoryUrl + url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" credentials { - username = System.getenv("GITHUB_ACTOR") ?: "NONE" - password = System.getenv("GITHUB_TOKEN") ?: "NONE" + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" } } } @@ -537,7 +538,7 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { } static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle") } boolean performBuildScriptUpdate(String projectDir) { @@ -579,7 +580,7 @@ configure(updateBuildScript) { def checkPropertyExists(String propertyName) { if (project.hasProperty(propertyName) == false) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") } } From 9adf1b66502b217652e1fec79b3df38e962b5841 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 17 Jan 2022 20:13:53 -0800 Subject: [PATCH 149/219] maven publish buildscript update --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..a6b5f68 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +# Any Github changes require admin approval +/.github/** @GTNewHorizons/admin + From a37aeac5350f39bc4dcea08a8450c2e4c41e64a8 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 17 Jan 2022 20:15:32 -0800 Subject: [PATCH 150/219] maven publish buildscript update --- .github/workflows/release-tags.yml | 6 +++++ build.gradle | 41 +++++++++++++++--------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml index 25c354b..c86d888 100644 --- a/.github/workflows/release-tags.yml +++ b/.github/workflows/release-tags.yml @@ -43,3 +43,9 @@ jobs: prerelease: false title: "${{ env.RELEASE_VERSION }}" files: build/libs/*.jar + + - name: Publish to Maven + run: ./gradlew publish + env: + MAVEN_USER: ${{ secrets.MAVEN_USER }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} diff --git a/build.gradle b/build.gradle index 43dfa37..cd021ef 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,9 @@ -//version: 8fa7883b6196c1765266f4e6ddf3118d5043aafb +//version: 1642464427 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. -Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates. +Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. */ @@ -32,7 +32,7 @@ buildscript { } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' } } @@ -151,12 +151,16 @@ configurations.all { // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version 'git config core.fileMode false'.execute() -// Pulls version from git tag + +// Pulls version first from the VERSION env and then git tag +String identifiedVersion try { - version = minecraftVersion + "-" + gitVersion() + String versionOverride = System.getenv("VERSION") ?: null + identifiedVersion = versionOverride == null ? gitVersion() : versionOverride + version = minecraftVersion + "-" + identifiedVersion } catch (Exception e) { - throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); + throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag, or the VERSION override must be set!"); } group = modGroup @@ -223,7 +227,7 @@ dependencies { annotationProcessor("com.google.code.gson:gson:2.8.6") annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") // using 0.8 to workaround a issue in 0.7 which fails mixin application - compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + compile("com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH") { // Mixin includes a lot of dependencies that are too up-to-date exclude module: "launchwrapper" exclude module: "guava" @@ -231,7 +235,7 @@ dependencies { exclude module: "commons-io" exclude module: "log4j-core" } - compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev") + compile("com.github.GTNewHorizons:SpongeMixins:1.5.0") } } @@ -498,22 +502,19 @@ publishing { artifact source: apiJar, classifier: "api" } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" artifactId = System.getenv("ARTIFACT_ID") ?: project.name - version = System.getenv("ARTIFACT_VERSION") ?: project.version + // Using the identified version, not project.version as it has the prepended 1.7.10 + version = System.getenv("RELEASE_VERSION") ?: identifiedVersion } } - + repositories { maven { - String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" - String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" - String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" - name = "GitHubPackages" - url = githubRepositoryUrl + url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" credentials { - username = System.getenv("GITHUB_ACTOR") ?: "NONE" - password = System.getenv("GITHUB_TOKEN") ?: "NONE" + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" } } } @@ -537,7 +538,7 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { } static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle") } boolean performBuildScriptUpdate(String projectDir) { @@ -579,7 +580,7 @@ configure(updateBuildScript) { def checkPropertyExists(String propertyName) { if (project.hasProperty(propertyName) == false) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") } } From 1ee3abf0ff795762a2a8e169746014e57715a41c Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 17 Jan 2022 20:23:27 -0800 Subject: [PATCH 151/219] update dependencies --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 2ace0e6..08759fe 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ // Add your dependencies here dependencies { - compile("com.github.GTNewHorizons:CodeChickenLib:master-SNAPSHOT:dev") + compile("com.github.GTNewHorizons:CodeChickenLib:1.1.5.1:dev") } From 5423d96eb787fee3b139b364d46b06bde0c49647 Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 1 Feb 2022 13:47:00 -0600 Subject: [PATCH 152/219] update build script (#4) --- build.gradle | 154 +++++++++++++++++++++++++++++++++++++------- gradle.properties | 8 +-- repositories.gradle | 4 ++ 3 files changed, 138 insertions(+), 28 deletions(-) diff --git a/build.gradle b/build.gradle index cd021ef..7914dd8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1642464427 +//version: 1643020202 /* DO NOT CHANGE THIS FILE! @@ -32,16 +32,18 @@ buildscript { } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7' } } plugins { id 'idea' + id 'eclipse' id 'scala' id("org.ajoberstar.grgit") version("3.1.1") id("com.github.johnrengelman.shadow") version("4.0.4") id("com.palantir.git-version") version("0.12.3") + id('de.undercouch.download') version('4.1.2') id("maven-publish") } @@ -88,6 +90,7 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") +boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" @@ -171,6 +174,19 @@ else { archivesBaseName = modId } + +def arguments = [] +def jvmArguments = [] + +if(usesMixins.toBoolean()) { + arguments += [ + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + jvmArguments += [ + "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" + ] +} + minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion runDir = "run" @@ -190,6 +206,20 @@ minecraft { replace gradleTokenGroupName, modGroup } } + + clientIntellijRun { + args(arguments) + jvmArgs(jvmArguments) + + if(developmentEnvironmentUserName) { + args("--username", developmentEnvironmentUserName) + } + } + + serverIntellijRun { + args(arguments) + jvmArgs(jvmArguments) + } } if(file("addon.gradle").exists()) { @@ -321,15 +351,6 @@ afterEvaluate { } runClient { - def arguments = [] - - if(usesMixins.toBoolean()) { - arguments += [ - "--mods=../build/libs/$modId-${version}.jar", - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - } - if(developmentEnvironmentUserName) { arguments += [ "--username", @@ -338,19 +359,12 @@ runClient { } args(arguments) + jvmArgs(jvmArguments) } runServer { - def arguments = [] - - if (usesMixins.toBoolean()) { - arguments += [ - "--mods=../build/libs/$modId-${version}.jar", - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - } - args(arguments) + jvmArgs(jvmArguments) } tasks.withType(JavaExec).configureEach { @@ -484,20 +498,34 @@ task apiJar(type: Jar) { } artifacts { - archives sourcesJar + if(!noPublishedSources) { + archives sourcesJar + } archives devJar if(apiPackage) { archives apiJar } } +// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), +// and isn't strictly needed with the POM so just disable it. +tasks.withType(GenerateModuleMetadata) { + enabled = false +} + + // publishing publishing { publications { maven(MavenPublication) { - artifact source: jar - artifact source: sourcesJar, classifier: "src" - artifact source: devJar, classifier: "dev" + from components.java + if(usesShadowedDependencies.toBoolean()) { + artifact source: shadowJar, classifier: "" + } + if(!noPublishedSources) { + artifact source: sourcesJar, classifier: "src" + } + artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage) { artifact source: apiJar, classifier: "api" } @@ -506,6 +534,18 @@ publishing { artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + + // Remove all non GTNH deps here. + // Original intention was to remove an invalid forgeBin being generated without a groupId (mandatory), but + // it also removes all of the MC deps + pom.withXml { + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + it.groupId.text() != 'com.github.GTNewHorizons' + }.each() { + it.parent().remove(it) + } + } } } @@ -576,6 +616,72 @@ configure(updateBuildScript) { description = 'Updates the build script to the latest version' } +// Deobfuscation + +def deobf(String sourceURL) { + try { + URL url = new URL(sourceURL) + String fileName = url.getFile() + + //get rid of directories: + int lastSlash = fileName.lastIndexOf("/") + if(lastSlash > 0) { + fileName = fileName.substring(lastSlash + 1) + } + //get rid of extension: + if(fileName.endsWith(".jar")) { + fileName = fileName.substring(0, fileName.lastIndexOf(".")) + } + + String hostName = url.getHost() + if(hostName.startsWith("www.")) { + hostName = hostName.substring(4) + } + List parts = Arrays.asList(hostName.split("\\.")) + Collections.reverse(parts) + hostName = String.join(".", parts) + + return deobf(sourceURL, hostName + "/" + fileName) + } catch(Exception e) { + return deobf(sourceURL, "deobf/" + String.valueOf(sourceURL.hashCode())) + } +} + +// The method above is to be prefered. Use this method if the filename is not at the end of the URL. +def deobf(String sourceURL, String fileName) { + String cacheDir = System.getProperty("user.home") + "/.gradle/caches/" + String bon2Dir = cacheDir + "forge_gradle/deobf" + String bon2File = bon2Dir + "/BON2-2.5.0.jar" + String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar" + String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar" + + if(file(deobfFile).exists()) { + return files(deobfFile) + } + + download { + src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar' + dest bon2File + quiet true + overwrite false + } + + download { + src sourceURL + dest obfFile + quiet true + overwrite false + } + + exec { + commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch' + workingDir bon2Dir + standardOutput = new ByteArrayOutputStream() + } + + return files(deobfFile) +} + // Helper methods def checkPropertyExists(String propertyName) { diff --git a/gradle.properties b/gradle.properties index 76af7f9..59d5c49 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,7 @@ autoUpdateBuildScript = false minecraftVersion = 1.7.10 forgeVersion = 10.13.4.1614 -# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name each time you +# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you # restart Minecraft in development. Choose this dependent on your mod: # Do you need consistent player progressing (for example Thaumcraft)? -> Select a name # Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty @@ -23,7 +23,7 @@ developmentEnvironmentUserName = Developer # Define a source file of your project with: # public static final String VERSION = "GRADLETOKEN_VERSION"; -# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's +# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's # version in @Mod([...], version = VERSION, [...]) # Leave these properties empty to skip individual token replacements replaceGradleTokenInFile = @@ -37,7 +37,7 @@ gradleTokenGroupName = # Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api apiPackage = -# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/ +# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ # Example value: mymodid_at.cfg accessTransformersFile = @@ -48,7 +48,7 @@ mixinPlugin = # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! mixinsPackage = # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! -# This parameter is for legacy compatability only +# This parameter is for legacy compatibility only # Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin coreModClass = # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class diff --git a/repositories.gradle b/repositories.gradle index f7d641b..871afc7 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,5 +1,9 @@ // Add any additional repositiroes for your dependencies here repositories { + maven { + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + } } From 817438ec827f93ec721a4689ece631abad105d37 Mon Sep 17 00:00:00 2001 From: bombcar Date: Fri, 11 Feb 2022 10:09:24 -0600 Subject: [PATCH 153/219] Remove MCVersion warning (#6) * buildscript * fix hammer --- build.gradle | 296 +++++++++++++----- dependencies.gradle | 2 +- repositories.gradle | 7 +- .../core/launch/CodeChickenCorePlugin.java | 2 + .../codechicken/core/launch/DepLoader.java | 6 +- src/main/resources/mcmod.info | 4 +- 6 files changed, 231 insertions(+), 86 deletions(-) diff --git a/build.gradle b/build.gradle index cd021ef..3d3fd92 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,14 @@ -//version: 1642464427 +//version: 1644510936 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. - */ +*/ +import org.gradle.internal.logging.text.StyledTextOutput +import org.gradle.internal.logging.text.StyledTextOutputFactory +import org.gradle.internal.logging.text.StyledTextOutput.Style import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar @@ -15,36 +18,46 @@ import java.util.concurrent.TimeUnit buildscript { repositories { maven { - name = "forge" - url = "https://maven.minecraftforge.net" + name 'forge' + url 'https://maven.minecraftforge.net' } maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' } maven { - name = "Scala CI dependencies" - url = "https://repo1.maven.org/maven2/" + name 'Scala CI dependencies' + url 'https://repo1.maven.org/maven2/' } maven { - name = "jitpack" - url = "https://jitpack.io" + name 'jitpack' + url 'https://jitpack.io' } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7' } } plugins { + id 'java-library' id 'idea' + id 'eclipse' id 'scala' - id("org.ajoberstar.grgit") version("3.1.1") - id("com.github.johnrengelman.shadow") version("4.0.4") - id("com.palantir.git-version") version("0.12.3") - id("maven-publish") + id 'maven-publish' + id('org.jetbrains.kotlin.jvm') version ('1.6.10') apply false + id('org.ajoberstar.grgit') version('4.1.1') + id('com.github.johnrengelman.shadow') version('4.0.4') + id('com.palantir.git-version') version('0.13.0') apply false + id('de.undercouch.download') version('5.0.1') } +if (project.file('.git/HEAD').isFile()) { + apply plugin: 'com.palantir.git-version' +} + +def out = services.get(StyledTextOutputFactory).create("an-output") + apply plugin: 'forge' def projectJavaVersion = JavaLanguageVersion.of(8) @@ -88,27 +101,31 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") +boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" +String kotlinSourceDir = "src/main/kotlin/" String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") -if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) +String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") +if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } if(apiPackage) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } } if(accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(getFile(targetFile).exists() == false) { + if(!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } @@ -120,15 +137,17 @@ if(usesMixins.toBoolean()) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { - throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt" + if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) } } @@ -136,8 +155,9 @@ if(coreModClass) { String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { - throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt" + if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) } } @@ -150,17 +170,33 @@ configurations.all { } // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version -'git config core.fileMode false'.execute() +try { + 'git config core.fileMode false'.execute() +} +catch (Exception e) { + out.style(Style.Failure).println("git isn't installed at all") +} // Pulls version first from the VERSION env and then git tag String identifiedVersion +String versionOverride = System.getenv("VERSION") ?: null try { - String versionOverride = System.getenv("VERSION") ?: null identifiedVersion = versionOverride == null ? gitVersion() : versionOverride - version = minecraftVersion + "-" + identifiedVersion } catch (Exception e) { - throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag, or the VERSION override must be set!"); + out.style(Style.Failure).text( + 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' + + 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + + 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)' + ) + versionOverride = 'NO-GIT-TAG-SET' + identifiedVersion = versionOverride +} +version = minecraftVersion + '-' + identifiedVersion +String modVersion = identifiedVersion + +if( identifiedVersion.equals(versionOverride) ) { + out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } group = modGroup @@ -171,6 +207,19 @@ else { archivesBaseName = modId } + +def arguments = [] +def jvmArguments = [] + +if(usesMixins.toBoolean()) { + arguments += [ + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + jvmArguments += [ + "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" + ] +} + minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion runDir = "run" @@ -184,12 +233,26 @@ minecraft { replace gradleTokenModName, modName } if(gradleTokenVersion) { - replace gradleTokenVersion, versionDetails().lastTag + replace gradleTokenVersion, modVersion } if(gradleTokenGroupName) { replace gradleTokenGroupName, modGroup } } + + clientIntellijRun { + args(arguments) + jvmArgs(jvmArguments) + + if(developmentEnvironmentUserName) { + args("--username", developmentEnvironmentUserName) + } + } + + serverIntellijRun { + args(arguments) + jvmArgs(jvmArguments) + } } if(file("addon.gradle").exists()) { @@ -206,36 +269,36 @@ configurations { repositories { maven { - name = "Overmind forge repo mirror" - url = "https://gregtech.overminddl1.com/" + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' } if(usesMixins.toBoolean()) { maven { - name = "sponge" - url = "https://repo.spongepowered.org/repository/maven-public" + name 'sponge' + url 'https://repo.spongepowered.org/repository/maven-public' } maven { - url = "https://jitpack.io" + url 'https://jitpack.io' } } } dependencies { if(usesMixins.toBoolean()) { - annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3") - annotationProcessor("com.google.guava:guava:24.1.1-jre") - annotationProcessor("com.google.code.gson:gson:2.8.6") - annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") + annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') + annotationProcessor('com.google.guava:guava:24.1.1-jre') + annotationProcessor('com.google.code.gson:gson:2.8.6') + annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT') // using 0.8 to workaround a issue in 0.7 which fails mixin application - compile("com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH") { + compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') { // Mixin includes a lot of dependencies that are too up-to-date - exclude module: "launchwrapper" - exclude module: "guava" - exclude module: "gson" - exclude module: "commons-io" - exclude module: "log4j-core" + exclude module: 'launchwrapper' + exclude module: 'guava' + exclude module: 'gson' + exclude module: 'commons-io' + exclude module: 'log4j-core' } - compile("com.github.GTNewHorizons:SpongeMixins:1.5.0") + compile('com.github.GTNewHorizons:SpongeMixins:1.5.0') } } @@ -321,15 +384,6 @@ afterEvaluate { } runClient { - def arguments = [] - - if(usesMixins.toBoolean()) { - arguments += [ - "--mods=../build/libs/$modId-${version}.jar", - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - } - if(developmentEnvironmentUserName) { arguments += [ "--username", @@ -338,19 +392,12 @@ runClient { } args(arguments) + jvmArgs(jvmArguments) } runServer { - def arguments = [] - - if (usesMixins.toBoolean()) { - arguments += [ - "--mods=../build/libs/$modId-${version}.jar", - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - } - args(arguments) + jvmArgs(jvmArguments) } tasks.withType(JavaExec).configureEach { @@ -366,23 +413,23 @@ processResources // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version - + // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { include 'mcmod.info' - // replace version and mcversion + // replace modVersion and minecraftVersion expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName + "modVersion": modVersion, + "modId": modId, + "modName": modName } if(usesMixins.toBoolean()) { from refMap } - // copy everything else, thats not the mcmod.info + // copy everything else that's not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' } @@ -484,20 +531,32 @@ task apiJar(type: Jar) { } artifacts { - archives sourcesJar + if(!noPublishedSources) { + archives sourcesJar + } archives devJar if(apiPackage) { archives apiJar } } -// publishing +// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), +// and isn't strictly needed with the POM so just disable it. +tasks.withType(GenerateModuleMetadata) { + enabled = false +} + publishing { publications { maven(MavenPublication) { - artifact source: jar - artifact source: sourcesJar, classifier: "src" - artifact source: devJar, classifier: "dev" + from components.java + if(usesShadowedDependencies.toBoolean()) { + artifact source: shadowJar, classifier: "" + } + if(!noPublishedSources) { + artifact source: sourcesJar, classifier: "src" + } + artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage) { artifact source: apiJar, classifier: "api" } @@ -506,6 +565,21 @@ publishing { artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + + // remove extra garbage from who knows where + pom.withXml { + def badPomGroup = ['net.minecraft', 'com.google.code.findbugs', 'org.ow2.asm', 'com.typesafe.akka', 'com.typesafe', 'org.scala-lang', + 'org.scala-lang.plugins', 'net.sf.jopt-simple', 'lzma', 'com.mojang', 'org.apache.commons', 'org.apache.httpcomponents', + 'commons-logging', 'java3d', 'net.sf.trove4j', 'com.ibm.icu', 'com.paulscode', 'io.netty', 'com.google.guava', + 'commons-io', 'commons-codec', 'net.java.jinput', 'net.java.jutils', 'com.google.code.gson', 'org.apache.logging.log4j', + 'org.lwjgl.lwjgl', 'tv.twitch', ''] + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + badPomGroup.contains(it.groupId.text()) + }.each() { + it.parent().remove(it) + } + } } } @@ -533,7 +607,7 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { performBuildScriptUpdate(projectDir.toString()) } else { - println("Build script update available! Run 'gradle updateBuildScript'") + out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") } } @@ -545,7 +619,7 @@ boolean performBuildScriptUpdate(String projectDir) { if (isNewBuildScriptVersionAvailable(projectDir)) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } - print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") return true } return false @@ -576,6 +650,72 @@ configure(updateBuildScript) { description = 'Updates the build script to the latest version' } +// Deobfuscation + +def deobf(String sourceURL) { + try { + URL url = new URL(sourceURL) + String fileName = url.getFile() + + //get rid of directories: + int lastSlash = fileName.lastIndexOf("/") + if(lastSlash > 0) { + fileName = fileName.substring(lastSlash + 1) + } + //get rid of extension: + if(fileName.endsWith(".jar")) { + fileName = fileName.substring(0, fileName.lastIndexOf(".")) + } + + String hostName = url.getHost() + if(hostName.startsWith("www.")) { + hostName = hostName.substring(4) + } + List parts = Arrays.asList(hostName.split("\\.")) + Collections.reverse(parts) + hostName = String.join(".", parts) + + return deobf(sourceURL, hostName + "/" + fileName) + } catch(Exception e) { + return deobf(sourceURL, "deobf/" + String.valueOf(sourceURL.hashCode())) + } +} + +// The method above is to be preferred. Use this method if the filename is not at the end of the URL. +def deobf(String sourceURL, String fileName) { + String cacheDir = System.getProperty("user.home") + "/.gradle/caches/" + String bon2Dir = cacheDir + "forge_gradle/deobf" + String bon2File = bon2Dir + "/BON2-2.5.0.jar" + String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar" + String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar" + + if(file(deobfFile).exists()) { + return files(deobfFile) + } + + download.run { + src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar' + dest bon2File + quiet true + overwrite false + } + + download.run { + src sourceURL + dest obfFile + quiet true + overwrite false + } + + exec { + commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch' + workingDir bon2Dir + standardOutput = new ByteArrayOutputStream() + } + + return files(deobfFile) +} + // Helper methods def checkPropertyExists(String propertyName) { diff --git a/dependencies.gradle b/dependencies.gradle index 08759fe..5dc55d7 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ // Add your dependencies here dependencies { - compile("com.github.GTNewHorizons:CodeChickenLib:1.1.5.1:dev") + compile('com.github.GTNewHorizons:CodeChickenLib:1.1.5.3:dev') } diff --git a/repositories.gradle b/repositories.gradle index 7d02b58..c0d848e 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -2,6 +2,11 @@ repositories { maven { - url = "https://jitpack.io" + name 'GTNH Maven' + url 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/' + allowInsecureProtocol + } + maven { + url 'https://jitpack.io' } } diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 284b84d..34614ae 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -26,11 +26,13 @@ import cpw.mods.fml.relauncher.FMLInjectionData; import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @TransformerExclusions(value = {"codechicken.core.asm", "codechicken.obfuscator"}) +@MCVersion( "1.7.10" ) public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index bf4e7d7..c2c0376 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -8,12 +8,11 @@ import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import net.minecraft.launchwrapper.LaunchClassLoader; import sun.misc.URLClassPath; import sun.net.util.URLUtil; -import codechicken.core.launch.CodeChickenCorePlugin; - import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; @@ -30,8 +29,8 @@ import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.ByteBuffer; -import java.util.*; import java.util.List; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -42,6 +41,7 @@ * For autodownloading stuff. * This is really unoriginal, mostly ripped off FML, credits to cpw. */ +@MCVersion( "1.7.10" ) public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); private static final String owner = "CB's DepLoader"; diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 29f8f00..058b8a5 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -2,9 +2,7 @@ { "modid": "${modId}", "name": "${modName}", -"description": "Base common code for all chickenbones mods. - -Supporters: JBoyJr", +"description": "Base common code for all chickenbones mods. Supporters: JBoyJr", "version": "${modVersion}", "mcversion": "${minecraftVersion}", "url": "http://www.minecraftforum.net/topic/909223", From cd994ecd27aa5d5fc8477b83dc7838d5fdb6e417 Mon Sep 17 00:00:00 2001 From: bombcar Date: Thu, 17 Feb 2022 12:11:06 -0600 Subject: [PATCH 154/219] Fix memory check default on (#7) * fix memory check * update buildscripts * spaces * extra ) --- .editorconfig | 19 +++++ .github/scripts/test-no-crash-reports.sh | 9 --- .github/scripts/test_no_error_reports | 51 ++++++++++++ .github/workflows/build-and-test.yml | 20 ++--- build.gradle | 79 +++++++++++-------- gradle.properties | 2 +- .../core/launch/CodeChickenCorePlugin.java | 24 +++--- src/main/resources/mcmod.info | 19 ++--- 8 files changed, 150 insertions(+), 73 deletions(-) create mode 100644 .editorconfig delete mode 100644 .github/scripts/test-no-crash-reports.sh create mode 100755 .github/scripts/test_no_error_reports diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6effbc9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +# This is the universal Text Editor Configuration +# for all GTNewHorizons projects +# See: https://editorconfig.org/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{bat,ini}] +end_of_line = crlf + +[*.{dtd,json,info,mcmeta,md,sh,svg,xml,xsd,xsl,yaml,yml}] +indent_size = 2 diff --git a/.github/scripts/test-no-crash-reports.sh b/.github/scripts/test-no-crash-reports.sh deleted file mode 100644 index c67e342..0000000 --- a/.github/scripts/test-no-crash-reports.sh +++ /dev/null @@ -1,9 +0,0 @@ -directory="run/crash-reports" -if [ -d $directory ]; then - echo "Crash reports detected:" - cat $directory/* - exit 1 -else - echo "No crash reports detected" - exit 0 -fi diff --git a/.github/scripts/test_no_error_reports b/.github/scripts/test_no_error_reports new file mode 100755 index 0000000..1fcc739 --- /dev/null +++ b/.github/scripts/test_no_error_reports @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# bashsupport disable=BP5006 # Global environment variables +RUNDIR="run" \ + CRASH="crash-reports" \ + SERVERLOG="server.log" + +# enable nullglob to get 0 results when no match rather than the pattern +shopt -s nullglob + +# store matches in array +crash_reports=("$RUNDIR/$CRASH/crash"*.txt) + +# if array not empty there are crash_reports +if [ "${#crash_reports[@]}" -gt 0 ]; then + # get the latest crash_report from array + latest_crash_report="${crash_reports[-1]}" + { + printf 'Latest crash report detected %s:\n' "${latest_crash_report##*/}" + cat "$latest_crash_report" + } >&2 + exit 1 +fi + +if grep --quiet --fixed-strings 'Fatal errors were detected' "$SERVERLOG"; then + { + printf 'Fatal errors detected:\n' + cat server.log + } >&2 + exit 1 +fi + +if grep --quiet --fixed-strings 'The state engine was in incorrect state ERRORED and forced into state SERVER_STOPPED' \ + "$SERVERLOG"; then + { + printf 'Server force stopped:' + cat server.log + } >&2 + exit 1 +fi + +if ! grep --quiet --perl-regexp --only-matching '.+Done \(.+\)\! For help, type "help" or "\?"' "$SERVERLOG"; then + { + printf 'Server did not finish startup:' + cat server.log + } >&2 + exit 1 +fi + +printf 'No crash reports detected' +exit 0 diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 6c9b3cb..56a1ad5 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -14,32 +14,32 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - with: + with: fetch-depth: 0 - + - name: Set up JDK 8 uses: actions/setup-java@v2 with: java-version: '8' distribution: 'adopt' cache: gradle - + - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Setup the workspace run: ./gradlew setupCIWorkspace - + - name: Build the mod run: ./gradlew build - - name: Run server for 1 minute + - name: Run server for 1.5 minutes run: | mkdir run - echo "eula=true" > run/eula.txt - timeout 10 ./gradlew runServer || true + echo "eula=true" > run/eula.txt + timeout 90 ./gradlew runServer 2>&1 | tee -a server.log || true - - name: Test no crashes happend + - name: Test no errors reported during server run run: | - chmod +x .github/scripts/test-no-crash-reports.sh - .github/scripts/test-no-crash-reports.sh + chmod +x .github/scripts/test_no_error_reports + .github/scripts/test_no_error_reports diff --git a/build.gradle b/build.gradle index 3d3fd92..c8cf37c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1644510936 +//version: 1644894948 /* DO NOT CHANGE THIS FILE! @@ -6,7 +6,7 @@ Also, you may replace this file at any time if there is an update available. Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. */ -import org.gradle.internal.logging.text.StyledTextOutput +import org.gradle.internal.logging.text.StyledTextOutput import org.gradle.internal.logging.text.StyledTextOutputFactory import org.gradle.internal.logging.text.StyledTextOutput.Style @@ -45,18 +45,20 @@ plugins { id 'eclipse' id 'scala' id 'maven-publish' - id('org.jetbrains.kotlin.jvm') version ('1.6.10') apply false - id('org.ajoberstar.grgit') version('4.1.1') - id('com.github.johnrengelman.shadow') version('4.0.4') - id('com.palantir.git-version') version('0.13.0') apply false - id('de.undercouch.download') version('5.0.1') + id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false + id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false + id 'org.ajoberstar.grgit' version '4.1.1' + id 'com.github.johnrengelman.shadow' version '4.0.4' + id 'com.palantir.git-version' version '0.13.0' apply false + id 'de.undercouch.download' version '5.0.1' + id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false } if (project.file('.git/HEAD').isFile()) { apply plugin: 'com.palantir.git-version' } -def out = services.get(StyledTextOutputFactory).create("an-output") +def out = services.get(StyledTextOutputFactory).create('an-output') apply plugin: 'forge' @@ -173,7 +175,7 @@ configurations.all { try { 'git config core.fileMode false'.execute() } -catch (Exception e) { +catch (Exception ignored) { out.style(Style.Failure).println("git isn't installed at all") } @@ -183,19 +185,21 @@ String versionOverride = System.getenv("VERSION") ?: null try { identifiedVersion = versionOverride == null ? gitVersion() : versionOverride } -catch (Exception e) { +catch (Exception ignored) { out.style(Style.Failure).text( 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' + - 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + + 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)' ) versionOverride = 'NO-GIT-TAG-SET' identifiedVersion = versionOverride } version = minecraftVersion + '-' + identifiedVersion -String modVersion = identifiedVersion +ext { + modVersion = identifiedVersion +} -if( identifiedVersion.equals(versionOverride) ) { +if(identifiedVersion == versionOverride) { out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } @@ -207,7 +211,6 @@ else { archivesBaseName = modId } - def arguments = [] def jvmArguments = [] @@ -221,8 +224,8 @@ if(usesMixins.toBoolean()) { } minecraft { - version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion - runDir = "run" + version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion + runDir = 'run' if (replaceGradleTokenInFile) { replaceIn replaceGradleTokenInFile @@ -255,8 +258,8 @@ minecraft { } } -if(file("addon.gradle").exists()) { - apply from: "addon.gradle" +if(file('addon.gradle').exists()) { + apply from: 'addon.gradle' } apply from: 'repositories.gradle' @@ -304,7 +307,7 @@ dependencies { apply from: 'dependencies.gradle' -def mixingConfigRefMap = "mixins." + modId + ".refmap.json" +def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" @@ -408,12 +411,11 @@ tasks.withType(JavaExec).configureEach { ) } -processResources -{ +processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version - + // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { include 'mcmod.info' @@ -437,7 +439,7 @@ processResources def getManifestAttributes() { def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) { + if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } @@ -453,7 +455,7 @@ def getManifestAttributes() { manifestAttributes += [ "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean() ] } return manifestAttributes @@ -540,12 +542,15 @@ artifacts { } } -// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), +// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), // and isn't strictly needed with the POM so just disable it. tasks.withType(GenerateModuleMetadata) { enabled = false } +// workaround variable hiding in pom processing +def projectConfigs = project.configurations + publishing { publications { maven(MavenPublication) { @@ -565,17 +570,21 @@ publishing { artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - - // remove extra garbage from who knows where + + // remove extra garbage from minecraft and minecraftDeps configuration pom.withXml { - def badPomGroup = ['net.minecraft', 'com.google.code.findbugs', 'org.ow2.asm', 'com.typesafe.akka', 'com.typesafe', 'org.scala-lang', - 'org.scala-lang.plugins', 'net.sf.jopt-simple', 'lzma', 'com.mojang', 'org.apache.commons', 'org.apache.httpcomponents', - 'commons-logging', 'java3d', 'net.sf.trove4j', 'com.ibm.icu', 'com.paulscode', 'io.netty', 'com.google.guava', - 'commons-io', 'commons-codec', 'net.java.jinput', 'net.java.jutils', 'com.google.code.gson', 'org.apache.logging.log4j', - 'org.lwjgl.lwjgl', 'tv.twitch', ''] + def badArtifacts = [:].withDefault {[] as Set} + for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) { + for (dependency in configuration.allDependencies) { + badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name + } + } + // example for specifying extra stuff to ignore + // badArtifacts["org.example.group"] += "artifactName" + Node pomNode = asNode() pomNode.dependencies.'*'.findAll() { - badPomGroup.contains(it.groupId.text()) + badArtifacts[it.groupId.text()].contains(it.artifactId.text()) }.each() { it.parent().remove(it) } @@ -688,7 +697,7 @@ def deobf(String sourceURL, String fileName) { String bon2File = bon2Dir + "/BON2-2.5.0.jar" String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar" String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar" - + if(file(deobfFile).exists()) { return files(deobfFile) } @@ -719,7 +728,7 @@ def deobf(String sourceURL, String fileName) { // Helper methods def checkPropertyExists(String propertyName) { - if (project.hasProperty(propertyName) == false) { + if (!project.hasProperty(propertyName)) { throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") } } diff --git a/gradle.properties b/gradle.properties index 55f3a6d..5e76708 100644 --- a/gradle.properties +++ b/gradle.properties @@ -37,7 +37,7 @@ gradleTokenGroupName = # Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api apiPackage = -# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/ +# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ # Example value: mymodid_at.cfg accessTransformersFile = diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 34614ae..7f01222 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -18,6 +18,7 @@ import javax.swing.event.HyperlinkListener; import codechicken.core.asm.*; +import codechicken.lib.config.ConfigTag; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.CoreModManager; @@ -36,7 +37,8 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; - public static final String version = "GRADLETOKEN_VERSION"; + @Deprecated + public static final String version = "1.1.3-unused"; public static File minecraftDir; public static String currentMcVersion; @@ -122,17 +124,17 @@ public static String humanReadableByteCountBin(long bytes) { return String.format("%.1f %cB", value / 1024.0, ci.current()); } - public static void systemCheck(String minRAM) { - long minBytes = parseSize(minRAM); + public static void systemCheck(ConfigTag checkRAM) { + long minBytes = parseSize(checkRAM.getTag("minRAM").setComment("Amount of RAM minimum this modpack needs to load").getValue("3GB")); if (Runtime.getRuntime().maxMemory() < minBytes) { - String err = "You should have at least " + minRAM + " of RAM but you have only allocated " + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; + String err = "You should have at least " + humanReadableByteCountBin(minBytes) + " of RAM but you have only allocated " + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; logger.error(err); JEditorPane ep = new JEditorPane("text/html", - "" + - err + - "
GTNH seriously won't run without enough RAM. See the Wiki for details." + - "
Recommended values are between 4GB and 6GB. Check your launcher's JVM arguments." + + "" + err + "
" + checkRAM.getTag("modPack").setComment("Name of the modpack").getValue("Unidentified ModPack") + + " seriously won't run without enough RAM. " + checkRAM.getTag("wiki").setComment("Webpage describing RAM settings").getValue("See DownloadMoreRam.com for details.") + + "
Recommended values are between " + checkRAM.getTag("recRAM").setComment("Lower bound of recommended RAM").getValue("4GB") + " and " + + checkRAM.getTag("recRAMUpper").setComment("Upper bound of recommended RAM").getValue("6GB") + ". Check your launcher's JVM arguments." + ""); ep.setEditable(false); @@ -187,7 +189,11 @@ public void injectData(Map data) { @Override public Void call() { CodeChickenCoreModContainer.loadConfig(); - systemCheck(CodeChickenCoreModContainer.config.getTag("minRAM").getValue("3GB")); + ConfigTag checkRAM; + checkRAM = CodeChickenCoreModContainer.config.getTag("checks") + .setComment("Configuration options for checking various requirements for a modpack.").useBraces(); + if(checkRAM.getTag("checkRAM").setComment("If set to true, check RAM available for Minecraft before continuing to load").getBooleanValue(false)) + systemCheck(checkRAM); TweakTransformer.load(); scanCodeChickenMods(); diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 058b8a5..e5c2574 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -1,11 +1,12 @@ -[ { -"modid": "${modId}", -"name": "${modName}", -"description": "Base common code for all chickenbones mods. Supporters: JBoyJr", -"version": "${modVersion}", -"mcversion": "${minecraftVersion}", -"url": "http://www.minecraftforum.net/topic/909223", -"authorList": [ "ChickenBones" ] + "modListVersion": 2, + "modList": [{ + "modid": "${modId}", + "name": "${modName}", + "description": "Base common code for all chickenbones mods. Supporters: JBoyJr", + "version": "${modVersion}", + "mcversion": "${minecraftVersion}", + "url": "http://www.minecraftforum.net/topic/909223", + "authorList": ["ChickenBones"] + }] } -] \ No newline at end of file From 1908388ce750998b87b2b9c959bf34724aa5eae3 Mon Sep 17 00:00:00 2001 From: MuXiu1997 Date: Sat, 16 Apr 2022 14:39:07 +0800 Subject: [PATCH 155/219] Does not dump asm by default --- src/main/java/codechicken/lib/asm/ModularASMTransformer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java index 39e0d4c..e05ff4f 100644 --- a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java +++ b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java @@ -38,7 +38,7 @@ public byte[] transform(byte[] bytes) { } bytes = createBytes(cnode, writeFlags); - if(config.getTag("dump_asm").getBooleanValue(true)) + if(config.getTag("dump_asm").getBooleanValue(false)) dump(bytes, new File("asm/ccl_modular/"+cnode.name.replace('/', '#')+".txt"), false, false); return bytes; } catch (RuntimeException e) { From cef8a9cbc0da8f29cc7d77a65e9e446d29591e83 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sat, 16 Jul 2022 10:47:27 -0700 Subject: [PATCH 156/219] [ci skip] Migrate github actions to GTNH-Actions-Workflows --- .github/workflows/build-and-test.yml | 36 ++------------------ .github/workflows/release-tags.yml | 51 ++++------------------------ 2 files changed, 9 insertions(+), 78 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 56a1ad5..3ee2f68 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -1,5 +1,3 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Build and test @@ -11,35 +9,5 @@ on: jobs: build-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - name: Run server for 1.5 minutes - run: | - mkdir run - echo "eula=true" > run/eula.txt - timeout 90 ./gradlew runServer 2>&1 | tee -a server.log || true - - - name: Test no errors reported during server run - run: | - chmod +x .github/scripts/test_no_error_reports - .github/scripts/test_no_error_reports + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master + secrets: inherit diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml index c86d888..e4c0be6 100644 --- a/.github/workflows/release-tags.yml +++ b/.github/workflows/release-tags.yml @@ -1,51 +1,14 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Release tagged build on: push: - tags: - - '*' + tags: [ '*' ] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set release version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew +permissions: + contents: write - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - name: Release under current tag - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "${{ env.RELEASE_VERSION }}" - prerelease: false - title: "${{ env.RELEASE_VERSION }}" - files: build/libs/*.jar - - - name: Publish to Maven - run: ./gradlew publish - env: - MAVEN_USER: ${{ secrets.MAVEN_USER }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} +jobs: + release-tags: + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master + secrets: inherit From fcd42c8496018f1f0aa62225dd3f2a99614a079f Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sat, 16 Jul 2022 10:47:29 -0700 Subject: [PATCH 157/219] [ci skip] Migrate github actions to GTNH-Actions-Workflows --- .github/scripts/test-no-crash-reports.sh | 9 ----- .github/workflows/build-and-test.yml | 36 +---------------- .github/workflows/release-tags.yml | 51 ++++-------------------- 3 files changed, 9 insertions(+), 87 deletions(-) delete mode 100644 .github/scripts/test-no-crash-reports.sh diff --git a/.github/scripts/test-no-crash-reports.sh b/.github/scripts/test-no-crash-reports.sh deleted file mode 100644 index c67e342..0000000 --- a/.github/scripts/test-no-crash-reports.sh +++ /dev/null @@ -1,9 +0,0 @@ -directory="run/crash-reports" -if [ -d $directory ]; then - echo "Crash reports detected:" - cat $directory/* - exit 1 -else - echo "No crash reports detected" - exit 0 -fi diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 6c9b3cb..3ee2f68 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -1,5 +1,3 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Build and test @@ -11,35 +9,5 @@ on: jobs: build-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - name: Run server for 1 minute - run: | - mkdir run - echo "eula=true" > run/eula.txt - timeout 10 ./gradlew runServer || true - - - name: Test no crashes happend - run: | - chmod +x .github/scripts/test-no-crash-reports.sh - .github/scripts/test-no-crash-reports.sh + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master + secrets: inherit diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml index c86d888..e4c0be6 100644 --- a/.github/workflows/release-tags.yml +++ b/.github/workflows/release-tags.yml @@ -1,51 +1,14 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Release tagged build on: push: - tags: - - '*' + tags: [ '*' ] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set release version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew +permissions: + contents: write - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - name: Release under current tag - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "${{ env.RELEASE_VERSION }}" - prerelease: false - title: "${{ env.RELEASE_VERSION }}" - files: build/libs/*.jar - - - name: Publish to Maven - run: ./gradlew publish - env: - MAVEN_USER: ${{ secrets.MAVEN_USER }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} +jobs: + release-tags: + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master + secrets: inherit From b8a70cb09b72964cc368077b843c292f419ce666 Mon Sep 17 00:00:00 2001 From: TechnoParadox Date: Tue, 30 Aug 2022 20:45:47 +0200 Subject: [PATCH 158/219] Fix NPE Fix NPE when CodeChhickenLib attempts to unload a chunk that is already null --- src/main/java/codechicken/lib/world/WorldExtension.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/lib/world/WorldExtension.java b/src/main/java/codechicken/lib/world/WorldExtension.java index 3015f93..b4cfe0e 100644 --- a/src/main/java/codechicken/lib/world/WorldExtension.java +++ b/src/main/java/codechicken/lib/world/WorldExtension.java @@ -49,7 +49,7 @@ protected final void loadChunk(Chunk chunk) protected final void unloadChunk(Chunk chunk) { - chunkMap.get(chunk).unload(); + if (chunkMap.get(chunk) != null) chunkMap.get(chunk).unload(); } protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) From 818b13551bb2162140e4b3ff0bfbd8b615d5f293 Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Wed, 31 Aug 2022 22:31:23 +0800 Subject: [PATCH 159/219] remove @InterfaceDependancyTransformer (#8) * remove @InterfaceDependancyTransformer This is no longer used, and I want less class transformer in the LaunchClassLoader * apply spotless --- .gitattributes | 35 ++ build.gradle | 466 +++++++++++++----- settings.gradle | 10 + .../codechicken/core/CCUpdateChecker.java | 53 +- .../codechicken/core/ClassDiscoverer.java | 58 +-- .../java/codechicken/core/ClientUtils.java | 15 +- .../java/codechicken/core/CommonUtils.java | 12 +- .../codechicken/core/GuiModListScroll.java | 87 ++-- .../codechicken/core/IGuiPacketSender.java | 3 +- .../java/codechicken/core/IStringMatcher.java | 3 +- .../java/codechicken/core/ProfileTimer.java | 9 +- .../codechicken/core/ReflectionManager.java | 295 +++++------ .../java/codechicken/core/ServerUtils.java | 44 +- .../java/codechicken/core/TaskProfiler.java | 56 +-- .../asm/CodeChickenAccessTransformer.java | 34 +- .../core/asm/CodeChickenCoreModContainer.java | 25 +- .../asm/DefaultImplementationTransformer.java | 151 +++--- .../core/asm/DelegatedTransformer.java | 136 +++-- .../core/asm/DependancyLister.java | 67 +-- .../core/asm/InterfaceDependancies.java | 6 +- .../asm/InterfaceDependancyTransformer.java | 53 -- .../core/asm/MCPDeobfuscationTransformer.java | 83 ++-- .../codechicken/core/asm/MethodASMifier.java | 18 +- .../core/asm/TweakTransformer.java | 89 ++-- .../core/commands/CoreCommand.java | 34 +- .../core/commands/PlayerCommand.java | 51 +- .../core/commands/ServerCommand.java | 25 +- .../core/featurehack/EntityRenderHook.java | 18 +- .../core/featurehack/EntityUpdateHook.java | 33 +- .../core/featurehack/FeatureHack.java | 27 +- .../core/featurehack/GameDataManipulator.java | 27 +- .../core/featurehack/LiquidTextures.java | 53 +- .../featurehack/RenderEntityRenderHook.java | 22 +- .../core/featurehack/RenderNull.java | 12 +- .../featurehack/TweakTransformerHelper.java | 41 +- .../core/featurehack/mc/TextureLavaFX.java | 68 ++- .../featurehack/mc/TextureLavaFlowFX.java | 85 ++-- .../core/featurehack/mc/TextureWaterFX.java | 52 +- .../featurehack/mc/TextureWaterFlowFX.java | 77 ++- .../core/fluid/ExtendedFluidTank.java | 93 ++-- .../codechicken/core/fluid/FluidUtils.java | 70 ++- .../codechicken/core/fluid/TankAccess.java | 21 +- .../codechicken/core/gui/ClickCounter.java | 21 +- .../codechicken/core/gui/GuiCCButton.java | 29 +- .../codechicken/core/gui/GuiCCTextField.java | 139 ++---- .../codechicken/core/gui/GuiScreenWidget.java | 100 ++-- .../codechicken/core/gui/GuiScrollPane.java | 71 ++- .../codechicken/core/gui/GuiScrollSlot.java | 55 +-- .../java/codechicken/core/gui/GuiWidget.java | 67 +-- .../core/gui/IGuiActionListener.java | 5 +- .../core/internal/CCCEventHandler.java | 12 +- .../core/inventory/GuiContainerWidget.java | 109 ++-- .../core/launch/CodeChickenCorePlugin.java | 161 +++--- .../codechicken/core/launch/DepLoader.java | 183 +++---- .../obfuscator/ConstantObfuscator.java | 71 ++- .../obfuscator/DummyOutputStream.java | 7 +- .../obfuscator/IHeirachyEvaluator.java | 6 +- .../codechicken/obfuscator/ILogStreams.java | 4 +- .../codechicken/obfuscator/ObfDirection.java | 19 +- .../codechicken/obfuscator/ObfRemapper.java | 100 ++-- .../obfuscator/ObfuscationMap.java | 288 +++++------ .../obfuscator/ObfuscationRun.java | 248 ++++------ .../obfuscator/SystemLogStreams.java | 13 +- 63 files changed, 1991 insertions(+), 2334 deletions(-) create mode 100644 .gitattributes create mode 100644 settings.gradle delete mode 100644 src/main/java/codechicken/core/asm/InterfaceDependancyTransformer.java diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9917fc4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,35 @@ +* text eol=lf + +*.jar binary + +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +*.svg text +*.eps binary + +*.kar binary +*.m4a binary +*.mid binary +*.midi binary +*.mp3 binary +*.ogg binary +*.ra binary + +*.7z binary +*.gz binary +*.tar binary +*.tgz binary +*.zip binary + +*.patch -text + +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +*autogenerated binary \ No newline at end of file diff --git a/build.gradle b/build.gradle index c8cf37c..997b94d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,26 +1,36 @@ -//version: 1644894948 +//version: 1661114848 /* -DO NOT CHANGE THIS FILE! + DO NOT CHANGE THIS FILE! + Also, you may replace this file at any time if there is an update available. + Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. + */ -Also, you may replace this file at any time if there is an update available. -Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. -*/ - -import org.gradle.internal.logging.text.StyledTextOutput -import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.gradle.internal.logging.text.StyledTextOutput.Style import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.gradle.internal.logging.text.StyledTextOutput.Style +import org.gradle.internal.logging.text.StyledTextOutputFactory +import java.nio.file.Files +import java.nio.file.Paths import java.util.concurrent.TimeUnit +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream +import java.util.zip.ZipOutputStream buildscript { repositories { + mavenCentral() + maven { name 'forge' url 'https://maven.minecraftforge.net' } + maven { + // GTNH ForgeGradle Fork + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + } maven { name 'sonatype' url 'https://oss.sonatype.org/content/repositories/snapshots/' @@ -29,30 +39,37 @@ buildscript { name 'Scala CI dependencies' url 'https://repo1.maven.org/maven2/' } - maven { - name 'jitpack' - url 'https://jitpack.io' - } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7' + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.9' } } - plugins { id 'java-library' id 'idea' id 'eclipse' id 'scala' id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false - id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false - id 'org.ajoberstar.grgit' version '4.1.1' + id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false + id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false + id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false + id 'org.ajoberstar.grgit' version '4.1.1' id 'com.github.johnrengelman.shadow' version '4.0.4' - id 'com.palantir.git-version' version '0.13.0' apply false - id 'de.undercouch.download' version '5.0.1' - id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false + id 'com.palantir.git-version' version '0.13.0' apply false + id 'de.undercouch.download' version '5.0.1' + id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false + id 'com.diffplug.spotless' version '6.7.2' apply false } +boolean settingsupdated = verifySettingsGradle() +settingsupdated = verifyGitAttributes() || settingsupdated +if (settingsupdated) + throw new GradleException("Settings has been updated, please re-run task.") + +dependencies { + implementation 'com.diffplug:blowdryer:1.6.0' +} + +apply plugin: 'com.diffplug.blowdryer' if (project.file('.git/HEAD').isFile()) { apply plugin: 'com.palantir.git-version' @@ -78,7 +95,14 @@ idea { } } -if(JavaVersion.current() != JavaVersion.VERSION_1_8) { +boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false + +if (!disableSpotless) { + apply plugin: 'com.diffplug.spotless' + apply from: Blowdryer.file('spotless.gradle') +} + +if (JavaVersion.current() != JavaVersion.VERSION_1_8) { throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) } @@ -103,8 +127,11 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - +boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false +boolean usesMixinDebug = project.hasProperty('usesMixinDebug') ?: project.usesMixins.toBoolean() +boolean forceEnableMixins = project.hasProperty('forceEnableMixins') ? project.forceEnableMixins.toBoolean() : false +String channel = project.hasProperty('channel') ? project.channel : 'stable' +String mappingsVersion = project.hasProperty('mappingsVersion') ? project.mappingsVersion : '12' String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" @@ -112,53 +139,53 @@ String kotlinSourceDir = "src/main/kotlin/" String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") -if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { +if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } -if(apiPackage) { +if (apiPackage) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } } -if(accessTransformersFile) { +if (accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(!getFile(targetFile).exists()) { + if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } -if(usesMixins.toBoolean()) { - if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { +if (usesMixins.toBoolean()) { + if (mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!") } targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) + if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt" - if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) } } -if(coreModClass) { +if (coreModClass) { String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt" - if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) } } @@ -188,7 +215,7 @@ try { catch (Exception ignored) { out.style(Style.Failure).text( 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' + - 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + + 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)' ) versionOverride = 'NO-GIT-TAG-SET' @@ -199,28 +226,31 @@ ext { modVersion = identifiedVersion } -if(identifiedVersion == versionOverride) { +if (identifiedVersion == versionOverride) { out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } group = modGroup -if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { +if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName -} -else { +} else { archivesBaseName = modId } def arguments = [] def jvmArguments = [] -if(usesMixins.toBoolean()) { +if (usesMixins.toBoolean() || forceEnableMixins) { arguments += [ - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - jvmArguments += [ - "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" ] + if (usesMixinDebug.toBoolean()) { + jvmArguments += [ + "-Dmixin.debug.countInjections=true", + "-Dmixin.debug.verbose=true", + "-Dmixin.debug.export=true" + ] + } } minecraft { @@ -229,16 +259,16 @@ minecraft { if (replaceGradleTokenInFile) { replaceIn replaceGradleTokenInFile - if(gradleTokenModId) { + if (gradleTokenModId) { replace gradleTokenModId, modId } - if(gradleTokenModName) { + if (gradleTokenModName) { replace gradleTokenModName, modName } - if(gradleTokenVersion) { + if (gradleTokenVersion) { replace gradleTokenVersion, modVersion } - if(gradleTokenGroupName) { + if (gradleTokenGroupName) { replace gradleTokenGroupName, modGroup } } @@ -247,7 +277,7 @@ minecraft { args(arguments) jvmArgs(jvmArguments) - if(developmentEnvironmentUserName) { + if (developmentEnvironmentUserName) { args("--username", developmentEnvironmentUserName) } } @@ -258,7 +288,7 @@ minecraft { } } -if(file('addon.gradle').exists()) { +if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } @@ -275,7 +305,7 @@ repositories { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean() || forceEnableMixins) { maven { name 'sponge' url 'https://repo.spongepowered.org/repository/maven-public' @@ -287,11 +317,13 @@ repositories { } dependencies { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') annotationProcessor('com.google.guava:guava:24.1.1-jre') annotationProcessor('com.google.code.gson:gson:2.8.6') annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT') + } + if (usesMixins.toBoolean() || forceEnableMixins) { // using 0.8 to workaround a issue in 0.7 which fails mixin application compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') { // Mixin includes a lot of dependencies that are too up-to-date @@ -312,18 +344,23 @@ def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfig def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { - if(usesMixins.toBoolean()) { - getFile("/src/main/resources/mixins." + modId + ".json").text = """{ + if (usesMixins.toBoolean()) { + def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json"); + if (!mixinConfigFile.exists()) { + mixinConfigFile.text = """{ "required": true, "minVersion": "0.7.11", "package": "${modGroup}.${mixinsPackage}", "plugin": "${modGroup}.${mixinPlugin}", "refmap": "${mixingConfigRefMap}", "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8" + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] } - """ + } } } @@ -344,7 +381,10 @@ shadowJar { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] dependsOn(relocateShadowJar) } @@ -359,38 +399,38 @@ jar { attributes(getManifestAttributes()) } - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { dependsOn(shadowJar) enabled = false } } reobf { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { addExtraSrgFile mixinSrg } } afterEvaluate { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { tasks.compileJava { options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobf.srg}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", - // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code - "-XDenableSunApiLintControl", - "-XDignore.symbol.file" + "-AreobfSrgFile=${tasks.reobf.srg}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" ] } } } runClient { - if(developmentEnvironmentUserName) { + if (developmentEnvironmentUserName) { arguments += [ - "--username", - developmentEnvironmentUserName + "--username", + developmentEnvironmentUserName ] } @@ -405,9 +445,9 @@ runServer { tasks.withType(JavaExec).configureEach { javaLauncher.set( - javaToolchains.launcherFor { - languageVersion = projectJavaVersion - } + javaToolchains.launcherFor { + languageVersion = projectJavaVersion + } ) } @@ -415,6 +455,7 @@ processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version + exclude("spotless.gradle") // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { @@ -427,43 +468,44 @@ processResources { "modName": modName } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { from refMap } // copy everything else that's not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' + exclude 'spotless.gradle' } } def getManifestAttributes() { def manifestAttributes = [:] - if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { + if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + if (accessTransformersFile) { + manifestAttributes += ["FMLAT": accessTransformersFile.toString()] } - if(coreModClass) { + if (coreModClass) { manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean() + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : "mixins." + modId + ".json", + "ForceLoadAsMod": !containsMixinsAndOrCoreModOnly.toBoolean() ] } return manifestAttributes } task sourcesJar(type: Jar) { - from (sourceSets.main.allJava) - from (file("$projectDir/LICENSE")) + from(sourceSets.main.allSource) + from(file("$projectDir/LICENSE")) getArchiveClassifier().set('sources') } @@ -482,7 +524,10 @@ task shadowDevJar(type: ShadowJar) { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { @@ -510,22 +555,22 @@ task devJar(type: Jar) { attributes(getManifestAttributes()) } - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { dependsOn(circularResolverJar) enabled = false } } task apiJar(type: Jar) { - from (sourceSets.main.allJava) { + from(sourceSets.main.allSource) { include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } - from (sourceSets.main.output) { + from(sourceSets.main.output) { include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } - from (sourceSets.main.resources.srcDirs) { + from(sourceSets.main.resources.srcDirs) { include("LICENSE") } @@ -533,11 +578,11 @@ task apiJar(type: Jar) { } artifacts { - if(!noPublishedSources) { + if (!noPublishedSources) { archives sourcesJar } archives devJar - if(apiPackage) { + if (apiPackage) { archives apiJar } } @@ -555,11 +600,11 @@ publishing { publications { maven(MavenPublication) { from components.java - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { artifact source: shadowJar, classifier: "" } - if(!noPublishedSources) { - artifact source: sourcesJar, classifier: "src" + if (!noPublishedSources) { + artifact source: sourcesJar, classifier: "sources" } artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage) { @@ -573,8 +618,11 @@ publishing { // remove extra garbage from minecraft and minecraftDeps configuration pom.withXml { - def badArtifacts = [:].withDefault {[] as Set} - for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) { + def badArtifacts = [:].withDefault { [] as Set } + for (configuration in [ + projectConfigs.minecraft, + projectConfigs.minecraftDeps + ]) { for (dependency in configuration.allDependencies) { badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name } @@ -612,7 +660,7 @@ task updateBuildScript { } } -if (isNewBuildScriptVersionAvailable(projectDir.toString())) { +if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { performBuildScriptUpdate(projectDir.toString()) } else { @@ -621,7 +669,40 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { } static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle") +} + +static URL exampleSettingsGradleUrl() { + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example") +} + +static URL exampleGitAttributesUrl() { + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes") +} + + +boolean verifyGitAttributes() { + def gitattributesFile = getFile(".gitattributes") + if (!gitattributesFile.exists()) { + println("Downloading default .gitattributes") + exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } } + exec { + workingDir '.' + commandLine 'git', 'add', '--renormalize', '.' + } + return true + } + return false +} + +boolean verifySettingsGradle() { + def settingsFile = getFile("settings.gradle") + if (!settingsFile.exists()) { + println("Downloading default settings.gradle") + exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } + return true + } + return false } boolean performBuildScriptUpdate(String projectDir) { @@ -629,6 +710,10 @@ boolean performBuildScriptUpdate(String projectDir) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + boolean settingsupdated = verifySettingsGradle() + settingsupdated = verifyGitAttributes() || settingsupdated + if (settingsupdated) + throw new GradleException("Settings has been updated, please re-run task.") return true } return false @@ -648,7 +733,7 @@ boolean isNewBuildScriptVersionAvailable(String projectDir) { static String getVersionHash(String buildScriptContent) { String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") - if(versionLine != null) { + if (versionLine != null) { return versionLine.split(": ").last() } return "" @@ -659,7 +744,103 @@ configure(updateBuildScript) { description = 'Updates the build script to the latest version' } -// Deobfuscation +// Parameter Deobfuscation + +task deobfParams { + doLast { + + String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" + String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" + String paramsCSV = "$mcpDir/params.csv" + + download.run { + src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" + dest mcpZIP + overwrite false + } + + if (!file(paramsCSV).exists()) { + println("Extracting MCP archive ...") + unzip(mcpZIP, mcpDir) + } + + println("Parsing params.csv ...") + Map params = new HashMap<>() + Files.lines(Paths.get(paramsCSV)).forEach { line -> + String[] cells = line.split(",") + if (cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) { + params.put(cells[0], cells[1]) + } + } + + out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!") + out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.") + } +} + +static int replaceParams(File file, Map params) { + int fileCount = 0 + + if (file.isDirectory()) { + for (File f : file.listFiles()) { + fileCount += replaceParams(f, params) + } + return fileCount + } + println("Visiting ${file.getName()} ...") + try { + String content = new String(Files.readAllBytes(file.toPath())) + int hash = content.hashCode() + params.forEach { key, value -> + content = content.replaceAll(key, value) + } + if (hash != content.hashCode()) { + Files.write(file.toPath(), content.getBytes("UTF-8")) + return 1 + } + } catch (Exception e) { + e.printStackTrace() + } + return 0 +} + +// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681) +static unzip(String zipFileName, String outputDir) { + byte[] buffer = new byte[16384] + ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName)) + ZipEntry zipEntry = zis.getNextEntry() + while (zipEntry != null) { + File newFile = new File(outputDir + File.separator, zipEntry.name) + if (zipEntry.isDirectory()) { + if (!newFile.isDirectory() && !newFile.mkdirs()) { + throw new IOException("Failed to create directory $newFile") + } + } else { + // fix for Windows-created archives + File parent = newFile.parentFile + if (!parent.isDirectory() && !parent.mkdirs()) { + throw new IOException("Failed to create directory $parent") + } + // write file content + FileOutputStream fos = new FileOutputStream(newFile) + int len = 0 + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len) + } + fos.close() + } + zipEntry = zis.getNextEntry() + } + zis.closeEntry() + zis.close() +} + +configure(deobfParams) { + group = 'forgegradle' + description = 'Rename all obfuscated parameter names inherited from Minecraft classes' +} + +// Dependency Deobfuscation def deobf(String sourceURL) { try { @@ -668,42 +849,57 @@ def deobf(String sourceURL) { //get rid of directories: int lastSlash = fileName.lastIndexOf("/") - if(lastSlash > 0) { + if (lastSlash > 0) { fileName = fileName.substring(lastSlash + 1) } //get rid of extension: - if(fileName.endsWith(".jar")) { + if (fileName.endsWith(".jar") || fileName.endsWith(".litemod")) { fileName = fileName.substring(0, fileName.lastIndexOf(".")) } String hostName = url.getHost() - if(hostName.startsWith("www.")) { + if (hostName.startsWith("www.")) { hostName = hostName.substring(4) } List parts = Arrays.asList(hostName.split("\\.")) Collections.reverse(parts) hostName = String.join(".", parts) - return deobf(sourceURL, hostName + "/" + fileName) - } catch(Exception e) { - return deobf(sourceURL, "deobf/" + String.valueOf(sourceURL.hashCode())) + return deobf(sourceURL, "$hostName/$fileName") + } catch (Exception e) { + return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } } // The method above is to be preferred. Use this method if the filename is not at the end of the URL. -def deobf(String sourceURL, String fileName) { - String cacheDir = System.getProperty("user.home") + "/.gradle/caches/" - String bon2Dir = cacheDir + "forge_gradle/deobf" - String bon2File = bon2Dir + "/BON2-2.5.0.jar" - String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar" - String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar" - - if(file(deobfFile).exists()) { +def deobf(String sourceURL, String rawFileName) { + String bon2Version = "2.5.1" + String fileName = URLDecoder.decode(rawFileName, "UTF-8") + String cacheDir = "$project.gradle.gradleUserHomeDir/caches" + String bon2Dir = "$cacheDir/forge_gradle/deobf" + String bon2File = "$bon2Dir/BON2-${bon2Version}.jar" + String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" + String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar" + + if (file(deobfFile).exists()) { return files(deobfFile) } + String mappingsVer + String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' + if (remoteMappings) { + String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" + String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" + + zipMappings(mappingsZIP, remoteMappings, bon2Dir) + + mappingsVer = "snapshot_$id" + } else { + mappingsVer = "${channel}_$mappingsVersion" + } + download.run { - src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar' + src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar" dest bon2File quiet true overwrite false @@ -717,14 +913,48 @@ def deobf(String sourceURL, String fileName) { } exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch' + commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' workingDir bon2Dir - standardOutput = new ByteArrayOutputStream() + standardOutput = new FileOutputStream("${deobfFile}.log") } return files(deobfFile) } +def zipMappings(String zipPath, String url, String bon2Dir) { + File zipFile = new File(zipPath) + if (zipFile.exists()) { + return + } + + String fieldsCache = "$bon2Dir/data/fields.csv" + String methodsCache = "$bon2Dir/data/methods.csv" + + download.run { + src "${url}fields.csv" + dest fieldsCache + quiet true + } + download.run { + src "${url}methods.csv" + dest methodsCache + quiet true + } + + zipFile.getParentFile().mkdirs() + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)) + + zos.putNextEntry(new ZipEntry("fields.csv")) + Files.copy(Paths.get(fieldsCache), zos) + zos.closeEntry() + + zos.putNextEntry(new ZipEntry("methods.csv")) + Files.copy(Paths.get(methodsCache), zos) + zos.closeEntry() + + zos.close() +} + // Helper methods def checkPropertyExists(String propertyName) { diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..93c852a --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +plugins { + id 'com.diffplug.blowdryerSetup' version '1.6.0' +} + +apply plugin: 'com.diffplug.blowdryerSetup' + +blowdryerSetup { + github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.5') + //devLocal '.' // Use this when testing config updates locally +} diff --git a/src/main/java/codechicken/core/CCUpdateChecker.java b/src/main/java/codechicken/core/CCUpdateChecker.java index 5616434..7f26b41 100644 --- a/src/main/java/codechicken/core/CCUpdateChecker.java +++ b/src/main/java/codechicken/core/CCUpdateChecker.java @@ -1,5 +1,10 @@ package codechicken.core; +import codechicken.core.launch.CodeChickenCorePlugin; +import com.google.common.base.Function; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.versioning.ComparableVersion; +import cpw.mods.fml.relauncher.FMLInjectionData; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -9,23 +14,14 @@ import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; - -import codechicken.core.launch.CodeChickenCorePlugin; -import com.google.common.base.Function; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.versioning.ComparableVersion; -import cpw.mods.fml.relauncher.FMLInjectionData; - import net.minecraft.client.Minecraft; import net.minecraft.util.ChatComponentText; import net.minecraft.util.StatCollector; -public class CCUpdateChecker -{ +public class CCUpdateChecker { private static final ArrayList updates = new ArrayList(); - private static class ThreadUpdateCheck extends Thread - { + private static class ThreadUpdateCheck extends Thread { private final URL url; private final Function handler; @@ -46,11 +42,11 @@ public void run() { BufferedReader read = new BufferedReader(new InputStreamReader(conn.getInputStream())); String ret = read.readLine(); read.close(); - if(ret == null) ret = ""; + if (ret == null) ret = ""; handler.apply(ret); - } catch (SocketTimeoutException ignored) {} - catch (UnknownHostException ignored) {} - catch (IOException iox) { + } catch (SocketTimeoutException ignored) { + } catch (UnknownHostException ignored) { + } catch (IOException iox) { iox.printStackTrace(); } } @@ -58,12 +54,10 @@ public void run() { public static void tick() { Minecraft mc = Minecraft.getMinecraft(); - if (!mc.inGameHasFocus) - return; + if (!mc.inGameHasFocus) return; synchronized (updates) { - for (String s : updates) - mc.thePlayer.addChatMessage(new ChatComponentText(s)); + for (String s : updates) mc.thePlayer.addChatMessage(new ChatComponentText(s)); updates.clear(); } } @@ -79,19 +73,22 @@ public static String mcVersion() { } public static void updateCheck(final String mod, final String version) { - updateCheck("http://www.chickenbones.net/Files/notification/version.php?" + - "version=" + mcVersion() + "&" + - "file=" + mod, - new Function() - { - @Override public Void apply(String ret) { + updateCheck( + "http://www.chickenbones.net/Files/notification/version.php?" + "version=" + + mcVersion() + "&" + "file=" + + mod, + new Function() { + @Override + public Void apply(String ret) { if (!ret.startsWith("Ret: ")) { - CodeChickenCorePlugin.logger.error("Failed to check update for " + mod + " returned: " + ret); + CodeChickenCorePlugin.logger.error( + "Failed to check update for " + mod + " returned: " + ret); return null; } ComparableVersion newversion = new ComparableVersion(ret.substring(5)); if (newversion.compareTo(new ComparableVersion(version)) > 0) - addUpdateMessage(StatCollector.translateToLocalFormatted("codechickencore.update", newversion, mod)); + addUpdateMessage( + StatCollector.translateToLocalFormatted("codechickencore.update", newversion, mod)); return null; } }); @@ -105,7 +102,7 @@ public static void updateCheck(String url, Function handler) { try { new ThreadUpdateCheck(new URL(url), handler).start(); } catch (MalformedURLException e) { - CodeChickenCorePlugin.logger.error("Malformed URL: "+url, e); + CodeChickenCorePlugin.logger.error("Malformed URL: " + url, e); } } } diff --git a/src/main/java/codechicken/core/ClassDiscoverer.java b/src/main/java/codechicken/core/ClassDiscoverer.java index d36b248..6ccbbc2 100644 --- a/src/main/java/codechicken/core/ClassDiscoverer.java +++ b/src/main/java/codechicken/core/ClassDiscoverer.java @@ -1,5 +1,12 @@ package codechicken.core; +import codechicken.core.launch.CodeChickenCorePlugin; +import codechicken.lib.asm.ASMHelper; +import com.google.common.collect.ImmutableList; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModClassLoader; +import cpw.mods.fml.relauncher.CoreModManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -8,22 +15,10 @@ import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; - import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.tree.ClassNode; -import codechicken.core.launch.CodeChickenCorePlugin; -import codechicken.lib.asm.ASMHelper; - -import com.google.common.collect.ImmutableList; - -import cpw.mods.fml.common.FMLLog; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.ModClassLoader; -import cpw.mods.fml.relauncher.CoreModManager; - -public class ClassDiscoverer -{ +public class ClassDiscoverer { public IStringMatcher matcher; public String[] superclasses; public ArrayList> classes; @@ -40,10 +35,13 @@ public ClassDiscoverer(IStringMatcher matcher, Class... superclasses) { } public ClassDiscoverer(Class... superclasses) { - this(new IStringMatcher() - { - public boolean matches(String test) {return true;} - }, superclasses); + this( + new IStringMatcher() { + public boolean matches(String test) { + return true; + } + }, + superclasses); } public ArrayList> findClasses() { @@ -59,13 +57,11 @@ private void checkAddClass(String resource) { try { String classname = resource.replace(".class", "").replace("\\", ".").replace("/", "."); byte[] bytes = Launch.classLoader.getClassBytes(classname); - if (bytes == null) - return; + if (bytes == null) return; ClassNode cnode = ASMHelper.createClassNode(bytes); for (String superclass : superclasses) - if (!cnode.interfaces.contains(superclass) && !cnode.superName.equals(superclass)) - return; + if (!cnode.interfaces.contains(superclass) && !cnode.superName.equals(superclass)) return; addClass(classname); } catch (IOException e) { @@ -85,25 +81,30 @@ private void addClass(String classname) { private void findClasspathMods() { List knownLibraries = ImmutableList.builder() .addAll(modClassLoader.getDefaultLibraries()) - .addAll(CoreModManager.getLoadedCoremods()).build(); + .addAll(CoreModManager.getLoadedCoremods()) + .build(); File[] minecraftSources = modClassLoader.getParentSources(); HashSet searchedSources = new HashSet(); for (File minecraftSource : minecraftSources) { - if (searchedSources.contains(minecraftSource.getAbsolutePath())) - continue; + if (searchedSources.contains(minecraftSource.getAbsolutePath())) continue; searchedSources.add(minecraftSource.getAbsolutePath()); if (minecraftSource.isFile()) { if (!knownLibraries.contains(minecraftSource.getName())) { - FMLLog.fine("Found a minecraft related file at %s, examining for codechicken classes", minecraftSource.getAbsolutePath()); + FMLLog.fine( + "Found a minecraft related file at %s, examining for codechicken classes", + minecraftSource.getAbsolutePath()); try { readFromZipFile(minecraftSource); } catch (Exception e) { - CodeChickenCorePlugin.logger.error("Failed to scan " + minecraftSource.getAbsolutePath() + ", the zip file is invalid", e); + CodeChickenCorePlugin.logger.error( + "Failed to scan " + minecraftSource.getAbsolutePath() + ", the zip file is invalid", e); } } } else if (minecraftSource.isDirectory()) { - FMLLog.fine("Found a minecraft related directory at %s, examining for codechicken classes", minecraftSource.getAbsolutePath()); + FMLLog.fine( + "Found a minecraft related directory at %s, examining for codechicken classes", + minecraftSource.getAbsolutePath()); readFromDirectory(minecraftSource, minecraftSource); } } @@ -123,8 +124,7 @@ private void readFromZipFile(File file) throws IOException { if (!zipentry.isDirectory() && matcher.matches(name)) { checkAddClass(fullname); } - } - while (true); + } while (true); fileinputstream.close(); } diff --git a/src/main/java/codechicken/core/ClientUtils.java b/src/main/java/codechicken/core/ClientUtils.java index 621f206..73adfe7 100644 --- a/src/main/java/codechicken/core/ClientUtils.java +++ b/src/main/java/codechicken/core/ClientUtils.java @@ -1,12 +1,10 @@ package codechicken.core; import codechicken.core.internal.CCCEventHandler; - import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.network.NetworkManager; @@ -14,8 +12,7 @@ import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.World; -public class ClientUtils extends CommonUtils -{ +public class ClientUtils extends CommonUtils { private static Minecraft mc() { return Minecraft.getMinecraft(); } @@ -24,15 +21,14 @@ public static World getWorld() { return mc().theWorld; } - public static boolean inWorld()//TODO unused - { + public static boolean inWorld() // TODO unused + { return mc().getNetHandler() != null; } public static void openSMPGui(int windowId, GuiScreen gui) { mc().displayGuiScreen(gui); - if (windowId != 0) - mc().thePlayer.openContainer.windowId = windowId; + if (windowId != 0) mc().thePlayer.openContainer.windowId = windowId; } public static float getRenderFrame() { @@ -63,7 +59,8 @@ public static String getWorldSaveName() { public static void enhanceSupportersList(Object mod) { ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod); - mc.getMetadata().description = mc.getMetadata().description.replace("Supporters:", EnumChatFormatting.AQUA+"Supporters:"); + mc.getMetadata().description = + mc.getMetadata().description.replace("Supporters:", EnumChatFormatting.AQUA + "Supporters:"); GuiModListScroll.register(mod); } } diff --git a/src/main/java/codechicken/core/CommonUtils.java b/src/main/java/codechicken/core/CommonUtils.java index 1368501..11301b2 100644 --- a/src/main/java/codechicken/core/CommonUtils.java +++ b/src/main/java/codechicken/core/CommonUtils.java @@ -1,16 +1,14 @@ package codechicken.core; -import java.io.File; - import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.FMLInjectionData; +import java.io.File; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; -public class CommonUtils -{ +public class CommonUtils { public static boolean isClient() { return FMLCommonHandler.instance().getSide().isClient(); } @@ -37,14 +35,12 @@ public static File getMinecraftDir() { } public static String getRelativePath(File parent, File child) { - if (parent.isFile() || !child.getPath().startsWith(parent.getPath())) - return null; + if (parent.isFile() || !child.getPath().startsWith(parent.getPath())) return null; return child.getPath().substring(parent.getPath().length() + 1); } - public static void registerHandledEntity(Class entityClass, String identifier) - { + public static void registerHandledEntity(Class entityClass, String identifier) { EntityList.classToStringMapping.put(entityClass, identifier); EntityList.stringToClassMapping.put(identifier, entityClass); } diff --git a/src/main/java/codechicken/core/GuiModListScroll.java b/src/main/java/codechicken/core/GuiModListScroll.java index 8375fcf..299b04f 100644 --- a/src/main/java/codechicken/core/GuiModListScroll.java +++ b/src/main/java/codechicken/core/GuiModListScroll.java @@ -1,5 +1,8 @@ package codechicken.core; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.glReadPixels; + import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.lib.gui.GuiDraw; import codechicken.lib.vec.Rectangle4i; @@ -7,17 +10,6 @@ import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModMetadata; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.MinecraftForgeClient; -import org.lwjgl.BufferUtils; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; - -import javax.imageio.ImageIO; - -import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL11.glReadPixels; - import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -25,9 +17,14 @@ import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; +import javax.imageio.ImageIO; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.MinecraftForgeClient; +import org.lwjgl.BufferUtils; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; -public class GuiModListScroll -{ +public class GuiModListScroll { private static List scrollMods = new LinkedList(); public static void register(Object mod) { @@ -37,8 +34,7 @@ public static void register(Object mod) { private static void register(ModContainer mod) { if (MinecraftForgeClient.getStencilBits() == 0) CodeChickenCorePlugin.logger.error("Unable to do mod description scrolling due to lack of stencil buffer"); - else - scrollMods.add(mod); + else scrollMods.add(mod); } private static void screenshotStencil(int x) { @@ -49,11 +45,11 @@ private static void screenshotStencil(int x) { glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glReadPixels(0, 0, d.width, d.height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf); - for(int i = 0; i < d.width; i++) - for(int j = 0; j < d.height; j++) - img.setRGB(i, d.height-j-1, buf.get(j * d.width + i) == 0 ? 0 : 0xFFFFFF); + for (int i = 0; i < d.width; i++) + for (int j = 0; j < d.height; j++) + img.setRGB(i, d.height - j - 1, buf.get(j * d.width + i) == 0 ? 0 : 0xFFFFFF); try { - ImageIO.write(img, "png", new File("stencil"+x+".png")); + ImageIO.write(img, "png", new File("stencil" + x + ".png")); } catch (IOException e) { e.printStackTrace(); } @@ -63,36 +59,35 @@ private static void screenshotStencil(int x) { private static double scroll; private static double lastFrameTime; private static double timeStart; + public static void draw(GuiModList gui, int mouseX, int mouseY) { ModContainer selectedMod = ReflectionManager.getField(GuiModList.class, ModContainer.class, gui, "selectedMod"); - if(selectedMod != lastMod) { + if (selectedMod != lastMod) { lastMod = selectedMod; scroll = 0; timeStart = ClientUtils.getRenderTime(); } - if(!scrollMods.contains(selectedMod) || selectedMod.getMetadata().autogenerated) - return; + if (!scrollMods.contains(selectedMod) || selectedMod.getMetadata().autogenerated) return; int y1 = calcDescY(gui, selectedMod); int y1draw = y1 + 10; - int y2 = gui.height-38; + int y2 = gui.height - 38; int x1 = ReflectionManager.getField(GuiModList.class, Integer.class, gui, "listWidth") + 20; int x2 = gui.width - 20; - if(x2 - x1 <= 20) - return; + if (x2 - x1 <= 20) return; glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glColorMask(false, false, false, false); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - GuiDraw.drawRect(0, 0, gui.width, gui.height, -1);//clear stencil buffer + GuiDraw.drawRect(0, 0, gui.width, gui.height, -1); // clear stencil buffer screenshotStencil(1); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - GuiDraw.drawRect(x1, y1, gui.width - x1, gui.height - y1, -1);//add description area (even below button) + GuiDraw.drawRect(x1, y1, gui.width - x1, gui.height - y1, -1); // add description area (even below button) glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - GuiDraw.drawRect(gui.width / 2 - 75, y2, 200, 20, -1);//subtract done button + GuiDraw.drawRect(gui.width / 2 - 75, y2, 200, 20, -1); // subtract done button screenshotStencil(2); @@ -100,13 +95,13 @@ public static void draw(GuiModList gui, int mouseX, int mouseY) { glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - gui.drawDefaultBackground();//fill stencil with background + gui.drawDefaultBackground(); // fill stencil with background glColorMask(false, false, false, false); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); GuiDraw.drawRect(0, 0, gui.width, gui.height, -1); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - GuiDraw.drawRect(x1, y1draw, x2-x1, y2-y1draw, -1); + GuiDraw.drawRect(x1, y1draw, x2 - x1, y2 - y1draw, -1); screenshotStencil(3); @@ -114,10 +109,13 @@ public static void draw(GuiModList gui, int mouseX, int mouseY) { glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); String description = selectedMod.getMetadata().description; - int height = GuiDraw.fontRenderer.listFormattedStringToWidth(description, x2-x1).size()*GuiDraw.fontRenderer.FONT_HEIGHT; + int height = GuiDraw.fontRenderer + .listFormattedStringToWidth(description, x2 - x1) + .size() + * GuiDraw.fontRenderer.FONT_HEIGHT; - boolean needsScroll = height > y2-y1draw; - if((ClientUtils.getRenderTime() - timeStart) > 40 && needsScroll) { + boolean needsScroll = height > y2 - y1draw; + if ((ClientUtils.getRenderTime() - timeStart) > 40 && needsScroll) { double dt = ClientUtils.getRenderTime() - lastFrameTime; if (new Rectangle4i(x1, y1draw, x2 - x1, y2 - y1draw).contains(mouseX, mouseY)) { double d = Keyboard.isKeyDown(Keyboard.KEY_UP) ? -1 : Keyboard.isKeyDown(Keyboard.KEY_DOWN) ? 1 : 0; @@ -128,16 +126,16 @@ public static void draw(GuiModList gui, int mouseX, int mouseY) { } lastFrameTime = ClientUtils.getRenderTime(); - //draw description + // draw description double dy = scroll % (height + 20); GL11.glPushMatrix(); - GL11.glTranslated(0, -dy, 0); - GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2-x1, 0xDDDDDD); - if(needsScroll) { - GL11.glTranslated(0, height + 20, 0); - GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD); - } + GL11.glTranslated(0, -dy, 0); + GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD); + if (needsScroll) { + GL11.glTranslated(0, height + 20, 0); + GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD); + } GL11.glPopMatrix(); glDisable(GL_STENCIL_TEST); @@ -150,14 +148,13 @@ public static void draw(GuiModList gui, int mouseX, int mouseY) { private static int calcDescY(GuiModList gui, ModContainer mod) { ModMetadata meta = mod.getMetadata(); int y = 35; - if(!!meta.logoFile.isEmpty() && ReflectionManager.getField(GuiModList.class, ResourceLocation.class, gui, "cachedLogo") != null) + if (!!meta.logoFile.isEmpty() + && ReflectionManager.getField(GuiModList.class, ResourceLocation.class, gui, "cachedLogo") != null) y += 65; y += 12; // title y += 40; // necessary lines - if(!meta.credits.isEmpty()) - y += 10; - if(!meta.childMods.isEmpty()) - y += 10; + if (!meta.credits.isEmpty()) y += 10; + if (!meta.childMods.isEmpty()) y += 10; return y; } } diff --git a/src/main/java/codechicken/core/IGuiPacketSender.java b/src/main/java/codechicken/core/IGuiPacketSender.java index 30b5783..b8b0902 100644 --- a/src/main/java/codechicken/core/IGuiPacketSender.java +++ b/src/main/java/codechicken/core/IGuiPacketSender.java @@ -2,7 +2,6 @@ import net.minecraft.entity.player.EntityPlayerMP; -public interface IGuiPacketSender -{ +public interface IGuiPacketSender { void sendPacket(EntityPlayerMP player, int windowId); } diff --git a/src/main/java/codechicken/core/IStringMatcher.java b/src/main/java/codechicken/core/IStringMatcher.java index 12e320c..781b17a 100644 --- a/src/main/java/codechicken/core/IStringMatcher.java +++ b/src/main/java/codechicken/core/IStringMatcher.java @@ -1,6 +1,5 @@ package codechicken.core; -public interface IStringMatcher -{ +public interface IStringMatcher { public boolean matches(String test); } diff --git a/src/main/java/codechicken/core/ProfileTimer.java b/src/main/java/codechicken/core/ProfileTimer.java index 627ac65..3fb9fef 100644 --- a/src/main/java/codechicken/core/ProfileTimer.java +++ b/src/main/java/codechicken/core/ProfileTimer.java @@ -2,8 +2,7 @@ import codechicken.core.launch.CodeChickenCorePlugin; -public class ProfileTimer -{ +public class ProfileTimer { public double decay; public long startTime; public long nanoTime; @@ -30,11 +29,11 @@ public void start() { } public void end() { - long t = System.nanoTime()-startTime; - nanoTime = (long)(nanoTime*decay+t*(1-decay)); + long t = System.nanoTime() - startTime; + nanoTime = (long) (nanoTime * decay + t * (1 - decay)); scanCount++; - if(logScans > 0 && scanCount % logScans == 0) + if (logScans > 0 && scanCount % logScans == 0) CodeChickenCorePlugin.logger.info("Profiled " + logName + " " + nanoTime + "ns"); } } diff --git a/src/main/java/codechicken/core/ReflectionManager.java b/src/main/java/codechicken/core/ReflectionManager.java index c52c92d..32fa16a 100644 --- a/src/main/java/codechicken/core/ReflectionManager.java +++ b/src/main/java/codechicken/core/ReflectionManager.java @@ -1,19 +1,16 @@ package codechicken.core; +import codechicken.lib.asm.ObfMapping; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; -import codechicken.lib.asm.ObfMapping; - -public class ReflectionManager -{ +public class ReflectionManager { public static HashMap, Class> primitiveWrappers = new HashMap, Class>(); - - static - { + + static { primitiveWrappers.put(Integer.TYPE, Integer.class); primitiveWrappers.put(Short.TYPE, Short.class); primitiveWrappers.put(Byte.TYPE, Byte.class); @@ -23,293 +20,247 @@ public class ReflectionManager primitiveWrappers.put(Boolean.TYPE, Boolean.class); primitiveWrappers.put(Character.TYPE, Character.class); } - - public static boolean isInstance(Class class1, Object obj) - { + + public static boolean isInstance(Class class1, Object obj) { Class primitive = primitiveWrappers.get(class1); - if(primitive != null) - { - if(primitive == Long.class && Long.class.isInstance(obj)) - return true; - if((primitive == Long.class || primitive == Integer.class) && Integer.class.isInstance(obj)) - return true; - if((primitive == Long.class || primitive == Integer.class || primitive == Short.class) && Short.class.isInstance(obj)) - return true; - if((primitive == Long.class || primitive == Integer.class || primitive == Short.class || primitive == Byte.class) && Integer.class.isInstance(obj)) - return true; - - if(primitive == Double.class && Double.class.isInstance(obj)) - return true; - if((primitive == Double.class || primitive == Float.class) && Float.class.isInstance(obj)) - return true; - + if (primitive != null) { + if (primitive == Long.class && Long.class.isInstance(obj)) return true; + if ((primitive == Long.class || primitive == Integer.class) && Integer.class.isInstance(obj)) return true; + if ((primitive == Long.class || primitive == Integer.class || primitive == Short.class) + && Short.class.isInstance(obj)) return true; + if ((primitive == Long.class + || primitive == Integer.class + || primitive == Short.class + || primitive == Byte.class) + && Integer.class.isInstance(obj)) return true; + + if (primitive == Double.class && Double.class.isInstance(obj)) return true; + if ((primitive == Double.class || primitive == Float.class) && Float.class.isInstance(obj)) return true; + return primitive.isInstance(obj); } return class1.isInstance(obj); } - - public static Class findClass(String name) - { + + public static Class findClass(String name) { return findClass(name, true); } - - public static boolean classExists(String name) - { + + public static boolean classExists(String name) { return findClass(name, false) != null; } - - public static Class findClass(String name, boolean init) - { - try - { + + public static Class findClass(String name, boolean init) { + try { return Class.forName(name, init, ReflectionManager.class.getClassLoader()); - } - catch (ClassNotFoundException cnfe) - { - try - { - return Class.forName("net.minecraft.src."+name, init, ReflectionManager.class.getClassLoader()); - } - catch (ClassNotFoundException cnfe2) - { + } catch (ClassNotFoundException cnfe) { + try { + return Class.forName("net.minecraft.src." + name, init, ReflectionManager.class.getClassLoader()); + } catch (ClassNotFoundException cnfe2) { return null; } } } - public static void setField(Class class1, Object instance, String name, Object value) throws IllegalArgumentException, IllegalAccessException - { - setField(class1, instance, new String[]{name}, value); + public static void setField(Class class1, Object instance, String name, Object value) + throws IllegalArgumentException, IllegalAccessException { + setField(class1, instance, new String[] {name}, value); } - - public static void setField(Class class1, Object instance, String[] names, Object value) throws IllegalArgumentException, IllegalAccessException - { - for(Field field : class1.getDeclaredFields()) - { + + public static void setField(Class class1, Object instance, String[] names, Object value) + throws IllegalArgumentException, IllegalAccessException { + for (Field field : class1.getDeclaredFields()) { boolean match = false; - for(String name : names) - { - if(field.getName().equals(name)) - { + for (String name : names) { + if (field.getName().equals(name)) { match = true; break; } } - if(!match) - { + if (!match) { continue; - } - + } + field.setAccessible(true); field.set(instance, value); return; } } - - public static void setField(Class class1, Object instance, int fieldindex, Object value) throws IllegalArgumentException, IllegalAccessException - { + + public static void setField(Class class1, Object instance, int fieldindex, Object value) + throws IllegalArgumentException, IllegalAccessException { Field field = class1.getDeclaredFields()[fieldindex]; field.setAccessible(true); field.set(instance, value); } - + /** * Static function * void return type * single name */ - public static void callMethod(Class class1, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { - callMethod(class1, null, new String[]{name}, params); + public static void callMethod(Class class1, String name, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + callMethod(class1, null, new String[] {name}, params); } - + /** * Static function * void return type * single name */ - public static void callMethod(Class class1, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { + public static void callMethod(Class class1, String[] names, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { callMethod(class1, null, names, params); } - + /** * void return type * single name */ - public static void callMethod(Class class1, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { - callMethod(class1, null, instance, new String[]{name}, params); + public static void callMethod(Class class1, Object instance, String name, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + callMethod(class1, null, instance, new String[] {name}, params); } - + /** * void return type */ - public static void callMethod(Class class1, Object instance, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { + public static void callMethod(Class class1, Object instance, String[] names, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { callMethod(class1, null, instance, names, params); } - + /** * Static method * single name */ - public static R callMethod(Class class1, Class returntype, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { - return callMethod(class1, returntype, null, new String[]{name}, params); + public static R callMethod(Class class1, Class returntype, String name, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + return callMethod(class1, returntype, null, new String[] {name}, params); } - + /** * Static method */ - public static R callMethod(Class class1, Class returntype, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { + public static R callMethod(Class class1, Class returntype, String[] names, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { return callMethod(class1, returntype, null, names, params); } - + /** * sinlge name */ - public static R callMethod(Class class1, Class returntype, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { - return callMethod(class1, returntype, instance, new String[]{name}, params); + public static R callMethod(Class class1, Class returntype, Object instance, String name, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + return callMethod(class1, returntype, instance, new String[] {name}, params); } - - public static R callMethod(Class class1, Class returntype, Object instance, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException - { - nextMethod: for(Method method : class1.getDeclaredMethods()) - { + + public static R callMethod( + Class class1, Class returntype, Object instance, String[] names, Object... params) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + nextMethod: + for (Method method : class1.getDeclaredMethods()) { boolean match = false; - for(String name : names) - { - if(method.getName().equals(name)) - { + for (String name : names) { + if (method.getName().equals(name)) { match = true; break; } } - if(!match) - { + if (!match) { continue; } - + Class[] paramtypes = method.getParameterTypes(); - if(paramtypes.length != params.length) - continue; - - for(int i = 0; i < params.length; i++) - { - if(!isInstance(paramtypes[i], params[i])) - continue nextMethod; + if (paramtypes.length != params.length) continue; + + for (int i = 0; i < params.length; i++) { + if (!isInstance(paramtypes[i], params[i])) continue nextMethod; } - + method.setAccessible(true); - return (R)method.invoke(instance, params); + return (R) method.invoke(instance, params); } return null; } - - public static T getField(Class class1, Class fieldType, Object instance, int fieldIndex) throws IllegalArgumentException, IllegalAccessException - { + + public static T getField(Class class1, Class fieldType, Object instance, int fieldIndex) + throws IllegalArgumentException, IllegalAccessException { Field field = class1.getDeclaredFields()[fieldIndex]; field.setAccessible(true); return (T) field.get(instance); } - - public static T getField(Class class1, Class fieldType, Object instance, String fieldName) - { - try - { + + public static T getField(Class class1, Class fieldType, Object instance, String fieldName) { + try { Field field = class1.getDeclaredField(fieldName); field.setAccessible(true); return (T) field.get(instance); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } - public static T newInstance(Class class1, Object... params) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException - { - nextMethod: for(Constructor constructor : class1.getDeclaredConstructors()) - { + public static T newInstance(Class class1, Object... params) + throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { + nextMethod: + for (Constructor constructor : class1.getDeclaredConstructors()) { Class[] paramtypes = constructor.getParameterTypes(); - if(paramtypes.length != params.length) - continue; - - for(int i = 0; i < params.length; i++) - { - if(!isInstance(paramtypes[i], params[i])) - continue nextMethod; + if (paramtypes.length != params.length) continue; + + for (int i = 0; i < params.length; i++) { + if (!isInstance(paramtypes[i], params[i])) continue nextMethod; } - + constructor.setAccessible(true); - return (T)constructor.newInstance(params); + return (T) constructor.newInstance(params); } return null; } - public static boolean hasField(Class class1, String fieldName) - { - try - { + public static boolean hasField(Class class1, String fieldName) { + try { class1.getDeclaredField(fieldName); return true; - } - catch(NoSuchFieldException nfe) - { + } catch (NoSuchFieldException nfe) { return false; } } - - public static T get(Field field, Class class1) - { + + public static T get(Field field, Class class1) { return get(field, class1, null); } - public static T get(Field field, Class class1, Object instance) - { - try - { - return (T)field.get(instance); - } - catch(Exception e) - { + public static T get(Field field, Class class1, Object instance) { + try { + return (T) field.get(instance); + } catch (Exception e) { throw new RuntimeException(e); } } - - public static void set(Field field, Object value) - { + + public static void set(Field field, Object value) { set(field, null, value); } - - public static void set(Field field, Object instance, Object value) - { - try - { + + public static void set(Field field, Object instance, Object value) { + try { field.set(instance, value); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } - public static Field getField(ObfMapping mapping) - { + public static Field getField(ObfMapping mapping) { mapping.toRuntime(); - - try - { + + try { Class clazz = ReflectionManager.class.getClassLoader().loadClass(mapping.javaClass()); Field field = clazz.getDeclaredField(mapping.s_name); field.setAccessible(true); return field; - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } diff --git a/src/main/java/codechicken/core/ServerUtils.java b/src/main/java/codechicken/core/ServerUtils.java index 7b9db6d..42c93c4 100644 --- a/src/main/java/codechicken/core/ServerUtils.java +++ b/src/main/java/codechicken/core/ServerUtils.java @@ -1,22 +1,20 @@ package codechicken.core; +import codechicken.lib.asm.ObfMapping; +import com.mojang.authlib.GameProfile; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; - -import codechicken.lib.asm.ObfMapping; -import com.mojang.authlib.GameProfile; -import net.minecraft.server.MinecraftServer; -import net.minecraft.inventory.Container; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.Container; +import net.minecraft.server.MinecraftServer; import net.minecraft.util.IChatComponent; -public class ServerUtils extends CommonUtils -{ +public class ServerUtils extends CommonUtils { public static MinecraftServer mc() { return MinecraftServer.getServer(); } @@ -31,9 +29,7 @@ public static List getPlayers() { public static ArrayList getPlayersInDimension(int dimension) { ArrayList players = new ArrayList(); - for (EntityPlayer p : getPlayers()) - if(p.dimension == dimension) - players.add(p); + for (EntityPlayer p : getPlayers()) if (p.dimension == dimension) players.add(p); return players; } @@ -50,13 +46,20 @@ public static void openSMPContainer(EntityPlayerMP player, Container container, private static Field field_152661_c; private static Class c_ProfileEntry; private static Method func_152668_a; + static { try { - field_152661_c = ReflectionManager.getField(new ObfMapping("net/minecraft/server/management/PlayerProfileCache", "field_152661_c", "[Ljava/util/Map;")); - c_ProfileEntry = ServerUtils.class.getClassLoader().loadClass("net.minecraft.server.management.PlayerProfileCache$ProfileEntry"); - func_152668_a = c_ProfileEntry.getDeclaredMethod( - new ObfMapping("net/minecraft/server/management/PlayerProfileCache$ProfileEntry", - "func_152668_a", "()Lcom/mojang/authlib/GameProfile;").toRuntime().s_name); + field_152661_c = ReflectionManager.getField(new ObfMapping( + "net/minecraft/server/management/PlayerProfileCache", "field_152661_c", "[Ljava/util/Map;")); + c_ProfileEntry = ServerUtils.class + .getClassLoader() + .loadClass("net.minecraft.server.management.PlayerProfileCache$ProfileEntry"); + func_152668_a = c_ProfileEntry.getDeclaredMethod(new ObfMapping( + "net/minecraft/server/management/PlayerProfileCache$ProfileEntry", + "func_152668_a", + "()Lcom/mojang/authlib/GameProfile;") + .toRuntime() + .s_name); func_152668_a.setAccessible(true); } catch (Exception e) { @@ -66,14 +69,12 @@ public static void openSMPContainer(EntityPlayerMP player, Container container, public static GameProfile getGameProfile(String username) { EntityPlayer player = getPlayer(username); - if(player != null) - return player.getGameProfile(); + if (player != null) return player.getGameProfile(); username = username.toLowerCase(Locale.ROOT); - try {//use reflection to bypass saving the game profiles every time we ask the cache for one + try { // use reflection to bypass saving the game profiles every time we ask the cache for one Object cacheEntry = ((Map) field_152661_c.get(mc().func_152358_ax())).get(username); - if(cacheEntry != null) - return (GameProfile) func_152668_a.invoke(cacheEntry); + if (cacheEntry != null) return (GameProfile) func_152668_a.invoke(cacheEntry); } catch (Exception e) { throw new RuntimeException(e); } @@ -90,7 +91,6 @@ public static boolean isPlayerOwner(String username) { } public static void sendChatToAll(IChatComponent msg) { - for(EntityPlayer p : getPlayers()) - p.addChatComponentMessage(msg); + for (EntityPlayer p : getPlayers()) p.addChatComponentMessage(msg); } } diff --git a/src/main/java/codechicken/core/TaskProfiler.java b/src/main/java/codechicken/core/TaskProfiler.java index c1ca80d..30f92bb 100644 --- a/src/main/java/codechicken/core/TaskProfiler.java +++ b/src/main/java/codechicken/core/TaskProfiler.java @@ -5,61 +5,51 @@ import java.util.List; import java.util.Map.Entry; -public class TaskProfiler -{ - public static class ProfilerResult - { +public class TaskProfiler { + public static class ProfilerResult { public final String name; public final long time; public final double fraction; - - public ProfilerResult(String name, long time, long totalTime) - { + + public ProfilerResult(String name, long time, long totalTime) { this.name = name; this.time = time; - fraction = time/(double)totalTime; + fraction = time / (double) totalTime; } } - + public HashMap times = new HashMap(); - + public String currentSection; private long startTime; private long totalTime; - - public void start(String section) - { - if(currentSection != null) - end(); - + + public void start(String section) { + if (currentSection != null) end(); + currentSection = section; startTime = System.nanoTime(); } - - public void end() - { - long time = System.nanoTime()-startTime; - totalTime+=time; - + + public void end() { + long time = System.nanoTime() - startTime; + totalTime += time; + Long prev = times.get(currentSection); - if(prev == null) - prev = 0L; - times.put(currentSection, prev+time); + if (prev == null) prev = 0L; + times.put(currentSection, prev + time); currentSection = null; } - - public List getResults() - { + + public List getResults() { ArrayList results = new ArrayList(times.size()); - for(Entry e : times.entrySet()) + for (Entry e : times.entrySet()) results.add(new ProfilerResult(e.getKey(), e.getValue(), totalTime)); return results; } - public void clear() - { - if(currentSection != null) - end(); + public void clear() { + if (currentSection != null) end(); times.clear(); totalTime = 0; } diff --git a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java index d948541..d293700 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java @@ -1,17 +1,13 @@ package codechicken.core.asm; -import java.io.IOException; -import java.lang.reflect.Field; - -import com.google.common.collect.ImmutableBiMap; - import codechicken.lib.asm.ObfMapping; - +import com.google.common.collect.ImmutableBiMap; import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import java.io.IOException; +import java.lang.reflect.Field; -public class CodeChickenAccessTransformer extends AccessTransformer -{ +public class CodeChickenAccessTransformer extends AccessTransformer { private static boolean makeAllPublic; private static Field f_classNameBiMap; private static Object emptyMap = ImmutableBiMap.of(); @@ -22,17 +18,17 @@ public CodeChickenAccessTransformer() throws IOException { } private void loadPublicConfig() { - if (ObfMapping.obfuscated) - return; + if (ObfMapping.obfuscated) return; - makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic") - .setComment("Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader." + - "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers." + - "\nSuch mods are doing the wrong thing and should be fixed.") + makeAllPublic = CodeChickenCoreModContainer.config + .getTag("dev.runtimePublic") + .setComment( + "Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader." + + "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers." + + "\nSuch mods are doing the wrong thing and should be fixed.") .getBooleanValue(false); - if (!makeAllPublic) - return; + if (!makeAllPublic) return; try { f_classNameBiMap = FMLDeobfuscatingRemapper.class.getDeclaredField("classNameBiMap"); @@ -45,11 +41,9 @@ private void loadPublicConfig() { @Override public byte[] transform(String name, String transformedName, byte[] bytes) { boolean setPublic = makeAllPublic && name.startsWith("net.minecraft."); - if (setPublic) - setClassMap(name); + if (setPublic) setClassMap(name); bytes = super.transform(name, transformedName, bytes); - if (setPublic) - restoreClassMap(); + if (setPublic) restoreClassMap(); return bytes; } diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index da49e93..da6e773 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -1,34 +1,31 @@ package codechicken.core.asm; -import java.io.File; -import java.util.LinkedList; -import java.util.List; - import codechicken.core.CCUpdateChecker; import codechicken.core.ClientUtils; import codechicken.core.featurehack.LiquidTextures; import codechicken.core.internal.CCCEventHandler; import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.lib.config.ConfigFile; - import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; - import cpw.mods.fml.common.*; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.versioning.ArtifactVersion; import cpw.mods.fml.common.versioning.VersionParser; import cpw.mods.fml.common.versioning.VersionRange; +import java.io.File; +import java.util.LinkedList; +import java.util.List; import net.minecraftforge.common.MinecraftForge; -public class CodeChickenCoreModContainer extends DummyModContainer -{ +public class CodeChickenCoreModContainer extends DummyModContainer { public static ConfigFile config; public static void loadConfig() { - if(config == null) - config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg")).setComment("CodeChickenCore configuration file."); + if (config == null) + config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg")) + .setComment("CodeChickenCore configuration file."); } public CodeChickenCoreModContainer() { @@ -46,7 +43,7 @@ private static ModMetadata getModMetadata() { @Override public List getDependants() { LinkedList deps = new LinkedList(); - if(!getVersion().contains("$")) { + if (!getVersion().contains("$")) { deps.add(VersionParser.parseVersionReference("Forge@[10.13.3,)")); deps.add(VersionParser.parseVersionReference("NotEnoughItems@[1.0.5,)")); deps.add(VersionParser.parseVersionReference("EnderStorage@[1.4.7,)")); @@ -65,15 +62,13 @@ public boolean registerBus(EventBus bus, LoadController controller) { @Subscribe public void preInit(FMLPreInitializationEvent event) { - if (event.getSide().isClient()) - LiquidTextures.init(); + if (event.getSide().isClient()) LiquidTextures.init(); } @Subscribe public void init(FMLInitializationEvent event) { if (event.getSide().isClient()) { - if (config.getTag("checkUpdates").getBooleanValue(true)) - CCUpdateChecker.updateCheck(getModId()); + if (config.getTag("checkUpdates").getBooleanValue(true)) CCUpdateChecker.updateCheck(getModId()); ClientUtils.enhanceSupportersList("CodeChickenCore"); diff --git a/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java index df16917..57127df 100644 --- a/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java +++ b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java @@ -1,94 +1,89 @@ package codechicken.core.asm; +import codechicken.lib.asm.ASMHelper; +import codechicken.lib.asm.ClassHeirachyManager; +import codechicken.lib.asm.ObfMapping; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; - +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.launchwrapper.LaunchClassLoader; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; -import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.ClassHeirachyManager; -import codechicken.lib.asm.ObfMapping; - -import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraft.launchwrapper.LaunchClassLoader; +public class DefaultImplementationTransformer implements IClassTransformer { + private static LaunchClassLoader cl = (LaunchClassLoader) ClassHeirachyManager.class.getClassLoader(); -public class DefaultImplementationTransformer implements IClassTransformer -{ - private static LaunchClassLoader cl = (LaunchClassLoader)ClassHeirachyManager.class.getClassLoader(); private static ClassNode getClassNode(String name) { - try { - return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.'))); - } catch (IOException e) { - throw new RuntimeException(e); - } + try { + return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.'))); + } catch (IOException e) { + throw new RuntimeException(e); + } } - - static class InterfaceImpl - { - public final String iname; - public ArrayList impls = new ArrayList(); - - public InterfaceImpl(String iname, String cname) - { - this.iname = iname; - HashSet names = new HashSet(); - ClassNode inode = getClassNode(iname); - for(MethodNode method : inode.methods) - names.add(method.name+method.desc); - - ClassNode cnode = getClassNode(cname); - for(MethodNode method : cnode.methods) - if(names.contains(method.name+method.desc)) { - impls.add(method); - method.desc = new ObfMapping(cnode.name, method.name, method.desc).toRuntime().s_desc; - } - } - public boolean patch(ClassNode cnode) { - LinkedList names = new LinkedList(); - for(MethodNode method : cnode.methods) { - ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime(); - names.add(m.s_name+m.s_desc); - } + static class InterfaceImpl { + public final String iname; + public ArrayList impls = new ArrayList(); - boolean changed = false; - for(MethodNode impl : impls) { - if(names.contains(impl.name+impl.desc)) - continue; - - MethodNode copy = new MethodNode(impl.access, impl.name, impl.desc, - impl.signature, impl.exceptions == null ? null : impl.exceptions.toArray(new String[0])); - ASMHelper.copy(impl, copy); - cnode.methods.add(impl); - changed = true; - } - return changed; - } - } - - private static HashMap impls = new HashMap(); - - public static void registerDefaultImpl(String iname, String cname) { - impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname)); - } - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - if(transformedName.startsWith("net.minecraft") || impls.isEmpty()) - return bytes; - - ClassNode cnode = ASMHelper.createClassNode(bytes); - boolean changed = false; - for(String iname : cnode.interfaces) { - InterfaceImpl impl = impls.get(iname); - if(impl != null) - changed |= impl.patch(cnode); - } - - return changed ? ASMHelper.createBytes(cnode, 0) : bytes; - } + public InterfaceImpl(String iname, String cname) { + this.iname = iname; + HashSet names = new HashSet(); + ClassNode inode = getClassNode(iname); + for (MethodNode method : inode.methods) names.add(method.name + method.desc); + + ClassNode cnode = getClassNode(cname); + for (MethodNode method : cnode.methods) + if (names.contains(method.name + method.desc)) { + impls.add(method); + method.desc = new ObfMapping(cnode.name, method.name, method.desc).toRuntime().s_desc; + } + } + + public boolean patch(ClassNode cnode) { + LinkedList names = new LinkedList(); + for (MethodNode method : cnode.methods) { + ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime(); + names.add(m.s_name + m.s_desc); + } + + boolean changed = false; + for (MethodNode impl : impls) { + if (names.contains(impl.name + impl.desc)) continue; + + MethodNode copy = new MethodNode( + impl.access, + impl.name, + impl.desc, + impl.signature, + impl.exceptions == null ? null : impl.exceptions.toArray(new String[0])); + ASMHelper.copy(impl, copy); + cnode.methods.add(impl); + changed = true; + } + return changed; + } + } + + private static HashMap impls = new HashMap(); + + public static void registerDefaultImpl(String iname, String cname) { + impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname)); + } + + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) { + if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes; + + ClassNode cnode = ASMHelper.createClassNode(bytes); + boolean changed = false; + for (String iname : cnode.interfaces) { + InterfaceImpl impl = impls.get(iname); + if (impl != null) changed |= impl.patch(cnode); + } + + return changed ? ASMHelper.createBytes(cnode, 0) : bytes; + } } diff --git a/src/main/java/codechicken/core/asm/DelegatedTransformer.java b/src/main/java/codechicken/core/asm/DelegatedTransformer.java index c212469..6d5d820 100644 --- a/src/main/java/codechicken/core/asm/DelegatedTransformer.java +++ b/src/main/java/codechicken/core/asm/DelegatedTransformer.java @@ -1,5 +1,7 @@ package codechicken.core.asm; +import static codechicken.core.launch.CodeChickenCorePlugin.logger; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -11,141 +13,117 @@ import java.util.Stack; import java.util.jar.JarFile; import java.util.zip.ZipEntry; - +import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Opcodes; -import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraft.launchwrapper.LaunchClassLoader; - -import static codechicken.core.launch.CodeChickenCorePlugin.logger; - -public class DelegatedTransformer implements IClassTransformer -{ +public class DelegatedTransformer implements IClassTransformer { private static ArrayList delegatedTransformers; private static Method m_defineClass; private static Field f_cachedClasses; - - public DelegatedTransformer() - { + + public DelegatedTransformer() { delegatedTransformers = new ArrayList(); - try - { - m_defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE); + try { + m_defineClass = ClassLoader.class.getDeclaredMethod( + "defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE); m_defineClass.setAccessible(true); f_cachedClasses = LaunchClassLoader.class.getDeclaredField("cachedClasses"); f_cachedClasses.setAccessible(true); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } - + @Override - public byte[] transform(String name, String tname, byte[] bytes) - { + public byte[] transform(String name, String tname, byte[] bytes) { if (bytes == null) return null; - for(IClassTransformer trans : delegatedTransformers) - bytes = trans.transform(name, tname, bytes); + for (IClassTransformer trans : delegatedTransformers) bytes = trans.transform(name, tname, bytes); return bytes; } - public static void addTransformer(String transformer, JarFile jar, File jarFile) - { + public static void addTransformer(String transformer, JarFile jar, File jarFile) { logger.debug("Adding CCTransformer: " + transformer); - try - { + try { byte[] bytes; bytes = Launch.classLoader.getClassBytes(transformer); - - if(bytes == null) - { - String resourceName = transformer.replace('.', '/')+".class"; + + if (bytes == null) { + String resourceName = transformer.replace('.', '/') + ".class"; ZipEntry entry = jar.getEntry(resourceName); - if(entry == null) - throw new Exception("Failed to add transformer: "+transformer+". Entry not found in jar file "+jarFile.getName()); - + if (entry == null) + throw new Exception("Failed to add transformer: " + transformer + ". Entry not found in jar file " + + jarFile.getName()); + bytes = readFully(jar.getInputStream(entry)); } - + defineDependancies(bytes, jar, jarFile); Class clazz = defineClass(transformer, bytes); - - if(!IClassTransformer.class.isAssignableFrom(clazz)) - throw new Exception("Failed to add transformer: "+transformer+" is not an instance of IClassTransformer"); - + + if (!IClassTransformer.class.isAssignableFrom(clazz)) + throw new Exception( + "Failed to add transformer: " + transformer + " is not an instance of IClassTransformer"); + IClassTransformer classTransformer; - try - { - classTransformer = (IClassTransformer) clazz.getDeclaredConstructor(File.class).newInstance(jarFile); - } - catch(NoSuchMethodException nsme) - { + try { + classTransformer = (IClassTransformer) + clazz.getDeclaredConstructor(File.class).newInstance(jarFile); + } catch (NoSuchMethodException nsme) { classTransformer = (IClassTransformer) clazz.newInstance(); } delegatedTransformers.add(classTransformer); - } - catch(Exception e) - { + } catch (Exception e) { e.printStackTrace(); - } + } } - - private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile) throws Exception - { + + private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile) throws Exception { defineDependancies(bytes, jar, jarFile, new Stack()); } - private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile, Stack depStack) throws Exception - { + private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile, Stack depStack) + throws Exception { ClassReader reader = new ClassReader(bytes); DependancyLister lister = new DependancyLister(Opcodes.ASM4); reader.accept(lister, 0); - + depStack.push(reader.getClassName()); - - for(String dependancy : lister.getDependancies()) - { - if(depStack.contains(dependancy)) - continue; - - try - { + + for (String dependancy : lister.getDependancies()) { + if (depStack.contains(dependancy)) continue; + + try { Launch.classLoader.loadClass(dependancy.replace('/', '.')); - } - catch(ClassNotFoundException cnfe) - { - ZipEntry entry = jar.getEntry(dependancy+".class"); - if(entry == null) - throw new Exception("Dependency "+dependancy+" not found in jar file "+jarFile.getName()); - + } catch (ClassNotFoundException cnfe) { + ZipEntry entry = jar.getEntry(dependancy + ".class"); + if (entry == null) + throw new Exception("Dependency " + dependancy + " not found in jar file " + jarFile.getName()); + byte[] depbytes = readFully(jar.getInputStream(entry)); defineDependancies(depbytes, jar, jarFile, depStack); - logger.debug("Defining dependancy: "+dependancy); - + logger.debug("Defining dependancy: " + dependancy); + defineClass(dependancy.replace('/', '.'), depbytes); } } - + depStack.pop(); } - private static Class defineClass(String classname, byte[] bytes) throws Exception - { + private static Class defineClass(String classname, byte[] bytes) throws Exception { Class clazz = (Class) m_defineClass.invoke(Launch.classLoader, classname, bytes, 0, bytes.length); - ((Map>)f_cachedClasses.get(Launch.classLoader)).put(classname, clazz); + ((Map>) f_cachedClasses.get(Launch.classLoader)).put(classname, clazz); return clazz; } - public static byte[] readFully(InputStream stream) throws IOException - { + public static byte[] readFully(InputStream stream) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(stream.available()); int r; - while ((r = stream.read()) != -1) - { + while ((r = stream.read()) != -1) { bos.write(r); } diff --git a/src/main/java/codechicken/core/asm/DependancyLister.java b/src/main/java/codechicken/core/asm/DependancyLister.java index a732bbf..92549a1 100644 --- a/src/main/java/codechicken/core/asm/DependancyLister.java +++ b/src/main/java/codechicken/core/asm/DependancyLister.java @@ -5,91 +5,74 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -public class DependancyLister extends ClassVisitor -{ +public class DependancyLister extends ClassVisitor { private static Pattern classdesc = Pattern.compile("L(.+?);"); - - private class DependancyMethodLister extends MethodVisitor - { - public DependancyMethodLister(int api) - { + + private class DependancyMethodLister extends MethodVisitor { + public DependancyMethodLister(int api) { super(api); } - + @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) - { + public void visitFieldInsn(int opcode, String owner, String name, String desc) { dependDesc(desc); } - + @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) - { + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { dependDesc(desc); } - + @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) - { + public void visitMethodInsn(int opcode, String owner, String name, String desc) { depend(owner); dependDesc(desc); } } - + private HashSet dependancies = new HashSet(); - public DependancyLister(int api) - { + public DependancyLister(int api) { super(api); } - + @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) - { + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { dependDesc(desc); return null; } - - private void dependDesc(String desc) - { + + private void dependDesc(String desc) { Matcher match = classdesc.matcher(desc); - while(match.find()) - { + while (match.find()) { String s = match.group(); - depend(s.substring(1, s.length()-1)); + depend(s.substring(1, s.length() - 1)); } } - private void depend(String classname) - { + private void depend(String classname) { dependancies.add(classname); } @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) - { + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { dependDesc(desc); return new DependancyMethodLister(Opcodes.ASM4); } - + @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) - { + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { depend(superName); - if(interfaces != null) - for(String interfacename : interfaces) - depend(interfacename); + if (interfaces != null) for (String interfacename : interfaces) depend(interfacename); } - - public List getDependancies() - { + + public List getDependancies() { return new ArrayList(dependancies); } } diff --git a/src/main/java/codechicken/core/asm/InterfaceDependancies.java b/src/main/java/codechicken/core/asm/InterfaceDependancies.java index 9048a0f..bf8e682 100644 --- a/src/main/java/codechicken/core/asm/InterfaceDependancies.java +++ b/src/main/java/codechicken/core/asm/InterfaceDependancies.java @@ -5,10 +5,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) -public @interface InterfaceDependancies -{ - -} +public @interface InterfaceDependancies {} diff --git a/src/main/java/codechicken/core/asm/InterfaceDependancyTransformer.java b/src/main/java/codechicken/core/asm/InterfaceDependancyTransformer.java deleted file mode 100644 index 7992829..0000000 --- a/src/main/java/codechicken/core/asm/InterfaceDependancyTransformer.java +++ /dev/null @@ -1,53 +0,0 @@ -package codechicken.core.asm; - -import java.util.Iterator; - -import codechicken.lib.asm.ASMInit; -import net.minecraft.launchwrapper.Launch; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AnnotationNode; -import org.objectweb.asm.tree.ClassNode; - -import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.ObfMapping; - -import net.minecraft.launchwrapper.IClassTransformer; - -public class InterfaceDependancyTransformer implements IClassTransformer -{ - static { - ASMInit.init(); - } - - @Override - public byte[] transform(String name, String tname, byte[] bytes) { - if (bytes == null) return null; - ClassNode cnode = ASMHelper.createClassNode(bytes); - - boolean hasDependancyInterfaces = false; - if (cnode.visibleAnnotations != null) - for (AnnotationNode ann : cnode.visibleAnnotations) - if (ann.desc.equals(Type.getDescriptor(InterfaceDependancies.class))) { - hasDependancyInterfaces = true; - break; - } - - if (!hasDependancyInterfaces) - return bytes; - - hasDependancyInterfaces = false; - for (Iterator iterator = cnode.interfaces.iterator(); iterator.hasNext(); ) { - try { - Launch.classLoader.findClass(new ObfMapping(iterator.next()).toRuntime().javaClass()); - } catch (ClassNotFoundException cnfe) { - iterator.remove(); - hasDependancyInterfaces = true; - } - } - - if (!hasDependancyInterfaces) - return bytes; - - return ASMHelper.createBytes(cnode, 0); - } -} diff --git a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java index 45d6d53..9af7f6f 100644 --- a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java +++ b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java @@ -1,13 +1,23 @@ package codechicken.core.asm; +import codechicken.lib.asm.ASMHelper; +import codechicken.lib.asm.ASMInit; +import codechicken.lib.asm.CC_ClassWriter; +import codechicken.lib.asm.ObfMapping; +import codechicken.obfuscator.IHeirachyEvaluator; +import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; +import codechicken.obfuscator.ObfuscationRun; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import cpw.mods.fml.common.asm.transformers.AccessTransformer; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; import java.util.Map.Entry; - -import codechicken.lib.asm.ASMInit; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; @@ -15,28 +25,12 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - -import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.CC_ClassWriter; -import codechicken.lib.asm.ObfMapping; -import codechicken.obfuscator.IHeirachyEvaluator; -import codechicken.obfuscator.ObfuscationRun; -import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; -import cpw.mods.fml.common.asm.transformers.AccessTransformer; - -import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraft.launchwrapper.LaunchClassLoader; - -public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator -{ +public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator { static { ASMInit.init(); } - public static class LoadPlugin implements IFMLLoadingPlugin - { + public static class LoadPlugin implements IFMLLoadingPlugin { @Override public String[] getASMTransformerClass() { return new String[0]; @@ -78,7 +72,8 @@ public String getAccessTransformerClass() { try { f_transformers = LaunchClassLoader.class.getDeclaredField("transformers"); f_modifiers = AccessTransformer.class.getDeclaredField("modifiers"); - Class c_Modifier = Class.forName(AccessTransformer.class.getName() + "$Modifier", false, Launch.classLoader); + Class c_Modifier = + Class.forName(AccessTransformer.class.getName() + "$Modifier", false, Launch.classLoader); f_Modifier_name = c_Modifier.getDeclaredField("name"); f_Modifier_desc = c_Modifier.getDeclaredField("desc"); @@ -115,21 +110,25 @@ private static List getTransformers() { public static void load() { CodeChickenCoreModContainer.loadConfig(); - if (CodeChickenCoreModContainer.config.getTag("dev.deobfuscate") + if (CodeChickenCoreModContainer.config + .getTag("dev.deobfuscate") .setComment("set to true to completely deobfuscate mcp names") .getBooleanValue(!ObfMapping.obfuscated)) { - run = new ObfuscationRun(false, ObfMapping.MCPRemapper.getConfFiles(), + run = new ObfuscationRun( + false, + ObfMapping.MCPRemapper.getConfFiles(), ObfuscationRun.fillDefaults(new HashMap())); run.obf.setHeirachyEvaluator(instance); run.setQuiet().parseMappings(); - Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";")); + Collections.addAll( + excludedPackages, run.config.get("excludedPackages").split(";")); if (ObfMapping.obfuscated) { ObfMapping.loadMCPRemapper(); run.setSeargeConstants(); getTransformers().add(instance); } else { - getTransformers().add(0, instance);//insert transformer as first. + getTransformers().add(0, instance); // insert transformer as first. } } } @@ -141,8 +140,7 @@ public byte[] transform(String name, String transformedName, byte[] bytes) { activated = true; } - if (!activated || bytes == null) - return bytes; + if (!activated || bytes == null) return bytes; ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES); ClassWriter cw = new CC_ClassWriter(0, true); @@ -153,21 +151,20 @@ public byte[] transform(String name, String transformedName, byte[] bytes) { private byte[] injectCallback(byte[] bytes) { ClassNode cnode = ASMHelper.createClassNode(bytes); MethodNode mnode = ASMHelper.findMethod(new ObfMapping(cnode.name, "", "()V"), cnode); - mnode.instructions.insert(new MethodInsnNode(INVOKESTATIC, "codechicken/core/asm/MCPDeobfuscationTransformer", "loadCallback", "()V")); + mnode.instructions.insert(new MethodInsnNode( + INVOKESTATIC, "codechicken/core/asm/MCPDeobfuscationTransformer", "loadCallback", "()V")); return ASMHelper.createBytes(cnode, 0); } public static void loadCallback() { if (ObfMapping.obfuscated) { - //move ourselves to the end + // move ourselves to the end List transformers = getTransformers(); transformers.remove(instance); transformers.add(instance); } else { - //remap access transformers - for (IClassTransformer t : getTransformers()) - if (t instanceof AccessTransformer) - remapAccessTransformer(t); + // remap access transformers + for (IClassTransformer t : getTransformers()) if (t instanceof AccessTransformer) remapAccessTransformer(t); } } @@ -207,10 +204,10 @@ public List getParents(ObfuscationEntry desc) { name = name.replace('/', '.'); try { byte[] bytes = Launch.classLoader.getClassBytes(name); - if (bytes != null) - return ObfuscationRun.getParents(ASMHelper.createClassNode(bytes)); - } catch (IOException ignored) {} - //clear the miss cache because the library containing it might be loaded later + if (bytes != null) return ObfuscationRun.getParents(ASMHelper.createClassNode(bytes)); + } catch (IOException ignored) { + } + // clear the miss cache because the library containing it might be loaded later Launch.classLoader.clearNegativeEntries(Collections.singleton(name)); return null; } @@ -218,19 +215,15 @@ public List getParents(ObfuscationEntry desc) { @Override public boolean isLibClass(ObfuscationEntry desc) { String name = desc.srg.s_owner; - for (String p : excludedPackages) - if (name.startsWith(p)) - return true; + for (String p : excludedPackages) if (name.startsWith(p)) return true; return false; } public static String unmap(String name) { - if (run == null) - return null; + if (run == null) return null; ObfuscationEntry e = run.obf.lookupMcpClass(name); - if (e == null) - return null; + if (e == null) return null; return e.obf.s_owner; } diff --git a/src/main/java/codechicken/core/asm/MethodASMifier.java b/src/main/java/codechicken/core/asm/MethodASMifier.java index 8a40d79..55a1519 100644 --- a/src/main/java/codechicken/core/asm/MethodASMifier.java +++ b/src/main/java/codechicken/core/asm/MethodASMifier.java @@ -1,8 +1,10 @@ package codechicken.core.asm; +import static org.objectweb.asm.Opcodes.*; + +import codechicken.lib.asm.ObfMapping; import java.io.File; import java.io.PrintWriter; - import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; @@ -10,13 +12,7 @@ import org.objectweb.asm.util.Printer; import org.objectweb.asm.util.TraceMethodVisitor; -import codechicken.core.launch.CodeChickenCorePlugin; -import codechicken.lib.asm.ObfMapping; - -import static org.objectweb.asm.Opcodes.*; - -public class MethodASMifier extends ClassVisitor -{ +public class MethodASMifier extends ClassVisitor { PrintWriter printWriter; ObfMapping method; Printer asmifier; @@ -55,10 +51,8 @@ public static void printMethod(ObfMapping method, Printer printer, File toFile) public static void printMethod(ObfMapping method, byte[] bytes, Printer printer, File toFile) { try { - if (!toFile.getParentFile().exists()) - toFile.getParentFile().mkdirs(); - if (!toFile.exists()) - toFile.createNewFile(); + if (!toFile.getParentFile().exists()) toFile.getParentFile().mkdirs(); + if (!toFile.exists()) toFile.createNewFile(); PrintWriter printWriter = new PrintWriter(toFile); diff --git a/src/main/java/codechicken/core/asm/TweakTransformer.java b/src/main/java/codechicken/core/asm/TweakTransformer.java index 77484f5..8ae895e 100644 --- a/src/main/java/codechicken/core/asm/TweakTransformer.java +++ b/src/main/java/codechicken/core/asm/TweakTransformer.java @@ -1,23 +1,20 @@ package codechicken.core.asm; +import static codechicken.lib.asm.InsnComparator.*; + import codechicken.lib.asm.*; import codechicken.lib.asm.ModularASMTransformer.MethodReplacer; import codechicken.lib.asm.ModularASMTransformer.MethodTransformer; import codechicken.lib.asm.ModularASMTransformer.MethodWriter; +import codechicken.lib.config.ConfigTag; +import java.util.Map; +import net.minecraft.launchwrapper.IClassTransformer; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; -import codechicken.lib.config.ConfigTag; -import net.minecraft.launchwrapper.IClassTransformer; - -import java.util.Map; - -import static codechicken.lib.asm.InsnComparator.*; - -public class TweakTransformer implements IClassTransformer, Opcodes -{ +public class TweakTransformer implements IClassTransformer, Opcodes { static { ASMInit.init(); } @@ -28,53 +25,71 @@ public class TweakTransformer implements IClassTransformer, Opcodes public static void load() { CodeChickenCoreModContainer.loadConfig(); - tweaks = CodeChickenCoreModContainer.config.getTag("tweaks") - .setComment("Various tweaks that can be applied to game mechanics.").useBraces(); + tweaks = CodeChickenCoreModContainer.config + .getTag("tweaks") + .setComment("Various tweaks that can be applied to game mechanics.") + .useBraces(); tweaks.removeTag("persistantLava"); if (tweaks.getTag("environmentallyFriendlyCreepers") - .setComment("If set to true, creepers will not destroy landscape. (A version of mobGriefing setting just for creepers)") + .setComment( + "If set to true, creepers will not destroy landscape. (A version of mobGriefing setting just for creepers)") .getBooleanValue(false)) { - transformer.add(new MethodReplacer(new ObfMapping("net/minecraft/entity/monster/EntityCreeper", "func_146077_cc", "()V"), - blocks.get("d_environmentallyFriendlyCreepers"), blocks.get("environmentallyFriendlyCreepers"))); + transformer.add(new MethodReplacer( + new ObfMapping("net/minecraft/entity/monster/EntityCreeper", "func_146077_cc", "()V"), + blocks.get("d_environmentallyFriendlyCreepers"), + blocks.get("environmentallyFriendlyCreepers"))); } if (!tweaks.getTag("softLeafReplace") .setComment("If set to false, leaves will only replace air when growing") .getBooleanValue(false)) { - transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping("net/minecraft/block/Block", "canBeReplacedByLeaves", "(Lnet/minecraft/world/IBlockAccess;III)Z"), blocks.get("softLeafReplace"))); + transformer.add(new MethodWriter( + ACC_PUBLIC, + new ObfMapping( + "net/minecraft/block/Block", + "canBeReplacedByLeaves", + "(Lnet/minecraft/world/IBlockAccess;III)Z"), + blocks.get("softLeafReplace"))); } if (tweaks.getTag("doFireTickOut") - .setComment("If set to true and doFireTick is disabled in the game rules, fire will still dissipate if it's not over a fire source") + .setComment( + "If set to true and doFireTick is disabled in the game rules, fire will still dissipate if it's not over a fire source") .getBooleanValue(true)) { - transformer.add(new MethodTransformer(new ObfMapping("net/minecraft/block/BlockFire", "func_149674_a", "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) - { - @Override - public void transform(MethodNode mv) { - ASMBlock needle = blocks.get("n_doFireTick"); - ASMBlock inject = blocks.get("doFireTick"); + transformer.add( + new MethodTransformer(new ObfMapping( + "net/minecraft/block/BlockFire", + "func_149674_a", + "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) { + @Override + public void transform(MethodNode mv) { + ASMBlock needle = blocks.get("n_doFireTick"); + ASMBlock inject = blocks.get("doFireTick"); - ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list)); - LabelNode jlabel = key.get("LRET"); - mv.instructions.insertBefore(jlabel, new JumpInsnNode(GOTO, inject.get("LSKIP"))); - mv.instructions.insert(jlabel, inject.list.list); - } - }); + ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list)); + LabelNode jlabel = key.get("LRET"); + mv.instructions.insertBefore(jlabel, new JumpInsnNode(GOTO, inject.get("LSKIP"))); + mv.instructions.insert(jlabel, inject.list.list); + } + }); } if (tweaks.getTag("finiteWater") .setComment("If set to true two adjacent water source blocks will not generate a third.") .getBooleanValue(false)) { - transformer.add(new MethodTransformer(new ObfMapping("net/minecraft/block/BlockDynamicLiquid", "func_149674_a", "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) - { - @Override - public void transform(MethodNode mv) { - ASMBlock needle = blocks.get("finiteWater"); - ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list)); - mv.instructions.insertBefore(key.list.getFirst(), new JumpInsnNode(GOTO, key.get("LEND"))); - } - }); + transformer.add( + new MethodTransformer(new ObfMapping( + "net/minecraft/block/BlockDynamicLiquid", + "func_149674_a", + "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) { + @Override + public void transform(MethodNode mv) { + ASMBlock needle = blocks.get("finiteWater"); + ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list)); + mv.instructions.insertBefore(key.list.getFirst(), new JumpInsnNode(GOTO, key.get("LEND"))); + } + }); } } diff --git a/src/main/java/codechicken/core/commands/CoreCommand.java b/src/main/java/codechicken/core/commands/CoreCommand.java index aaf30c4..dffde45 100644 --- a/src/main/java/codechicken/core/commands/CoreCommand.java +++ b/src/main/java/codechicken/core/commands/CoreCommand.java @@ -1,25 +1,22 @@ package codechicken.core.commands; -import java.util.List; - import codechicken.core.ServerUtils; +import java.util.List; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.ChunkCoordinates; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.command.ICommand; -import net.minecraft.command.ICommandSender; import net.minecraft.util.IChatComponent; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; -public abstract class CoreCommand implements ICommand -{ - public class WCommandSender implements ICommandSender - { +public abstract class CoreCommand implements ICommand { + public class WCommandSender implements ICommandSender { public ICommandSender wrapped; public WCommandSender(ICommandSender sender) { @@ -78,15 +75,13 @@ public String getCommandUsage(ICommandSender var1) { public void processCommand(ICommandSender listener, String[] args) { WCommandSender wsender = new WCommandSender(listener); - if (args.length < minimumParameters() || - args.length == 1 && args[0].equals("help")) { + if (args.length < minimumParameters() || args.length == 1 && args[0].equals("help")) { printHelp(wsender); return; } String command = getCommandName(); - for (String arg : args) - command += " " + arg; + for (String arg : args) command += " " + arg; handleCommand(command, wsender.getCommandSenderName(), args, wsender); } @@ -131,15 +126,14 @@ public boolean isUsernameIndex(String[] astring, int i) { public boolean canCommandSenderUseCommand(ICommandSender var1) { if (OPOnly()) { if (var1 instanceof EntityPlayer) - return MinecraftServer.getServer().getConfigurationManager().func_152596_g(((EntityPlayer) var1).getGameProfile()); - else if (var1 instanceof MinecraftServer) - return true; - else - return false; + return MinecraftServer.getServer() + .getConfigurationManager() + .func_152596_g(((EntityPlayer) var1).getGameProfile()); + else if (var1 instanceof MinecraftServer) return true; + else return false; } return true; } - public abstract int minimumParameters(); } diff --git a/src/main/java/codechicken/core/commands/PlayerCommand.java b/src/main/java/codechicken/core/commands/PlayerCommand.java index 1b42cd5..694f03d 100644 --- a/src/main/java/codechicken/core/commands/PlayerCommand.java +++ b/src/main/java/codechicken/core/commands/PlayerCommand.java @@ -1,60 +1,53 @@ package codechicken.core.commands; -import net.minecraft.util.MovingObjectPosition.MovingObjectType; -import net.minecraft.world.ChunkPosition; +import net.minecraft.command.ICommandSender; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.command.ICommandSender; import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.MovingObjectPosition.MovingObjectType; import net.minecraft.util.Vec3; +import net.minecraft.world.ChunkPosition; import net.minecraft.world.WorldServer; -public abstract class PlayerCommand extends CoreCommand -{ +public abstract class PlayerCommand extends CoreCommand { @Override - public boolean canCommandSenderUseCommand(ICommandSender var1) - { - if(!super.canCommandSenderUseCommand(var1)) - return false; + public boolean canCommandSenderUseCommand(ICommandSender var1) { + if (!super.canCommandSenderUseCommand(var1)) return false; return var1 instanceof EntityPlayer; } - - + @Override - public void handleCommand(String command, String playername, String[] args, WCommandSender listener) - { - EntityPlayerMP player = (EntityPlayerMP)listener.wrapped; + public void handleCommand(String command, String playername, String[] args, WCommandSender listener) { + EntityPlayerMP player = (EntityPlayerMP) listener.wrapped; handleCommand(getWorld(player), player, args); } - + public abstract void handleCommand(WorldServer world, EntityPlayerMP player, String[] args); - - public ChunkPosition getPlayerLookingAtBlock(EntityPlayerMP player, float reach) - { - Vec3 vec3d = Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); + + public ChunkPosition getPlayerLookingAtBlock(EntityPlayerMP player, float reach) { + Vec3 vec3d = + Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); Vec3 vec3d1 = player.getLook(1.0F); Vec3 vec3d2 = vec3d.addVector(vec3d1.xCoord * reach, vec3d1.yCoord * reach, vec3d1.zCoord * reach); MovingObjectPosition hit = player.worldObj.rayTraceBlocks(vec3d, vec3d2); - if(hit == null || hit.typeOfHit != MovingObjectType.BLOCK) - { + if (hit == null || hit.typeOfHit != MovingObjectType.BLOCK) { return null; } - + return new ChunkPosition(hit.blockX, hit.blockY, hit.blockZ); } - - public Entity getPlayerLookingAtEntity(EntityPlayerMP player, float reach) - { - Vec3 vec3d = Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); + + public Entity getPlayerLookingAtEntity(EntityPlayerMP player, float reach) { + Vec3 vec3d = + Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); Vec3 vec3d1 = player.getLook(1.0F); Vec3 vec3d2 = vec3d.addVector(vec3d1.xCoord * reach, vec3d1.yCoord * reach, vec3d1.zCoord * reach); MovingObjectPosition hit = player.worldObj.rayTraceBlocks(vec3d, vec3d2); - if(hit == null || hit.typeOfHit != MovingObjectType.ENTITY) - { + if (hit == null || hit.typeOfHit != MovingObjectType.ENTITY) { return null; } - + return hit.entityHit; } } diff --git a/src/main/java/codechicken/core/commands/ServerCommand.java b/src/main/java/codechicken/core/commands/ServerCommand.java index ef06809..86cdc6a 100644 --- a/src/main/java/codechicken/core/commands/ServerCommand.java +++ b/src/main/java/codechicken/core/commands/ServerCommand.java @@ -1,28 +1,23 @@ package codechicken.core.commands; -import net.minecraft.server.MinecraftServer; import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; -public abstract class ServerCommand extends CoreCommand -{ +public abstract class ServerCommand extends CoreCommand { @Override - public void processCommand(ICommandSender var1, String[] var2) - { - handleCommand(var2, (MinecraftServer)var1); + public void processCommand(ICommandSender var1, String[] var2) { + handleCommand(var2, (MinecraftServer) var1); } - + @Override - public boolean canCommandSenderUseCommand(ICommandSender var1) - { - if(!super.canCommandSenderUseCommand(var1)) - return false; + public boolean canCommandSenderUseCommand(ICommandSender var1) { + if (!super.canCommandSenderUseCommand(var1)) return false; return var1 instanceof MinecraftServer; } - + public abstract void handleCommand(String[] args, MinecraftServer listener); - public final boolean OPOnly() - { + public final boolean OPOnly() { return false; - } + } } diff --git a/src/main/java/codechicken/core/featurehack/EntityRenderHook.java b/src/main/java/codechicken/core/featurehack/EntityRenderHook.java index 8e89361..9d51fef 100644 --- a/src/main/java/codechicken/core/featurehack/EntityRenderHook.java +++ b/src/main/java/codechicken/core/featurehack/EntityRenderHook.java @@ -4,10 +4,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; -public class EntityRenderHook extends Entity -{ - public static interface IRenderCallback - { +public class EntityRenderHook extends Entity { + public static interface IRenderCallback { public void render(float frame, int pass); public boolean shouldRenderInPass(int pass); @@ -26,21 +24,17 @@ public EntityRenderHook(World world, double x, double y, double z, IRenderCallba @Override public void onUpdate() { - if (!callback.isValid()) - setDead(); + if (!callback.isValid()) setDead(); } @Override - protected void entityInit() { - } + protected void entityInit() {} @Override - protected void readEntityFromNBT(NBTTagCompound var1) { - } + protected void readEntityFromNBT(NBTTagCompound var1) {} @Override - protected void writeEntityToNBT(NBTTagCompound var1) { - } + protected void writeEntityToNBT(NBTTagCompound var1) {} @Override public boolean shouldRenderInPass(int pass) { diff --git a/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java b/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java index c6890d8..36eff20 100644 --- a/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java +++ b/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java @@ -4,44 +4,33 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; -public class EntityUpdateHook extends Entity -{ - public static interface IUpdateCallback - { +public class EntityUpdateHook extends Entity { + public static interface IUpdateCallback { public void onUpdate(); public boolean isValid(); } - + public final IUpdateCallback callback; - public EntityUpdateHook(World world, int x, int y, int z, IUpdateCallback callback) - { + + public EntityUpdateHook(World world, int x, int y, int z, IUpdateCallback callback) { super(world); setPosition(x, y, z); this.callback = callback; } @Override - public void onUpdate() - { - if(!callback.isValid()) - setDead(); - else - callback.onUpdate(); + public void onUpdate() { + if (!callback.isValid()) setDead(); + else callback.onUpdate(); } @Override - protected void entityInit() - { - } + protected void entityInit() {} @Override - protected void readEntityFromNBT(NBTTagCompound var1) - { - } + protected void readEntityFromNBT(NBTTagCompound var1) {} @Override - protected void writeEntityToNBT(NBTTagCompound var1) - { - } + protected void writeEntityToNBT(NBTTagCompound var1) {} } diff --git a/src/main/java/codechicken/core/featurehack/FeatureHack.java b/src/main/java/codechicken/core/featurehack/FeatureHack.java index 0f210d9..911a97b 100644 --- a/src/main/java/codechicken/core/featurehack/FeatureHack.java +++ b/src/main/java/codechicken/core/featurehack/FeatureHack.java @@ -5,34 +5,27 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class FeatureHack -{ +public class FeatureHack { private static boolean updateHookEnabled = false; private static boolean renderHookEnabled = false; - - public static void enableUpdateHook() - { - if(updateHookEnabled) - return; - + + public static void enableUpdateHook() { + if (updateHookEnabled) return; + updateHookEnabled = true; - if(FMLCommonHandler.instance().getSide().isClient()) - enableClientUpdateHook(); + if (FMLCommonHandler.instance().getSide().isClient()) enableClientUpdateHook(); } @SideOnly(Side.CLIENT) - public static void enableRenderHook() - { - if(renderHookEnabled) - return; - + public static void enableRenderHook() { + if (renderHookEnabled) return; + renderHookEnabled = true; RenderingRegistry.registerEntityRenderingHandler(EntityUpdateHook.class, new RenderNull()); } @SideOnly(Side.CLIENT) - private static void enableClientUpdateHook() - { + private static void enableClientUpdateHook() { RenderingRegistry.registerEntityRenderingHandler(EntityRenderHook.class, new RenderEntityRenderHook()); } } diff --git a/src/main/java/codechicken/core/featurehack/GameDataManipulator.java b/src/main/java/codechicken/core/featurehack/GameDataManipulator.java index 87e2dc4..2a1f0e3 100644 --- a/src/main/java/codechicken/core/featurehack/GameDataManipulator.java +++ b/src/main/java/codechicken/core/featurehack/GameDataManipulator.java @@ -1,27 +1,30 @@ package codechicken.core.featurehack; import codechicken.lib.asm.ObfMapping; +import java.lang.reflect.Field; +import java.util.Map; import net.minecraft.item.Item; import net.minecraft.util.ObjectIntIdentityMap; import net.minecraft.util.RegistryNamespaced; import net.minecraft.util.RegistrySimple; -import java.lang.reflect.Field; -import java.util.Map; - -public class GameDataManipulator -{ +public class GameDataManipulator { public static Field f_registryObjects; public static Field f_underlyingIntegerMap; - static - { + static { try { f_registryObjects = RegistrySimple.class.getDeclaredField( - new ObfMapping("net/minecraft/util/RegistrySimple", "field_82596_a", "Ljava/util/Map;").toRuntime().s_name); + new ObfMapping("net/minecraft/util/RegistrySimple", "field_82596_a", "Ljava/util/Map;") + .toRuntime() + .s_name); f_registryObjects.setAccessible(true); - f_underlyingIntegerMap = RegistryNamespaced.class.getDeclaredField( - new ObfMapping("net/minecraft/util/RegistryNamespaced", "field_148759_a", "Lnet/minecraft/util/ObjectIntIdentityMap;").toRuntime().s_name); + f_underlyingIntegerMap = RegistryNamespaced.class.getDeclaredField(new ObfMapping( + "net/minecraft/util/RegistryNamespaced", + "field_148759_a", + "Lnet/minecraft/util/ObjectIntIdentityMap;") + .toRuntime() + .s_name); f_underlyingIntegerMap.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); @@ -31,8 +34,8 @@ public class GameDataManipulator public static void replaceItem(int id, Item item) { try { String name = Item.itemRegistry.getNameForObject(Item.getItemById(id)); - ((Map)f_registryObjects.get(Item.itemRegistry)).put(name, item); - ((ObjectIntIdentityMap)f_underlyingIntegerMap.get(Item.itemRegistry)).func_148746_a(item, id); + ((Map) f_registryObjects.get(Item.itemRegistry)).put(name, item); + ((ObjectIntIdentityMap) f_underlyingIntegerMap.get(Item.itemRegistry)).func_148746_a(item, id); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/codechicken/core/featurehack/LiquidTextures.java b/src/main/java/codechicken/core/featurehack/LiquidTextures.java index 2911c5a..9c00606 100644 --- a/src/main/java/codechicken/core/featurehack/LiquidTextures.java +++ b/src/main/java/codechicken/core/featurehack/LiquidTextures.java @@ -1,58 +1,56 @@ package codechicken.core.featurehack; -import java.lang.reflect.Field; import codechicken.core.ReflectionManager; +import codechicken.core.asm.TweakTransformer; import codechicken.core.featurehack.mc.TextureLavaFX; import codechicken.core.featurehack.mc.TextureLavaFlowFX; import codechicken.core.featurehack.mc.TextureWaterFX; import codechicken.core.featurehack.mc.TextureWaterFlowFX; +import codechicken.lib.asm.ObfMapping; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import net.minecraft.block.Block; +import java.lang.reflect.Field; import net.minecraft.init.Blocks; import net.minecraft.util.IIcon; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.MinecraftForge; -import codechicken.core.asm.TweakTransformer; -import codechicken.lib.asm.ObfMapping; - -public class LiquidTextures -{ +public class LiquidTextures { public static IIcon[] newTextures = new IIcon[4]; - + public static boolean replaceLava; public static boolean replaceWater; - + private static Field field_tex; - - public static void init() - { - replaceWater = TweakTransformer.tweaks.getTag("replaceWaterFX").setComment("Set this to true to use the pre1.5 water textures").getBooleanValue(false); - replaceLava = TweakTransformer.tweaks.getTag("replaceLavaFX").setComment("Set this to true to use the pre1.5 lava textures").getBooleanValue(false); - if(replaceWater) - { + + public static void init() { + replaceWater = TweakTransformer.tweaks + .getTag("replaceWaterFX") + .setComment("Set this to true to use the pre1.5 water textures") + .getBooleanValue(false); + replaceLava = TweakTransformer.tweaks + .getTag("replaceLavaFX") + .setComment("Set this to true to use the pre1.5 lava textures") + .getBooleanValue(false); + if (replaceWater) { newTextures[0] = new TextureWaterFX().texture; newTextures[1] = new TextureWaterFlowFX().texture; } - if(replaceLava) - { + if (replaceLava) { newTextures[2] = new TextureLavaFX().texture; newTextures[3] = new TextureLavaFlowFX().texture; } - - if(replaceWater || replaceLava) - { + + if (replaceWater || replaceLava) { MinecraftForge.EVENT_BUS.register(new LiquidTextures()); - field_tex = ReflectionManager.getField(new ObfMapping("net/minecraft/block/BlockLiquid", "field_149806_a", "[Lnet/minecraft/util/IIcon;")); + field_tex = ReflectionManager.getField( + new ObfMapping("net/minecraft/block/BlockLiquid", "field_149806_a", "[Lnet/minecraft/util/IIcon;")); } } @SubscribeEvent - public void postStitch(TextureStitchEvent.Post event) - { + public void postStitch(TextureStitchEvent.Post event) { IIcon[] icons; - if(replaceLava) - { + if (replaceLava) { icons = ReflectionManager.get(field_tex, IIcon[].class, Blocks.flowing_lava); icons[0] = newTextures[2]; icons[1] = newTextures[3]; @@ -60,8 +58,7 @@ public void postStitch(TextureStitchEvent.Post event) icons[0] = newTextures[2]; icons[1] = newTextures[3]; } - if(replaceWater) - { + if (replaceWater) { icons = ReflectionManager.get(field_tex, IIcon[].class, Blocks.flowing_water); icons[0] = newTextures[0]; icons[1] = newTextures[1]; diff --git a/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java b/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java index d72a2cb..53ba9aa 100644 --- a/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java +++ b/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java @@ -1,26 +1,22 @@ package codechicken.core.featurehack; -import org.lwjgl.opengl.GL11; - +import net.minecraft.client.renderer.entity.Render; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; -import net.minecraft.client.renderer.entity.Render; import net.minecraftforge.client.MinecraftForgeClient; +import org.lwjgl.opengl.GL11; -public class RenderEntityRenderHook extends Render -{ +public class RenderEntityRenderHook extends Render { @Override - public void doRender(Entity entity, double x, double y, double z, float f, float frame) - { - EntityRenderHook hook = (EntityRenderHook)entity; - GL11.glTranslated(x-hook.posX, y-hook.posY, z-hook.posZ); - ((EntityRenderHook)entity).callback.render(frame, MinecraftForgeClient.getRenderPass()); - GL11.glTranslated(hook.posX-x, hook.posY-y, hook.posZ-z); + public void doRender(Entity entity, double x, double y, double z, float f, float frame) { + EntityRenderHook hook = (EntityRenderHook) entity; + GL11.glTranslated(x - hook.posX, y - hook.posY, z - hook.posZ); + ((EntityRenderHook) entity).callback.render(frame, MinecraftForgeClient.getRenderPass()); + GL11.glTranslated(hook.posX - x, hook.posY - y, hook.posZ - z); } @Override - protected ResourceLocation getEntityTexture(Entity entity) - { + protected ResourceLocation getEntityTexture(Entity entity) { return null; } } diff --git a/src/main/java/codechicken/core/featurehack/RenderNull.java b/src/main/java/codechicken/core/featurehack/RenderNull.java index e6fc568..9d6d099 100644 --- a/src/main/java/codechicken/core/featurehack/RenderNull.java +++ b/src/main/java/codechicken/core/featurehack/RenderNull.java @@ -4,16 +4,12 @@ import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; -public class RenderNull extends Render -{ +public class RenderNull extends Render { @Override - public void doRender(Entity var1, double var2, double var4, double var6, float var8, float var9) - { - } - + public void doRender(Entity var1, double var2, double var4, double var6, float var8, float var9) {} + @Override - protected ResourceLocation getEntityTexture(Entity entity) - { + protected ResourceLocation getEntityTexture(Entity entity) { return null; } } diff --git a/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java b/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java index 816320b..c03af77 100644 --- a/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java +++ b/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java @@ -1,38 +1,37 @@ package codechicken.core.featurehack; -import java.util.Random; +import static net.minecraftforge.common.util.ForgeDirection.UP; +import java.util.Random; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.world.World; -import static net.minecraftforge.common.util.ForgeDirection.UP; - -public class TweakTransformerHelper -{ - public static void quenchFireTick(World world, int x, int y, int z, Random rand) - { +public class TweakTransformerHelper { + public static void quenchFireTick(World world, int x, int y, int z, Random rand) { Block base = world.getBlock(x, y - 1, z); boolean supported = (base != null && base.isFireSource(world, x, y - 1, z, UP)); - - if (!Blocks.fire.canPlaceBlockAt(world, x, y, z) || - !supported && world.isRaining() && (world.canLightningStrikeAt(x, y, z) || world.canLightningStrikeAt(x - 1, y, z) || world.canLightningStrikeAt(x + 1, y, z) || world.canLightningStrikeAt(x, y, z - 1) || world.canLightningStrikeAt(x, y, z + 1))) - world.setBlockToAir(x, y, z); - else - { + + if (!Blocks.fire.canPlaceBlockAt(world, x, y, z) + || !supported + && world.isRaining() + && (world.canLightningStrikeAt(x, y, z) + || world.canLightningStrikeAt(x - 1, y, z) + || world.canLightningStrikeAt(x + 1, y, z) + || world.canLightningStrikeAt(x, y, z - 1) + || world.canLightningStrikeAt(x, y, z + 1))) world.setBlockToAir(x, y, z); + else { int meta = world.getBlockMetadata(x, y, z); - if(meta < 15) - world.setBlockMetadataWithNotify(x, y, z, meta+rand.nextInt(3)/2, 0); - + if (meta < 15) world.setBlockMetadataWithNotify(x, y, z, meta + rand.nextInt(3) / 2, 0); + world.scheduleBlockUpdate(x, y, z, Blocks.fire, Blocks.fire.tickRate(world) + rand.nextInt(10)); - - if(!supported && !Blocks.fire.canCatchFire(world, x, y - 1, z, UP) && meta == 15 && rand.nextInt(4) == 0) + + if (!supported && !Blocks.fire.canCatchFire(world, x, y - 1, z, UP) && meta == 15 && rand.nextInt(4) == 0) world.setBlockToAir(x, y, z); } } - - public static boolean canPlaceBlockAt(World world, int x, int y, int z) - { + + public static boolean canPlaceBlockAt(World world, int x, int y, int z) { Block block = world.getBlock(x, y, z); return block.isAir(world, x, y, z) || block.isReplaceable(world, x, y, z); } diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java index dabbbe3..0ebfd58 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java @@ -7,22 +7,19 @@ import net.minecraft.util.MathHelper; @SideOnly(Side.CLIENT) -public class TextureLavaFX extends TextureFX -{ +public class TextureLavaFX extends TextureFX { protected float[] field_76876_g = new float[256]; protected float[] field_76878_h = new float[256]; protected float[] field_76879_i = new float[256]; protected float[] field_76877_j = new float[256]; - public TextureLavaFX() - { + public TextureLavaFX() { super(16, "lava_still_fx"); setup(); } @Override - public void setup() - { + public void setup() { super.setup(); field_76876_g = new float[tileSizeSquare]; field_76878_h = new float[tileSizeSquare]; @@ -30,8 +27,7 @@ public void setup() field_76877_j = new float[tileSizeSquare]; } - public void onTick() - { + public void onTick() { int var2; float var3; int var5; @@ -40,36 +36,40 @@ public void onTick() int var8; int var9; - for (int var1 = 0; var1 < tileSizeBase; ++var1) - { - for (var2 = 0; var2 < tileSizeBase; ++var2) - { + for (int var1 = 0; var1 < tileSizeBase; ++var1) { + for (var2 = 0; var2 < tileSizeBase; ++var2) { var3 = 0.0F; - int var4 = (int)(MathHelper.sin(var2 * (float)Math.PI * 2.0F / 16.0F) * 1.2F); - var5 = (int)(MathHelper.sin(var1 * (float)Math.PI * 2.0F / 16.0F) * 1.2F); + int var4 = (int) (MathHelper.sin(var2 * (float) Math.PI * 2.0F / 16.0F) * 1.2F); + var5 = (int) (MathHelper.sin(var1 * (float) Math.PI * 2.0F / 16.0F) * 1.2F); - for (var6 = var1 - 1; var6 <= var1 + 1; ++var6) - { - for (var7 = var2 - 1; var7 <= var2 + 1; ++var7) - { + for (var6 = var1 - 1; var6 <= var1 + 1; ++var6) { + for (var7 = var2 - 1; var7 <= var2 + 1; ++var7) { var8 = var6 + var4 & tileSizeMask; var9 = var7 + var5 & tileSizeMask; var3 += this.field_76876_g[var8 + var9 * tileSizeBase]; } } - this.field_76878_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + (this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76879_i[(var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76879_i[(var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] + this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) / 4.0F * 0.8F; - this.field_76879_i[var1 + var2 * tileSizeBase] += this.field_76877_j[var1 + var2 * tileSizeBase] * 0.01F; - - if (this.field_76879_i[var1 + var2 * tileSizeBase] < 0.0F) - { + this.field_76878_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + + (this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + + this.field_76879_i[ + (var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + + this.field_76879_i[ + (var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] + + this.field_76879_i[ + (var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) + / 4.0F + * 0.8F; + this.field_76879_i[var1 + var2 * tileSizeBase] += + this.field_76877_j[var1 + var2 * tileSizeBase] * 0.01F; + + if (this.field_76879_i[var1 + var2 * tileSizeBase] < 0.0F) { this.field_76879_i[var1 + var2 * tileSizeBase] = 0.0F; } this.field_76877_j[var1 + var2 * tileSizeBase] -= 0.06F; - if (Math.random() < 0.005D) - { + if (Math.random() < 0.005D) { this.field_76877_j[var1 + var2 * tileSizeBase] = 1.5F; } } @@ -79,26 +79,22 @@ public void onTick() this.field_76878_h = this.field_76876_g; this.field_76876_g = var11; - for (var2 = 0; var2 < tileSizeSquare; ++var2) - { + for (var2 = 0; var2 < tileSizeSquare; ++var2) { var3 = this.field_76876_g[var2] * 2.0F; - if (var3 > 1.0F) - { + if (var3 > 1.0F) { var3 = 1.0F; } - if (var3 < 0.0F) - { + if (var3 < 0.0F) { var3 = 0.0F; } - var5 = (int)(var3 * 100.0F + 155.0F); - var6 = (int)(var3 * var3 * 255.0F); - var7 = (int)(var3 * var3 * var3 * var3 * 128.0F); + var5 = (int) (var3 * 100.0F + 155.0F); + var6 = (int) (var3 * var3 * 255.0F); + var7 = (int) (var3 * var3 * var3 * var3 * 128.0F); - if (this.anaglyphEnabled) - { + if (this.anaglyphEnabled) { var8 = (var5 * 30 + var6 * 59 + var7 * 11) / 100; var9 = (var5 * 30 + var6 * 70) / 100; int var10 = (var5 * 30 + var7 * 70) / 100; diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java index b1912d7..849c102 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java @@ -7,28 +7,25 @@ import net.minecraft.util.MathHelper; @SideOnly(Side.CLIENT) -public class TextureLavaFlowFX extends TextureFX -{ +public class TextureLavaFlowFX extends TextureFX { protected float[] field_76871_g = new float[256]; protected float[] field_76874_h = new float[256]; protected float[] field_76875_i = new float[256]; protected float[] field_76872_j = new float[256]; int field_76873_k = 0; - //shadow + // shadow public int tileSizeBase = 16; public int tileSizeSquare = 256; public int tileSizeMask = 15; public int tileSizeSquareMask = 255; - public TextureLavaFlowFX() - { + public TextureLavaFlowFX() { super(32, "lava_flow_fx"); } @Override - public void setup() - { + public void setup() { super.setup(); field_76871_g = new float[tileSizeSquare]; field_76874_h = new float[tileSizeSquare]; @@ -37,8 +34,7 @@ public void setup() field_76873_k = 0; } - public void onTick() - { + public void onTick() { ++this.field_76873_k; int var2; float var3; @@ -48,36 +44,40 @@ public void onTick() int var8; int var9; - for (int var1 = 0; var1 < tileSizeBase; ++var1) - { - for (var2 = 0; var2 < tileSizeBase; ++var2) - { + for (int var1 = 0; var1 < tileSizeBase; ++var1) { + for (var2 = 0; var2 < tileSizeBase; ++var2) { var3 = 0.0F; - int var4 = (int)(MathHelper.sin(var2 * (float)Math.PI * 2.0F / 16.0F) * 1.2F); - var5 = (int)(MathHelper.sin(var1 * (float)Math.PI * 2.0F / 16.0F) * 1.2F); + int var4 = (int) (MathHelper.sin(var2 * (float) Math.PI * 2.0F / 16.0F) * 1.2F); + var5 = (int) (MathHelper.sin(var1 * (float) Math.PI * 2.0F / 16.0F) * 1.2F); - for (var6 = var1 - 1; var6 <= var1 + 1; ++var6) - { - for (var7 = var2 - 1; var7 <= var2 + 1; ++var7) - { + for (var6 = var1 - 1; var6 <= var1 + 1; ++var6) { + for (var7 = var2 - 1; var7 <= var2 + 1; ++var7) { var8 = var6 + var4 & tileSizeMask; var9 = var7 + var5 & tileSizeMask; var3 += this.field_76871_g[var8 + var9 * tileSizeBase]; } } - this.field_76874_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + (this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76875_i[(var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76875_i[(var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] + this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) / 4.0F * 0.8F; - this.field_76875_i[var1 + var2 * tileSizeBase] += this.field_76872_j[var1 + var2 * tileSizeBase] * 0.01F; - - if (this.field_76875_i[var1 + var2 * tileSizeBase] < 0.0F) - { + this.field_76874_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + + (this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + + this.field_76875_i[ + (var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + + this.field_76875_i[ + (var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] + + this.field_76875_i[ + (var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) + / 4.0F + * 0.8F; + this.field_76875_i[var1 + var2 * tileSizeBase] += + this.field_76872_j[var1 + var2 * tileSizeBase] * 0.01F; + + if (this.field_76875_i[var1 + var2 * tileSizeBase] < 0.0F) { this.field_76875_i[var1 + var2 * tileSizeBase] = 0.0F; } this.field_76872_j[var1 + var2 * tileSizeBase] -= 0.06F; - if (Math.random() < 0.005D) - { + if (Math.random() < 0.005D) { this.field_76872_j[var1 + var2 * tileSizeBase] = 1.5F; } } @@ -87,26 +87,22 @@ public void onTick() this.field_76874_h = this.field_76871_g; this.field_76871_g = var11; - for (var2 = 0; var2 < tileSizeSquare; ++var2) - { + for (var2 = 0; var2 < tileSizeSquare; ++var2) { var3 = this.field_76871_g[(var2 - this.field_76873_k / 3 * tileSizeBase) & tileSizeSquareMask] * 2.0F; - if (var3 > 1.0F) - { + if (var3 > 1.0F) { var3 = 1.0F; } - if (var3 < 0.0F) - { + if (var3 < 0.0F) { var3 = 0.0F; } - var5 = (int)(var3 * 100.0F + 155.0F); - var6 = (int)(var3 * var3 * 255.0F); - var7 = (int)(var3 * var3 * var3 * var3 * 128.0F); + var5 = (int) (var3 * 100.0F + 155.0F); + var6 = (int) (var3 * var3 * 255.0F); + var7 = (int) (var3 * var3 * var3 * var3 * 128.0F); - if (this.anaglyphEnabled) - { + if (this.anaglyphEnabled) { var8 = (var5 * 30 + var6 * 59 + var7 * 11) / 100; var9 = (var5 * 30 + var6 * 70) / 100; int var10 = (var5 * 30 + var7 * 70) / 100; @@ -115,17 +111,16 @@ public void onTick() var7 = var10; } - int px = var2&tileSizeMask; - int py = var2/tileSizeBase; + int px = var2 & tileSizeMask; + int py = var2 / tileSizeBase; writeColour(px, py, var5, var6, var7, -1); - writeColour(px+16, py, var5, var6, var7, -1); - writeColour(px, py+16, var5, var6, var7, -1); - writeColour(px+16, py+16, var5, var6, var7, -1); + writeColour(px + 16, py, var5, var6, var7, -1); + writeColour(px, py + 16, var5, var6, var7, -1); + writeColour(px + 16, py + 16, var5, var6, var7, -1); } } - private void writeColour(int px, int py, int var5, int var6, int var7, int var8) - { - imageData[py*32+px] = new ColourRGBA(var5, var6, var7, var8).argb(); + private void writeColour(int px, int py, int var5, int var6, int var7, int var8) { + imageData[py * 32 + px] = new ColourRGBA(var5, var6, var7, var8).argb(); } } diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java index bb62c42..bb3c0ec 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java @@ -6,8 +6,7 @@ import cpw.mods.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) -public class TextureWaterFX extends TextureFX -{ +public class TextureWaterFX extends TextureFX { /** red RGB value for water texture */ protected float[] red = new float[256]; @@ -19,15 +18,14 @@ public class TextureWaterFX extends TextureFX /** alpha RGB value for water texture */ protected float[] alpha = new float[256]; - public TextureWaterFX() - { + + public TextureWaterFX() { super(16, "water_still_fx"); setup(); } @Override - public void setup() - { + public void setup() { super.setup(); red = new float[tileSizeSquare]; green = new float[tileSizeSquare]; @@ -35,22 +33,18 @@ public void setup() alpha = new float[tileSizeSquare]; } - public void onTick() - { + public void onTick() { int var1; int var2; float var3; int var5; int var6; - for (var1 = 0; var1 < tileSizeBase; ++var1) - { - for (var2 = 0; var2 < tileSizeBase; ++var2) - { + for (var1 = 0; var1 < tileSizeBase; ++var1) { + for (var2 = 0; var2 < tileSizeBase; ++var2) { var3 = 0.0F; - for (int var4 = var1 - 1; var4 <= var1 + 1; ++var4) - { + for (int var4 = var1 - 1; var4 <= var1 + 1; ++var4) { var5 = var4 & tileSizeMask; var6 = var2 & tileSizeMask; var3 += this.red[var5 + var6 * tileSizeBase]; @@ -60,21 +54,17 @@ public void onTick() } } - for (var1 = 0; var1 < tileSizeBase; ++var1) - { - for (var2 = 0; var2 < tileSizeBase; ++var2) - { + for (var1 = 0; var1 < tileSizeBase; ++var1) { + for (var2 = 0; var2 < tileSizeBase; ++var2) { this.blue[var1 + var2 * tileSizeBase] += this.alpha[var1 + var2 * tileSizeBase] * 0.05F; - if (this.blue[var1 + var2 * tileSizeBase] < 0.0F) - { + if (this.blue[var1 + var2 * tileSizeBase] < 0.0F) { this.blue[var1 + var2 * tileSizeBase] = 0.0F; } this.alpha[var1 + var2 * tileSizeBase] -= 0.1F; - if (Math.random() < 0.05D) - { + if (Math.random() < 0.05D) { this.alpha[var1 + var2 * tileSizeBase] = 0.5F; } } @@ -84,28 +74,24 @@ public void onTick() this.green = this.red; this.red = var12; - for (var2 = 0; var2 < tileSizeSquare; ++var2) - { + for (var2 = 0; var2 < tileSizeSquare; ++var2) { var3 = this.red[var2]; - if (var3 > 1.0F) - { + if (var3 > 1.0F) { var3 = 1.0F; } - if (var3 < 0.0F) - { + if (var3 < 0.0F) { var3 = 0.0F; } float var13 = var3 * var3; - var5 = (int)(32.0F + var13 * 32.0F); - var6 = (int)(50.0F + var13 * 64.0F); + var5 = (int) (32.0F + var13 * 32.0F); + var6 = (int) (50.0F + var13 * 64.0F); int var7 = 255; - int var8 = (int)(146.0F + var13 * 50.0F); + int var8 = (int) (146.0F + var13 * 50.0F); - if (this.anaglyphEnabled) - { + if (this.anaglyphEnabled) { int var9 = (var5 * 30 + var6 * 59 + var7 * 11) / 100; int var10 = (var5 * 30 + var6 * 70) / 100; int var11 = (var5 * 30 + var7 * 70) / 100; diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java index d6b92cd..7632a16 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java @@ -6,28 +6,25 @@ import cpw.mods.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) -public class TextureWaterFlowFX extends TextureFX -{ +public class TextureWaterFlowFX extends TextureFX { protected float[] field_76880_g = new float[256]; protected float[] field_76883_h = new float[256]; protected float[] field_76884_i = new float[256]; protected float[] field_76881_j = new float[256]; private int tickCounter = 0; - - //shadow + + // shadow public int tileSizeBase = 16; public int tileSizeSquare = 256; public int tileSizeMask = 15; public int tileSizeSquareMask = 255; - public TextureWaterFlowFX() - { + public TextureWaterFlowFX() { super(32, "water_flow_fx"); } @Override - public void setup() - { + public void setup() { super.setup(); field_76880_g = new float[tileSizeSquare]; field_76883_h = new float[tileSizeSquare]; @@ -36,8 +33,7 @@ public void setup() tickCounter = 0; } - public void onTick() - { + public void onTick() { ++this.tickCounter; int var1; int var2; @@ -45,38 +41,33 @@ public void onTick() int var5; int var6; - for (var1 = 0; var1 < tileSizeBase; ++var1) - { - for (var2 = 0; var2 < tileSizeBase; ++var2) - { + for (var1 = 0; var1 < tileSizeBase; ++var1) { + for (var2 = 0; var2 < tileSizeBase; ++var2) { var3 = 0.0F; - for (int var4 = var2 - 2; var4 <= var2; ++var4) - { + for (int var4 = var2 - 2; var4 <= var2; ++var4) { var5 = var1 & tileSizeMask; var6 = var4 & tileSizeMask; var3 += this.field_76880_g[var5 + var6 * tileSizeBase]; } - this.field_76883_h[var1 + var2 * tileSizeBase] = var3 / 3.2F + this.field_76884_i[var1 + var2 * tileSizeBase] * 0.8F; + this.field_76883_h[var1 + var2 * tileSizeBase] = + var3 / 3.2F + this.field_76884_i[var1 + var2 * tileSizeBase] * 0.8F; } } - for (var1 = 0; var1 < tileSizeBase; ++var1) - { - for (var2 = 0; var2 < tileSizeBase; ++var2) - { - this.field_76884_i[var1 + var2 * tileSizeBase] += this.field_76881_j[var1 + var2 * tileSizeBase] * 0.05F; + for (var1 = 0; var1 < tileSizeBase; ++var1) { + for (var2 = 0; var2 < tileSizeBase; ++var2) { + this.field_76884_i[var1 + var2 * tileSizeBase] += + this.field_76881_j[var1 + var2 * tileSizeBase] * 0.05F; - if (this.field_76884_i[var1 + var2 * tileSizeBase] < 0.0F) - { + if (this.field_76884_i[var1 + var2 * tileSizeBase] < 0.0F) { this.field_76884_i[var1 + var2 * tileSizeBase] = 0.0F; } this.field_76881_j[var1 + var2 * tileSizeBase] -= 0.3F; - if (Math.random() < 0.2D) - { + if (Math.random() < 0.2D) { this.field_76881_j[var1 + var2 * tileSizeBase] = 0.5F; } } @@ -86,28 +77,24 @@ public void onTick() this.field_76883_h = this.field_76880_g; this.field_76880_g = var12; - for (var2 = 0; var2 < tileSizeSquare; ++var2) - { + for (var2 = 0; var2 < tileSizeSquare; ++var2) { var3 = this.field_76880_g[var2 - this.tickCounter * tileSizeBase & tileSizeSquareMask]; - if (var3 > 1.0F) - { + if (var3 > 1.0F) { var3 = 1.0F; } - if (var3 < 0.0F) - { + if (var3 < 0.0F) { var3 = 0.0F; } float var13 = var3 * var3; - var5 = (int)(32.0F + var13 * 32.0F); - var6 = (int)(50.0F + var13 * 64.0F); + var5 = (int) (32.0F + var13 * 32.0F); + var6 = (int) (50.0F + var13 * 64.0F); int var7 = 255; - int var8 = (int)(146.0F + var13 * 50.0F); + int var8 = (int) (146.0F + var13 * 50.0F); - if (this.anaglyphEnabled) - { + if (this.anaglyphEnabled) { int var9 = (var5 * 30 + var6 * 59 + var7 * 11) / 100; int var10 = (var5 * 30 + var6 * 70) / 100; int var11 = (var5 * 30 + var7 * 70) / 100; @@ -116,18 +103,16 @@ public void onTick() var7 = var11; } - - int px = var2&tileSizeMask; - int py = var2/tileSizeBase; + int px = var2 & tileSizeMask; + int py = var2 / tileSizeBase; writeColour(px, py, var5, var6, var7, var8); - writeColour(px+16, py, var5, var6, var7, var8); - writeColour(px, py+16, var5, var6, var7, var8); - writeColour(px+16, py+16, var5, var6, var7, var8); + writeColour(px + 16, py, var5, var6, var7, var8); + writeColour(px, py + 16, var5, var6, var7, var8); + writeColour(px + 16, py + 16, var5, var6, var7, var8); } } - private void writeColour(int px, int py, int var5, int var6, int var7, int var8) - { - imageData[py*32+px] = new ColourRGBA(var5, var6, var7, var8).argb(); + private void writeColour(int px, int py, int var5, int var6, int var7, int var8) { + imageData[py * 32 + px] = new ColourRGBA(var5, var6, var7, var8).argb(); } } diff --git a/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java b/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java index fc067f7..06cc648 100644 --- a/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java +++ b/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java @@ -5,15 +5,13 @@ import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidTank; -public class ExtendedFluidTank implements IFluidTank -{ +public class ExtendedFluidTank implements IFluidTank { private FluidStack fluid; private boolean changeType; private int capacity; - - public ExtendedFluidTank(FluidStack type, int capacity) - { - if(type == null) { + + public ExtendedFluidTank(FluidStack type, int capacity) { + if (type == null) { type = FluidUtils.water; changeType = true; } @@ -21,97 +19,76 @@ public ExtendedFluidTank(FluidStack type, int capacity) fluid = FluidUtils.copy(type, 0); this.capacity = capacity; } - - public ExtendedFluidTank(int capacity) - { + + public ExtendedFluidTank(int capacity) { this(null, capacity); } - + @Override - public FluidStack getFluid() - { + public FluidStack getFluid() { return fluid.copy(); } @Override - public int getCapacity() - { + public int getCapacity() { return capacity; } - public boolean canAccept(FluidStack type) - { + public boolean canAccept(FluidStack type) { return type == null || (fluid.amount == 0 && changeType) || fluid.isFluidEqual(type); } @Override - public int fill(FluidStack resource, boolean doFill) - { - if(resource == null) - return 0; - - if(!canAccept(resource)) - return 0; - - int tofill = Math.min(getCapacity()-fluid.amount, resource.amount); - if(doFill && tofill > 0) - { - if(!fluid.isFluidEqual(resource)) - fluid = FluidUtils.copy(resource, fluid.amount+tofill); - else - fluid.amount+=tofill; + public int fill(FluidStack resource, boolean doFill) { + if (resource == null) return 0; + + if (!canAccept(resource)) return 0; + + int tofill = Math.min(getCapacity() - fluid.amount, resource.amount); + if (doFill && tofill > 0) { + if (!fluid.isFluidEqual(resource)) fluid = FluidUtils.copy(resource, fluid.amount + tofill); + else fluid.amount += tofill; onLiquidChanged(); } - + return tofill; } @Override - public FluidStack drain(int maxDrain, boolean doDrain) - { - if(fluid.amount == 0 || maxDrain <= 0) - return null; - + public FluidStack drain(int maxDrain, boolean doDrain) { + if (fluid.amount == 0 || maxDrain <= 0) return null; + int todrain = Math.min(maxDrain, fluid.amount); - if(doDrain && todrain > 0) - { - fluid.amount-=todrain; + if (doDrain && todrain > 0) { + fluid.amount -= todrain; onLiquidChanged(); } return FluidUtils.copy(fluid, todrain); } - - public FluidStack drain(FluidStack resource, boolean doDrain) - { - if (resource == null || !resource.isFluidEqual(fluid)) - return null; - + + public FluidStack drain(FluidStack resource, boolean doDrain) { + if (resource == null || !resource.isFluidEqual(fluid)) return null; + return drain(resource.amount, doDrain); } - public void onLiquidChanged() - { - } + public void onLiquidChanged() {} - public void fromTag(NBTTagCompound tag) - { + public void fromTag(NBTTagCompound tag) { fluid = FluidUtils.read(tag); } - - public NBTTagCompound toTag() - { + + public NBTTagCompound toTag() { return FluidUtils.write(fluid, new NBTTagCompound()); } @Override - public int getFluidAmount() - { + public int getFluidAmount() { return fluid.amount; } @Override - public FluidTankInfo getInfo() - { + public FluidTankInfo getInfo() { return new FluidTankInfo(this); } } diff --git a/src/main/java/codechicken/core/fluid/FluidUtils.java b/src/main/java/codechicken/core/fluid/FluidUtils.java index 1466cc1..689b1c3 100644 --- a/src/main/java/codechicken/core/fluid/FluidUtils.java +++ b/src/main/java/codechicken/core/fluid/FluidUtils.java @@ -11,87 +11,73 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidHandler; -public class FluidUtils -{ +public class FluidUtils { public static int B = FluidContainerRegistry.BUCKET_VOLUME; public static FluidStack water = new FluidStack(FluidRegistry.WATER, 1000); public static FluidStack lava = new FluidStack(FluidRegistry.LAVA, 1000); - public static boolean fillTankWithContainer(IFluidHandler tank, EntityPlayer player) - { + public static boolean fillTankWithContainer(IFluidHandler tank, EntityPlayer player) { ItemStack stack = player.getCurrentEquippedItem(); FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(stack); - if(liquid == null) - return false; + if (liquid == null) return false; - if(tank.fill(ForgeDirection.UNKNOWN, liquid, false) != liquid.amount && !player.capabilities.isCreativeMode) + if (tank.fill(ForgeDirection.UNKNOWN, liquid, false) != liquid.amount && !player.capabilities.isCreativeMode) return false; - + tank.fill(ForgeDirection.UNKNOWN, liquid, true); - - if(!player.capabilities.isCreativeMode) + + if (!player.capabilities.isCreativeMode) InventoryUtils.consumeItem(player.inventory, player.inventory.currentItem); player.inventoryContainer.detectAndSendChanges(); return true; } - public static boolean emptyTankIntoContainer(IFluidHandler tank, EntityPlayer player, FluidStack tankLiquid) - { + public static boolean emptyTankIntoContainer(IFluidHandler tank, EntityPlayer player, FluidStack tankLiquid) { ItemStack stack = player.getCurrentEquippedItem(); - if(!FluidContainerRegistry.isEmptyContainer(stack)) - return false; - + if (!FluidContainerRegistry.isEmptyContainer(stack)) return false; + ItemStack filled = FluidContainerRegistry.fillFluidContainer(tankLiquid, stack); FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(filled); - if(liquid == null || filled == null) - return false; - + if (liquid == null || filled == null) return false; + tank.drain(ForgeDirection.UNKNOWN, liquid.amount, true); - if(!player.capabilities.isCreativeMode) - { - if(stack.stackSize == 1) - player.inventory.setInventorySlotContents(player.inventory.currentItem, filled); - else if(player.inventory.addItemStackToInventory(filled)) - stack.stackSize--; - else - return false; + if (!player.capabilities.isCreativeMode) { + if (stack.stackSize == 1) player.inventory.setInventorySlotContents(player.inventory.currentItem, filled); + else if (player.inventory.addItemStackToInventory(filled)) stack.stackSize--; + else return false; } - - player.inventoryContainer.detectAndSendChanges(); + + player.inventoryContainer.detectAndSendChanges(); return true; } - public static FluidStack copy(FluidStack liquid, int quantity) - { + public static FluidStack copy(FluidStack liquid, int quantity) { liquid = liquid.copy(); liquid.amount = quantity; return liquid; } - public static FluidStack read(NBTTagCompound tag) - { + public static FluidStack read(NBTTagCompound tag) { FluidStack stack = FluidStack.loadFluidStackFromNBT(tag); return stack != null ? stack : FluidUtils.emptyFluid(); } - - public static NBTTagCompound write(FluidStack fluid, NBTTagCompound tag) - { - return fluid == null || fluid.getFluid() == null ? new NBTTagCompound() : fluid.writeToNBT(new NBTTagCompound()); + + public static NBTTagCompound write(FluidStack fluid, NBTTagCompound tag) { + return fluid == null || fluid.getFluid() == null + ? new NBTTagCompound() + : fluid.writeToNBT(new NBTTagCompound()); } - public static int getLuminosity(FluidStack stack, double density) - { + public static int getLuminosity(FluidStack stack, double density) { Fluid fluid = stack.getFluid(); - if(fluid == null) - return 0; + if (fluid == null) return 0; int light = fluid.getLuminosity(stack); - if(fluid.isGaseous()) - light=(int)(light*density); + if (fluid.isGaseous()) light = (int) (light * density); return light; } diff --git a/src/main/java/codechicken/core/fluid/TankAccess.java b/src/main/java/codechicken/core/fluid/TankAccess.java index 8cbdcf1..e3f6575 100644 --- a/src/main/java/codechicken/core/fluid/TankAccess.java +++ b/src/main/java/codechicken/core/fluid/TankAccess.java @@ -4,29 +4,24 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidHandler; -public class TankAccess -{ +public class TankAccess { public IFluidHandler tank; public ForgeDirection side; - - public TankAccess(IFluidHandler tank, ForgeDirection side) - { + + public TankAccess(IFluidHandler tank, ForgeDirection side) { this.tank = tank; this.side = side; } - - public TankAccess(IFluidHandler tank, int side) - { + + public TankAccess(IFluidHandler tank, int side) { this(tank, ForgeDirection.getOrientation(side)); } - public int fill(FluidStack resource, boolean doFill) - { + public int fill(FluidStack resource, boolean doFill) { return tank.fill(side, resource, doFill); } - - public FluidStack drain(int maxDrain, boolean doDrain) - { + + public FluidStack drain(int maxDrain, boolean doDrain) { return tank.drain(side, maxDrain, doDrain); } } diff --git a/src/main/java/codechicken/core/gui/ClickCounter.java b/src/main/java/codechicken/core/gui/ClickCounter.java index 1e2181b..7faeea6 100644 --- a/src/main/java/codechicken/core/gui/ClickCounter.java +++ b/src/main/java/codechicken/core/gui/ClickCounter.java @@ -1,20 +1,17 @@ package codechicken.core.gui; import com.google.common.base.Objects; - import java.util.Map; import java.util.TreeMap; -public class ClickCounter -{ - public class ClickCount - { +public class ClickCounter { + public class ClickCount { public T clicked; public long time; public int count; public boolean update(T clicked) { - if(!Objects.equal(this.clicked, clicked)) { + if (!Objects.equal(this.clicked, clicked)) { this.clicked = clicked; count = 0; time = Long.MIN_VALUE; @@ -28,8 +25,7 @@ public boolean update(T clicked) { public ClickCount getCount(int button) { ClickCount c = buttons.get(button); - if(c == null) - buttons.put(button, c = new ClickCount()); + if (c == null) buttons.put(button, c = new ClickCount()); return c; } @@ -40,14 +36,11 @@ public void mouseDown(T clicked, int button) { public int mouseUp(T clicked, int button) { ClickCount c = getCount(button); - if(!c.update(clicked)) - return 0; + if (!c.update(clicked)) return 0; long time = System.currentTimeMillis(); - if(time-c.time < 500) - c.count++; - else - c.count = 1; + if (time - c.time < 500) c.count++; + else c.count = 1; c.time = time; return c.count; } diff --git a/src/main/java/codechicken/core/gui/GuiCCButton.java b/src/main/java/codechicken/core/gui/GuiCCButton.java index c1571ef..4a1ea29 100644 --- a/src/main/java/codechicken/core/gui/GuiCCButton.java +++ b/src/main/java/codechicken/core/gui/GuiCCButton.java @@ -1,13 +1,11 @@ package codechicken.core.gui; import net.minecraft.client.Minecraft; - import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; -public class GuiCCButton extends GuiWidget -{ +public class GuiCCButton extends GuiWidget { public String text; public String actionCommand; private boolean isEnabled = true; @@ -34,28 +32,35 @@ public void setEnabled(boolean b) { public void mouseClicked(int x, int y, int button) { if (isEnabled && pointInside(x, y) && actionCommand != null) { sendAction(actionCommand, button); - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + Minecraft.getMinecraft() + .getSoundHandler() + .playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); } } @Override public void draw(int mousex, int mousey, float frame) { - if (!visible) - return; + if (!visible) return; drawButtonTex(mousex, mousey); - if(text != null) - drawText(mousex, mousey); + if (text != null) drawText(mousex, mousey); } public void drawButtonTex(int mousex, int mousey) { GL11.glColor4f(1, 1, 1, 1); renderEngine.bindTexture(guiTex); int state = getButtonTex(mousex, mousey); - drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2);//top left - drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2);//top right - drawTexturedModalRect(x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom left - drawTexturedModalRect(x + width / 2, y + height / 2, 200 - width / 2, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom right + drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2); // top left + drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2); // top right + drawTexturedModalRect( + x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2); // bottom left + drawTexturedModalRect( + x + width / 2, + y + height / 2, + 200 - width / 2, + 46 + state * 20 + 20 - height / 2, + width / 2, + height / 2); // bottom right } public int getButtonTex(int mousex, int mousey) { diff --git a/src/main/java/codechicken/core/gui/GuiCCTextField.java b/src/main/java/codechicken/core/gui/GuiCCTextField.java index 84463b4..944853b 100644 --- a/src/main/java/codechicken/core/gui/GuiCCTextField.java +++ b/src/main/java/codechicken/core/gui/GuiCCTextField.java @@ -2,187 +2,148 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ChatAllowedCharacters; - import org.lwjgl.input.Keyboard; -public class GuiCCTextField extends GuiWidget -{ +public class GuiCCTextField extends GuiWidget { private String text; private boolean isFocused; private boolean isEnabled; - + public int maxStringLength; public int cursorCounter; public String actionCommand; - + private String allowedCharacters; - public GuiCCTextField(int x, int y, int width, int height, String text) - { + public GuiCCTextField(int x, int y, int width, int height, String text) { super(x, y, width, height); isFocused = false; isEnabled = true; this.text = text; } - public GuiCCTextField setActionCommand(String s) - { + public GuiCCTextField setActionCommand(String s) { actionCommand = s; return this; } - public void setText(String s) - { - if(s.equals(text)) - return; + public void setText(String s) { + if (s.equals(text)) return; String oldText = text; text = s; onTextChanged(oldText); } - public void onTextChanged(String oldText) - { - } + public void onTextChanged(String oldText) {} - public final String getText() - { + public final String getText() { return text; } - - public final boolean isEnabled() - { + + public final boolean isEnabled() { return isEnabled; } - public void setEnabled(boolean b) - { + public void setEnabled(boolean b) { isEnabled = b; - if(!isEnabled && isFocused) - setFocused(false); + if (!isEnabled && isFocused) setFocused(false); } - - public final boolean isFocused() - { + + public final boolean isFocused() { return isFocused; } @Override - public void update() - { + public void update() { cursorCounter++; } @Override - public void keyTyped(char c, int keycode) - { - if(!isEnabled || !isFocused) - return; + public void keyTyped(char c, int keycode) { + if (!isEnabled || !isFocused) return; /*if(c == '\t')//tab { parentGuiScreen.selectNextField(); }*/ - if(c == '\026')//paste + if (c == '\026') // paste { String s = GuiScreen.getClipboardString(); - if(s == null || s.equals("")) - return; + if (s == null || s.equals("")) return; - for(int i = 0; i < s.length(); i++) - { - if(text.length() == maxStringLength) - return; + for (int i = 0; i < s.length(); i++) { + if (text.length() == maxStringLength) return; char tc = s.charAt(i); - if(canAddChar(tc)) - setText(text + tc); + if (canAddChar(tc)) setText(text + tc); } } - if(keycode == Keyboard.KEY_RETURN) - { + if (keycode == Keyboard.KEY_RETURN) { setFocused(false); sendAction(actionCommand, getText()); } - if(keycode == Keyboard.KEY_BACK && text.length() > 0) - setText(text.substring(0, text.length() - 1)); + if (keycode == Keyboard.KEY_BACK && text.length() > 0) setText(text.substring(0, text.length() - 1)); - if((text.length() < maxStringLength || maxStringLength == 0) && canAddChar(c)) - setText(text + c); + if ((text.length() < maxStringLength || maxStringLength == 0) && canAddChar(c)) setText(text + c); } - public boolean canAddChar(char c) - { - return allowedCharacters == null ? ChatAllowedCharacters.isAllowedCharacter(c) : allowedCharacters.indexOf(c) >= 0; + public boolean canAddChar(char c) { + return allowedCharacters == null + ? ChatAllowedCharacters.isAllowedCharacter(c) + : allowedCharacters.indexOf(c) >= 0; } @Override - public void mouseClicked(int x, int y, int button) - { - if(isEnabled && pointInside(x, y)) - { + public void mouseClicked(int x, int y, int button) { + if (isEnabled && pointInside(x, y)) { setFocused(true); - if(button == 1) - setText(""); - } - else - setFocused(false); + if (button == 1) setText(""); + } else setFocused(false); } - public void setFocused(boolean focus) - { - if(focus == isFocused) - return; + public void setFocused(boolean focus) { + if (focus == isFocused) return; isFocused = focus; onFocusChanged(); } - public void onFocusChanged() - { - if(isFocused) - cursorCounter = 0; + public void onFocusChanged() { + if (isFocused) cursorCounter = 0; } - + @Override - public void draw(int i, int j, float f) - { + public void draw(int i, int j, float f) { drawBackground(); drawText(); } - public void drawBackground() - { + public void drawBackground() { drawRect(x - 1, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0); drawRect(x, y, x + width, y + height, 0xff000000); } - - public String getDrawText() - { + + public String getDrawText() { String s = getText(); - if(isEnabled && isFocused && (cursorCounter / 6) % 2 == 0) - s+="_"; + if (isEnabled && isFocused && (cursorCounter / 6) % 2 == 0) s += "_"; return s; } - - public void drawText() - { - drawString(fontRenderer, getDrawText(), x + 4, y + height/2 - 4, getTextColour()); + + public void drawText() { + drawString(fontRenderer, getDrawText(), x + 4, y + height / 2 - 4, getTextColour()); } - public int getTextColour() - { + public int getTextColour() { return isEnabled ? 0xe0e0e0 : 0x707070; } - public GuiCCTextField setMaxStringLength(int i) - { + public GuiCCTextField setMaxStringLength(int i) { maxStringLength = i; return this; } - public GuiCCTextField setAllowedCharacters(String s) - { + public GuiCCTextField setAllowedCharacters(String s) { allowedCharacters = s; return this; } diff --git a/src/main/java/codechicken/core/gui/GuiScreenWidget.java b/src/main/java/codechicken/core/gui/GuiScreenWidget.java index 1138a9b..5136ffa 100644 --- a/src/main/java/codechicken/core/gui/GuiScreenWidget.java +++ b/src/main/java/codechicken/core/gui/GuiScreenWidget.java @@ -1,43 +1,35 @@ package codechicken.core.gui; +import codechicken.lib.gui.GuiDraw; import java.awt.Point; import java.util.ArrayList; - -import codechicken.lib.gui.GuiDraw; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; -public class GuiScreenWidget extends GuiScreen implements IGuiActionListener -{ +public class GuiScreenWidget extends GuiScreen implements IGuiActionListener { public ArrayList widgets = new ArrayList(); public int xSize, ySize, guiTop, guiLeft; - public GuiScreenWidget() - { + public GuiScreenWidget() { this(176, 166); } - public GuiScreenWidget(int xSize, int ySize) - { + public GuiScreenWidget(int xSize, int ySize) { super(); this.xSize = xSize; this.ySize = ySize; } @Override - public void initGui() - { + public void initGui() { guiTop = (height - ySize) / 2; guiLeft = (width - xSize) / 2; - if(!widgets.isEmpty()) - resize(); + if (!widgets.isEmpty()) resize(); } - public void reset() - { + public void reset() { widgets.clear(); initGui(); addWidgets(); @@ -45,106 +37,78 @@ public void reset() } @Override - public void setWorldAndResolution(Minecraft mc, int i, int j) - { + public void setWorldAndResolution(Minecraft mc, int i, int j) { boolean init = this.mc == null; super.setWorldAndResolution(mc, i, j); - if(init) { + if (init) { addWidgets(); resize(); } } - public void add(GuiWidget widget) - { + public void add(GuiWidget widget) { widgets.add(widget); widget.onAdded(this); } @Override - public void drawScreen(int mousex, int mousey, float f) - { + public void drawScreen(int mousex, int mousey, float f) { GL11.glTranslated(guiLeft, guiTop, 0); drawBackground(); - for(GuiWidget widget : widgets) - widget.draw(mousex-guiLeft, mousey-guiTop, f); + for (GuiWidget widget : widgets) widget.draw(mousex - guiLeft, mousey - guiTop, f); drawForeground(); GL11.glTranslated(-guiLeft, -guiTop, 0); } - public void drawBackground() - { - } + public void drawBackground() {} - public void drawForeground() - { - } + public void drawForeground() {} @Override - protected void mouseClicked(int x, int y, int button) - { + protected void mouseClicked(int x, int y, int button) { super.mouseClicked(x, y, button); - for(GuiWidget widget : widgets) - widget.mouseClicked(x-guiLeft, y-guiTop, button); + for (GuiWidget widget : widgets) widget.mouseClicked(x - guiLeft, y - guiTop, button); } @Override - protected void mouseMovedOrUp(int x, int y, int button) - { + protected void mouseMovedOrUp(int x, int y, int button) { super.mouseMovedOrUp(x, y, button); - for(GuiWidget widget : widgets) - widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button); + for (GuiWidget widget : widgets) widget.mouseMovedOrUp(x - guiLeft, y - guiTop, button); } @Override - protected void mouseClickMove(int x, int y, int button, long time) - { + protected void mouseClickMove(int x, int y, int button, long time) { super.mouseClickMove(x, y, button, time); - for(GuiWidget widget : widgets) - widget.mouseDragged(x-guiLeft, y-guiTop, button, time); + for (GuiWidget widget : widgets) widget.mouseDragged(x - guiLeft, y - guiTop, button, time); } @Override - public void updateScreen() - { + public void updateScreen() { super.updateScreen(); - if(mc.currentScreen == this) - for(GuiWidget widget : widgets) - widget.update(); + if (mc.currentScreen == this) for (GuiWidget widget : widgets) widget.update(); } @Override - public void keyTyped(char c, int keycode) - { + public void keyTyped(char c, int keycode) { super.keyTyped(c, keycode); - for(GuiWidget widget : widgets) - widget.keyTyped(c, keycode); + for (GuiWidget widget : widgets) widget.keyTyped(c, keycode); } @Override - public void handleMouseInput() - { + public void handleMouseInput() { super.handleMouseInput(); int i = Mouse.getEventDWheel(); - if(i != 0) - { + if (i != 0) { Point p = GuiDraw.getMousePosition(); int scroll = i > 0 ? 1 : -1; - for(GuiWidget widget : widgets) - widget.mouseScrolled(p.x, p.y, scroll); + for (GuiWidget widget : widgets) widget.mouseScrolled(p.x, p.y, scroll); } } @Override - public void actionPerformed(String ident, Object... params) - { - } + public void actionPerformed(String ident, Object... params) {} - public void resize() - { - } + public void resize() {} - public void addWidgets() - { - } + public void addWidgets() {} } diff --git a/src/main/java/codechicken/core/gui/GuiScrollPane.java b/src/main/java/codechicken/core/gui/GuiScrollPane.java index e51050f..aa91bc9 100644 --- a/src/main/java/codechicken/core/gui/GuiScrollPane.java +++ b/src/main/java/codechicken/core/gui/GuiScrollPane.java @@ -2,11 +2,9 @@ import codechicken.lib.math.MathHelper; import codechicken.lib.vec.Rectangle4i; - import java.awt.*; -public abstract class GuiScrollPane extends GuiWidget -{ +public abstract class GuiScrollPane extends GuiWidget { protected int scrollclicky = -1; protected float scrollpercent; protected int scrollmousey; @@ -29,7 +27,8 @@ public void setMargins(int left, int top, int right, int bottom) { } public Rectangle windowBounds() { - return new Rectangle(x+marginleft, y+margintop, width-marginleft-marginright, height-margintop-marginbottom); + return new Rectangle( + x + marginleft, y + margintop, width - marginleft - marginright, height - margintop - marginbottom); } public abstract int contentHeight(); @@ -42,8 +41,10 @@ public Dimension scrollbarDim() { public Rectangle scrollbarBounds() { Dimension dim = scrollbarDim(); return new Rectangle( - x + width - dim.width, y + (int) ((height - dim.height) * percentscrolled + 0.4999), - dim.width, dim.height); + x + width - dim.width, + y + (int) ((height - dim.height) * percentscrolled + 0.4999), + dim.width, + dim.height); } public void scrollUp() { @@ -55,7 +56,7 @@ public void scrollDown() { } public void scroll(int i) { - percentscrolled += i * height / (float)(2*contentHeight()); + percentscrolled += i * height / (float) (2 * contentHeight()); calculatePercentScrolled(); } @@ -102,15 +103,18 @@ public void mouseClicked(int mx, int my, int button) { Rectangle w = windowBounds(); int barempty = height - sbar.height; - if (button == 0 && - sbar.height < height && //the scroll bar can move (not full length) - mx >= sbar.x && mx <= sbar.x + sbar.width && - my >= y && my <= y + height)//in the scroll pane + if (button == 0 + && sbar.height < height + && // the scroll bar can move (not full length) + mx >= sbar.x + && mx <= sbar.x + sbar.width + && my >= y + && my <= y + height) // in the scroll pane { if (my < sbar.y) { percentscrolled = (my - y) / (float) barempty; calculatePercentScrolled(); - } else if (my > sbar.y+sbar.height) { + } else if (my > sbar.y + sbar.height) { percentscrolled = (my - y - sbar.height + 1) / (float) barempty; calculatePercentScrolled(); } else { @@ -118,8 +122,7 @@ public void mouseClicked(int mx, int my, int button) { scrollpercent = percentscrolled; scrollmousey = my; } - } else if (w.contains(mx, my)) - slotDown(mx - w.x, my - w.y + scrolledPixels(), button); + } else if (w.contains(mx, my)) slotDown(mx - w.x, my - w.y + scrolledPixels(), button); } /** @@ -137,10 +140,9 @@ public void slotUp(int mx, int my, int button) {} @Override public void mouseMovedOrUp(int mx, int my, int button) { Rectangle w = windowBounds(); - if (isScrolling() && button == 0)//we were scrolling and we released mouse - scrollclicky = -1; - else if (w.contains(mx, my)) - slotUp(mx - w.x, my - w.y + scrolledPixels(), button); + if (isScrolling() && button == 0) // we were scrolling and we released mouse + scrollclicky = -1; + else if (w.contains(mx, my)) slotUp(mx - w.x, my - w.y + scrolledPixels(), button); } @Override @@ -151,12 +153,9 @@ public void mouseDragged(int mousex, int mousey, int button, long time) { int barupallowed = (int) ((height - sbarh) * scrollpercent + 0.5); int bardownallowed = (height - sbarh) - barupallowed; - if (-scrolldiff > barupallowed) - scrollmousey = scrollclicky - barupallowed; - else if (scrolldiff > bardownallowed) - scrollmousey = scrollclicky + bardownallowed; - else - scrollmousey = mousey; + if (-scrolldiff > barupallowed) scrollmousey = scrollclicky - barupallowed; + else if (scrolldiff > bardownallowed) scrollmousey = scrollclicky + bardownallowed; + else scrollmousey = mousey; calculatePercentScrolled(); } @@ -180,7 +179,7 @@ public boolean contains(int mx, int my) { public void draw(int mx, int my, float frame) { Rectangle w = windowBounds(); drawBackground(frame); - drawContent(mx-w.x, my+scrolledPixels()-w.y, frame); + drawContent(mx - w.x, my + scrolledPixels() - w.y, frame); drawOverlay(frame); drawScrollbar(frame); } @@ -192,24 +191,22 @@ public void drawBackground(float frame) { public abstract void drawContent(int mx, int my, float frame); public void drawOverlay(float frame) { - //outlines - drawRect(x, y - 1, x + width, y, 0xffa0a0a0);//top - drawRect(x, y + height, x + width, y + height + 1, 0xffa0a0a0);//bottom - drawRect(x - 1, y - 1, x, y + height + 1, 0xffa0a0a0);//left - drawRect(x + width, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);//right + // outlines + drawRect(x, y - 1, x + width, y, 0xffa0a0a0); // top + drawRect(x, y + height, x + width, y + height + 1, 0xffa0a0a0); // bottom + drawRect(x - 1, y - 1, x, y + height + 1, 0xffa0a0a0); // left + drawRect(x + width, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0); // right } public void drawScrollbar(float frame) { Rectangle r = scrollbarBounds(); - drawRect(r.x, r.y, r.x + r.width, r.y + r.height, 0xFF8B8B8B);//corners - drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, 0xFFF0F0F0);//topleft up - drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, 0xFF555555);//bottom right down - drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, 0xFFC6C6C6);//scrollbar + drawRect(r.x, r.y, r.x + r.width, r.y + r.height, 0xFF8B8B8B); // corners + drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, 0xFFF0F0F0); // topleft up + drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, 0xFF555555); // bottom right down + drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, 0xFFC6C6C6); // scrollbar int algn = scrollbarGuideAlignment(); - if (algn != 0) - drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, 0xFF808080);//lineguide + if (algn != 0) drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, 0xFF808080); // lineguide } - } diff --git a/src/main/java/codechicken/core/gui/GuiScrollSlot.java b/src/main/java/codechicken/core/gui/GuiScrollSlot.java index e1da5dd..442a4b1 100644 --- a/src/main/java/codechicken/core/gui/GuiScrollSlot.java +++ b/src/main/java/codechicken/core/gui/GuiScrollSlot.java @@ -1,11 +1,9 @@ package codechicken.core.gui; -import org.lwjgl.input.Keyboard; - import java.awt.*; +import org.lwjgl.input.Keyboard; -public abstract class GuiScrollSlot extends GuiScrollPane -{ +public abstract class GuiScrollSlot extends GuiScrollPane { protected String actionCommand; public boolean focused; protected ClickCounter click = new ClickCounter(); @@ -40,13 +38,11 @@ public void selectPrev() {} protected abstract void drawSlot(int slot, int x, int y, int mx, int my, float frame); - protected void unfocus() { - } + protected void unfocus() {} public void setFocused(boolean focus) { focused = focus; - if (!focused) - unfocus(); + if (!focused) unfocus(); } @Override @@ -56,37 +52,34 @@ public int contentHeight() { public int getSlotY(int slot) { int h = 0; - for(int i = 0; i < slot; i++) - h+=getSlotHeight(i); + for (int i = 0; i < slot; i++) h += getSlotHeight(i); return h; } public int getSlot(int my) { - if (my < 0) - return -1; + if (my < 0) return -1; int y = 0; - for(int i = 0; i < getNumSlots(); i++) { + for (int i = 0; i < getNumSlots(); i++) { int h = getSlotHeight(i); - if(my >= y && my < y+h) - return i; - y+=h; + if (my >= y && my < y + h) return i; + y += h; } return -1; } public int getClickedSlot(int my) { - return getSlot(my-windowBounds().y+scrolledPixels()); + return getSlot(my - windowBounds().y + scrolledPixels()); } @Override public int scrolledPixels() { int scrolled = super.scrolledPixels(); - if(!smoothScroll) { + if (!smoothScroll) { int slot = getSlot(scrolled); int sloty = getSlotY(slot); int sloth = getSlotHeight(slot); - scrolled = sloty+(int)((scrolled-sloty)/(double)sloth+0.5)*sloth; + scrolled = sloty + (int) ((scrolled - sloty) / (double) sloth + 0.5) * sloth; } return scrolled; } @@ -106,8 +99,7 @@ public int scrollbarGuideAlignment() { @Override public Rectangle scrollbarBounds() { Rectangle r = super.scrollbarBounds(); - if(scrollbarAlignment() == -1) - r.x = x; + if (scrollbarAlignment() == -1) r.x = x; return r; } @@ -125,21 +117,16 @@ public void slotDown(int mx, int my, int button) { public void slotUp(int mx, int my, int button) { int slot = getSlot(my); int c = click.mouseUp(slot >= 0 ? slot : null, button); - if(c > 0 && slot >= 0) - slotClicked(slot, button, mx, my-getSlotY(slot), c); + if (c > 0 && slot >= 0) slotClicked(slot, button, mx, my - getSlotY(slot), c); } @Override public void keyTyped(char c, int keycode) { - if (!focused) - return; + if (!focused) return; - if (keycode == Keyboard.KEY_UP) - selectPrev(); - if (keycode == Keyboard.KEY_DOWN) - selectNext(); - if (keycode == Keyboard.KEY_RETURN && actionCommand != null) - sendAction(actionCommand); + if (keycode == Keyboard.KEY_UP) selectPrev(); + if (keycode == Keyboard.KEY_DOWN) selectNext(); + if (keycode == Keyboard.KEY_RETURN && actionCommand != null) sendAction(actionCommand); } @Override @@ -149,9 +136,9 @@ public void drawContent(int mx, int my, float frame) { int y = 0; for (int slot = 0; slot < getNumSlots(); slot++) { int h = getSlotHeight(slot); - if (y+h > scrolled && y < scrolled+w.height) - drawSlot(slot, w.x, w.y+y-scrolledPixels(), mx, my-y, frame); - y+=h; + if (y + h > scrolled && y < scrolled + w.height) + drawSlot(slot, w.x, w.y + y - scrolledPixels(), mx, my - y, frame); + y += h; } } } diff --git a/src/main/java/codechicken/core/gui/GuiWidget.java b/src/main/java/codechicken/core/gui/GuiWidget.java index b73d1ee..a4a0cbe 100644 --- a/src/main/java/codechicken/core/gui/GuiWidget.java +++ b/src/main/java/codechicken/core/gui/GuiWidget.java @@ -7,78 +7,57 @@ import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; -public class GuiWidget extends Gui -{ +public class GuiWidget extends Gui { protected static final ResourceLocation guiTex = new ResourceLocation("textures/gui/widgets.png"); - + public GuiScreen parentScreen; public TextureManager renderEngine; public FontRenderer fontRenderer; - + public int x; public int y; public int width; public int height; - - public GuiWidget(int x, int y, int width, int height) - { + + public GuiWidget(int x, int y, int width, int height) { setSize(x, y, width, height); } - - public void setSize(int x, int y, int width, int height) - { + + public void setSize(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } - public boolean pointInside(int px, int py) - { + public boolean pointInside(int px, int py) { return px >= x && px < x + width && py >= y && py < y + height; } - - public void sendAction(String actionCommand, Object... params) - { + + public void sendAction(String actionCommand, Object... params) { sendAction(parentScreen, actionCommand, params); } - public static void sendAction(GuiScreen screen, String actionCommand, Object... params) - { - if(actionCommand != null && screen instanceof IGuiActionListener) + public static void sendAction(GuiScreen screen, String actionCommand, Object... params) { + if (actionCommand != null && screen instanceof IGuiActionListener) ((IGuiActionListener) screen).actionPerformed(actionCommand, params); } - public void mouseClicked(int x, int y, int button) - { - } + public void mouseClicked(int x, int y, int button) {} - public void mouseMovedOrUp(int x, int y, int button) - { - } - - public void mouseDragged(int x, int y, int button, long time) - { - } - - public void update() - { - } + public void mouseMovedOrUp(int x, int y, int button) {} - public void draw(int mousex, int mousey, float frame) - { - } + public void mouseDragged(int x, int y, int button, long time) {} - public void keyTyped(char c, int keycode) - { - } + public void update() {} - public void mouseScrolled(int x, int y, int scroll) - { - } - - public void onAdded(GuiScreen s) - { + public void draw(int mousex, int mousey, float frame) {} + + public void keyTyped(char c, int keycode) {} + + public void mouseScrolled(int x, int y, int scroll) {} + + public void onAdded(GuiScreen s) { Minecraft mc = Minecraft.getMinecraft(); parentScreen = s; renderEngine = mc.renderEngine; diff --git a/src/main/java/codechicken/core/gui/IGuiActionListener.java b/src/main/java/codechicken/core/gui/IGuiActionListener.java index 8540251..c32c02a 100644 --- a/src/main/java/codechicken/core/gui/IGuiActionListener.java +++ b/src/main/java/codechicken/core/gui/IGuiActionListener.java @@ -1,6 +1,5 @@ package codechicken.core.gui; -public interface IGuiActionListener -{ +public interface IGuiActionListener { public void actionPerformed(String actionCommand, Object... params); -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/core/internal/CCCEventHandler.java b/src/main/java/codechicken/core/internal/CCCEventHandler.java index 3775fe2..59d5263 100644 --- a/src/main/java/codechicken/core/internal/CCCEventHandler.java +++ b/src/main/java/codechicken/core/internal/CCCEventHandler.java @@ -1,7 +1,6 @@ package codechicken.core.internal; import codechicken.core.CCUpdateChecker; - import codechicken.core.GuiModListScroll; import cpw.mods.fml.client.GuiModList; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -11,14 +10,13 @@ import cpw.mods.fml.relauncher.SideOnly; import net.minecraftforge.client.event.GuiScreenEvent; -public class CCCEventHandler -{ +public class CCCEventHandler { public static int renderTime; public static float renderFrame; @SubscribeEvent public void clientTick(TickEvent.ClientTickEvent event) { - if(event.phase == Phase.END) { + if (event.phase == Phase.END) { CCUpdateChecker.tick(); renderTime++; } @@ -26,14 +24,12 @@ public void clientTick(TickEvent.ClientTickEvent event) { @SubscribeEvent public void renderTick(TickEvent.RenderTickEvent event) { - if(event.phase == Phase.START) - renderFrame = event.renderTickTime; + if (event.phase == Phase.START) renderFrame = event.renderTickTime; } @SubscribeEvent @SideOnly(Side.CLIENT) public void posGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { - if(event.gui instanceof GuiModList) - GuiModListScroll.draw((GuiModList)event.gui, event.mouseX, event.mouseY); + if (event.gui instanceof GuiModList) GuiModListScroll.draw((GuiModList) event.gui, event.mouseX, event.mouseY); } } diff --git a/src/main/java/codechicken/core/inventory/GuiContainerWidget.java b/src/main/java/codechicken/core/inventory/GuiContainerWidget.java index 919ca8a..c14d900 100644 --- a/src/main/java/codechicken/core/inventory/GuiContainerWidget.java +++ b/src/main/java/codechicken/core/inventory/GuiContainerWidget.java @@ -1,127 +1,96 @@ package codechicken.core.inventory; -import java.awt.Point; -import java.util.ArrayList; - -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - -import codechicken.lib.gui.GuiDraw; import codechicken.core.gui.GuiWidget; import codechicken.core.gui.IGuiActionListener; - +import codechicken.lib.gui.GuiDraw; +import java.awt.Point; +import java.util.ArrayList; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.inventory.Container; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; -public class GuiContainerWidget extends GuiContainer implements IGuiActionListener -{ +public class GuiContainerWidget extends GuiContainer implements IGuiActionListener { public ArrayList widgets = new ArrayList(); - - public GuiContainerWidget(Container inventorySlots) - { + + public GuiContainerWidget(Container inventorySlots) { this(inventorySlots, 176, 166); } - - public GuiContainerWidget(Container inventorySlots, int xSize, int ySize) - { + + public GuiContainerWidget(Container inventorySlots, int xSize, int ySize) { super(inventorySlots); this.xSize = xSize; this.ySize = ySize; } - + @Override - public void setWorldAndResolution(Minecraft mc, int i, int j) - { + public void setWorldAndResolution(Minecraft mc, int i, int j) { super.setWorldAndResolution(mc, i, j); - if(widgets.isEmpty()) - addWidgets(); + if (widgets.isEmpty()) addWidgets(); } - - public void add(GuiWidget widget) - { + + public void add(GuiWidget widget) { widgets.add(widget); widget.onAdded(this); } @Override - protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey) - { + protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey) { GL11.glTranslated(guiLeft, guiTop, 0); drawBackground(); - for(GuiWidget widget : widgets) - widget.draw(mousex-guiLeft, mousey-guiTop, f); - + for (GuiWidget widget : widgets) widget.draw(mousex - guiLeft, mousey - guiTop, f); + GL11.glTranslated(-guiLeft, -guiTop, 0); } - - public void drawBackground() - { - } + + public void drawBackground() {} @Override - protected void mouseClicked(int x, int y, int button) - { + protected void mouseClicked(int x, int y, int button) { super.mouseClicked(x, y, button); - for(GuiWidget widget : widgets) - widget.mouseClicked(x-guiLeft, y-guiTop, button); + for (GuiWidget widget : widgets) widget.mouseClicked(x - guiLeft, y - guiTop, button); } - + @Override - protected void mouseMovedOrUp(int x, int y, int button) - { + protected void mouseMovedOrUp(int x, int y, int button) { super.mouseMovedOrUp(x, y, button); - for(GuiWidget widget : widgets) - widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button); + for (GuiWidget widget : widgets) widget.mouseMovedOrUp(x - guiLeft, y - guiTop, button); } - + @Override - protected void mouseClickMove(int x, int y, int button, long time) - { + protected void mouseClickMove(int x, int y, int button, long time) { super.mouseClickMove(x, y, button, time); - for(GuiWidget widget : widgets) - widget.mouseDragged(x-guiLeft, y-guiTop, button, time); + for (GuiWidget widget : widgets) widget.mouseDragged(x - guiLeft, y - guiTop, button, time); } - + @Override - public void updateScreen() - { + public void updateScreen() { super.updateScreen(); - if(mc.currentScreen == this) - for(GuiWidget widget : widgets) - widget.update(); + if (mc.currentScreen == this) for (GuiWidget widget : widgets) widget.update(); } - + @Override - public void keyTyped(char c, int keycode) - { + public void keyTyped(char c, int keycode) { super.keyTyped(c, keycode); - for(GuiWidget widget : widgets) - widget.keyTyped(c, keycode); + for (GuiWidget widget : widgets) widget.keyTyped(c, keycode); } @Override - public void handleMouseInput() - { + public void handleMouseInput() { super.handleMouseInput(); int i = Mouse.getEventDWheel(); - if(i != 0) - { + if (i != 0) { Point p = GuiDraw.getMousePosition(); int scroll = i > 0 ? 1 : -1; - for(GuiWidget widget : widgets) - widget.mouseScrolled(p.x, p.y, scroll); + for (GuiWidget widget : widgets) widget.mouseScrolled(p.x, p.y, scroll); } } @Override - public void actionPerformed(String ident, Object... params) - { - } + public void actionPerformed(String ident, Object... params) {} - public void addWidgets() - { - } + public void addWidgets() {} @Override public void onGuiClosed() { diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 7f01222..a1e3b69 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -1,5 +1,16 @@ package codechicken.core.launch; +import codechicken.core.asm.*; +import codechicken.lib.config.ConfigTag; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.versioning.DefaultArtifactVersion; +import cpw.mods.fml.common.versioning.VersionParser; +import cpw.mods.fml.relauncher.CoreModManager; +import cpw.mods.fml.relauncher.FMLInjectionData; +import cpw.mods.fml.relauncher.IFMLCallHook; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; import java.awt.*; import java.io.File; import java.lang.reflect.Constructor; @@ -11,32 +22,18 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; - import javax.swing.JEditorPane; import javax.swing.JOptionPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; - -import codechicken.core.asm.*; -import codechicken.lib.config.ConfigTag; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.CoreModManager; - -import cpw.mods.fml.common.versioning.DefaultArtifactVersion; -import cpw.mods.fml.common.versioning.VersionParser; -import cpw.mods.fml.relauncher.FMLInjectionData; -import cpw.mods.fml.relauncher.IFMLCallHook; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @TransformerExclusions(value = {"codechicken.core.asm", "codechicken.obfuscator"}) -@MCVersion( "1.7.10" ) -public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook -{ +@MCVersion("1.7.10") +public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; + @Deprecated public static final String version = "1.1.3-unused"; @@ -45,8 +42,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook public static Logger logger = LogManager.getLogger("CodeChickenCore"); public CodeChickenCorePlugin() { - if (minecraftDir != null) - return;//get called twice, once for IFMLCallHook + if (minecraftDir != null) return; // get called twice, once for IFMLCallHook minecraftDir = (File) FMLInjectionData.data()[6]; currentMcVersion = (String) FMLInjectionData.data()[4]; @@ -58,11 +54,20 @@ public CodeChickenCorePlugin() { private void injectDeobfPlugin() { try { Class wrapperClass = Class.forName("cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper"); - Constructor wrapperConstructor = wrapperClass.getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class); + Constructor wrapperConstructor = wrapperClass.getConstructor( + String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class); Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins"); wrapperConstructor.setAccessible(true); f_loadPlugins.setAccessible(true); - ((List)f_loadPlugins.get(null)).add(2, wrapperConstructor.newInstance("CCCDeobfPlugin", new MCPDeobfuscationTransformer.LoadPlugin(), null, 0, new String[0])); + ((List) f_loadPlugins.get(null)) + .add( + 2, + wrapperConstructor.newInstance( + "CCCDeobfPlugin", + new MCPDeobfuscationTransformer.LoadPlugin(), + null, + 0, + new String[0])); } catch (Exception e) { logger.error("Failed to inject MCPDeobfuscation Transformer", e); } @@ -74,22 +79,22 @@ public static void versionCheck(String reqVersion, String mod) { String err = "This version of " + mod + " does not support minecraft version " + mcVersion; logger.error(err); - JEditorPane ep = new JEditorPane("text/html", - "" + - err + - "
Remove it from your coremods folder and check here for updates" + - ""); + JEditorPane ep = new JEditorPane( + "text/html", + "" + err + + "
Remove it from your coremods folder and check here for updates" + + ""); ep.setEditable(false); ep.setOpaque(false); - ep.addHyperlinkListener(new HyperlinkListener() - { + ep.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent event) { try { if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception ignored) {} + } catch (Exception ignored) { + } } }); @@ -101,11 +106,15 @@ public void hyperlinkUpdate(HyperlinkEvent event) { public static long parseSize(String text) { double d = Double.parseDouble(text.replaceAll("[GMK]B?$", "")); long l = Math.round(d * 1024 * 1024 * 1024L); - switch (text.replaceAll("\\d?","").toUpperCase().charAt(0)) { - default: l /= 1024; - case 'K': l /= 1024; - case 'M': l /= 1024; - case 'G': return l; + switch (text.replaceAll("\\d?", "").toUpperCase().charAt(0)) { + default: + l /= 1024; + case 'K': + l /= 1024; + case 'M': + l /= 1024; + case 'G': + return l; } } @@ -125,28 +134,45 @@ public static String humanReadableByteCountBin(long bytes) { } public static void systemCheck(ConfigTag checkRAM) { - long minBytes = parseSize(checkRAM.getTag("minRAM").setComment("Amount of RAM minimum this modpack needs to load").getValue("3GB")); + long minBytes = parseSize(checkRAM.getTag("minRAM") + .setComment("Amount of RAM minimum this modpack needs to load") + .getValue("3GB")); if (Runtime.getRuntime().maxMemory() < minBytes) { - String err = "You should have at least " + humanReadableByteCountBin(minBytes) + " of RAM but you have only allocated " + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; + String err = "You should have at least " + humanReadableByteCountBin(minBytes) + + " of RAM but you have only allocated " + + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; logger.error(err); - JEditorPane ep = new JEditorPane("text/html", - "" + err + "
" + checkRAM.getTag("modPack").setComment("Name of the modpack").getValue("Unidentified ModPack") + - " seriously won't run without enough RAM. " + checkRAM.getTag("wiki").setComment("Webpage describing RAM settings").getValue("See DownloadMoreRam.com for details.") + - "
Recommended values are between " + checkRAM.getTag("recRAM").setComment("Lower bound of recommended RAM").getValue("4GB") + " and " + - checkRAM.getTag("recRAMUpper").setComment("Upper bound of recommended RAM").getValue("6GB") + ". Check your launcher's JVM arguments." + - ""); + JEditorPane ep = new JEditorPane( + "text/html", + "" + err + "
" + + checkRAM.getTag("modPack") + .setComment("Name of the modpack") + .getValue("Unidentified ModPack") + + " seriously won't run without enough RAM. " + + checkRAM.getTag("wiki") + .setComment("Webpage describing RAM settings") + .getValue( + "See DownloadMoreRam.com for details.") + + "
Recommended values are between " + + checkRAM.getTag("recRAM") + .setComment("Lower bound of recommended RAM") + .getValue("4GB") + " and " + + checkRAM.getTag("recRAMUpper") + .setComment("Upper bound of recommended RAM") + .getValue("6GB") + + ". Check your launcher's JVM arguments." + ""); ep.setEditable(false); ep.setOpaque(false); - ep.addHyperlinkListener(new HyperlinkListener() - { + ep.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent event) { try { if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception ignored) {} + } catch (Exception ignored) { + } } }); @@ -159,12 +185,12 @@ public void hyperlinkUpdate(HyperlinkEvent event) { @Override public String[] getASMTransformerClass() { versionCheck(mcVersion, "CodeChickenCore"); - return new String[]{ - "codechicken.lib.asm.ClassHeirachyManager", - "codechicken.core.asm.InterfaceDependancyTransformer", - "codechicken.core.asm.TweakTransformer", - "codechicken.core.asm.DelegatedTransformer", - "codechicken.core.asm.DefaultImplementationTransformer"}; + return new String[] { + "codechicken.lib.asm.ClassHeirachyManager", + "codechicken.core.asm.TweakTransformer", + "codechicken.core.asm.DelegatedTransformer", + "codechicken.core.asm.DefaultImplementationTransformer" + }; } @Override @@ -183,17 +209,19 @@ public String getSetupClass() { } @Override - public void injectData(Map data) { - } + public void injectData(Map data) {} @Override public Void call() { CodeChickenCoreModContainer.loadConfig(); ConfigTag checkRAM; - checkRAM = CodeChickenCoreModContainer.config.getTag("checks") - .setComment("Configuration options for checking various requirements for a modpack.").useBraces(); - if(checkRAM.getTag("checkRAM").setComment("If set to true, check RAM available for Minecraft before continuing to load").getBooleanValue(false)) - systemCheck(checkRAM); + checkRAM = CodeChickenCoreModContainer.config + .getTag("checks") + .setComment("Configuration options for checking various requirements for a modpack.") + .useBraces(); + if (checkRAM.getTag("checkRAM") + .setComment("If set to true, check RAM available for Minecraft before continuing to load") + .getBooleanValue(false)) systemCheck(checkRAM); TweakTransformer.load(); scanCodeChickenMods(); @@ -202,31 +230,24 @@ public Void call() { private void scanCodeChickenMods() { File modsDir = new File(minecraftDir, "mods"); - for (File file : modsDir.listFiles()) - scanMod(file); + for (File file : modsDir.listFiles()) scanMod(file); File versionModsDir = new File(minecraftDir, "mods/" + currentMcVersion); - if (versionModsDir.exists()) - for (File file : versionModsDir.listFiles()) - scanMod(file); + if (versionModsDir.exists()) for (File file : versionModsDir.listFiles()) scanMod(file); } private void scanMod(File file) { - if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) - return; + if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return; try { JarFile jar = new JarFile(file); try { Manifest manifest = jar.getManifest(); - if (manifest == null) - return; + if (manifest == null) return; Attributes attr = manifest.getMainAttributes(); - if (attr == null) - return; + if (attr == null) return; String transformer = attr.getValue("CCTransformer"); - if (transformer != null) - DelegatedTransformer.addTransformer(transformer, jar, file); + if (transformer != null) DelegatedTransformer.addTransformer(transformer, jar, file); } finally { jar.close(); } diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index c2c0376..630e0c9 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -9,13 +9,6 @@ import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; -import net.minecraft.launchwrapper.LaunchClassLoader; -import sun.misc.URLClassPath; -import sun.net.util.URLUtil; - -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; import java.awt.*; import java.awt.Dialog.ModalityType; import java.awt.event.WindowAdapter; @@ -29,19 +22,25 @@ import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.ByteBuffer; -import java.util.List; import java.util.*; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import net.minecraft.launchwrapper.LaunchClassLoader; +import sun.misc.URLClassPath; +import sun.net.util.URLUtil; /** * For autodownloading stuff. * This is really unoriginal, mostly ripped off FML, credits to cpw. */ -@MCVersion( "1.7.10" ) +@MCVersion("1.7.10") public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); private static final String owner = "CB's DepLoader"; @@ -74,10 +73,12 @@ public static class Downloader extends JOptionPane implements IDownloadDisplay { private Box makeProgressPanel() { Box box = Box.createVerticalBox(); box.add(Box.createRigidArea(new Dimension(0, 10))); - JLabel welcomeLabel = new JLabel("" + owner + " is setting up your minecraft environment"); + JLabel welcomeLabel = new JLabel("" + owner + + " is setting up your minecraft environment"); box.add(welcomeLabel); welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); - welcomeLabel = new JLabel("Please wait, " + owner + " has some tasks to do before you can play"); + welcomeLabel = + new JLabel("Please wait, " + owner + " has some tasks to do before you can play"); welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); box.add(welcomeLabel); box.add(Box.createRigidArea(new Dimension(0, 10))); @@ -93,12 +94,11 @@ private Box makeProgressPanel() { @Override public JDialog makeDialog() { - if (container != null) - return container; + if (container != null) return container; setMessageType(JOptionPane.INFORMATION_MESSAGE); setMessage(makeProgressPanel()); - setOptions(new Object[]{"Stop"}); + setOptions(new Object[] {"Stop"}); addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { @@ -119,39 +119,40 @@ public void propertyChange(PropertyChangeEvent evt) { container.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - requestClose("Closing this window will stop minecraft from launching\nAre you sure you wish to do this?"); + requestClose( + "Closing this window will stop minecraft from launching\nAre you sure you wish to do this?"); } }); return container; } protected void requestClose(String message) { - int shouldClose = JOptionPane.showConfirmDialog(container, message, "Are you sure you want to stop?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); - if (shouldClose == JOptionPane.YES_OPTION) - container.dispose(); + int shouldClose = JOptionPane.showConfirmDialog( + container, + message, + "Are you sure you want to stop?", + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE); + if (shouldClose == JOptionPane.YES_OPTION) container.dispose(); stopIt = true; - if (pokeThread != null) - pokeThread.interrupt(); + if (pokeThread != null) pokeThread.interrupt(); } @Override public void updateProgressString(String progressUpdate, Object... data) { - //FMLLog.finest(progressUpdate, data); - if (currentActivity != null) - currentActivity.setText(String.format(progressUpdate, data)); + // FMLLog.finest(progressUpdate, data); + if (currentActivity != null) currentActivity.setText(String.format(progressUpdate, data)); } @Override public void resetProgress(int sizeGuess) { - if (progress != null) - progress.getModel().setRangeProperties(0, 0, 0, sizeGuess, false); + if (progress != null) progress.getModel().setRangeProperties(0, 0, 0, sizeGuess, false); } @Override public void updateProgress(int fullLength) { - if (progress != null) - progress.getModel().setValue(fullLength); + if (progress != null) progress.getModel().setValue(fullLength); } @Override @@ -166,12 +167,13 @@ public boolean shouldStopIt() { @Override public void showErrorDialog(String name, String url) { - JEditorPane ep = new JEditorPane("text/html", - "" + - owner + " was unable to download required library " + name + - "
Check your internet connection and try restarting or download it manually from" + - "
" + url + " and put it in your mods folder" + - ""); + JEditorPane ep = new JEditorPane( + "text/html", + "" + owner + + " was unable to download required library " + name + + "
Check your internet connection and try restarting or download it manually from" + + "
" + url + " and put it in your mods folder" + ""); ep.setEditable(false); ep.setOpaque(false); @@ -192,16 +194,13 @@ public void hyperlinkUpdate(HyperlinkEvent event) { public static class DummyDownloader implements IDownloadDisplay { @Override - public void resetProgress(int sizeGuess) { - } + public void resetProgress(int sizeGuess) {} @Override - public void setPokeThread(Thread currentThread) { - } + public void setPokeThread(Thread currentThread) {} @Override - public void updateProgress(int fullLength) { - } + public void updateProgress(int fullLength) {} @Override public boolean shouldStopIt() { @@ -209,8 +208,7 @@ public boolean shouldStopIt() { } @Override - public void updateProgressString(String string, Object... data) { - } + public void updateProgressString(String string, Object... data) {} @Override public Object makeDialog() { @@ -218,12 +216,10 @@ public Object makeDialog() { } @Override - public void showErrorDialog(String name, String url) { - } + public void showErrorDialog(String name, String url) {} } - public static class VersionedFile - { + public static class VersionedFile { public final Pattern pattern; public final String filename; public final ComparableVersion version; @@ -233,11 +229,10 @@ public VersionedFile(String filename, Pattern pattern) { this.pattern = pattern; this.filename = filename; Matcher m = pattern.matcher(filename); - if(m.matches()) { + if (m.matches()) { name = m.group(1); version = new ComparableVersion(m.group(2)); - } - else { + } else { name = null; version = null; } @@ -248,8 +243,7 @@ public boolean matches() { } } - public static class Dependency - { + public static class Dependency { public String url; public VersionedFile file; @@ -281,21 +275,20 @@ public DepLoadInst() { modsDir = new File(mcDir, "mods"); v_modsDir = new File(mcDir, "mods/" + mcVer); - if (!v_modsDir.exists()) - v_modsDir.mkdirs(); + if (!v_modsDir.exists()) v_modsDir.mkdirs(); } private void addClasspath(String name) { try { - ((LaunchClassLoader) DepLoader.class.getClassLoader()).addURL(new File(v_modsDir, name).toURI().toURL()); + ((LaunchClassLoader) DepLoader.class.getClassLoader()) + .addURL(new File(v_modsDir, name).toURI().toURL()); } catch (MalformedURLException e) { throw new RuntimeException(e); } } private void deleteMod(File mod) { - if (mod.delete()) - return; + if (mod.delete()) return; try { ClassLoader cl = DepLoader.class.getClassLoader(); @@ -319,7 +312,8 @@ private void deleteMod(File mod) { if (!mod.delete()) { mod.deleteOnExit(); - String msg = owner + " was unable to delete file " + mod.getPath() + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; + String msg = owner + " was unable to delete file " + mod.getPath() + + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; CodeChickenCorePlugin.logger.error(msg); if (!GraphicsEnvironment.isHeadless()) JOptionPane.showMessageDialog(null, msg, "An update error has occurred", JOptionPane.ERROR_MESSAGE); @@ -348,7 +342,8 @@ private void download(Dependency dep) { } catch (Exception e) { libFile.delete(); if (downloadMonitor.shouldStopIt()) { - CodeChickenCorePlugin.logger.error("You have stopped the downloading operation before it could complete"); + CodeChickenCorePlugin.logger.error( + "You have stopped the downloading operation before it could complete"); System.exit(1); return; } @@ -359,7 +354,9 @@ private void download(Dependency dep) { private void download(InputStream is, int sizeGuess, File target) throws Exception { if (sizeGuess > downloadBuffer.capacity()) - throw new Exception(String.format("The file %s is too large to be downloaded by " + owner + " - the download is invalid", target.getName())); + throw new Exception(String.format( + "The file %s is too large to be downloaded by " + owner + " - the download is invalid", + target.getName())); downloadBuffer.clear(); @@ -393,9 +390,7 @@ private void download(InputStream is, int sizeGuess, File target) throws Excepti /*String cksum = generateChecksum(downloadBuffer); if (cksum.equals(validationHash)) {*/ - if (!target.exists()) - target.createNewFile(); - + if (!target.exists()) target.createNewFile(); downloadBuffer.position(0); FileOutputStream fos = new FileOutputStream(target); @@ -414,19 +409,16 @@ private void download(InputStream is, int sizeGuess, File target) throws Excepti private String checkExisting(Dependency dep) { for (File f : modsDir.listFiles()) { VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); - if (!vfile.matches() || !vfile.name.equals(dep.file.name)) - continue; + if (!vfile.matches() || !vfile.name.equals(dep.file.name)) continue; - if (f.renameTo(new File(v_modsDir, f.getName()))) - continue; + if (f.renameTo(new File(v_modsDir, f.getName()))) continue; deleteMod(f); } for (File f : v_modsDir.listFiles()) { VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); - if (!vfile.matches() || !vfile.name.equals(dep.file.name)) - continue; + if (!vfile.matches() || !vfile.name.equals(dep.file.name)) continue; int cmp = vfile.version.compareTo(dep.file.version); if (cmp < 0) { @@ -435,27 +427,25 @@ private String checkExisting(Dependency dep) { return null; } if (cmp > 0) { - CodeChickenCorePlugin.logger.warn("Warning: version of " + dep.file.name + ", " + vfile.version + " is newer than request " + dep.file.version); + CodeChickenCorePlugin.logger.warn("Warning: version of " + dep.file.name + ", " + vfile.version + + " is newer than request " + dep.file.version); return f.getName(); } - return f.getName();//found dependency + return f.getName(); // found dependency } return null; } public void load() { scanDepInfos(); - if (depMap.isEmpty()) - return; + if (depMap.isEmpty()) return; loadDeps(); activateDeps(); } private void activateDeps() { - for (Dependency dep : depMap.values()) - if (dep.coreLib) - addClasspath(dep.existing); + for (Dependency dep : depMap.values()) if (dep.coreLib) addClasspath(dep.existing); } private void loadDeps() { @@ -477,7 +467,7 @@ private void loadDeps() { private void load(Dependency dep) { dep.existing = checkExisting(dep); - if (dep.existing == null)//download dep + if (dep.existing == null) // download dep { download(dep); dep.existing = dep.file.filename; @@ -493,8 +483,7 @@ private List modFiles() { private void scanDepInfos() { for (File file : modFiles()) { - if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) - continue; + if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) continue; scanDepInfo(file); } @@ -505,11 +494,11 @@ private void scanDepInfo(File file) { ZipFile zip = new ZipFile(file); ZipEntry e = zip.getEntry("dependancies.info"); if (e == null) e = zip.getEntry("dependencies.info"); - if (e != null) - loadJSon(zip.getInputStream(e)); + if (e != null) loadJSon(zip.getInputStream(e)); zip.close(); } catch (Exception e) { - CodeChickenCorePlugin.logger.error("Failed to load dependencies.info from " + file.getName() + " as JSON"); + CodeChickenCorePlugin.logger.error( + "Failed to load dependencies.info from " + file.getName() + " as JSON"); e.printStackTrace(); } } @@ -517,47 +506,41 @@ private void scanDepInfo(File file) { private void loadJSon(InputStream input) throws IOException { InputStreamReader reader = new InputStreamReader(input); JsonElement root = new JsonParser().parse(reader); - if (root.isJsonArray()) - loadJSonArr(root); - else - loadJson(root.getAsJsonObject()); + if (root.isJsonArray()) loadJSonArr(root); + else loadJson(root.getAsJsonObject()); reader.close(); } private void loadJSonArr(JsonElement root) throws IOException { - for (JsonElement node : root.getAsJsonArray()) - loadJson(node.getAsJsonObject()); + for (JsonElement node : root.getAsJsonArray()) loadJson(node.getAsJsonObject()); } private void loadJson(JsonObject node) throws IOException { - boolean obfuscated = ((LaunchClassLoader) DepLoader.class.getClassLoader()) - .getClassBytes("net.minecraft.world.World") == null; + boolean obfuscated = + ((LaunchClassLoader) DepLoader.class.getClassLoader()).getClassBytes("net.minecraft.world.World") + == null; String testClass = node.get("class").getAsString(); - if (DepLoader.class.getResource("/" + testClass.replace('.', '/') + ".class") != null) - return; + if (DepLoader.class.getResource("/" + testClass.replace('.', '/') + ".class") != null) return; String repo = node.get("repo").getAsString(); String filename = node.get("file").getAsString(); - if (!obfuscated && node.has("dev")) - filename = node.get("dev").getAsString(); + if (!obfuscated && node.has("dev")) filename = node.get("dev").getAsString(); boolean coreLib = node.has("coreLib") && node.get("coreLib").getAsBoolean(); Pattern pattern = null; try { - if(node.has("pattern")) + if (node.has("pattern")) pattern = Pattern.compile(node.get("pattern").getAsString()); } catch (PatternSyntaxException e) { CodeChickenCorePlugin.logger.error("Invalid filename pattern: " + node.get("pattern")); e.printStackTrace(); } - if(pattern == null) - pattern = Pattern.compile("(\\w+).*?([\\d\\.]+)[-\\w]*\\.[^\\d]+"); + if (pattern == null) pattern = Pattern.compile("(\\w+).*?([\\d\\.]+)[-\\w]*\\.[^\\d]+"); VersionedFile file = new VersionedFile(filename, pattern); - if (!file.matches()) - throw new RuntimeException("Invalid filename format for dependency: " + filename); + if (!file.matches()) throw new RuntimeException("Invalid filename format for dependency: " + filename); addDep(new Dependency(repo, file, coreLib)); } @@ -570,8 +553,7 @@ private void addDep(Dependency newDep) { } private boolean mergeNew(Dependency oldDep, Dependency newDep) { - if (oldDep == null) - return true; + if (oldDep == null) return true; Dependency newest = newDep.file.version.compareTo(oldDep.file.version) > 0 ? newDep : oldDep; newest.coreLib = newDep.coreLib || oldDep.coreLib; @@ -603,8 +585,7 @@ public String getSetupClass() { } @Override - public void injectData(Map data) { - } + public void injectData(Map data) {} @Override public Void call() { diff --git a/src/main/java/codechicken/obfuscator/ConstantObfuscator.java b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java index bb090c5..0af3660 100644 --- a/src/main/java/codechicken/obfuscator/ConstantObfuscator.java +++ b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java @@ -1,5 +1,8 @@ package codechicken.obfuscator; +import static org.objectweb.asm.tree.AbstractInsnNode.*; + +import codechicken.lib.asm.ObfMapping; import java.util.LinkedList; import java.util.List; import org.objectweb.asm.Opcodes; @@ -9,42 +12,30 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; -import codechicken.lib.asm.ObfMapping; - -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -public class ConstantObfuscator implements Opcodes -{ +public class ConstantObfuscator implements Opcodes { public ObfRemapper obf; public List descCalls = new LinkedList(); public List classCalls = new LinkedList(); - - public ConstantObfuscator(ObfRemapper obf, String[] a_classCalls, String[] a_descCalls) - { + + public ConstantObfuscator(ObfRemapper obf, String[] a_classCalls, String[] a_descCalls) { this.obf = obf; - for(String callDesc : a_classCalls) - classCalls.add(ObfMapping.fromDesc(callDesc)); - - for(String callDesc : a_descCalls) - descCalls.add(ObfMapping.fromDesc(callDesc)); + for (String callDesc : a_classCalls) classCalls.add(ObfMapping.fromDesc(callDesc)); + + for (String callDesc : a_descCalls) descCalls.add(ObfMapping.fromDesc(callDesc)); } - public void transform(ClassNode cnode) - { - for(MethodNode method : cnode.methods) - for(AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) + public void transform(ClassNode cnode) { + for (MethodNode method : cnode.methods) + for (AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) obfuscateInsnSeq(insn); } - - private void obfuscateInsnSeq(AbstractInsnNode insn) - { - if(matchesClass(insn)) - { + + private void obfuscateInsnSeq(AbstractInsnNode insn) { + if (matchesClass(insn)) { LdcInsnNode node1 = (LdcInsnNode) insn; node1.cst = obf.map((String) node1.cst); } - if(matchesDesc(insn)) - { + if (matchesDesc(insn)) { LdcInsnNode node1 = (LdcInsnNode) insn; LdcInsnNode node2 = (LdcInsnNode) node1.getNext(); LdcInsnNode node3 = (LdcInsnNode) node2.getNext(); @@ -54,30 +45,24 @@ private void obfuscateInsnSeq(AbstractInsnNode insn) node3.cst = mapping.s_desc; } } - - private boolean matchesClass(AbstractInsnNode insn) - { - if(insn.getType() != LDC_INSN) return false; + + private boolean matchesClass(AbstractInsnNode insn) { + if (insn.getType() != LDC_INSN) return false; insn = insn.getNext(); - if(insn == null || insn.getType() != METHOD_INSN) return false; - for(ObfMapping m : classCalls) - if(m.matches((MethodInsnNode) insn)) - return true; + if (insn == null || insn.getType() != METHOD_INSN) return false; + for (ObfMapping m : classCalls) if (m.matches((MethodInsnNode) insn)) return true; return false; } - - private boolean matchesDesc(AbstractInsnNode insn) - { - if(insn.getType() != LDC_INSN) return false; + + private boolean matchesDesc(AbstractInsnNode insn) { + if (insn.getType() != LDC_INSN) return false; insn = insn.getNext(); - if(insn == null || insn.getType() != LDC_INSN) return false; + if (insn == null || insn.getType() != LDC_INSN) return false; insn = insn.getNext(); - if(insn == null || insn.getType() != LDC_INSN) return false; + if (insn == null || insn.getType() != LDC_INSN) return false; insn = insn.getNext(); - if(insn == null || insn.getType() != METHOD_INSN) return false; - for(ObfMapping m : descCalls) - if(m.matches((MethodInsnNode) insn)) - return true; + if (insn == null || insn.getType() != METHOD_INSN) return false; + for (ObfMapping m : descCalls) if (m.matches((MethodInsnNode) insn)) return true; return false; } } diff --git a/src/main/java/codechicken/obfuscator/DummyOutputStream.java b/src/main/java/codechicken/obfuscator/DummyOutputStream.java index 50093ef..475526c 100644 --- a/src/main/java/codechicken/obfuscator/DummyOutputStream.java +++ b/src/main/java/codechicken/obfuscator/DummyOutputStream.java @@ -2,12 +2,9 @@ import java.io.OutputStream; -public class DummyOutputStream extends OutputStream -{ +public class DummyOutputStream extends OutputStream { public static DummyOutputStream instance = new DummyOutputStream(); @Override - public void write(int b) - { - } + public void write(int b) {} } diff --git a/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java b/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java index 4c43444..bca8fa0 100644 --- a/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java +++ b/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java @@ -1,11 +1,9 @@ package codechicken.obfuscator; -import java.util.List; - import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; +import java.util.List; -public interface IHeirachyEvaluator -{ +public interface IHeirachyEvaluator { /** * @param desc The mapping descriptor of the class to evaluate heirachy for * @return A list of parents (srg or obf names) diff --git a/src/main/java/codechicken/obfuscator/ILogStreams.java b/src/main/java/codechicken/obfuscator/ILogStreams.java index 0992103..3beeedf 100644 --- a/src/main/java/codechicken/obfuscator/ILogStreams.java +++ b/src/main/java/codechicken/obfuscator/ILogStreams.java @@ -2,8 +2,8 @@ import java.io.PrintStream; -public interface ILogStreams -{ +public interface ILogStreams { public PrintStream err(); + public PrintStream out(); } diff --git a/src/main/java/codechicken/obfuscator/ObfDirection.java b/src/main/java/codechicken/obfuscator/ObfDirection.java index 3405be2..a1bb715 100644 --- a/src/main/java/codechicken/obfuscator/ObfDirection.java +++ b/src/main/java/codechicken/obfuscator/ObfDirection.java @@ -3,32 +3,27 @@ import codechicken.lib.asm.ObfMapping; import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; -public class ObfDirection -{ +public class ObfDirection { public boolean obfuscate; public boolean srg; public boolean srg_cst; - - public ObfDirection setObfuscate(boolean obfuscate) - { + + public ObfDirection setObfuscate(boolean obfuscate) { this.obfuscate = obfuscate; return this; } - - public ObfDirection setSearge(boolean srg) - { + + public ObfDirection setSearge(boolean srg) { this.srg = srg; return this; } - public ObfDirection setSeargeConstants(boolean srg_cst) - { + public ObfDirection setSeargeConstants(boolean srg_cst) { this.srg_cst = srg_cst; return this; } - public ObfMapping obfuscate(ObfuscationEntry map) - { + public ObfMapping obfuscate(ObfuscationEntry map) { return srg ? map.srg : obfuscate ? map.obf : map.mcp; } } diff --git a/src/main/java/codechicken/obfuscator/ObfRemapper.java b/src/main/java/codechicken/obfuscator/ObfRemapper.java index 3cc70e7..b4668b5 100644 --- a/src/main/java/codechicken/obfuscator/ObfRemapper.java +++ b/src/main/java/codechicken/obfuscator/ObfRemapper.java @@ -1,91 +1,69 @@ package codechicken.obfuscator; -import org.objectweb.asm.commons.Remapper; - import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; +import org.objectweb.asm.commons.Remapper; -public class ObfRemapper extends Remapper -{ +public class ObfRemapper extends Remapper { public final ObfuscationMap obf; public ObfDirection dir; - - public ObfRemapper(ObfuscationMap obf, ObfDirection dir) - { + + public ObfRemapper(ObfuscationMap obf, ObfDirection dir) { this.obf = obf; this.dir = dir; } - + @Override - public String map(String name) - { - if(name.indexOf('$') >= 0) - return map(name.substring(0, name.indexOf('$')))+name.substring(name.indexOf('$')); - + public String map(String name) { + if (name.indexOf('$') >= 0) + return map(name.substring(0, name.indexOf('$'))) + name.substring(name.indexOf('$')); + ObfuscationEntry map; - if(dir.obfuscate) - map = obf.lookupMcpClass(name); - else - map = obf.lookupObfClass(name); - - if(map != null) - return dir.obfuscate(map).s_owner; - + if (dir.obfuscate) map = obf.lookupMcpClass(name); + else map = obf.lookupObfClass(name); + + if (map != null) return dir.obfuscate(map).s_owner; + return name; } - + @Override - public String mapFieldName(String owner, String name, String desc) - { + public String mapFieldName(String owner, String name, String desc) { ObfuscationEntry map; - if(dir.obfuscate) - map = obf.lookupMcpField(owner, name); - else - map = obf.lookupObfField(owner, name); - - if(map == null) - map = obf.lookupSrgField(owner, name); - - if(map != null) - return dir.obfuscate(map).s_name; - + if (dir.obfuscate) map = obf.lookupMcpField(owner, name); + else map = obf.lookupObfField(owner, name); + + if (map == null) map = obf.lookupSrgField(owner, name); + + if (map != null) return dir.obfuscate(map).s_name; + return name; } - + @Override - public String mapMethodName(String owner, String name, String desc) - { - if(owner.length() == 0 || owner.charAt(0) == '[') - return name; - + public String mapMethodName(String owner, String name, String desc) { + if (owner.length() == 0 || owner.charAt(0) == '[') return name; + ObfuscationEntry map; - if(dir.obfuscate) - map = obf.lookupMcpMethod(owner, name, desc); - else - map = obf.lookupObfMethod(owner, name, desc); - - if(map == null) - map = obf.lookupSrg(name); - - if(map != null) - return dir.obfuscate(map).s_name; - + if (dir.obfuscate) map = obf.lookupMcpMethod(owner, name, desc); + else map = obf.lookupObfMethod(owner, name, desc); + + if (map == null) map = obf.lookupSrg(name); + + if (map != null) return dir.obfuscate(map).s_name; + return name; } @Override - public Object mapValue(Object cst) - { - if(cst instanceof String) - { - if(dir.srg_cst) - { + public Object mapValue(Object cst) { + if (cst instanceof String) { + if (dir.srg_cst) { ObfuscationEntry map = obf.lookupSrg((String) cst); - if(map != null) - return dir.obfuscate(map).s_name; + if (map != null) return dir.obfuscate(map).s_name; } return cst; } - + return super.mapValue(cst); } } diff --git a/src/main/java/codechicken/obfuscator/ObfuscationMap.java b/src/main/java/codechicken/obfuscator/ObfuscationMap.java index 3350e5a..0183ff7 100644 --- a/src/main/java/codechicken/obfuscator/ObfuscationMap.java +++ b/src/main/java/codechicken/obfuscator/ObfuscationMap.java @@ -1,5 +1,8 @@ package codechicken.obfuscator; +import codechicken.lib.asm.ObfMapping; +import com.google.common.base.Function; +import com.google.common.collect.ArrayListMultimap; import java.io.File; import java.util.HashMap; import java.util.HashSet; @@ -7,162 +10,127 @@ import java.util.Map; import java.util.Map.Entry; -import com.google.common.base.Function; -import com.google.common.collect.ArrayListMultimap; - -import codechicken.lib.asm.ObfMapping; - -public class ObfuscationMap -{ - public class ObfuscationEntry - { +public class ObfuscationMap { + public class ObfuscationEntry { public final ObfMapping obf; public final ObfMapping srg; public final ObfMapping mcp; - - public ObfuscationEntry(ObfMapping obf, ObfMapping srg, ObfMapping mcp) - { + + public ObfuscationEntry(ObfMapping obf, ObfMapping srg, ObfMapping mcp) { this.obf = obf; this.srg = srg; this.mcp = mcp; } } - - private class ClassEntry extends ObfuscationEntry - { + + private class ClassEntry extends ObfuscationEntry { public Map mcpMap = new HashMap(); public Map srgMap = new HashMap(); public Map obfMap = new HashMap(); - - public ClassEntry(String obf, String srg) - { - super(new ObfMapping(obf, "", ""), - new ObfMapping(srg, "", ""), - new ObfMapping(srg, "", "")); + + public ClassEntry(String obf, String srg) { + super(new ObfMapping(obf, "", ""), new ObfMapping(srg, "", ""), new ObfMapping(srg, "", "")); } - - public ObfuscationEntry addEntry(ObfMapping obf_desc, ObfMapping srg_desc) - { + + public ObfuscationEntry addEntry(ObfMapping obf_desc, ObfMapping srg_desc) { ObfuscationEntry entry = new ObfuscationEntry(obf_desc, srg_desc, srg_desc.copy()); obfMap.put(obf_desc.s_name.concat(obf_desc.s_desc), entry); srgMap.put(srg_desc.s_name, entry); - - if(srg_desc.s_name.startsWith("field_") || srg_desc.s_name.startsWith("func_")) + + if (srg_desc.s_name.startsWith("field_") || srg_desc.s_name.startsWith("func_")) srgMemberMap.put(srg_desc.s_name, entry); - + return entry; } - public void inheritFrom(ClassEntry p) - { + public void inheritFrom(ClassEntry p) { inherit(obfMap, p.obfMap); inherit(srgMap, p.srgMap); inherit(mcpMap, p.mcpMap); } - - private void inherit(Map child, Map parent) - { - for(Entry e : parent.entrySet()) - if(!child.containsKey(e.getKey())) - child.put(e.getKey(), e.getValue()); + + private void inherit(Map child, Map parent) { + for (Entry e : parent.entrySet()) + if (!child.containsKey(e.getKey())) child.put(e.getKey(), e.getValue()); } } - + private Map srgMap = new HashMap(); private Map obfMap = new HashMap(); private ArrayListMultimap srgMemberMap = ArrayListMultimap.create(); - + private IHeirachyEvaluator heirachyEvaluator; private HashSet mappedClasses = new HashSet(); public ILogStreams log = SystemLogStreams.inst; - - public ObfuscationMap setHeirachyEvaluator(IHeirachyEvaluator eval) - { + + public ObfuscationMap setHeirachyEvaluator(IHeirachyEvaluator eval) { heirachyEvaluator = eval; return this; } - - public ObfuscationMap setLog(ILogStreams log) - { + + public ObfuscationMap setLog(ILogStreams log) { this.log = log; return this; } - - public ObfuscationEntry addClass(String obf, String srg) - { + + public ObfuscationEntry addClass(String obf, String srg) { return addEntry(new ObfMapping(obf, "", ""), new ObfMapping(srg, "", "")); } - - public ObfuscationEntry addField(String obf_owner, String obf_name, String srg_owner, String srg_name) - { - return addEntry(new ObfMapping(obf_owner, obf_name, ""), - new ObfMapping(srg_owner, srg_name, "")); + + public ObfuscationEntry addField(String obf_owner, String obf_name, String srg_owner, String srg_name) { + return addEntry(new ObfMapping(obf_owner, obf_name, ""), new ObfMapping(srg_owner, srg_name, "")); } - - public ObfuscationEntry addMethod(String obf_owner, String obf_name, String obf_desc, String srg_owner, String srg_name, String srg_desc) - { - return addEntry(new ObfMapping(obf_owner, obf_name, obf_desc), - new ObfMapping(srg_owner, srg_name, srg_desc)); + + public ObfuscationEntry addMethod( + String obf_owner, String obf_name, String obf_desc, String srg_owner, String srg_name, String srg_desc) { + return addEntry(new ObfMapping(obf_owner, obf_name, obf_desc), new ObfMapping(srg_owner, srg_name, srg_desc)); } - - public ObfuscationEntry addEntry(ObfMapping obf_desc, ObfMapping srg_desc) - { + + public ObfuscationEntry addEntry(ObfMapping obf_desc, ObfMapping srg_desc) { ClassEntry e = srgMap.get(srg_desc.s_owner); - if(e == null) - { + if (e == null) { e = new ClassEntry(obf_desc.s_owner, srg_desc.s_owner); obfMap.put(obf_desc.s_owner, e); srgMap.put(srg_desc.s_owner, e); } - if(obf_desc.s_name.length() > 0) - return e.addEntry(obf_desc, srg_desc); - + if (obf_desc.s_name.length() > 0) return e.addEntry(obf_desc, srg_desc); + return e; } - - public void addMcpName(String srg_name, String mcp_name) - { + + public void addMcpName(String srg_name, String mcp_name) { List entries = srgMemberMap.get(srg_name); - if(entries.isEmpty()) - { - log.err().println("Tried to add mcp name ("+mcp_name+") for unknown srg key ("+srg_name+")"); + if (entries.isEmpty()) { + log.err().println("Tried to add mcp name (" + mcp_name + ") for unknown srg key (" + srg_name + ")"); return; } - for(ObfuscationEntry entry : entries) - { + for (ObfuscationEntry entry : entries) { entry.mcp.s_name = mcp_name; srgMap.get(entry.srg.s_owner).mcpMap.put(entry.mcp.s_name.concat(entry.mcp.s_desc), entry); } } - - public ObfuscationEntry lookupSrg(String srg_key) - { + + public ObfuscationEntry lookupSrg(String srg_key) { List list = srgMemberMap.get(srg_key); return list.isEmpty() ? null : list.get(0); } - - public ObfuscationEntry lookupMcpClass(String name) - { + + public ObfuscationEntry lookupMcpClass(String name) { return srgMap.get(name); } - public ObfuscationEntry lookupObfClass(String name) - { + public ObfuscationEntry lookupObfClass(String name) { return obfMap.get(name); } - public ObfuscationEntry lookupMcpField(String owner, String name) - { + public ObfuscationEntry lookupMcpField(String owner, String name) { return lookupMcpMethod(owner, name, ""); } - public ObfuscationEntry lookupSrgField(String owner, String name) - { - if(name.startsWith("field_")) - { + public ObfuscationEntry lookupSrgField(String owner, String name) { + if (name.startsWith("field_")) { ObfuscationEntry e = lookupSrg(name); - if(e != null) - return e; + if (e != null) return e; } evaluateHeirachy(owner); @@ -170,174 +138,144 @@ public ObfuscationEntry lookupSrgField(String owner, String name) return e == null ? null : e.srgMap.get(name); } - public ObfuscationEntry lookupObfField(String owner, String name) - { + public ObfuscationEntry lookupObfField(String owner, String name) { return lookupObfMethod(owner, name, ""); } - public ObfuscationEntry lookupMcpMethod(String owner, String name, String desc) - { + public ObfuscationEntry lookupMcpMethod(String owner, String name, String desc) { evaluateHeirachy(owner); ClassEntry e = srgMap.get(owner); return e == null ? null : e.mcpMap.get(name.concat(desc)); } - public ObfuscationEntry lookupObfMethod(String owner, String name, String desc) - { + public ObfuscationEntry lookupObfMethod(String owner, String name, String desc) { evaluateHeirachy(owner); ClassEntry e = obfMap.get(owner); return e == null ? null : e.obfMap.get(name.concat(desc)); } - - private boolean isMapped(ObfuscationEntry desc) - { + + private boolean isMapped(ObfuscationEntry desc) { return mappedClasses.contains(desc.srg.s_owner); } - - private ObfuscationEntry getOrCreateClassEntry(String name) - { + + private ObfuscationEntry getOrCreateClassEntry(String name) { ObfuscationEntry e = lookupObfClass(name); - if(e == null) - e = lookupMcpClass(name); - if(e == null) - e = addClass(name, name);//if the class isn't in obf or srg maps, it must be a custom mod class with no name change. + if (e == null) e = lookupMcpClass(name); + if (e == null) + e = addClass( + name, + name); // if the class isn't in obf or srg maps, it must be a custom mod class with no name change. return e; } - public ObfuscationEntry evaluateHeirachy(String name) - { + public ObfuscationEntry evaluateHeirachy(String name) { ObfuscationEntry desc = getOrCreateClassEntry(name); - if(isMapped(desc)) - return desc; + if (isMapped(desc)) return desc; mappedClasses.add(desc.srg.s_owner); - if(heirachyEvaluator == null) + if (heirachyEvaluator == null) throw new IllegalArgumentException("Cannot call method/field mappings if a heirachy evaluator is not set."); - - if(!heirachyEvaluator.isLibClass(desc)) - { + + if (!heirachyEvaluator.isLibClass(desc)) { List parents = heirachyEvaluator.getParents(desc); - if(parents == null) - log.err().println("Could not find class: "+desc.srg.s_owner); - else - for(String parent : parents) - inherit(desc, evaluateHeirachy(parent)); + if (parents == null) log.err().println("Could not find class: " + desc.srg.s_owner); + else for (String parent : parents) inherit(desc, evaluateHeirachy(parent)); } - + return desc; } - public void inherit(ObfuscationEntry desc, ObfuscationEntry p_desc) - { + public void inherit(ObfuscationEntry desc, ObfuscationEntry p_desc) { inherit(desc.srg.s_owner, p_desc.srg.s_owner); } - public void inherit(String name, String parent) - { + public void inherit(String name, String parent) { ClassEntry e = srgMap.get(name); - if(e == null) - throw new IllegalStateException("Tried to inerit to an undefined class: "+name+" extends "+parent); + if (e == null) + throw new IllegalStateException("Tried to inerit to an undefined class: " + name + " extends " + parent); ClassEntry p = srgMap.get(parent); - if(p == null) - throw new IllegalStateException("Tried to inerit from undefired parent: "+name+" extends "+parent); + if (p == null) + throw new IllegalStateException("Tried to inerit from undefired parent: " + name + " extends " + parent); e.inheritFrom(p); } - - public void parseMappings(File[] mappings) - { + + public void parseMappings(File[] mappings) { parseSRGS(mappings[0]); parseCSV(mappings[1]); parseCSV(mappings[2]); } - - public static String[] splitLast(String s, char c) - { + + public static String[] splitLast(String s, char c) { int i = s.lastIndexOf(c); - return new String[]{s.substring(0, i), s.substring(i+1)}; + return new String[] {s.substring(0, i), s.substring(i + 1)}; } - - public static String[] split4(String s, char c) - { + + public static String[] split4(String s, char c) { String[] split = new String[4]; int i2 = s.indexOf(c); split[0] = s.substring(0, i2); - int i = i2+1; + int i = i2 + 1; i2 = s.indexOf(c, i); split[1] = s.substring(i, i2); - i = i2+1; + i = i2 + 1; i2 = s.indexOf(c, i); split[2] = s.substring(i, i2); - i = i2+1; + i = i2 + 1; i2 = s.indexOf(c, i); split[3] = s.substring(i); return split; } - private void parseSRGS(File srgs) - { - log.out().println("Parsing "+srgs.getName()); - - Function function = new Function() - { + private void parseSRGS(File srgs) { + log.out().println("Parsing " + srgs.getName()); + + Function function = new Function() { @Override - public Void apply(String line) - { + public Void apply(String line) { int hpos = line.indexOf('#'); - if(hpos > 0) - line = line.substring(0, hpos).trim(); - if(line.startsWith("CL: ")) - { + if (hpos > 0) line = line.substring(0, hpos).trim(); + if (line.startsWith("CL: ")) { String[] params = splitLast(line.substring(4), ' '); addClass(params[0], params[1]); - } - else if(line.startsWith("FD: ")) - { + } else if (line.startsWith("FD: ")) { String[] params = splitLast(line.substring(4), ' '); String[] p1 = splitLast(params[0], '/'); String[] p2 = splitLast(params[1], '/'); - addField(p1[0], p1[1], - p2[0], p2[1]); + addField(p1[0], p1[1], p2[0], p2[1]); return null; - } - else if(line.startsWith("MD: ")) - { + } else if (line.startsWith("MD: ")) { String[] params = split4(line.substring(4), ' '); String[] p1 = splitLast(params[0], '/'); String[] p2 = splitLast(params[2], '/'); - addMethod(p1[0], p1[1], params[1], - p2[0], p2[1], params[3]); + addMethod(p1[0], p1[1], params[1], p2[0], p2[1], params[3]); return null; } return null; } }; - + ObfuscationRun.processLines(srgs, function); } - private void parseCSV(File csv) - { - log.out().println("Parsing "+csv.getName()); - - Function function = new Function() - { + private void parseCSV(File csv) { + log.out().println("Parsing " + csv.getName()); + + Function function = new Function() { @Override - public Void apply(String line) - { - if(line.startsWith("func_") || line.startsWith("field_")) - { + public Void apply(String line) { + if (line.startsWith("func_") || line.startsWith("field_")) { int i = line.indexOf(','); String srg = line.substring(0, i); - int i2 = i+1; + int i2 = i + 1; i = line.indexOf(',', i2); String mcp = line.substring(i2, i); - + addMcpName(srg, mcp); } return null; } }; - + ObfuscationRun.processLines(csv, function); } } diff --git a/src/main/java/codechicken/obfuscator/ObfuscationRun.java b/src/main/java/codechicken/obfuscator/ObfuscationRun.java index 67e2178..9831ab1 100644 --- a/src/main/java/codechicken/obfuscator/ObfuscationRun.java +++ b/src/main/java/codechicken/obfuscator/ObfuscationRun.java @@ -1,5 +1,6 @@ package codechicken.obfuscator; +import com.google.common.base.Function; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -12,242 +13,199 @@ import org.objectweb.asm.commons.RemappingClassAdapter; import org.objectweb.asm.tree.ClassNode; -import com.google.common.base.Function; - -public class ObfuscationRun implements ILogStreams -{ +public class ObfuscationRun implements ILogStreams { public final ObfDirection obfDir; public final ObfuscationMap obf; public final ObfRemapper obfMapper; public final ConstantObfuscator cstMappper; - + public File[] mappings; public Map config; - + private PrintStream out = System.out; private PrintStream err = System.err; private PrintStream quietStream = new PrintStream(DummyOutputStream.instance); - + private boolean verbose; private boolean quiet; public boolean clean; private long startTime; private boolean finished; - - public ObfuscationRun(boolean obfuscate, File[] mappings, Map config) - { + + public ObfuscationRun(boolean obfuscate, File[] mappings, Map config) { obfDir = new ObfDirection().setObfuscate(obfuscate); this.mappings = mappings; this.config = config; - + obf = new ObfuscationMap().setLog(this); obfMapper = new ObfRemapper(obf, obfDir); - cstMappper = new ConstantObfuscator(obfMapper, - config.get("classConstantCalls").split(","), + cstMappper = new ConstantObfuscator( + obfMapper, + config.get("classConstantCalls").split(","), config.get("descConstantCalls").split(",")); } - - public ObfuscationRun setClean() - { + + public ObfuscationRun setClean() { clean = true; return this; } - - public ObfuscationRun setVerbose() - { + + public ObfuscationRun setVerbose() { verbose = true; return this; } - - public ObfuscationRun setQuiet() - { + + public ObfuscationRun setQuiet() { quiet = true; return this; } - - public ObfuscationRun setOut(PrintStream p) - { + + public ObfuscationRun setOut(PrintStream p) { out = p; return this; } - - public PrintStream out() - { + + public PrintStream out() { return quiet ? quietStream : out; } - - public PrintStream fine() - { + + public PrintStream fine() { return verbose ? out : quietStream; } - - public ObfuscationRun setErr(PrintStream p) - { + + public ObfuscationRun setErr(PrintStream p) { err = p; return this; } - - public PrintStream err() - { + + public PrintStream err() { return quiet ? quietStream : err; } - public ObfuscationRun setSearge() - { + public ObfuscationRun setSearge() { obfDir.setSearge(true); return this; } - public ObfuscationRun setSeargeConstants() - { + public ObfuscationRun setSeargeConstants() { obfDir.setSeargeConstants(true); return this; } - - public void start() - { + + public void start() { startTime = System.currentTimeMillis(); } - - public static Map fillDefaults(Map config) - { - if(!config.containsKey("excludedPackages")) - config.put("excludedPackages", "java/;sun/;javax/;scala/;" + - "argo/;org/lwjgl/;org/objectweb/;org/bouncycastle/;com/google/"); - if(!config.containsKey("ignore")) - config.put("ignore", "."); - if(!config.containsKey("classConstantCalls")) - config.put("classConstantCalls", - "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;)V," + - "codechicken/lib/asm/ObfMapping.subclass(Ljava/lang/String;)Lcodechicken/lib/asm/ObfMapping;," + - "codechicken/lib/asm/ObfMapping.(Lcodechicken/lib/asm/ObfMapping;Ljava/lang/String;)V"); - if(!config.containsKey("descConstantCalls")) - config.put("descConstantCalls", - "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + - "org/objectweb/asm/MethodVisitor.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + - "org/objectweb/asm/tree/MethodNode.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + - "org/objectweb/asm/MethodVisitor.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + - "org/objectweb/asm/tree/MethodNode.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + - "org/objectweb/asm/tree/MethodInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + - "org/objectweb/asm/tree/FieldInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - + + public static Map fillDefaults(Map config) { + if (!config.containsKey("excludedPackages")) + config.put( + "excludedPackages", + "java/;sun/;javax/;scala/;" + "argo/;org/lwjgl/;org/objectweb/;org/bouncycastle/;com/google/"); + if (!config.containsKey("ignore")) config.put("ignore", "."); + if (!config.containsKey("classConstantCalls")) + config.put( + "classConstantCalls", + "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;)V," + + "codechicken/lib/asm/ObfMapping.subclass(Ljava/lang/String;)Lcodechicken/lib/asm/ObfMapping;," + + "codechicken/lib/asm/ObfMapping.(Lcodechicken/lib/asm/ObfMapping;Ljava/lang/String;)V"); + if (!config.containsKey("descConstantCalls")) + config.put( + "descConstantCalls", + "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/MethodVisitor.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/MethodNode.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/MethodVisitor.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/MethodNode.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/MethodInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/FieldInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + return config; } - public static void processLines(File file, Function function) - { - try - { + public static void processLines(File file, Function function) { + try { BufferedReader reader = new BufferedReader(new FileReader(file)); String line; - while((line = reader.readLine()) != null) - function.apply(line); + while ((line = reader.readLine()) != null) function.apply(line); reader.close(); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } - - public static void processFiles(File dir, Function function, boolean recursive) - { - for(File file : dir.listFiles()) - if(file.isDirectory() && recursive) - processFiles(file, function, recursive); - else - function.apply(file); - } - - public static void deleteDir(File directory, boolean remove) - { - if(!directory.exists()) - { - if(!remove)directory.mkdirs(); + + public static void processFiles(File dir, Function function, boolean recursive) { + for (File file : dir.listFiles()) + if (file.isDirectory() && recursive) processFiles(file, function, recursive); + else function.apply(file); + } + + public static void deleteDir(File directory, boolean remove) { + if (!directory.exists()) { + if (!remove) directory.mkdirs(); return; } - for(File file : directory.listFiles()) - { - if(file.isDirectory()) - { + for (File file : directory.listFiles()) { + if (file.isDirectory()) { deleteDir(file, true); - } - else - { - if(!file.delete()) - throw new RuntimeException("Delete Failed: "+file); + } else { + if (!file.delete()) throw new RuntimeException("Delete Failed: " + file); } } - if(remove) - { - if(!directory.delete()) - throw new RuntimeException("Delete Failed: "+directory); + if (remove) { + if (!directory.delete()) throw new RuntimeException("Delete Failed: " + directory); } } - + public static File[] parseConfDir(File confDir) { File srgDir = new File(confDir, "conf"); - if(!srgDir.exists()) - srgDir = confDir; - + if (!srgDir.exists()) srgDir = confDir; + File srgs = new File(srgDir, "packaged.srg"); - if(!srgs.exists()) - srgs = new File(srgDir, "joined.srg"); - if(!srgs.exists()) - throw new RuntimeException("Could not find packaged.srg or joined.srg"); - + if (!srgs.exists()) srgs = new File(srgDir, "joined.srg"); + if (!srgs.exists()) throw new RuntimeException("Could not find packaged.srg or joined.srg"); + File mapDir = new File(confDir, "mappings"); - if(!mapDir.exists()) - mapDir = confDir; - + if (!mapDir.exists()) mapDir = confDir; + File methods = new File(mapDir, "methods.csv"); - if(!methods.exists()) - throw new RuntimeException("Could not find methods.csv"); + if (!methods.exists()) throw new RuntimeException("Could not find methods.csv"); File fields = new File(mapDir, "fields.csv"); - if(!fields.exists()) - throw new RuntimeException("Could not find fields.csv"); - - return new File[]{srgs, methods, fields}; - } - - public long startTime() - { + if (!fields.exists()) throw new RuntimeException("Could not find fields.csv"); + + return new File[] {srgs, methods, fields}; + } + + public long startTime() { return startTime; } - public void remap(ClassNode cnode, ClassVisitor cv) - { + public void remap(ClassNode cnode, ClassVisitor cv) { cstMappper.transform(cnode); cnode.accept(new RemappingClassAdapter(cv, obfMapper)); } - public static List getParents(ClassNode cnode) - { + public static List getParents(ClassNode cnode) { List parents = new LinkedList(); - if(cnode.superName != null) - parents.add(cnode.superName); - - for(String s_interface : cnode.interfaces) - parents.add(s_interface); - + if (cnode.superName != null) parents.add(cnode.superName); + + for (String s_interface : cnode.interfaces) parents.add(s_interface); + return parents; } - public void finish(boolean errored) - { - long millis = System.currentTimeMillis()-startTime; - out().println((errored ? "Errored after" : "Done in ")+new DecimalFormat("0.00").format(millis/1000D)+"s"); + public void finish(boolean errored) { + long millis = System.currentTimeMillis() - startTime; + out().println((errored ? "Errored after" : "Done in ") + new DecimalFormat("0.00").format(millis / 1000D) + + "s"); finished = true; } - - public boolean finished() - { + + public boolean finished() { return finished; } - public void parseMappings() - { + public void parseMappings() { obf.parseMappings(mappings); } } diff --git a/src/main/java/codechicken/obfuscator/SystemLogStreams.java b/src/main/java/codechicken/obfuscator/SystemLogStreams.java index 1da29e2..aaddd2a 100644 --- a/src/main/java/codechicken/obfuscator/SystemLogStreams.java +++ b/src/main/java/codechicken/obfuscator/SystemLogStreams.java @@ -2,19 +2,16 @@ import java.io.PrintStream; -public class SystemLogStreams implements ILogStreams -{ +public class SystemLogStreams implements ILogStreams { public static SystemLogStreams inst = new SystemLogStreams(); - + @Override - public PrintStream err() - { + public PrintStream err() { return System.err; } - + @Override - public PrintStream out() - { + public PrintStream out() { return System.out; } } From 8d95baccb517470e728845547094f2c91acfdb75 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Thu, 5 Jan 2023 11:49:10 +0000 Subject: [PATCH 160/219] Update buildscript --- .gitattributes | 44 +++ build.gradle | 795 ++++++++++++++++++++++++++++++++++++------------ settings.gradle | 10 + 3 files changed, 662 insertions(+), 187 deletions(-) create mode 100644 .gitattributes create mode 100644 settings.gradle diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fd2792b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,44 @@ +* text eol=lf + +*.[jJ][aA][rR] binary + +*.[pP][nN][gG] binary +*.[jJ][pP][gG] binary +*.[jJ][pP][eE][gG] binary +*.[gG][iI][fF] binary +*.[tT][iI][fF] binary +*.[tT][iI][fF][fF] binary +*.[iI][cC][oO] binary +*.[sS][vV][gG] text +*.[eE][pP][sS] binary +*.[xX][cC][fF] binary + +*.[kK][aA][rR] binary +*.[mM]4[aA] binary +*.[mM][iI][dD] binary +*.[mM][iI][dD][iI] binary +*.[mM][pP]3 binary +*.[oO][gG][gG] binary +*.[rR][aA] binary + +*.7[zZ] binary +*.[gG][zZ] binary +*.[tT][aA][rR] binary +*.[tT][gG][zZ] binary +*.[zZ][iI][pP] binary + +*.[tT][cC][nN] binary +*.[sS][oO] binary +*.[dD][lL][lL] binary +*.[dD][yY][lL][iI][bB] binary +*.[pP][sS][dD] binary +*.[tT][tT][fF] binary +*.[oO][tT][fF] binary + +*.[pP][aA][tT][cC][hH] -text + +*.[bB][aA][tT] text eol=crlf +*.[cC][mM][dD] text eol=crlf +*.[pP][sS]1 text eol=crlf + +*[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary diff --git a/build.gradle b/build.gradle index 7914dd8..fa88ae1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,52 +1,90 @@ -//version: 1643020202 +//version: 1671313514 /* -DO NOT CHANGE THIS FILE! - -Also, you may replace this file at any time if there is an update available. -Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. + DO NOT CHANGE THIS FILE! + Also, you may replace this file at any time if there is an update available. + Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/build.gradle for updates. */ import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - +import com.matthewprenger.cursegradle.CurseArtifact +import com.matthewprenger.cursegradle.CurseRelation +import com.modrinth.minotaur.dependencies.ModDependency +import com.modrinth.minotaur.dependencies.VersionDependency +import org.gradle.internal.logging.text.StyledTextOutput.Style +import org.gradle.internal.logging.text.StyledTextOutputFactory + +import java.nio.file.Files +import java.nio.file.Paths import java.util.concurrent.TimeUnit +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream +import java.util.zip.ZipOutputStream buildscript { repositories { + mavenCentral() + maven { - name = "forge" - url = "https://maven.minecraftforge.net" + name 'forge' + url 'https://maven.minecraftforge.net' } maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" + // GTNH ForgeGradle and ASM Fork + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" } maven { - name = "Scala CI dependencies" - url = "https://repo1.maven.org/maven2/" + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' } maven { - name = "jitpack" - url = "https://jitpack.io" + name 'Scala CI dependencies' + url 'https://repo1.maven.org/maven2/' } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7' + //Overwrite the current ASM version to fix shading newer than java 8 applicatations. + classpath 'org.ow2.asm:asm-debug-all-custom:5.0.3' + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.13' } } - plugins { + id 'java-library' id 'idea' id 'eclipse' id 'scala' - id("org.ajoberstar.grgit") version("3.1.1") - id("com.github.johnrengelman.shadow") version("4.0.4") - id("com.palantir.git-version") version("0.12.3") - id('de.undercouch.download') version('4.1.2') - id("maven-publish") + id 'maven-publish' + id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false + id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false + id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false + id 'org.ajoberstar.grgit' version '4.1.1' + id 'com.github.johnrengelman.shadow' version '4.0.4' + id 'com.palantir.git-version' version '0.13.0' apply false + id 'de.undercouch.download' version '5.0.1' + id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false + id 'com.diffplug.spotless' version '6.7.2' apply false + id 'com.modrinth.minotaur' version '2.+' apply false + id 'com.matthewprenger.cursegradle' version '1.4.0' apply false +} +boolean settingsupdated = verifySettingsGradle() +settingsupdated = verifyGitAttributes() || settingsupdated +if (settingsupdated) + throw new GradleException("Settings has been updated, please re-run task.") + +dependencies { + implementation 'com.diffplug:blowdryer:1.6.0' +} + +apply plugin: 'com.diffplug.blowdryer' + +if (project.file('.git/HEAD').isFile()) { + apply plugin: 'com.palantir.git-version' } +def out = services.get(StyledTextOutputFactory).create('an-output') + apply plugin: 'forge' def projectJavaVersion = JavaLanguageVersion.of(8) @@ -65,7 +103,14 @@ idea { } } -if(JavaVersion.current() != JavaVersion.VERSION_1_8) { +boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false + +if (!disableSpotless) { + apply plugin: 'com.diffplug.spotless' + apply from: Blowdryer.file('spotless.gradle') +} + +if (JavaVersion.current() != JavaVersion.VERSION_1_8) { throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) } @@ -90,57 +135,80 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false +propertyDefaultIfUnset("noPublishedSources", false) +propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) +propertyDefaultIfUnset("forceEnableMixins", false) +propertyDefaultIfUnset("channel", "stable") +propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("modrinthProjectId", "") +propertyDefaultIfUnset("modrinthRelations", "") +propertyDefaultIfUnset("curseForgeProjectId", "") +propertyDefaultIfUnset("curseForgeRelations", "") String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" +String kotlinSourceDir = "src/main/kotlin/" + -String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") -String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") -if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) +final String modGroupPath = modGroup.toString().replaceAll("\\.", "/") +final String apiPackagePath = apiPackage.toString().replaceAll("\\.", "/") + +String targetPackageJava = javaSourceDir + modGroupPath +String targetPackageScala = scalaSourceDir + modGroupPath +String targetPackageKotlin = kotlinSourceDir + modGroupPath +if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } -if(apiPackage) { - targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) +if (apiPackage) { + targetPackageJava = javaSourceDir + modGroupPath + "/" + apiPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath + targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath + if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } } -if(accessTransformersFile) { +if (accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(getFile(targetFile).exists() == false) { + if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } -if(usesMixins.toBoolean()) { - if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { - throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!") +if (usesMixins.toBoolean()) { + if (mixinsPackage.isEmpty()) { + throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") } - - targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/") + final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/") + + targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath + targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath + if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } - String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { - throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + if (!mixinPlugin.isEmpty()) { + String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" + String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" + String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".kt" + if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) + } } } -if(coreModClass) { - String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { - throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) +if (coreModClass) { + final String coreModPath = coreModClass.toString().replaceAll("\\.", "/") + String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java" + String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java" + String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".kt" + if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) } } @@ -153,56 +221,78 @@ configurations.all { } // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version -'git config core.fileMode false'.execute() +try { + 'git config core.fileMode false'.execute() +} +catch (Exception ignored) { + out.style(Style.Failure).println("git isn't installed at all") +} // Pulls version first from the VERSION env and then git tag String identifiedVersion +String versionOverride = System.getenv("VERSION") ?: null try { - String versionOverride = System.getenv("VERSION") ?: null identifiedVersion = versionOverride == null ? gitVersion() : versionOverride - version = minecraftVersion + "-" + identifiedVersion } -catch (Exception e) { - throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag, or the VERSION override must be set!"); +catch (Exception ignored) { + out.style(Style.Failure).text( + 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' + + 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + + 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)' + ) + versionOverride = 'NO-GIT-TAG-SET' + identifiedVersion = versionOverride +} +version = minecraftVersion + '-' + identifiedVersion +ext { + modVersion = identifiedVersion +} + +if (identifiedVersion == versionOverride) { + out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } group = modGroup -if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { +if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName -} -else { +} else { archivesBaseName = modId } - def arguments = [] def jvmArguments = [] -if(usesMixins.toBoolean()) { +if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { arguments += [ - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - jvmArguments += [ - "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" ] + if (usesMixinDebug.toBoolean()) { + jvmArguments += [ + "-Dmixin.debug.countInjections=true", + "-Dmixin.debug.verbose=true", + "-Dmixin.debug.export=true" + ] + } } minecraft { - version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion - runDir = "run" + version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion + runDir = 'run' if (replaceGradleTokenInFile) { - replaceIn replaceGradleTokenInFile - if(gradleTokenModId) { + for (f in replaceGradleTokenInFile.split(',')) { + replaceIn f + } + if (gradleTokenModId) { replace gradleTokenModId, modId } - if(gradleTokenModName) { + if (gradleTokenModName) { replace gradleTokenModName, modName } - if(gradleTokenVersion) { - replace gradleTokenVersion, versionDetails().lastTag + if (gradleTokenVersion) { + replace gradleTokenVersion, modVersion } - if(gradleTokenGroupName) { + if (gradleTokenGroupName) { replace gradleTokenGroupName, modGroup } } @@ -211,7 +301,7 @@ minecraft { args(arguments) jvmArgs(jvmArguments) - if(developmentEnvironmentUserName) { + if (developmentEnvironmentUserName) { args("--username", developmentEnvironmentUserName) } } @@ -222,8 +312,8 @@ minecraft { } } -if(file("addon.gradle").exists()) { - apply from: "addon.gradle" +if (file('addon.gradle').exists()) { + apply from: 'addon.gradle' } apply from: 'repositories.gradle' @@ -236,58 +326,67 @@ configurations { repositories { maven { - name = "Overmind forge repo mirror" - url = "https://gregtech.overminddl1.com/" + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { maven { - name = "sponge" - url = "https://repo.spongepowered.org/repository/maven-public" + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" } - maven { - url = "https://jitpack.io" + if (usesMixinDebug.toBoolean()) { + maven { + name = "Fabric Maven" + url = "https://maven.fabricmc.net/" + } } } } dependencies { - if(usesMixins.toBoolean()) { - annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3") - annotationProcessor("com.google.guava:guava:24.1.1-jre") - annotationProcessor("com.google.code.gson:gson:2.8.6") - annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT") - // using 0.8 to workaround a issue in 0.7 which fails mixin application - compile("com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH") { - // Mixin includes a lot of dependencies that are too up-to-date - exclude module: "launchwrapper" - exclude module: "guava" - exclude module: "gson" - exclude module: "commons-io" - exclude module: "log4j-core" + if (usesMixins.toBoolean()) { + annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') + annotationProcessor('com.google.guava:guava:24.1.1-jre') + annotationProcessor('com.google.code.gson:gson:2.8.6') + annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.3:processor') + if (usesMixinDebug.toBoolean()) { + runtimeOnly('org.jetbrains:intellij-fernflower:1.2.1.16') } - compile("com.github.GTNewHorizons:SpongeMixins:1.5.0") + } + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + compile('com.gtnewhorizon:gtnhmixins:2.1.3') } } apply from: 'dependencies.gradle' -def mixingConfigRefMap = "mixins." + modId + ".refmap.json" +def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { - if(usesMixins.toBoolean()) { - getFile("/src/main/resources/mixins." + modId + ".json").text = """{ + if (usesMixins.toBoolean()) { + def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") + if (!mixinConfigFile.exists()) { + def mixinPluginLine = "" + if(!mixinPlugin.isEmpty()) { + // We might not have a mixin plugin if we're using early/late mixins + mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ + } + + mixinConfigFile.text = """{ "required": true, - "minVersion": "0.7.11", - "package": "${modGroup}.${mixinsPackage}", - "plugin": "${modGroup}.${mixinPlugin}", + "minVersion": "0.8.5-GTNH", + "package": "${modGroup}.${mixinsPackage}",${mixinPluginLine} "refmap": "${mixingConfigRefMap}", "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8" + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] } - """ + } } } @@ -308,7 +407,10 @@ shadowJar { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] dependsOn(relocateShadowJar) } @@ -323,38 +425,38 @@ jar { attributes(getManifestAttributes()) } - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { dependsOn(shadowJar) enabled = false } } reobf { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { addExtraSrgFile mixinSrg } } afterEvaluate { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { tasks.compileJava { options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobf.srg}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", - // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code - "-XDenableSunApiLintControl", - "-XDignore.symbol.file" + "-AreobfSrgFile=${tasks.reobf.srg}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" ] } } } runClient { - if(developmentEnvironmentUserName) { + if (developmentEnvironmentUserName) { arguments += [ - "--username", - developmentEnvironmentUserName + "--username", + developmentEnvironmentUserName ] } @@ -369,66 +471,67 @@ runServer { tasks.withType(JavaExec).configureEach { javaLauncher.set( - javaToolchains.launcherFor { - languageVersion = projectJavaVersion - } + javaToolchains.launcherFor { + languageVersion = projectJavaVersion + } ) } -processResources -{ +processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version + exclude("spotless.gradle") // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { include 'mcmod.info' - // replace version and mcversion + // replace modVersion and minecraftVersion expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName + "modVersion": modVersion, + "modId": modId, + "modName": modName } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { from refMap } - // copy everything else, thats not the mcmod.info + // copy everything else that's not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' + exclude 'spotless.gradle' } } def getManifestAttributes() { def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) { + if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + if (accessTransformersFile) { + manifestAttributes += ["FMLAT": accessTransformersFile.toString()] } - if(coreModClass) { + if (coreModClass) { manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : "mixins." + modId + ".json", + "ForceLoadAsMod": !containsMixinsAndOrCoreModOnly.toBoolean() ] } return manifestAttributes } task sourcesJar(type: Jar) { - from (sourceSets.main.allJava) - from (file("$projectDir/LICENSE")) + from(sourceSets.main.allSource) + from(file("$projectDir/LICENSE")) getArchiveClassifier().set('sources') } @@ -447,7 +550,10 @@ task shadowDevJar(type: ShadowJar) { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { @@ -475,22 +581,22 @@ task devJar(type: Jar) { attributes(getManifestAttributes()) } - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { dependsOn(circularResolverJar) enabled = false } } task apiJar(type: Jar) { - from (sourceSets.main.allJava) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' + from(sourceSets.main.allSource) { + include modGroupPath + "/" + apiPackagePath + '/**' } - from (sourceSets.main.output) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' + from(sourceSets.main.output) { + include modGroupPath + "/" + apiPackagePath + '/**' } - from (sourceSets.main.resources.srcDirs) { + from(sourceSets.main.resources.srcDirs) { include("LICENSE") } @@ -498,32 +604,33 @@ task apiJar(type: Jar) { } artifacts { - if(!noPublishedSources) { + if (!noPublishedSources) { archives sourcesJar } archives devJar - if(apiPackage) { + if (apiPackage) { archives apiJar } } -// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), +// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), // and isn't strictly needed with the POM so just disable it. tasks.withType(GenerateModuleMetadata) { enabled = false } +// workaround variable hiding in pom processing +def projectConfigs = project.configurations -// publishing publishing { publications { maven(MavenPublication) { from components.java - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { artifact source: shadowJar, classifier: "" } - if(!noPublishedSources) { - artifact source: sourcesJar, classifier: "src" + if (!noPublishedSources) { + artifact source: sourcesJar, classifier: "sources" } artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage) { @@ -534,14 +641,24 @@ publishing { artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - - // Remove all non GTNH deps here. - // Original intention was to remove an invalid forgeBin being generated without a groupId (mandatory), but - // it also removes all of the MC deps + + // remove extra garbage from minecraft and minecraftDeps configuration pom.withXml { + def badArtifacts = [:].withDefault { [] as Set } + for (configuration in [ + projectConfigs.minecraft, + projectConfigs.minecraftDeps + ]) { + for (dependency in configuration.allDependencies) { + badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name + } + } + // example for specifying extra stuff to ignore + // badArtifacts["org.example.group"] += "artifactName" + Node pomNode = asNode() pomNode.dependencies.'*'.findAll() { - it.groupId.text() != 'com.github.GTNewHorizons' + badArtifacts[it.groupId.text()].contains(it.artifactId.text()) }.each() { it.parent().remove(it) } @@ -560,6 +677,113 @@ publishing { } } +if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { + apply plugin: 'com.modrinth.minotaur' + + File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") + + modrinth { + token = System.getenv("MODRINTH_TOKEN") + projectId = modrinthProjectId + versionNumber = identifiedVersion + versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" + changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" + uploadFile = jar + additionalFiles = getSecondaryArtifacts() + gameVersions = [minecraftVersion] + loaders = ["forge"] + debugMode = false + } + + if (modrinthRelations.size() != 0) { + String[] deps = modrinthRelations.split(";") + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(":") + String[] qual = parts[0].split("-") + addModrinthDep(qual[0], qual[1], parts[1]) + } + } + if (usesMixins.toBoolean()) { + addModrinthDep("required", "project", "gtnhmixins") + } + tasks.modrinth.dependsOn(build) + tasks.publish.dependsOn(tasks.modrinth) +} + +if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) { + apply plugin: 'com.matthewprenger.cursegradle' + + File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") + + curseforge { + apiKey = System.getenv("CURSEFORGE_TOKEN") + project { + id = curseForgeProjectId + if (changelogFile.exists()) { + changelogType = "markdown" + changelog = changelogFile + } + releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" + addGameVersion minecraftVersion + addGameVersion "Forge" + mainArtifact jar + for (artifact in getSecondaryArtifacts()) addArtifact artifact + } + + options { + javaIntegration = false + forgeGradleIntegration = false + debug = false + } + } + + if (curseForgeRelations.size() != 0) { + String[] deps = curseForgeRelations.split(";") + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(":") + addCurseForgeRelation(parts[0], parts[1]) + } + } + if (usesMixins.toBoolean()) { + addCurseForgeRelation("requiredDependency", "gtnhmixins") + } + tasks.curseforge.dependsOn(build) + tasks.publish.dependsOn(tasks.curseforge) +} + +def addModrinthDep(scope, type, name) { + com.modrinth.minotaur.dependencies.Dependency dep; + if (!(scope in ["required", "optional", "incompatible", "embedded"])) { + throw new Exception("Invalid modrinth dependency scope: " + scope) + } + switch (type) { + case "project": + dep = new ModDependency(name, scope) + break + case "version": + dep = new VersionDependency(name, scope) + break + default: + throw new Exception("Invalid modrinth dependency type: " + type) + } + project.modrinth.dependencies.add(dep) +} + +def addCurseForgeRelation(type, name) { + if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { + throw new Exception("Invalid CurseForge relation type: " + type) + } + CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact + CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation())) + rel."$type"(name) +} + // Updating task updateBuildScript { doLast { @@ -569,23 +793,60 @@ task updateBuildScript { } } -if (isNewBuildScriptVersionAvailable(projectDir.toString())) { +if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { performBuildScriptUpdate(projectDir.toString()) } else { - println("Build script update available! Run 'gradle updateBuildScript'") + out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") } } static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle") +} + +static URL exampleSettingsGradleUrl() { + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example") +} + +static URL exampleGitAttributesUrl() { + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes") +} + + +boolean verifyGitAttributes() { + def gitattributesFile = getFile(".gitattributes") + if (!gitattributesFile.exists()) { + println("Downloading default .gitattributes") + exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } } + exec { + workingDir '.' + commandLine 'git', 'add', '--renormalize', '.' + } + return true + } + return false +} + +boolean verifySettingsGradle() { + def settingsFile = getFile("settings.gradle") + if (!settingsFile.exists()) { + println("Downloading default settings.gradle") + exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } + return true + } + return false } boolean performBuildScriptUpdate(String projectDir) { if (isNewBuildScriptVersionAvailable(projectDir)) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } - print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + boolean settingsupdated = verifySettingsGradle() + settingsupdated = verifyGitAttributes() || settingsupdated + if (settingsupdated) + throw new GradleException("Settings has been updated, please re-run task.") return true } return false @@ -605,7 +866,7 @@ boolean isNewBuildScriptVersionAvailable(String projectDir) { static String getVersionHash(String buildScriptContent) { String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") - if(versionLine != null) { + if (versionLine != null) { return versionLine.split(": ").last() } return "" @@ -616,7 +877,103 @@ configure(updateBuildScript) { description = 'Updates the build script to the latest version' } -// Deobfuscation +// Parameter Deobfuscation + +task deobfParams { + doLast { + + String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" + String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" + String paramsCSV = "$mcpDir/params.csv" + + download.run { + src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" + dest mcpZIP + overwrite false + } + + if (!file(paramsCSV).exists()) { + println("Extracting MCP archive ...") + unzip(mcpZIP, mcpDir) + } + + println("Parsing params.csv ...") + Map params = new HashMap<>() + Files.lines(Paths.get(paramsCSV)).forEach { line -> + String[] cells = line.split(",") + if (cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) { + params.put(cells[0], cells[1]) + } + } + + out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!") + out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.") + } +} + +static int replaceParams(File file, Map params) { + int fileCount = 0 + + if (file.isDirectory()) { + for (File f : file.listFiles()) { + fileCount += replaceParams(f, params) + } + return fileCount + } + println("Visiting ${file.getName()} ...") + try { + String content = new String(Files.readAllBytes(file.toPath())) + int hash = content.hashCode() + params.forEach { key, value -> + content = content.replaceAll(key, value) + } + if (hash != content.hashCode()) { + Files.write(file.toPath(), content.getBytes("UTF-8")) + return 1 + } + } catch (Exception e) { + e.printStackTrace() + } + return 0 +} + +// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681) +static unzip(String zipFileName, String outputDir) { + byte[] buffer = new byte[16384] + ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName)) + ZipEntry zipEntry = zis.getNextEntry() + while (zipEntry != null) { + File newFile = new File(outputDir + File.separator, zipEntry.name) + if (zipEntry.isDirectory()) { + if (!newFile.isDirectory() && !newFile.mkdirs()) { + throw new IOException("Failed to create directory $newFile") + } + } else { + // fix for Windows-created archives + File parent = newFile.parentFile + if (!parent.isDirectory() && !parent.mkdirs()) { + throw new IOException("Failed to create directory $parent") + } + // write file content + FileOutputStream fos = new FileOutputStream(newFile) + int len = 0 + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len) + } + fos.close() + } + zipEntry = zis.getNextEntry() + } + zis.closeEntry() + zis.close() +} + +configure(deobfParams) { + group = 'forgegradle' + description = 'Rename all obfuscated parameter names inherited from Minecraft classes' +} + +// Dependency Deobfuscation def deobf(String sourceURL) { try { @@ -625,48 +982,63 @@ def deobf(String sourceURL) { //get rid of directories: int lastSlash = fileName.lastIndexOf("/") - if(lastSlash > 0) { + if (lastSlash > 0) { fileName = fileName.substring(lastSlash + 1) } //get rid of extension: - if(fileName.endsWith(".jar")) { + if (fileName.endsWith(".jar") || fileName.endsWith(".litemod")) { fileName = fileName.substring(0, fileName.lastIndexOf(".")) } String hostName = url.getHost() - if(hostName.startsWith("www.")) { + if (hostName.startsWith("www.")) { hostName = hostName.substring(4) } List parts = Arrays.asList(hostName.split("\\.")) Collections.reverse(parts) hostName = String.join(".", parts) - return deobf(sourceURL, hostName + "/" + fileName) - } catch(Exception e) { - return deobf(sourceURL, "deobf/" + String.valueOf(sourceURL.hashCode())) + return deobf(sourceURL, "$hostName/$fileName") + } catch (Exception e) { + return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } } -// The method above is to be prefered. Use this method if the filename is not at the end of the URL. -def deobf(String sourceURL, String fileName) { - String cacheDir = System.getProperty("user.home") + "/.gradle/caches/" - String bon2Dir = cacheDir + "forge_gradle/deobf" - String bon2File = bon2Dir + "/BON2-2.5.0.jar" - String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar" - String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar" - - if(file(deobfFile).exists()) { +// The method above is to be preferred. Use this method if the filename is not at the end of the URL. +def deobf(String sourceURL, String rawFileName) { + String bon2Version = "2.5.1" + String fileName = URLDecoder.decode(rawFileName, "UTF-8") + String cacheDir = "$project.gradle.gradleUserHomeDir/caches" + String bon2Dir = "$cacheDir/forge_gradle/deobf" + String bon2File = "$bon2Dir/BON2-${bon2Version}.jar" + String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" + String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar" + + if (file(deobfFile).exists()) { return files(deobfFile) } - download { - src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar' + String mappingsVer + String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' + if (remoteMappings) { + String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" + String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" + + zipMappings(mappingsZIP, remoteMappings, bon2Dir) + + mappingsVer = "snapshot_$id" + } else { + mappingsVer = "${channel}_$mappingsVersion" + } + + download.run { + src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar" dest bon2File quiet true overwrite false } - download { + download.run { src sourceURL dest obfFile quiet true @@ -674,22 +1046,71 @@ def deobf(String sourceURL, String fileName) { } exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch' + commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' workingDir bon2Dir - standardOutput = new ByteArrayOutputStream() + standardOutput = new FileOutputStream("${deobfFile}.log") } return files(deobfFile) } +def zipMappings(String zipPath, String url, String bon2Dir) { + File zipFile = new File(zipPath) + if (zipFile.exists()) { + return + } + + String fieldsCache = "$bon2Dir/data/fields.csv" + String methodsCache = "$bon2Dir/data/methods.csv" + + download.run { + src "${url}fields.csv" + dest fieldsCache + quiet true + } + download.run { + src "${url}methods.csv" + dest methodsCache + quiet true + } + + zipFile.getParentFile().mkdirs() + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)) + + zos.putNextEntry(new ZipEntry("fields.csv")) + Files.copy(Paths.get(fieldsCache), zos) + zos.closeEntry() + + zos.putNextEntry(new ZipEntry("methods.csv")) + Files.copy(Paths.get(methodsCache), zos) + zos.closeEntry() + + zos.close() +} + // Helper methods def checkPropertyExists(String propertyName) { - if (project.hasProperty(propertyName) == false) { + if (!project.hasProperty(propertyName)) { throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") } } +def propertyDefaultIfUnset(String propertyName, defaultValue) { + if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { + project.ext.setProperty(propertyName, defaultValue) + } +} + def getFile(String relativePath) { return new File(projectDir, relativePath) } + +def getSecondaryArtifacts() { + // Because noPublishedSources from the beginning of the script is somehow not visible here... + boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false + def secondaryArtifacts = [devJar] + if (!noPublishedSources) secondaryArtifacts += [sourcesJar] + if (apiPackage) secondaryArtifacts += [apiJar] + return secondaryArtifacts +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..93c852a --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +plugins { + id 'com.diffplug.blowdryerSetup' version '1.6.0' +} + +apply plugin: 'com.diffplug.blowdryerSetup' + +blowdryerSetup { + github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.5') + //devLocal '.' // Use this when testing config updates locally +} From fa6fea68435298ea68267bf725c79b63e2787c6e Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Thu, 5 Jan 2023 11:49:32 +0000 Subject: [PATCH 161/219] Apply spotless --- .../java/codechicken/lib/asm/ASMBlock.java | 64 +- .../java/codechicken/lib/asm/ASMHelper.java | 142 ++-- .../java/codechicken/lib/asm/ASMInit.java | 6 +- .../java/codechicken/lib/asm/ASMReader.java | 46 +- .../codechicken/lib/asm/CC_ClassWriter.java | 31 +- .../lib/asm/ClassHeirachyManager.java | 67 +- .../lib/asm/ImportantInsnVisitor.java | 8 +- .../codechicken/lib/asm/InsnComparator.java | 54 +- .../codechicken/lib/asm/InsnListSection.java | 93 +-- .../lib/asm/LocalVariablesSorterVisitor.java | 48 +- .../lib/asm/ModularASMTransformer.java | 98 +-- .../java/codechicken/lib/asm/ObfMapping.java | 149 ++-- .../java/codechicken/lib/colour/Colour.java | 70 +- .../codechicken/lib/colour/ColourARGB.java | 25 +- .../codechicken/lib/colour/ColourRGBA.java | 8 +- .../lib/colour/CustomGradient.java | 29 +- .../codechicken/lib/config/ConfigFile.java | 23 +- .../codechicken/lib/config/ConfigTag.java | 54 +- .../lib/config/ConfigTagParent.java | 57 +- .../lib/config/DefaultingConfigFile.java | 9 +- .../lib/config/SimpleProperties.java | 140 ++-- .../codechicken/lib/data/MCDataInput.java | 20 +- .../lib/data/MCDataInputStream.java | 15 +- .../codechicken/lib/data/MCDataOutput.java | 19 +- .../lib/data/MCDataOutputStream.java | 13 +- .../lib/data/MCDataOutputWrapper.java | 23 +- .../java/codechicken/lib/gui/Canvas9Seg.java | 35 +- .../java/codechicken/lib/gui/GuiDraw.java | 53 +- .../lib/inventory/ContainerExtended.java | 129 ++-- .../lib/inventory/ContainerSynchronised.java | 13 +- .../lib/inventory/IContainerSyncVar.java | 9 +- .../lib/inventory/IntegerSync.java | 21 +- .../lib/inventory/InventoryCopy.java | 80 +- .../lib/inventory/InventoryNBT.java | 68 +- .../lib/inventory/InventoryRange.java | 52 +- .../lib/inventory/InventorySimple.java | 89 +-- .../lib/inventory/InventoryUtils.java | 101 ++- .../codechicken/lib/inventory/ItemKey.java | 23 +- .../codechicken/lib/inventory/SlotDummy.java | 64 +- .../lib/inventory/SlotDummyOutput.java | 11 +- .../lib/inventory/SlotHandleClicks.java | 6 +- .../java/codechicken/lib/lighting/LC.java | 11 +- .../codechicken/lib/lighting/LightMatrix.java | 77 +- .../codechicken/lib/lighting/LightModel.java | 37 +- .../lib/lighting/PlanarLightMatrix.java | 8 +- .../lib/lighting/PlanarLightModel.java | 6 +- .../lib/lighting/SimpleBrightnessModel.java | 6 +- .../java/codechicken/lib/math/MathHelper.java | 127 ++-- .../lib/packet/ICustomPacketTile.java | 3 +- .../codechicken/lib/packet/PacketCustom.java | 127 ++-- .../lib/raytracer/ExtendedMOP.java | 41 +- .../lib/raytracer/IndexedCuboid6.java | 10 +- .../codechicken/lib/raytracer/RayTracer.java | 139 ++-- .../codechicken/lib/render/BlockRenderer.java | 83 +- .../java/codechicken/lib/render/CCModel.java | 715 ++++++++---------- .../lib/render/CCModelLibrary.java | 94 +-- .../lib/render/CCRenderPipeline.java | 65 +- .../codechicken/lib/render/CCRenderState.java | 114 ++- .../lib/render/ColourMultiplier.java | 5 +- .../lib/render/EntityDigIconFX.java | 118 +-- .../codechicken/lib/render/FontUtils.java | 65 +- .../codechicken/lib/render/IFaceRenderer.java | 3 +- .../lib/render/ManagedTextureFX.java | 26 +- .../lib/render/PlaceholderTexture.java | 3 +- .../codechicken/lib/render/QBImporter.java | 442 +++++------ .../codechicken/lib/render/RenderUtils.java | 277 ++++--- .../codechicken/lib/render/ShaderProgram.java | 140 ++-- .../lib/render/SpriteSheetManager.java | 130 ++-- .../lib/render/TextureDataHolder.java | 21 +- .../codechicken/lib/render/TextureFX.java | 6 +- .../lib/render/TextureSpecial.java | 53 +- .../codechicken/lib/render/TextureUtils.java | 49 +- .../java/codechicken/lib/render/Vertex5.java | 9 +- .../java/codechicken/lib/render/uv/UV.java | 9 +- .../codechicken/lib/render/uv/UVRotation.java | 14 +- .../lib/render/uv/UVTransformation.java | 9 +- .../lib/render/uv/UVTransformationList.java | 77 +- .../lib/render/uv/UVTranslation.java | 5 +- .../codechicken/lib/tool/LibDownloader.java | 51 +- .../lib/tool/MCStripTransformer.java | 13 +- src/main/java/codechicken/lib/tool/Main.java | 5 +- .../lib/tool/StripClassLoader.java | 16 +- .../java/codechicken/lib/tool/ToolMain.java | 26 +- .../lib/tool/module/JOptModule.java | 20 +- .../lib/tool/module/ModuleQBConverter.java | 60 +- .../java/codechicken/lib/util/LangProxy.java | 9 +- .../java/codechicken/lib/vec/AxisCycle.java | 48 +- .../java/codechicken/lib/vec/BlockCoord.java | 210 +++-- .../java/codechicken/lib/vec/Cuboid6.java | 217 +++--- .../java/codechicken/lib/vec/CuboidCoord.java | 106 +-- .../codechicken/lib/vec/ITransformation.java | 3 +- .../IrreversibleTransformationException.java | 15 +- src/main/java/codechicken/lib/vec/Line3.java | 38 +- .../java/codechicken/lib/vec/Matrix4.java | 225 +++--- src/main/java/codechicken/lib/vec/Quat.java | 77 +- .../java/codechicken/lib/vec/Rectangle4i.java | 69 +- .../lib/vec/RedundantTransformation.java | 34 +- .../java/codechicken/lib/vec/Rotation.java | 347 +++++---- src/main/java/codechicken/lib/vec/Scale.java | 12 +- src/main/java/codechicken/lib/vec/SwapYZ.java | 22 +- .../codechicken/lib/vec/Transformation.java | 7 +- .../lib/vec/TransformationList.java | 154 ++-- .../java/codechicken/lib/vec/Translation.java | 12 +- .../lib/vec/VariableTransformation.java | 23 +- .../java/codechicken/lib/vec/Vector3.java | 364 ++++----- .../codechicken/lib/world/ChunkExtension.java | 81 +- .../codechicken/lib/world/IChunkLoadTile.java | 3 +- .../lib/world/TileChunkLoadHook.java | 18 +- .../codechicken/lib/world/WorldExtension.java | 94 +-- .../lib/world/WorldExtensionInstantiator.java | 11 +- .../lib/world/WorldExtensionManager.java | 185 ++--- 111 files changed, 3415 insertions(+), 4349 deletions(-) diff --git a/src/main/java/codechicken/lib/asm/ASMBlock.java b/src/main/java/codechicken/lib/asm/ASMBlock.java index c355437..5ab61a9 100644 --- a/src/main/java/codechicken/lib/asm/ASMBlock.java +++ b/src/main/java/codechicken/lib/asm/ASMBlock.java @@ -1,20 +1,18 @@ package codechicken.lib.asm; +import static org.objectweb.asm.tree.AbstractInsnNode.*; + import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; +import java.util.*; +import java.util.Map.Entry; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; -import java.util.*; -import java.util.Map.Entry; - -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -public class ASMBlock -{ +public class ASMBlock { public InsnListSection list; private BiMap labels; @@ -37,8 +35,7 @@ public ASMBlock() { public LabelNode getOrAdd(String s) { LabelNode l = get(s); - if (l == null) - labels.put(s, l = new LabelNode()); + if (l == null) labels.put(s, l = new LabelNode()); return l; } @@ -51,8 +48,8 @@ public void replaceLabels(Map labelMap, Set use switch (insn.getType()) { case LABEL: AbstractInsnNode insn2 = insn.clone(labelMap); - if (insn2 == insn)//identity mapping - continue; + if (insn2 == insn) // identity mapping + continue; if (usedLabels.contains(insn2)) throw new IllegalStateException("LabelNode cannot be a part of two InsnLists"); list.replace(insn, insn2); @@ -64,10 +61,9 @@ public void replaceLabels(Map labelMap, Set use list.replace(insn, insn.clone(labelMap)); } - for(Entry entry : labelMap.entrySet()) { + for (Entry entry : labelMap.entrySet()) { String key = labels.inverse().get(entry.getKey()); - if(key != null) - labels.put(key, entry.getValue()); + if (key != null) labels.put(key, entry.getValue()); } } @@ -77,8 +73,7 @@ public void replaceLabels(Map labelMap) { public void replaceLabel(String s, LabelNode l) { LabelNode old = get(s); - if (old != null) - replaceLabels(ImmutableMap.of(old, l)); + if (old != null) replaceLabels(ImmutableMap.of(old, l)); } /** @@ -86,20 +81,17 @@ public void replaceLabel(String s, LabelNode l) { * @return this */ public ASMBlock mergeLabels(ASMBlock other) { - if(labels.isEmpty() || other.labels.isEmpty()) - return this; + if (labels.isEmpty() || other.labels.isEmpty()) return this; - //common labels, give them our nodes + // common labels, give them our nodes HashMap labelMap = list.identityLabelMap(); - for(Entry entry : other.labels.entrySet()) { + for (Entry entry : other.labels.entrySet()) { LabelNode old = labels.get(entry.getKey()); - if(old != null) - labelMap.put(old, entry.getValue()); + if (old != null) labelMap.put(old, entry.getValue()); } HashSet usedLabels = new HashSet(); for (AbstractInsnNode insn = other.list.list.getFirst(); insn != null; insn = insn.getNext()) - if(insn.getType() == LABEL) - usedLabels.add((LabelNode) insn); + if (insn.getType() == LABEL) usedLabels.add((LabelNode) insn); replaceLabels(labelMap, usedLabels); return this; @@ -118,15 +110,14 @@ public ASMBlock copy() { BiMap labels = HashBiMap.create(); Map labelMap = list.cloneLabels(); - for(Entry entry : this.labels.entrySet()) + for (Entry entry : this.labels.entrySet()) labels.put(entry.getKey(), labelMap.get(entry.getValue())); return new ASMBlock(list.copy(labelMap), labels); } public ASMBlock applyLabels(InsnListSection list2) { - if(labels.isEmpty()) - return new ASMBlock(list2); + if (labels.isEmpty()) return new ASMBlock(list2); Set cFlowLabels1 = labels.values(); Set cFlowLabels2 = InsnComparator.getControlFlowLabels(list2); @@ -134,23 +125,23 @@ public ASMBlock applyLabels(InsnListSection list2) { HashMap labelMap = new HashMap(); - for(int i = 0, k = 0; i < list.size() && k < list2.size(); ) { + for (int i = 0, k = 0; i < list.size() && k < list2.size(); ) { AbstractInsnNode insn1 = list.get(i); - if(!InsnComparator.insnImportant(insn1, cFlowLabels1)) { + if (!InsnComparator.insnImportant(insn1, cFlowLabels1)) { i++; continue; } AbstractInsnNode insn2 = list2.get(k); - if(!InsnComparator.insnImportant(insn2, cFlowLabels2)) { + if (!InsnComparator.insnImportant(insn2, cFlowLabels2)) { k++; continue; } - if(insn1.getOpcode() != insn2.getOpcode()) - throw new IllegalArgumentException("Lists do not match:\n"+list+"\n\n"+list2); + if (insn1.getOpcode() != insn2.getOpcode()) + throw new IllegalArgumentException("Lists do not match:\n" + list + "\n\n" + list2); - switch(insn1.getType()) { + switch (insn1.getType()) { case LABEL: labelMap.put((LabelNode) insn1, (LabelNode) insn2); break; @@ -158,10 +149,11 @@ public ASMBlock applyLabels(InsnListSection list2) { labelMap.put(((JumpInsnNode) insn1).label, ((JumpInsnNode) insn2).label); break; } - i++; k++; + i++; + k++; } - for(Entry entry : labels.entrySet()) + for (Entry entry : labels.entrySet()) block.labels.put(entry.getKey(), labelMap.get(entry.getValue())); return block; @@ -170,4 +162,4 @@ public ASMBlock applyLabels(InsnListSection list2) { public InsnList rawListCopy() { return list.copy().list; } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/asm/ASMHelper.java b/src/main/java/codechicken/lib/asm/ASMHelper.java index 85526db..ce68788 100644 --- a/src/main/java/codechicken/lib/asm/ASMHelper.java +++ b/src/main/java/codechicken/lib/asm/ASMHelper.java @@ -2,6 +2,13 @@ import codechicken.lib.config.ConfigFile; import codechicken.lib.config.DefaultingConfigFile; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; @@ -12,48 +19,35 @@ import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceClassVisitor; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class ASMHelper -{ +public class ASMHelper { public static ConfigFile config = loadConfig(); public static Logger logger = LogManager.getLogger("CCL ASM"); private static ConfigFile loadConfig() { - try {//weak reference for environments without FML - File mcDir = (File)((Object[])Class.forName("cpw.mods.fml.relauncher.FMLInjectionData").getMethod("data").invoke(null))[6]; + try { // weak reference for environments without FML + File mcDir = (File) ((Object[]) Class.forName("cpw.mods.fml.relauncher.FMLInjectionData") + .getMethod("data") + .invoke(null)) + [6]; File file = new File(mcDir, "config/CodeChickenLib.cfg"); - if(ObfMapping.obfuscated) - return new DefaultingConfigFile(file); - else - return new ConfigFile(file).setComment("CodeChickenLib development configuration file."); + if (ObfMapping.obfuscated) return new DefaultingConfigFile(file); + else return new ConfigFile(file).setComment("CodeChickenLib development configuration file."); } catch (Exception ignored) { - return null;//no config for these systems + return null; // no config for these systems } } - public static interface Acceptor - { + public static interface Acceptor { public void accept(ClassVisitor cv) throws IOException; } public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) { - for (MethodNode mnode : cnode.methods) - if (methodmap.matches(mnode)) - return mnode; + for (MethodNode mnode : cnode.methods) if (methodmap.matches(mnode)) return mnode; return null; } public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) { - for (FieldNode fnode : cnode.fields) - if (fieldmap.matches(fnode)) - return fnode; + for (FieldNode fnode : cnode.fields) if (fieldmap.matches(fnode)) return fnode; return null; } @@ -86,23 +80,24 @@ public static InsnList cloneInsnList(Map labelMap, InsnLis return new InsnListSection(list).copy(labelMap).list; } - public static List cloneTryCatchBlocks(Map labelMap, List tcblocks) { + public static List cloneTryCatchBlocks( + Map labelMap, List tcblocks) { ArrayList clone = new ArrayList(); for (TryCatchBlockNode node : tcblocks) clone.add(new TryCatchBlockNode( - labelMap.get(node.start), - labelMap.get(node.end), - labelMap.get(node.handler), - node.type)); + labelMap.get(node.start), labelMap.get(node.end), labelMap.get(node.handler), node.type)); return clone; } - public static List cloneLocals(Map labelMap, List locals) { + public static List cloneLocals( + Map labelMap, List locals) { ArrayList clone = new ArrayList(locals.size()); for (LocalVariableNode node : locals) clone.add(new LocalVariableNode( - node.name, node.desc, node.signature, + node.name, + node.desc, + node.signature, labelMap.get(node.start), labelMap.get(node.end), node.index)); @@ -114,8 +109,7 @@ public static void copy(MethodNode src, MethodNode dst) { Map labelMap = cloneLabels(src.instructions); dst.instructions = cloneInsnList(labelMap, src.instructions); dst.tryCatchBlocks = cloneTryCatchBlocks(labelMap, src.tryCatchBlocks); - if (src.localVariables != null) - dst.localVariables = cloneLocals(labelMap, src.localVariables); + if (src.localVariables != null) dst.localVariables = cloneLocals(labelMap, src.localVariables); dst.visibleAnnotations = src.visibleAnnotations; dst.invisibleAnnotations = src.invisibleAnnotations; dst.visitMaxs(src.maxStack, src.maxLocals); @@ -130,7 +124,8 @@ public static int getLocal(List list, String name) { for (LocalVariableNode node : list) { if (node.name.equals(name)) { if (found >= 0) - throw new RuntimeException("Duplicate local variable: " + name + " not coded to handle this scenario."); + throw new RuntimeException( + "Duplicate local variable: " + name + " not coded to handle this scenario."); found = node.index; } @@ -140,24 +135,21 @@ public static int getLocal(List list, String name) { public static void replaceMethod(MethodNode original, MethodNode replacement) { original.instructions.clear(); - if (original.localVariables != null) - original.localVariables.clear(); - if (original.tryCatchBlocks != null) - original.tryCatchBlocks.clear(); + if (original.localVariables != null) original.localVariables.clear(); + if (original.tryCatchBlocks != null) original.tryCatchBlocks.clear(); replacement.accept(original); } - public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals, boolean textify) { + public static void dump( + Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals, boolean textify) { try { - if(!file.getParentFile().exists()) - file.getParentFile().mkdirs(); - if(!file.exists()) - file.createNewFile(); + if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); + if (!file.exists()) file.createNewFile(); PrintWriter pout = new PrintWriter(file); ClassVisitor cv = new TraceClassVisitor(null, textify ? new Textifier() : new ASMifier(), pout); - if(filterImportant) cv = new ImportantInsnVisitor(cv); - if(sortLocals) cv = new LocalVariablesSorterVisitor(cv); + if (filterImportant) cv = new ImportantInsnVisitor(cv); + if (sortLocals) cv = new LocalVariablesSorterVisitor(cv); acceptor.accept(cv); pout.close(); } catch (IOException e) { @@ -166,36 +158,50 @@ public static void dump(Acceptor acceptor, File file, boolean filterImportant, b } public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals) { - dump(acceptor, file, filterImportant, sortLocals, config.getTag("textify").getBooleanValue(true)); + dump( + acceptor, + file, + filterImportant, + sortLocals, + config.getTag("textify").getBooleanValue(true)); } public static void dump(final byte[] bytes, File file, boolean filterImportant, boolean sortLocals) { - dump(new Acceptor() - { - @Override - public void accept(ClassVisitor cv) { - new ClassReader(bytes).accept(cv, ClassReader.EXPAND_FRAMES); - } - }, file, filterImportant, sortLocals); + dump( + new Acceptor() { + @Override + public void accept(ClassVisitor cv) { + new ClassReader(bytes).accept(cv, ClassReader.EXPAND_FRAMES); + } + }, + file, + filterImportant, + sortLocals); } public static void dump(final InputStream is, File file, boolean filterImportant, boolean sortLocals) { - dump(new Acceptor() - { - @Override - public void accept(ClassVisitor cv) throws IOException { - new ClassReader(is).accept(cv, ClassReader.EXPAND_FRAMES); - } - }, file, filterImportant, sortLocals); + dump( + new Acceptor() { + @Override + public void accept(ClassVisitor cv) throws IOException { + new ClassReader(is).accept(cv, ClassReader.EXPAND_FRAMES); + } + }, + file, + filterImportant, + sortLocals); } public static void dump(final ClassNode cnode, File file, boolean filterImportant, boolean sortLocals) { - dump(new Acceptor() - { - @Override - public void accept(ClassVisitor cv) { - cnode.accept(cv); - } - }, file, filterImportant, sortLocals); + dump( + new Acceptor() { + @Override + public void accept(ClassVisitor cv) { + cnode.accept(cv); + } + }, + file, + filterImportant, + sortLocals); } } diff --git a/src/main/java/codechicken/lib/asm/ASMInit.java b/src/main/java/codechicken/lib/asm/ASMInit.java index ebc007f..a76db93 100644 --- a/src/main/java/codechicken/lib/asm/ASMInit.java +++ b/src/main/java/codechicken/lib/asm/ASMInit.java @@ -5,11 +5,11 @@ /** * Initialisation class for using this package. Call this on coremod load */ -public class ASMInit -{ +public class ASMInit { private static boolean initialised = false; + public static void init() { - if(!initialised) { + if (!initialised) { Launch.classLoader.addTransformerExclusion("codechicken.lib.asm"); Launch.classLoader.addTransformerExclusion("codechicken.lib.config"); initialised = true; diff --git a/src/main/java/codechicken/lib/asm/ASMReader.java b/src/main/java/codechicken/lib/asm/ASMReader.java index e5ca2d2..f7e6343 100644 --- a/src/main/java/codechicken/lib/asm/ASMReader.java +++ b/src/main/java/codechicken/lib/asm/ASMReader.java @@ -1,18 +1,16 @@ package codechicken.lib.asm; -import org.objectweb.asm.tree.*; +import static org.objectweb.asm.Opcodes.*; +import static org.objectweb.asm.tree.AbstractInsnNode.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.*; +import org.objectweb.asm.tree.*; -import static org.objectweb.asm.Opcodes.*; -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -public class ASMReader -{ +public class ASMReader { public static Map opCodes = new HashMap(); public static byte[] TYPE; @@ -175,14 +173,13 @@ public class ASMReader opCodes.put("IFNULL", IFNULL); opCodes.put("IFNONNULL", IFNONNULL); - //derived from classWriter, mapped to AbstractInsnNode + // derived from classWriter, mapped to AbstractInsnNode TYPE = new byte[200]; String s = "AAAAAAAAAAAAAAAABBJ__CCCCC____________________AAAAAAAACC" + "CCC____________________AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHCLMAA" + "AAAAEEEEFFFFGDBDAADDAA_NHH"; - for (int i = 0; i < s.length(); i++) - TYPE[i] = (byte) (s.charAt(i) - 'A'); + for (int i = 0; i < s.length(); i++) TYPE[i] = (byte) (s.charAt(i) - 'A'); } public static Map loadResource(String res) { @@ -217,10 +214,8 @@ public static Map loadResource(InputStream in, String res) { if (i_opcode == null) { if (split[0].equals("LINENUMBER")) insn = new LineNumberNode(Integer.parseInt(split[1]), block.getOrAdd(split[2])); - else if (split[0].startsWith("L")) - insn = block.getOrAdd(split[0]); - else - throw new Exception("Unknown opcode " + split[0]); + else if (split[0].startsWith("L")) insn = block.getOrAdd(split[0]); + else throw new Exception("Unknown opcode " + split[0]); } else { int opcode = i_opcode; switch (TYPE[opcode]) { @@ -239,9 +234,10 @@ else if (split[0].startsWith("L")) case FIELD_INSN: case METHOD_INSN: StringBuilder sb = new StringBuilder(); - for (int i = 1; i < split.length; i++) - sb.append(split[i]); - insn = ObfMapping.fromDesc(sb.toString()).toClassloading().toInsn(opcode); + for (int i = 1; i < split.length; i++) sb.append(split[i]); + insn = ObfMapping.fromDesc(sb.toString()) + .toClassloading() + .toInsn(opcode); break; case INVOKE_DYNAMIC_INSN: throw new Exception("Found INVOKEDYNAMIC while reading"); @@ -250,20 +246,16 @@ else if (split[0].startsWith("L")) break; case LDC_INSN: String cst = split[1]; - if(cst.equals("*")) - insn = new LdcInsnNode(null); - else if (cst.endsWith("\"")) - insn = new LdcInsnNode(cst.substring(1, cst.length() - 1)); + if (cst.equals("*")) insn = new LdcInsnNode(null); + else if (cst.endsWith("\"")) insn = new LdcInsnNode(cst.substring(1, cst.length() - 1)); else if (cst.endsWith("L")) insn = new LdcInsnNode(Long.valueOf(cst.substring(0, cst.length() - 1))); else if (cst.endsWith("F")) insn = new LdcInsnNode(Float.valueOf(cst.substring(0, cst.length() - 1))); else if (cst.endsWith("D")) insn = new LdcInsnNode(Double.valueOf(cst.substring(0, cst.length() - 1))); - else if (cst.contains(".")) - insn = new LdcInsnNode(Double.valueOf(cst)); - else - insn = new LdcInsnNode(Integer.valueOf(cst)); + else if (cst.contains(".")) insn = new LdcInsnNode(Double.valueOf(cst)); + else insn = new LdcInsnNode(Integer.valueOf(cst)); break; case IINC_INSN: insn = new IincInsnNode(opcode, Integer.parseInt(split[1])); @@ -281,11 +273,9 @@ else if (cst.contains(".")) } } - if (insn != null) - block.list.add(insn); + if (insn != null) block.list.add(insn); } catch (Exception e) { - System.err.println("Error while reading ASM Block " + - current + " from " + res + ", line: " + line); + System.err.println("Error while reading ASM Block " + current + " from " + res + ", line: " + line); e.printStackTrace(); } } diff --git a/src/main/java/codechicken/lib/asm/CC_ClassWriter.java b/src/main/java/codechicken/lib/asm/CC_ClassWriter.java index 1969dfe..74c86d2 100644 --- a/src/main/java/codechicken/lib/asm/CC_ClassWriter.java +++ b/src/main/java/codechicken/lib/asm/CC_ClassWriter.java @@ -2,36 +2,27 @@ import org.objectweb.asm.ClassWriter; - -public class CC_ClassWriter extends ClassWriter -{ +public class CC_ClassWriter extends ClassWriter { private final boolean runtime; - - public CC_ClassWriter(int flags) - { + + public CC_ClassWriter(int flags) { this(flags, false); } - - public CC_ClassWriter(int flags, boolean runtime) - { + + public CC_ClassWriter(int flags, boolean runtime) { super(flags); this.runtime = runtime; } - + @Override - protected String getCommonSuperClass(String type1, String type2) - { + protected String getCommonSuperClass(String type1, String type2) { String c = type1.replace('/', '.'); String d = type2.replace('/', '.'); - if(ClassHeirachyManager.classExtends(d, c)) - return type1; - if(ClassHeirachyManager.classExtends(c, d)) - return type2; - do - { + if (ClassHeirachyManager.classExtends(d, c)) return type1; + if (ClassHeirachyManager.classExtends(c, d)) return type2; + do { c = ClassHeirachyManager.getSuperClass(c, runtime); - } - while(!ClassHeirachyManager.classExtends(d, c)); + } while (!ClassHeirachyManager.classExtends(d, c)); return c.replace('.', '/'); } } diff --git a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java index 562bd9d..837a65f 100644 --- a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java +++ b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java @@ -1,26 +1,23 @@ package codechicken.lib.asm; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; import org.objectweb.asm.tree.ClassNode; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; - /** * This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed evaluation up slightly by automatically caching superclasses when they are first loaded. */ -public class ClassHeirachyManager implements IClassTransformer -{ +public class ClassHeirachyManager implements IClassTransformer { static { ASMInit.init(); } - public static class SuperCache - { + public static class SuperCache { String superclass; public HashSet parents = new HashSet(); private boolean flattened; @@ -30,8 +27,7 @@ public void add(String parent) { } public void flatten() { - if (flattened) - return; + if (flattened) return; for (String s : new ArrayList(parents)) { SuperCache c = declareClass(s); @@ -55,7 +51,9 @@ public static String toKey(String name) { public static String unKey(String name) { if (ObfMapping.obfuscated) - name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); + name = FMLDeobfuscatingRemapper.INSTANCE + .unmap(name.replace('.', '/')) + .replace('/', '.'); return name; } @@ -68,12 +66,11 @@ public static boolean classExtends(String name, String superclass) { name = toKey(name); superclass = toKey(superclass); - if (name.equals(superclass)) - return true; + if (name.equals(superclass)) return true; SuperCache cache = declareClass(name); - if (cache == null)//just can't handle this - return false; + if (cache == null) // just can't handle this + return false; cache.flatten(); return cache.parents.contains(superclass); @@ -83,19 +80,15 @@ private static SuperCache declareClass(String name) { name = toKey(name); SuperCache cache = superclasses.get(name); - if (cache != null) - return cache; + if (cache != null) return cache; try { byte[] bytes = cl.getClassBytes(unKey(name)); - if (bytes != null) - cache = declareASM(bytes); + if (bytes != null) cache = declareASM(bytes); } catch (Exception e) { } - if (cache != null) - return cache; - + if (cache != null) return cache; try { cache = declareReflection(name); @@ -109,16 +102,12 @@ private static SuperCache declareReflection(String name) throws ClassNotFoundExc Class aclass = Class.forName(name); SuperCache cache = getOrCreateCache(name); - if (aclass.isInterface()) - cache.superclass = "java.lang.Object"; - else if (name.equals("java.lang.Object")) - return cache; - else - cache.superclass = toKey(aclass.getSuperclass().getName()); + if (aclass.isInterface()) cache.superclass = "java.lang.Object"; + else if (name.equals("java.lang.Object")) return cache; + else cache.superclass = toKey(aclass.getSuperclass().getName()); cache.add(cache.superclass); - for (Class iclass : aclass.getInterfaces()) - cache.add(toKey(iclass.getName())); + for (Class iclass : aclass.getInterfaces()) cache.add(toKey(iclass.getName())); return cache; } @@ -130,40 +119,34 @@ private static SuperCache declareASM(byte[] bytes) { SuperCache cache = getOrCreateCache(name); cache.superclass = toKey(node.superName.replace('/', '.')); cache.add(cache.superclass); - for (String iclass : node.interfaces) - cache.add(toKey(iclass.replace('/', '.'))); + for (String iclass : node.interfaces) cache.add(toKey(iclass.replace('/', '.'))); return cache; } @Override public byte[] transform(String name, String tname, byte[] bytes) { - if (bytes == null) - return null; + if (bytes == null) return null; - if (!superclasses.containsKey(tname)) - declareASM(bytes); + if (!superclasses.containsKey(tname)) declareASM(bytes); return bytes; } public static SuperCache getOrCreateCache(String name) { SuperCache cache = superclasses.get(name); - if (cache == null) - superclasses.put(name, cache = new SuperCache()); + if (cache == null) superclasses.put(name, cache = new SuperCache()); return cache; } public static String getSuperClass(String name, boolean runtime) { name = toKey(name); SuperCache cache = declareClass(name); - if (cache == null) - return "java.lang.Object"; + if (cache == null) return "java.lang.Object"; cache.flatten(); String s = cache.superclass; - if (!runtime) - s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s); + if (!runtime) s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s); return s; } } diff --git a/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java b/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java index 6af770f..9368bfc 100644 --- a/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java +++ b/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java @@ -5,10 +5,8 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.MethodNode; -public class ImportantInsnVisitor extends ClassVisitor -{ - public class ImportantInsnMethodVisitor extends MethodVisitor - { +public class ImportantInsnVisitor extends ClassVisitor { + public class ImportantInsnMethodVisitor extends MethodVisitor { MethodVisitor delegate; public ImportantInsnMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) { @@ -19,7 +17,7 @@ public ImportantInsnMethodVisitor(int access, String name, String desc, String s @Override public void visitEnd() { super.visitEnd(); - MethodNode mnode = (MethodNode)mv; + MethodNode mnode = (MethodNode) mv; mnode.instructions = InsnComparator.getImportantList(mnode.instructions); mnode.accept(delegate); } diff --git a/src/main/java/codechicken/lib/asm/InsnComparator.java b/src/main/java/codechicken/lib/asm/InsnComparator.java index 5ec9cf0..238651f 100644 --- a/src/main/java/codechicken/lib/asm/InsnComparator.java +++ b/src/main/java/codechicken/lib/asm/InsnComparator.java @@ -1,15 +1,13 @@ package codechicken.lib.asm; +import static org.objectweb.asm.tree.AbstractInsnNode.*; + import com.google.common.base.Function; import com.google.common.collect.Maps; -import org.objectweb.asm.tree.*; - import java.util.*; +import org.objectweb.asm.tree.*; -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -public class InsnComparator -{ +public class InsnComparator { public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2) { return insn1.var == -1 || insn2.var == -1 || insn1.var == insn2.var; } @@ -39,8 +37,7 @@ public static boolean intInsnEqual(IntInsnNode node1, IntInsnNode node2) { } public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) { - if (node1.getOpcode() != node2.getOpcode()) - return false; + if (node1.getOpcode() != node2.getOpcode()) return false; switch (node2.getType()) { case VAR_INSN: @@ -63,7 +60,7 @@ public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) } public static boolean insnImportant(AbstractInsnNode insn, Set controlFlowLabels) { - switch(insn.getType()) { + switch (insn.getType()) { case LINE: case FRAME: return false; @@ -89,14 +86,12 @@ public static Set getControlFlowLabels(InsnList list) { case TABLESWITCH_INSN: TableSwitchInsnNode tsinsn = (TableSwitchInsnNode) insn; controlFlowLabels.add(tsinsn.dflt); - for (LabelNode label : tsinsn.labels) - controlFlowLabels.add(label); + for (LabelNode label : tsinsn.labels) controlFlowLabels.add(label); break; case LOOKUPSWITCH_INSN: LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode) insn; controlFlowLabels.add(lsinsn.dflt); - for (LabelNode label : lsinsn.labels) - controlFlowLabels.add(label); + for (LabelNode label : lsinsn.labels) controlFlowLabels.add(label); break; } } @@ -108,12 +103,10 @@ public static InsnList getImportantList(InsnList list) { } public static InsnListSection getImportantList(InsnListSection list) { - if (list.size() == 0) - return list; + if (list.size() == 0) return list; Set controlFlowLabels = getControlFlowLabels(list); - Map labelMap = Maps.asMap(controlFlowLabels, new Function() - { + Map labelMap = Maps.asMap(controlFlowLabels, new Function() { @Override public LabelNode apply(LabelNode input) { return input; @@ -121,9 +114,8 @@ public LabelNode apply(LabelNode input) { }); InsnListSection importantNodeList = new InsnListSection(); - for(AbstractInsnNode insn : list) - if (insnImportant(insn, controlFlowLabels)) - importantNodeList.add(insn.clone(labelMap)); + for (AbstractInsnNode insn : list) + if (insnImportant(insn, controlFlowLabels)) importantNodeList.add(insn.clone(labelMap)); return importantNodeList; } @@ -135,7 +127,7 @@ public static List find(InsnListSection haystack, InsnListSecti InsnListSection section = matches(haystack.drop(start), needle, controlFlowLabels); if (section != null) { list.add(section); - start = section.end-1; + start = section.end - 1; } } @@ -146,27 +138,26 @@ public static List find(InsnList haystack, InsnListSection need return find(new InsnListSection(haystack), needle); } - public static InsnListSection matches(InsnListSection haystack, InsnListSection needle, Set controlFlowLabels) { + public static InsnListSection matches( + InsnListSection haystack, InsnListSection needle, Set controlFlowLabels) { int h = 0, n = 0; for (; h < haystack.size() && n < needle.size(); h++) { AbstractInsnNode insn = haystack.get(h); - if(!insnImportant(insn, controlFlowLabels)) - continue; + if (!insnImportant(insn, controlFlowLabels)) continue; - if (!insnEqual(haystack.get(h), needle.get(n))) - return null; + if (!insnEqual(haystack.get(h), needle.get(n))) return null; n++; } - if (n != needle.size()) - return null; + if (n != needle.size()) return null; return haystack.take(h); } public static InsnListSection findOnce(InsnListSection haystack, InsnListSection needle) { List list = find(haystack, needle); - if(list.size() != 1) - throw new RuntimeException("Needle found " + list.size() + " times in Haystack:\n" + haystack + "\n\n" + needle); + if (list.size() != 1) + throw new RuntimeException( + "Needle found " + list.size() + " times in Haystack:\n" + haystack + "\n\n" + needle); return list.get(0); } @@ -177,8 +168,7 @@ public static InsnListSection findOnce(InsnList haystack, InsnListSection needle public static List findN(InsnListSection haystack, InsnListSection needle) { List list = find(haystack, needle); - if(list.isEmpty()) - throw new RuntimeException("Needle not found in Haystack:\n" + haystack + "\n\n" + needle); + if (list.isEmpty()) throw new RuntimeException("Needle not found in Haystack:\n" + haystack + "\n\n" + needle); return list; } diff --git a/src/main/java/codechicken/lib/asm/InsnListSection.java b/src/main/java/codechicken/lib/asm/InsnListSection.java index bdadda2..23a456c 100644 --- a/src/main/java/codechicken/lib/asm/InsnListSection.java +++ b/src/main/java/codechicken/lib/asm/InsnListSection.java @@ -1,9 +1,6 @@ package codechicken.lib.asm; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.tree.*; -import org.objectweb.asm.util.Textifier; -import org.objectweb.asm.util.TraceMethodVisitor; +import static org.objectweb.asm.tree.AbstractInsnNode.*; import java.io.PrintWriter; import java.io.StringWriter; @@ -12,16 +9,16 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; - -import static org.objectweb.asm.tree.AbstractInsnNode.*; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.tree.*; +import org.objectweb.asm.util.Textifier; +import org.objectweb.asm.util.TraceMethodVisitor; /** * A section of an InsnList, may become invalid if the insn list is modified */ -public class InsnListSection implements Iterable -{ - private class InsnListSectionIterator implements Iterator - { +public class InsnListSection implements Iterable { + private class InsnListSectionIterator implements Iterator { int i = 0; @Override @@ -51,7 +48,7 @@ public InsnListSection(InsnList list, int start, int end) { } public InsnListSection(InsnList list, AbstractInsnNode first, AbstractInsnNode last) { - this(list, list.indexOf(first), list.indexOf(last)+1); + this(list, list.indexOf(first), list.indexOf(last) + 1); } public InsnListSection(InsnList list) { @@ -63,8 +60,7 @@ public InsnListSection() { } public void accept(MethodVisitor mv) { - for(AbstractInsnNode insn : this) - insn.accept(mv); + for (AbstractInsnNode insn : this) insn.accept(mv); } public AbstractInsnNode getFirst() { @@ -103,35 +99,30 @@ public void add(AbstractInsnNode insn) { public void insertBefore(InsnList insns) { int s = insns.size(); - if(this.list.size() == 0) - list.insert(insns); - else - list.insertBefore(list.get(start), insns); - start+=s; - end+=s; + if (this.list.size() == 0) list.insert(insns); + else list.insertBefore(list.get(start), insns); + start += s; + end += s; } public void insert(InsnList insns) { - if(end == 0) - list.insert(insns); - else - list.insert(list.get(end-1), insns); + if (end == 0) list.insert(insns); + else list.insert(list.get(end - 1), insns); } public void replace(InsnList insns) { int s = insns.size(); remove(); insert(insns); - end = start+s; + end = start + s; } public void remove() { - while(end != start) - remove(0); + while (end != start) remove(0); } public void setLast(AbstractInsnNode last) { - end = list.indexOf(last)+1; + end = list.indexOf(last) + 1; } public void setFirst(AbstractInsnNode first) { @@ -147,7 +138,7 @@ public InsnListSection take(int n) { } public InsnListSection slice(int start, int end) { - return new InsnListSection(list, this.start+start, this.start+end); + return new InsnListSection(list, this.start + start, this.start + end); } /** @@ -155,11 +146,9 @@ public InsnListSection slice(int start, int end) { * @return this */ public InsnListSection trim(Set controlFlowLabels) { - while(start < end && !InsnComparator.insnImportant(getFirst(), controlFlowLabels)) - start++; + while (start < end && !InsnComparator.insnImportant(getFirst(), controlFlowLabels)) start++; - while(start < end && !InsnComparator.insnImportant(getLast(), controlFlowLabels)) - end--; + while (start < end && !InsnComparator.insnImportant(getLast(), controlFlowLabels)) end--; return this; } @@ -176,38 +165,34 @@ public void println() { System.out.println(toString()); } - public HashMap identityLabelMap() { + public HashMap identityLabelMap() { HashMap labelMap = new HashMap(); for (AbstractInsnNode insn : this) - switch(insn.getType()) { + switch (insn.getType()) { case LABEL: labelMap.put((LabelNode) insn, (LabelNode) insn); break; case JUMP_INSN: - labelMap.put(((JumpInsnNode)insn).label, ((JumpInsnNode)insn).label); + labelMap.put(((JumpInsnNode) insn).label, ((JumpInsnNode) insn).label); break; case LOOKUPSWITCH_INSN: - LookupSwitchInsnNode linsn = (LookupSwitchInsnNode)insn; + LookupSwitchInsnNode linsn = (LookupSwitchInsnNode) insn; labelMap.put(linsn.dflt, linsn.dflt); - for(LabelNode label : linsn.labels) - labelMap.put(label, label); + for (LabelNode label : linsn.labels) labelMap.put(label, label); break; case TABLESWITCH_INSN: - TableSwitchInsnNode tinsn = (TableSwitchInsnNode)insn; + TableSwitchInsnNode tinsn = (TableSwitchInsnNode) insn; labelMap.put(tinsn.dflt, tinsn.dflt); - for(LabelNode label : tinsn.labels) - labelMap.put(label, label); + for (LabelNode label : tinsn.labels) labelMap.put(label, label); break; case FRAME: - FrameNode fnode = (FrameNode)insn; - if(fnode.local != null) - for(Object o : fnode.local) - if(o instanceof LabelNode) - labelMap.put((LabelNode) o, (LabelNode) o); - if(fnode.stack != null) - for(Object o : fnode.stack) - if(o instanceof LabelNode) - labelMap.put((LabelNode) o, (LabelNode) o); + FrameNode fnode = (FrameNode) insn; + if (fnode.local != null) + for (Object o : fnode.local) + if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o); + if (fnode.stack != null) + for (Object o : fnode.stack) + if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o); break; } @@ -216,8 +201,7 @@ public HashMap identityLabelMap() { public Map cloneLabels() { Map labelMap = identityLabelMap(); - for(Entry entry : labelMap.entrySet()) - entry.setValue(new LabelNode()); + for (Entry entry : labelMap.entrySet()) entry.setValue(new LabelNode()); return labelMap; } @@ -228,8 +212,7 @@ public InsnListSection copy() { public InsnListSection copy(Map labelMap) { InsnListSection copy = new InsnListSection(); - for(AbstractInsnNode insn : this) - copy.add(insn.clone(labelMap)); + for (AbstractInsnNode insn : this) copy.add(insn.clone(labelMap)); return copy; } @@ -238,4 +221,4 @@ public InsnListSection copy(Map labelMap) { public Iterator iterator() { return new InsnListSectionIterator(); } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java b/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java index e843da6..dfd6ed9 100644 --- a/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java +++ b/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java @@ -1,37 +1,35 @@ package codechicken.lib.asm; +import java.util.Set; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.LocalVariablesSorter; -import java.util.Set; - -public class LocalVariablesSorterVisitor extends ClassVisitor - { - public Set methods; - public String owner; - - public LocalVariablesSorterVisitor(Set methods, ClassVisitor cv) { - super(Opcodes.ASM4, cv); - this.methods = methods; - } +public class LocalVariablesSorterVisitor extends ClassVisitor { + public Set methods; + public String owner; - public LocalVariablesSorterVisitor(ClassVisitor cv) { - this(null, cv); - } + public LocalVariablesSorterVisitor(Set methods, ClassVisitor cv) { + super(Opcodes.ASM4, cv); + this.methods = methods; + } - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - owner = name; - } + public LocalVariablesSorterVisitor(ClassVisitor cv) { + this(null, cv); + } - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); - return methods == null || methods.contains(new ObfMapping(owner, name, desc)) ? new LocalVariablesSorter(access, desc, mv) : mv; - } + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + owner = name; } - \ No newline at end of file + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); + return methods == null || methods.contains(new ObfMapping(owner, name, desc)) + ? new LocalVariablesSorter(access, desc, mv) + : mv; + } +} diff --git a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java index e05ff4f..7628f9e 100644 --- a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java +++ b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java @@ -1,19 +1,16 @@ package codechicken.lib.asm; +import static codechicken.lib.asm.ASMHelper.*; + +import java.io.File; +import java.util.*; import org.objectweb.asm.*; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodNode; -import java.io.File; -import java.util.*; - -import static codechicken.lib.asm.ASMHelper.*; - -public class ModularASMTransformer -{ - public static class ClassNodeTransformerList - { +public class ModularASMTransformer { + public static class ClassNodeTransformerList { List transformers = new LinkedList(); HashSet methodsToSort = new HashSet(); @@ -26,31 +23,30 @@ public byte[] transform(byte[] bytes) { ClassNode cnode = new ClassNode(); ClassReader reader = new ClassReader(bytes); ClassVisitor cv = cnode; - if(!methodsToSort.isEmpty()) - cv = new LocalVariablesSorterVisitor(methodsToSort, cv); + if (!methodsToSort.isEmpty()) cv = new LocalVariablesSorterVisitor(methodsToSort, cv); reader.accept(cv, ClassReader.EXPAND_FRAMES); try { int writeFlags = 0; - for(ClassNodeTransformer t : transformers) { + for (ClassNodeTransformer t : transformers) { t.transform(cnode); - writeFlags|=t.writeFlags; + writeFlags |= t.writeFlags; } bytes = createBytes(cnode, writeFlags); - if(config.getTag("dump_asm").getBooleanValue(false)) - dump(bytes, new File("asm/ccl_modular/"+cnode.name.replace('/', '#')+".txt"), false, false); + if (config.getTag("dump_asm").getBooleanValue(false)) + dump(bytes, new File("asm/ccl_modular/" + cnode.name.replace('/', '#') + ".txt"), false, false); return bytes; } catch (RuntimeException e) { - dump(bytes, new File("asm/ccl_modular/"+cnode.name.replace('/', '#')+".txt"), false, false); + dump(bytes, new File("asm/ccl_modular/" + cnode.name.replace('/', '#') + ".txt"), false, false); throw e; } } } - public static abstract class ClassNodeTransformer - { + public abstract static class ClassNodeTransformer { public int writeFlags; + public ClassNodeTransformer(int writeFlags) { this.writeFlags = writeFlags; } @@ -60,13 +56,13 @@ public ClassNodeTransformer() { } public abstract String className(); + public abstract void transform(ClassNode cnode); public void addMethodsToSort(Set set) {} } - public static abstract class MethodTransformer extends ClassNodeTransformer - { + public abstract static class MethodTransformer extends ClassNodeTransformer { public final ObfMapping method; public MethodTransformer(ObfMapping method) { @@ -81,28 +77,26 @@ public String className() { @Override public void transform(ClassNode cnode) { MethodNode mv = findMethod(method, cnode); - if (mv == null) - throw new RuntimeException("Method not found: " + method); + if (mv == null) throw new RuntimeException("Method not found: " + method); try { transform(mv); } catch (Exception e) { - throw new RuntimeException("Error transforming method: "+method, e); + throw new RuntimeException("Error transforming method: " + method, e); } } public abstract void transform(MethodNode mv); } - public static class MethodWriter extends ClassNodeTransformer - { + public static class MethodWriter extends ClassNodeTransformer { public final int access; public final ObfMapping method; public final String[] exceptions; public InsnList list; public MethodWriter(int access, ObfMapping method) { - this(access, method, null, (InsnList)null); + this(access, method, null, (InsnList) null); } public MethodWriter(int access, ObfMapping method, InsnList list) { @@ -114,7 +108,7 @@ public MethodWriter(int access, ObfMapping method, ASMBlock block) { } public MethodWriter(int access, ObfMapping method, String[] exceptions) { - this(access, method, exceptions, (InsnList)null); + this(access, method, exceptions, (InsnList) null); } public MethodWriter(int access, ObfMapping method, String[] exceptions, InsnList list) { @@ -136,28 +130,24 @@ public String className() { @Override public void transform(ClassNode cnode) { MethodNode mv = findMethod(method, cnode); - if(mv == null) - mv = (MethodNode) method.visitMethod(cnode, access, exceptions); + if (mv == null) mv = (MethodNode) method.visitMethod(cnode, access, exceptions); else { mv.access = access; mv.instructions.clear(); - if (mv.localVariables != null) - mv.localVariables.clear(); - if (mv.tryCatchBlocks != null) - mv.tryCatchBlocks.clear(); + if (mv.localVariables != null) mv.localVariables.clear(); + if (mv.tryCatchBlocks != null) mv.tryCatchBlocks.clear(); } write(mv); } public void write(MethodNode mv) { - logger.debug("Writing method "+method); + logger.debug("Writing method " + method); list.accept(mv); } } - public static class MethodInjector extends MethodTransformer - { + public static class MethodInjector extends MethodTransformer { public ASMBlock needle; public ASMBlock injection; public boolean before; @@ -188,29 +178,24 @@ public void addMethodsToSort(Set set) { @Override public void transform(MethodNode mv) { - if(needle == null) { - logger.debug("Injecting "+(before ? "before" : "after")+" method "+method); - if (before) - mv.instructions.insert(injection.rawListCopy()); - else - mv.instructions.add(injection.rawListCopy()); - } - else { + if (needle == null) { + logger.debug("Injecting " + (before ? "before" : "after") + " method " + method); + if (before) mv.instructions.insert(injection.rawListCopy()); + else mv.instructions.add(injection.rawListCopy()); + } else { for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) { - logger.debug("Injecting "+(before ? "before" : "after")+" method "+method+" @ "+key.start+" - "+key.end); + logger.debug("Injecting " + (before ? "before" : "after") + " method " + method + " @ " + key.start + + " - " + key.end); ASMBlock injectBlock = injection.copy().mergeLabels(needle.applyLabels(key)); - if (before) - key.insertBefore(injectBlock.list.list); - else - key.insert(injectBlock.list.list); + if (before) key.insertBefore(injectBlock.list.list); + else key.insert(injectBlock.list.list); } } } } - public static class MethodReplacer extends MethodTransformer - { + public static class MethodReplacer extends MethodTransformer { public ASMBlock needle; public ASMBlock replacement; @@ -232,15 +217,14 @@ public void addMethodsToSort(Set set) { @Override public void transform(MethodNode mv) { for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) { - logger.debug("Replacing method "+method+" @ "+key.start+" - "+key.end); + logger.debug("Replacing method " + method + " @ " + key.start + " - " + key.end); ASMBlock replaceBlock = replacement.copy().pullLabels(needle.applyLabels(key)); key.insert(replaceBlock.list.list); } } } - public static class FieldWriter extends ClassNodeTransformer - { + public static class FieldWriter extends ClassNodeTransformer { public final ObfMapping field; public final int access; public final Object value; @@ -270,14 +254,12 @@ public void transform(ClassNode cnode) { public void add(ClassNodeTransformer t) { ClassNodeTransformerList list = transformers.get(t.className()); - if(list == null) - transformers.put(t.className(), list = new ClassNodeTransformerList()); + if (list == null) transformers.put(t.className(), list = new ClassNodeTransformerList()); list.add(t); } public byte[] transform(String name, byte[] bytes) { - if(bytes == null) - return null; + if (bytes == null) return null; ClassNodeTransformerList list = transformers.get(name); return list == null ? bytes : list.transform(bytes); diff --git a/src/main/java/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java index 9861f25..39d1167 100644 --- a/src/main/java/codechicken/lib/asm/ObfMapping.java +++ b/src/main/java/codechicken/lib/asm/ObfMapping.java @@ -7,6 +7,13 @@ import com.google.common.io.Resources; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.relauncher.FMLInjectionData; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import javax.swing.*; import net.minecraft.launchwrapper.Launch; import net.minecraftforge.common.ForgeVersion; import org.objectweb.asm.ClassVisitor; @@ -15,18 +22,8 @@ import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.*; -import javax.swing.*; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -public class ObfMapping -{ - public static class ObfRemapper extends Remapper - { +public class ObfMapping { + public static class ObfRemapper extends Remapper { private HashMap fields = new HashMap(); private HashMap funcs = new HashMap(); @@ -36,20 +33,27 @@ public ObfRemapper() { Field rawMethodMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawMethodMaps"); rawFieldMapsField.setAccessible(true); rawMethodMapsField.setAccessible(true); - Map> rawFieldMaps = (Map>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); - Map> rawMethodMaps = (Map>) rawMethodMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + Map> rawFieldMaps = + (Map>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + Map> rawMethodMaps = + (Map>) rawMethodMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); if (rawFieldMaps == null) - throw new IllegalStateException("codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); + throw new IllegalStateException( + "codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); for (Map map : rawFieldMaps.values()) for (Entry entry : map.entrySet()) if (entry.getValue().startsWith("field")) - fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':'))); + fields.put( + entry.getValue(), + entry.getKey().substring(0, entry.getKey().indexOf(':'))); for (Map map : rawMethodMaps.values()) for (Entry entry : map.entrySet()) if (entry.getValue().startsWith("func")) - funcs.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf('('))); + funcs.put( + entry.getValue(), + entry.getKey().substring(0, entry.getKey().indexOf('('))); } catch (Exception e) { throw new RuntimeException(e); @@ -82,21 +86,20 @@ public boolean isObf(String typeName) { } } - public static class MCPRemapper extends Remapper implements LineProcessor - { + public static class MCPRemapper extends Remapper implements LineProcessor { public static File[] getConfFiles() { - ConfigTag tag = ASMHelper.config.getTag("mappingDir").setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping"); - for (int i = 0; i < DIR_GUESSES+DIR_ASKS; i++) { + ConfigTag tag = ASMHelper.config + .getTag("mappingDir") + .setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping"); + for (int i = 0; i < DIR_GUESSES + DIR_ASKS; i++) { File dir = confDirectoryGuess(i, tag); - if (dir == null || dir.isFile()) - continue; + if (dir == null || dir.isFile()) continue; File[] mappings; try { mappings = parseConfDir(dir); } catch (Exception e) { - if (i >= DIR_GUESSES) - e.printStackTrace(); + if (i >= DIR_GUESSES) e.printStackTrace(); continue; } @@ -109,6 +112,7 @@ public static File[] getConfFiles() { private static final int DIR_GUESSES = 5; private static final int DIR_ASKS = 3; + public static File confDirectoryGuess(int i, ConfigTag tag) { File mcDir = (File) FMLInjectionData.data()[6]; switch (i) { @@ -119,11 +123,15 @@ public static File confDirectoryGuess(int i, ConfigTag tag) { case 2: return new File(mcDir, "../build/unpacked/conf"); case 3: - return new File(System.getProperty("user.home"), ".gradle/caches/minecraft/net/minecraftforge/forge/"+ - FMLInjectionData.data()[4]+"-"+ ForgeVersion.getVersion()+"/unpacked/conf"); + return new File( + System.getProperty("user.home"), + ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + "-" + + ForgeVersion.getVersion() + "/unpacked/conf"); case 4: - return new File(System.getProperty("user.home"), ".gradle/caches/minecraft/net/minecraftforge/forge/"+ - FMLInjectionData.data()[4]+"-"+ ForgeVersion.getVersion()+"-"+FMLInjectionData.data()[4]+"/unpacked/conf"); + return new File( + System.getProperty("user.home"), + ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + "-" + + ForgeVersion.getVersion() + "-" + FMLInjectionData.data()[4] + "/unpacked/conf"); default: JFileChooser fc = new JFileChooser(mcDir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -135,27 +143,21 @@ public static File confDirectoryGuess(int i, ConfigTag tag) { public static File[] parseConfDir(File confDir) { File srgDir = new File(confDir, "conf"); - if (!srgDir.exists()) - srgDir = confDir; + if (!srgDir.exists()) srgDir = confDir; File srgs = new File(srgDir, "packaged.srg"); - if (!srgs.exists()) - srgs = new File(srgDir, "joined.srg"); - if (!srgs.exists()) - throw new RuntimeException("Could not find packaged.srg or joined.srg"); + if (!srgs.exists()) srgs = new File(srgDir, "joined.srg"); + if (!srgs.exists()) throw new RuntimeException("Could not find packaged.srg or joined.srg"); File mapDir = new File(confDir, "mappings"); - if (!mapDir.exists()) - mapDir = confDir; + if (!mapDir.exists()) mapDir = confDir; File methods = new File(mapDir, "methods.csv"); - if (!methods.exists()) - throw new RuntimeException("Could not find methods.csv"); + if (!methods.exists()) throw new RuntimeException("Could not find methods.csv"); File fields = new File(mapDir, "fields.csv"); - if (!fields.exists()) - throw new RuntimeException("Could not find fields.csv"); + if (!fields.exists()) throw new RuntimeException("Could not find fields.csv"); - return new File[]{srgs, methods, fields}; + return new File[] {srgs, methods, fields}; } private HashMap fields = new HashMap(); @@ -204,8 +206,7 @@ public Void getResult() { public static Remapper mcpMapper = null; public static void loadMCPRemapper() { - if (mcpMapper == null) - mcpMapper = new MCPRemapper(); + if (mcpMapper == null) mcpMapper = new MCPRemapper(); } public static final boolean obfuscated; @@ -214,10 +215,10 @@ public static void loadMCPRemapper() { boolean obf = true; try { obf = Launch.classLoader.getClassBytes("net.minecraft.world.World") == null; - } catch (IOException ignored) {} + } catch (IOException ignored) { + } obfuscated = obf; - if (!obf) - loadMCPRemapper(); + if (!obf) loadMCPRemapper(); } public String s_owner; @@ -233,8 +234,7 @@ public ObfMapping(String owner, String name, String desc) { this.s_name = name; this.s_desc = desc; - if (s_owner.contains(".")) - throw new IllegalArgumentException(s_owner); + if (s_owner.contains(".")) throw new IllegalArgumentException(s_owner); } public ObfMapping(ObfMapping descmap, String subclass) { @@ -243,20 +243,18 @@ public ObfMapping(ObfMapping descmap, String subclass) { public static ObfMapping fromDesc(String s) { int lastDot = s.lastIndexOf('.'); - if (lastDot < 0) - return new ObfMapping(s, "", ""); - int sep = s.indexOf('(');//methods + if (lastDot < 0) return new ObfMapping(s, "", ""); + int sep = s.indexOf('('); // methods int sep_end = sep; if (sep < 0) { - sep = s.indexOf(' ');//some stuffs + sep = s.indexOf(' '); // some stuffs sep_end = sep + 1; } if (sep < 0) { - sep = s.indexOf(':');//fields + sep = s.indexOf(':'); // fields sep_end = sep + 1; } - if (sep < 0) - return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), ""); + if (sep < 0) return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), ""); return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1, sep), s.substring(sep_end)); } @@ -274,12 +272,9 @@ public boolean matches(MethodInsnNode node) { } public AbstractInsnNode toInsn(int opcode) { - if (isClass()) - return new TypeInsnNode(opcode, s_owner); - else if (isMethod()) - return new MethodInsnNode(opcode, s_owner, s_name, s_desc); - else - return new FieldInsnNode(opcode, s_owner, s_name, s_desc); + if (isClass()) return new TypeInsnNode(opcode, s_owner); + else if (isMethod()) return new MethodInsnNode(opcode, s_owner, s_name, s_desc); + else return new FieldInsnNode(opcode, s_owner, s_name, s_desc); } public void visitTypeInsn(MethodVisitor mv, int opcode) { @@ -324,8 +319,7 @@ public String javaClass() { @Override public boolean equals(Object obj) { - if (!(obj instanceof ObfMapping)) - return false; + if (!(obj instanceof ObfMapping)) return false; ObfMapping desc = (ObfMapping) obj; return s_owner.equals(desc.s_owner) && s_name.equals(desc.s_name) && s_desc.equals(desc.s_desc); @@ -338,10 +332,8 @@ public int hashCode() { @Override public String toString() { - if (s_name.length() == 0) - return "[" + s_owner + "]"; - if (s_desc.length() == 0) - return "[" + s_owner + "." + s_name + "]"; + if (s_name.length() == 0) return "[" + s_owner + "]"; + if (s_desc.length() == 0) return "[" + s_owner + "." + s_name + "]"; return "[" + (isMethod() ? methodDesc() : fieldDesc()) + "]"; } @@ -366,20 +358,15 @@ public boolean isField() { } public ObfMapping map(Remapper mapper) { - if (mapper == null) - return this; + if (mapper == null) return this; - if (isMethod()) - s_name = mapper.mapMethodName(s_owner, s_name, s_desc); - else if (isField()) - s_name = mapper.mapFieldName(s_owner, s_name, s_desc); + if (isMethod()) s_name = mapper.mapMethodName(s_owner, s_name, s_desc); + else if (isField()) s_name = mapper.mapFieldName(s_owner, s_name, s_desc); s_owner = mapper.mapType(s_owner); - if (isMethod()) - s_desc = mapper.mapMethodDesc(s_desc); - else if (s_desc.length() > 0) - s_desc = mapper.mapDesc(s_desc); + if (isMethod()) s_desc = mapper.mapMethodDesc(s_desc); + else if (s_desc.length() > 0) s_desc = mapper.mapDesc(s_desc); return this; } @@ -390,10 +377,8 @@ public ObfMapping toRuntime() { } public ObfMapping toClassloading() { - if(!obfuscated) - map(mcpMapper); - else if(obfMapper.isObf(s_owner)) - map(obfMapper); + if (!obfuscated) map(mcpMapper); + else if (obfMapper.isObf(s_owner)) map(obfMapper); return this; } diff --git a/src/main/java/codechicken/lib/colour/Colour.java b/src/main/java/codechicken/lib/colour/Colour.java index 1bccdf3..a50df3b 100644 --- a/src/main/java/codechicken/lib/colour/Colour.java +++ b/src/main/java/codechicken/lib/colour/Colour.java @@ -5,28 +5,25 @@ import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import org.lwjgl.opengl.GL11; - import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.lwjgl.opengl.GL11; -public abstract class Colour implements Copyable -{ - public static IConfigType configRGB = new IConfigType() - { +public abstract class Colour implements Copyable { + public static IConfigType configRGB = new IConfigType() { @Override public String configValue(Colour entry) { String s = Long.toString(((long) entry.rgb()) << 32 >>> 32, 16); - while (s.length() < 6) - s = "0" + s; + while (s.length() < 6) s = "0" + s; return "0x" + s.toUpperCase(); } private final Pattern patternRGB = Pattern.compile("(\\d+),(\\d+),(\\d+)"); + @Override public Colour valueOf(String text) throws Exception { Matcher matcherRGB = patternRGB.matcher(text.replaceAll("\\s", "")); - if(matcherRGB.matches()) + if (matcherRGB.matches()) return new ColourRGBA( Integer.parseInt(matcherRGB.group(1)), Integer.parseInt(matcherRGB.group(2)), @@ -34,7 +31,7 @@ public Colour valueOf(String text) throws Exception { 0xFF); int hex = (int) Long.parseLong(text.replace("0x", ""), 16); - return new ColourRGBA(hex<<8|0xFF); + return new ColourRGBA(hex << 8 | 0xFF); } }; @@ -43,16 +40,14 @@ public Colour valueOf(String text) throws Exception { public byte b; public byte a; - public Colour(int r, int g, int b, int a) - { + public Colour(int r, int g, int b, int a) { this.r = (byte) r; this.g = (byte) g; this.b = (byte) b; this.a = (byte) a; } - public Colour(Colour colour) - { + public Colour(Colour colour) { r = colour.r; g = colour.g; b = colour.b; @@ -60,27 +55,23 @@ public Colour(Colour colour) } @SideOnly(Side.CLIENT) - public void glColour() - { + public void glColour() { GL11.glColor4ub(r, g, b, a); } @SideOnly(Side.CLIENT) - public void glColour(int a) - { + public void glColour(int a) { GL11.glColor4ub(r, g, b, (byte) a); } - + public abstract int pack(); @Override - public String toString() - { + public String toString() { return getClass().getSimpleName() + "[0x" + Integer.toHexString(pack()).toUpperCase() + "]"; } - public Colour add(Colour colour2) - { + public Colour add(Colour colour2) { a += colour2.a; r += colour2.r; g += colour2.g; @@ -88,8 +79,7 @@ public Colour add(Colour colour2) return this; } - public Colour sub(Colour colour2) - { + public Colour sub(Colour colour2) { int ia = (a & 0xFF) - (colour2.a & 0xFF); int ir = (r & 0xFF) - (colour2.r & 0xFF); int ig = (g & 0xFF) - (colour2.g & 0xFF); @@ -101,8 +91,7 @@ public Colour sub(Colour colour2) return this; } - public Colour invert() - { + public Colour invert() { a = (byte) (0xFF - (a & 0xFF)); r = (byte) (0xFF - (r & 0xFF)); g = (byte) (0xFF - (g & 0xFF)); @@ -110,8 +99,7 @@ public Colour invert() return this; } - public Colour multiply(Colour colour2) - { + public Colour multiply(Colour colour2) { a = (byte) ((a & 0xFF) * ((colour2.a & 0xFF) / 255D)); r = (byte) ((r & 0xFF) * ((colour2.r & 0xFF) / 255D)); g = (byte) ((g & 0xFF) * ((colour2.g & 0xFF) / 255D)); @@ -119,8 +107,7 @@ public Colour multiply(Colour colour2) return this; } - public Colour scale(double d) - { + public Colour scale(double d) { a = (byte) ((a & 0xFF) * d); r = (byte) ((r & 0xFF) * d); g = (byte) ((g & 0xFF) * d); @@ -128,13 +115,11 @@ public Colour scale(double d) return this; } - public Colour interpolate(Colour colour2, double d) - { + public Colour interpolate(Colour colour2, double d) { return this.add(colour2.copy().sub(this).scale(d)); } - public Colour multiplyC(double d) - { + public Colour multiplyC(double d) { r = (byte) MathHelper.clip((r & 0xFF) * d, 0, 255); g = (byte) MathHelper.clip((g & 0xFF) * d, 0, 255); b = (byte) MathHelper.clip((b & 0xFF) * d, 0, 255); @@ -144,23 +129,19 @@ public Colour multiplyC(double d) public abstract Colour copy(); - public int rgb() - { + public int rgb() { return (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); } - public int argb() - { + public int argb() { return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); } - public int rgba() - { + public int rgba() { return (r & 0xFF) << 24 | (g & 0xFF) << 16 | (b & 0xFF) << 8 | (a & 0xFF); } - public Colour set(Colour colour) - { + public Colour set(Colour colour) { r = colour.r; g = colour.g; b = colour.b; @@ -168,8 +149,7 @@ public Colour set(Colour colour) return this; } - public boolean equals(Colour colour) - { + public boolean equals(Colour colour) { return colour != null && rgba() == colour.rgba(); } } diff --git a/src/main/java/codechicken/lib/colour/ColourARGB.java b/src/main/java/codechicken/lib/colour/ColourARGB.java index 376ed0a..765c31a 100644 --- a/src/main/java/codechicken/lib/colour/ColourARGB.java +++ b/src/main/java/codechicken/lib/colour/ColourARGB.java @@ -1,34 +1,27 @@ package codechicken.lib.colour; -public class ColourARGB extends Colour -{ - public ColourARGB(int colour) - { +public class ColourARGB extends Colour { + public ColourARGB(int colour) { super((colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF, (colour >> 24) & 0xFF); } - - public ColourARGB(int a, int r, int g, int b) - { + + public ColourARGB(int a, int r, int g, int b) { super(r, g, b, a); } - public ColourARGB(ColourARGB colour) - { + public ColourARGB(ColourARGB colour) { super(colour); } - public ColourARGB copy() - { + public ColourARGB copy() { return new ColourARGB(this); } - public int pack() - { + public int pack() { return pack(this); } - public static int pack(Colour colour) - { - return (colour.a&0xFF) << 24 | (colour.r&0xFF) << 16 | (colour.g&0xFF) << 8 | (colour.b&0xFF); + public static int pack(Colour colour) { + return (colour.a & 0xFF) << 24 | (colour.r & 0xFF) << 16 | (colour.g & 0xFF) << 8 | (colour.b & 0xFF); } } diff --git a/src/main/java/codechicken/lib/colour/ColourRGBA.java b/src/main/java/codechicken/lib/colour/ColourRGBA.java index 61d4a29..85aeb6c 100644 --- a/src/main/java/codechicken/lib/colour/ColourRGBA.java +++ b/src/main/java/codechicken/lib/colour/ColourRGBA.java @@ -31,19 +31,19 @@ public static int pack(Colour colour) { } public static int multiply(int c1, int c2) { - if(c1 == -1) return c2; - if(c2 == -1) return c1; + if (c1 == -1) return c2; + if (c2 == -1) return c1; int r = (((c1 >>> 24) * (c2 >>> 24)) & 0xFF00) << 16; int g = (((c1 >> 16 & 0xFF) * (c2 >> 16 & 0xFF)) & 0xFF00) << 8; int b = ((c1 >> 8 & 0xFF) * (c2 >> 8 & 0xFF)) & 0xFF00; int a = ((c1 & 0xFF) * (c2 & 0xFF)) >> 8; - return r|g|b|a; + return r | g | b | a; } public static int multiplyC(int c, float f) { int r = (int) ((c >>> 24) * f); int g = (int) ((c >> 16 & 0xFF) * f); int b = (int) ((c >> 8 & 0xFF) * f); - return r<<24 | g<<16 | b<<8 | c&0xFF; + return r << 24 | g << 16 | b << 8 | c & 0xFF; } } diff --git a/src/main/java/codechicken/lib/colour/CustomGradient.java b/src/main/java/codechicken/lib/colour/CustomGradient.java index 159bf4b..1d5ac1c 100644 --- a/src/main/java/codechicken/lib/colour/CustomGradient.java +++ b/src/main/java/codechicken/lib/colour/CustomGradient.java @@ -2,35 +2,28 @@ import codechicken.lib.math.MathHelper; import codechicken.lib.render.TextureUtils; -import net.minecraft.util.ResourceLocation; - import java.awt.image.BufferedImage; +import net.minecraft.util.ResourceLocation; -public class CustomGradient -{ +public class CustomGradient { public int[] gradient; - - public CustomGradient(ResourceLocation textureFile) - { + + public CustomGradient(ResourceLocation textureFile) { BufferedImage img = TextureUtils.loadBufferedImage(textureFile); - if(img == null) - throw new RuntimeException("File not found: "+textureFile.toString()); + if (img == null) throw new RuntimeException("File not found: " + textureFile.toString()); int[] data = new int[img.getWidth()]; img.getRGB(0, 0, img.getWidth(), 1, data, 0, img.getWidth()); gradient = new int[img.getWidth()]; - for(int i = 0; i < data.length; i++) - gradient[i] = (data[i]<<8)|(((data[i])>>24)&0xFF); + for (int i = 0; i < data.length; i++) gradient[i] = (data[i] << 8) | (((data[i]) >> 24) & 0xFF); } - - public ColourRGBA getColour(double position) - { + + public ColourRGBA getColour(double position) { return new ColourRGBA(getColourI(position)); } - - public int getColourI(double position) - { - int off = (int)MathHelper.clip(gradient.length*position, 0, gradient.length-1); + + public int getColourI(double position) { + int off = (int) MathHelper.clip(gradient.length * position, 0, gradient.length - 1); return gradient[off]; } } diff --git a/src/main/java/codechicken/lib/config/ConfigFile.java b/src/main/java/codechicken/lib/config/ConfigFile.java index b634dae..ebab9fb 100644 --- a/src/main/java/codechicken/lib/config/ConfigFile.java +++ b/src/main/java/codechicken/lib/config/ConfigFile.java @@ -2,9 +2,8 @@ import java.io.*; -public class ConfigFile extends ConfigTagParent -{ - public static final byte[] crlf = new byte[]{0xD, 0xA}; +public class ConfigFile extends ConfigTagParent { + public static final byte[] crlf = new byte[] {0xD, 0xA}; public File file; private boolean loading; @@ -18,10 +17,8 @@ protected ConfigFile() {} protected void load(File file) { try { - if(!file.getParentFile().exists()) - file.getParentFile().mkdirs(); - if (!file.exists()) - file.createNewFile(); + if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); + if (!file.exists()) file.createNewFile(); } catch (IOException e) { throw new RuntimeException(e); } @@ -39,10 +36,8 @@ protected void loadConfig() { reader.mark(2000); String line = reader.readLine(); if (line != null && line.startsWith("#")) { - if (comment == null || comment.equals("")) - comment = line.substring(1); - else - comment = comment + "\n" + line.substring(1); + if (comment == null || comment.equals("")) comment = line.substring(1); + else comment = comment + "\n" + line.substring(1); } else { reader.reset(); break; @@ -81,15 +76,13 @@ public static String readLine(BufferedReader reader) throws IOException { } public static void writeLine(PrintWriter writer, String line, int tabs) { - for (int i = 0; i < tabs; i++) - writer.print('\t'); + for (int i = 0; i < tabs; i++) writer.print('\t'); writer.println(line); } public void saveConfig() { - if (loading) - return; + if (loading) return; PrintWriter writer; try { diff --git a/src/main/java/codechicken/lib/config/ConfigTag.java b/src/main/java/codechicken/lib/config/ConfigTag.java index e0eebd5..a565428 100644 --- a/src/main/java/codechicken/lib/config/ConfigTag.java +++ b/src/main/java/codechicken/lib/config/ConfigTag.java @@ -2,10 +2,8 @@ import java.io.PrintWriter; -public class ConfigTag extends ConfigTagParent -{ - public interface IConfigType - { +public class ConfigTag extends ConfigTagParent { + public interface IConfigType { public String configValue(T entry); public T valueOf(String text) throws Exception; @@ -81,9 +79,9 @@ public int getIntValue() { public int getIntValue(int defaultValue) { try { - if (value != null) - return getIntValue(); - } catch (NumberFormatException ignored) {} + if (value != null) return getIntValue(); + } catch (NumberFormatException ignored) { + } setIntValue(defaultValue); return defaultValue; @@ -91,19 +89,17 @@ public int getIntValue(int defaultValue) { public boolean getBooleanValue() { String value = getValue(); - if (value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) - return true; - else if (value != null && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) - return false; + if (value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) return true; + else if (value != null && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) return false; throw new NumberFormatException(qualifiedname + ".value=" + value); } public boolean getBooleanValue(boolean defaultValue) { try { - if (value != null) - return getBooleanValue(); - } catch (NumberFormatException ignored) {} + if (value != null) return getBooleanValue(); + } catch (NumberFormatException ignored) { + } setBooleanValue(defaultValue); return defaultValue; @@ -115,9 +111,9 @@ public int getHexValue() { public int getHexValue(int defaultValue) { try { - if (value != null) - return getHexValue(); - } catch (NumberFormatException ignored) {} + if (value != null) return getHexValue(); + } catch (NumberFormatException ignored) { + } setHexValue(defaultValue); return defaultValue; @@ -133,9 +129,9 @@ public T get(IConfigType type) { public T get(IConfigType type, T defaultValue) { try { - if (value != null) - return get(type); - } catch (Exception ignored) {} + if (value != null) return get(type); + } catch (Exception ignored) { + } set(type, defaultValue); return defaultValue; @@ -145,22 +141,17 @@ public void save(PrintWriter writer, int tabs, String bracequalifier, boolean fi String vname; if (qualifiedname.contains(".") && bracequalifier.length() > 0) vname = qualifiedname.substring(bracequalifier.length() + 1); - else - vname = qualifiedname; + else vname = qualifiedname; - if (newline && !first) - ConfigFile.writeLine(writer, "", tabs); + if (newline && !first) ConfigFile.writeLine(writer, "", tabs); writeComment(writer, tabs); - if (value != null) - ConfigFile.writeLine(writer, vname + "=" + value, tabs); + if (value != null) ConfigFile.writeLine(writer, vname + "=" + value, tabs); - if (!hasChildTags()) - return; + if (!hasChildTags()) return; if (brace) { - if (value == null) - ConfigFile.writeLine(writer, vname, tabs); + if (value == null) ConfigFile.writeLine(writer, vname, tabs); ConfigFile.writeLine(writer, "{", tabs); saveTagTree(writer, tabs + 1, qualifiedname); ConfigFile.writeLine(writer, "}", tabs); @@ -189,8 +180,7 @@ public ConfigTag setNewLine(boolean b) { public ConfigTag useBraces() { brace = true; - if (parent.newlinemode == 1) - newline = true; + if (parent.newlinemode == 1) newline = true; saveConfig(); return this; diff --git a/src/main/java/codechicken/lib/config/ConfigTagParent.java b/src/main/java/codechicken/lib/config/ConfigTagParent.java index 8eab85d..96ccfc9 100644 --- a/src/main/java/codechicken/lib/config/ConfigTagParent.java +++ b/src/main/java/codechicken/lib/config/ConfigTagParent.java @@ -6,10 +6,8 @@ import java.util.*; import java.util.Map.Entry; -public abstract class ConfigTagParent -{ - public static class TagOrderComparator implements Comparator - { +public abstract class ConfigTagParent { + public static class TagOrderComparator implements Comparator { int sortMode; public TagOrderComparator(int sortMode) { @@ -17,18 +15,13 @@ public TagOrderComparator(int sortMode) { } public int compare(ConfigTag o1, ConfigTag o2) { - if (o1.position != o2.position) - return compareInt(o1.position, o2.position); - if (o1.brace != o2.brace) - return o1.brace ? 1 : -1;//braced one goes after + if (o1.position != o2.position) return compareInt(o1.position, o2.position); + if (o1.brace != o2.brace) return o1.brace ? 1 : -1; // braced one goes after switch (sortMode) { case 1: - if (o1.value == o2.value) - return 0; - if (o1.value == null) - return 1; - if (o2.value == null) - return -1; + if (o1.value == o2.value) return 0; + if (o1.value == null) return 1; + if (o2.value == null) return -1; return o1.value.compareTo(o2.value); default: return o1.name.compareTo(o2.name); @@ -72,12 +65,9 @@ public ConfigTagParent setNewLineMode(int mode) { newlinemode = mode; for (Entry entry : childtags.entrySet()) { ConfigTag tag = entry.getValue(); - if (newlinemode == 0) - tag.newline = false; - else if (newlinemode == 1) - tag.newline = tag.brace; - else if (newlinemode == 2) - tag.newline = true; + if (newlinemode == 0) tag.newline = false; + else if (newlinemode == 1) tag.newline = tag.brace; + else if (newlinemode == 2) tag.newline = true; } saveConfig(); return this; @@ -104,14 +94,12 @@ public ConfigTag getTag(String tagname, boolean create) { String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos); ConfigTag basetag = childtags.get(basetagname); if (basetag == null) { - if (!create) - return null; + if (!create) return null; basetag = getNewTag(basetagname); saveConfig(); } - if (dotpos == -1) - return basetag; + if (dotpos == -1) return basetag; return basetag.getTag(tagname.substring(dotpos + 1), create); } @@ -122,15 +110,13 @@ public ConfigTag getTag(String tagname) { public boolean removeTag(String tagname) { ConfigTag tag = getTag(tagname, false); - if (tag == null) - return false; + if (tag == null) return false; int dotpos = tagname.lastIndexOf("."); String lastpart = dotpos == -1 ? tagname : tagname.substring(dotpos + 1, tagname.length()); if (tag.parent != null) { boolean ret = tag.parent.childtags.remove(lastpart) != null; - if (ret) - saveConfig(); + if (ret) saveConfig(); return ret; } @@ -143,8 +129,7 @@ public void addChild(ConfigTag tag) { public ArrayList getSortedTagList() { ArrayList taglist = new ArrayList(childtags.size()); - for (Entry tag : childtags.entrySet()) - taglist.add((T) tag.getValue()); + for (Entry tag : childtags.entrySet()) taglist.add((T) tag.getValue()); Collections.sort(taglist, new TagOrderComparator(sortMode)); return taglist; @@ -156,13 +141,10 @@ public void loadChildren(BufferedReader reader) { try { while (true) { String line = ConfigFile.readLine(reader); - if (line == null) - break; + if (line == null) break; if (line.startsWith("#")) { - if (comment.equals("")) - comment = line.substring(1); - else - comment = comment + "\n" + line.substring(1); + if (comment.equals("")) comment = line.substring(1); + else comment = comment + "\n" + line.substring(1); } else if (line.contains("=")) { String qualifiedname = line.substring(0, line.indexOf("=")); getTag(qualifiedname) @@ -197,8 +179,7 @@ public void saveTagTree(PrintWriter writer, int tabs, String bracequalifier) { public void writeComment(PrintWriter writer, int tabs) { if (comment != null && !comment.equals("")) { String[] comments = comment.split("\n"); - for (int i = 0; i < comments.length; i++) - ConfigFile.writeLine(writer, "#" + comments[i], tabs); + for (int i = 0; i < comments.length; i++) ConfigFile.writeLine(writer, "#" + comments[i], tabs); } } } diff --git a/src/main/java/codechicken/lib/config/DefaultingConfigFile.java b/src/main/java/codechicken/lib/config/DefaultingConfigFile.java index 27a7ef7..a8e1374 100644 --- a/src/main/java/codechicken/lib/config/DefaultingConfigFile.java +++ b/src/main/java/codechicken/lib/config/DefaultingConfigFile.java @@ -2,17 +2,14 @@ import java.io.File; -public class DefaultingConfigFile extends ConfigFile -{ +public class DefaultingConfigFile extends ConfigFile { public DefaultingConfigFile(File file) { super(); - if(file.exists()) - load(file); + if (file.exists()) load(file); } @Override public void saveConfig() { - if(file != null) - super.saveConfig(); + if (file != null) super.saveConfig(); } } diff --git a/src/main/java/codechicken/lib/config/SimpleProperties.java b/src/main/java/codechicken/lib/config/SimpleProperties.java index 4a33669..8e4e26d 100644 --- a/src/main/java/codechicken/lib/config/SimpleProperties.java +++ b/src/main/java/codechicken/lib/config/SimpleProperties.java @@ -5,142 +5,116 @@ import java.util.HashMap; import java.util.Map.Entry; -public class SimpleProperties -{ +public class SimpleProperties { public HashMap propertyMap = new HashMap(); public File propertyFile; public boolean saveOnChange = false; public String encoding; - + private boolean loading = false; - - public SimpleProperties(File file, boolean saveOnChange, String encoding) - { + + public SimpleProperties(File file, boolean saveOnChange, String encoding) { propertyFile = file; this.saveOnChange = saveOnChange; this.encoding = encoding; } - - public SimpleProperties(File file, boolean saveOnChange) - { + + public SimpleProperties(File file, boolean saveOnChange) { this(file, saveOnChange, Charset.defaultCharset().name()); } - - public SimpleProperties(File file) - { + + public SimpleProperties(File file) { this(file, true); } - - public void load() - { + + public void load() { clear(); loading = true; - - try - { - BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile), encoding)); - while(true) - { + + try { + BufferedReader reader = + new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile), encoding)); + while (true) { String read = reader.readLine(); - if(read == null) - break; + if (read == null) break; int equalIndex = read.indexOf('='); - if(equalIndex == -1) - continue; - - setProperty(read.substring(0, equalIndex), read.substring(equalIndex+1)); + if (equalIndex == -1) continue; + + setProperty(read.substring(0, equalIndex), read.substring(equalIndex + 1)); } reader.close(); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } loading = false; } - - public void save() - { - try - { + + public void save() { + try { PrintStream writer = new PrintStream(propertyFile); - - for(Entry entry : propertyMap.entrySet()) - { - writer.println(entry.getKey()+"="+entry.getValue()); + + for (Entry entry : propertyMap.entrySet()) { + writer.println(entry.getKey() + "=" + entry.getValue()); } - + writer.close(); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } - - public void clear() - { + + public void clear() { propertyMap.clear(); } - - public boolean hasProperty(String key) - { + + public boolean hasProperty(String key) { return propertyMap.containsKey(key); } - - public void removeProperty(String key) - { - if(propertyMap.remove(key) != null && saveOnChange && !loading) - save(); + + public void removeProperty(String key) { + if (propertyMap.remove(key) != null && saveOnChange && !loading) save(); } - - public void setProperty(String key, int value) - { + + public void setProperty(String key, int value) { setProperty(key, Integer.toString(value)); } - - public void setProperty(String key, boolean value) - { + + public void setProperty(String key, boolean value) { setProperty(key, Boolean.toString(value)); } - - public void setProperty(String key, String value) - { + + public void setProperty(String key, String value) { propertyMap.put(key, value); - if(saveOnChange && !loading) - save(); + if (saveOnChange && !loading) save(); } - - public int getProperty(String property, int defaultvalue) - { + + public int getProperty(String property, int defaultvalue) { try { return Integer.parseInt(getProperty(property, Integer.toString(defaultvalue))); - } catch(NumberFormatException nfe) - {return defaultvalue;} + } catch (NumberFormatException nfe) { + return defaultvalue; + } } - - public boolean getProperty(String property, boolean defaultvalue) - { + + public boolean getProperty(String property, boolean defaultvalue) { try { return Boolean.parseBoolean(getProperty(property, Boolean.toString(defaultvalue))); - } catch(NumberFormatException nfe) - {return defaultvalue;} + } catch (NumberFormatException nfe) { + return defaultvalue; + } } - - public String getProperty(String property, String defaultvalue) - { + + public String getProperty(String property, String defaultvalue) { String value = propertyMap.get(property); - if(value == null) - { + if (value == null) { setProperty(property, defaultvalue); return defaultvalue; } return value; } - - public String getProperty(String property) - { + + public String getProperty(String property) { return propertyMap.get(property); } } diff --git a/src/main/java/codechicken/lib/data/MCDataInput.java b/src/main/java/codechicken/lib/data/MCDataInput.java index 496c4a3..1d5eb12 100644 --- a/src/main/java/codechicken/lib/data/MCDataInput.java +++ b/src/main/java/codechicken/lib/data/MCDataInput.java @@ -5,24 +5,40 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; -public interface MCDataInput -{ +public interface MCDataInput { public long readLong(); + public int readInt(); + public short readShort(); + public int readUShort(); + public byte readByte(); + public short readUByte(); + public double readDouble(); + public float readFloat(); + public boolean readBoolean(); + public char readChar(); + public int readVarShort(); + public int readVarInt(); + public byte[] readByteArray(int length); + public String readString(); + public BlockCoord readCoord(); + public NBTTagCompound readNBTTagCompound(); + public ItemStack readItemStack(); + public FluidStack readFluidStack(); } diff --git a/src/main/java/codechicken/lib/data/MCDataInputStream.java b/src/main/java/codechicken/lib/data/MCDataInputStream.java index 18267be..5c53cab 100644 --- a/src/main/java/codechicken/lib/data/MCDataInputStream.java +++ b/src/main/java/codechicken/lib/data/MCDataInputStream.java @@ -2,18 +2,15 @@ import java.io.InputStream; -public class MCDataInputStream extends InputStream -{ +public class MCDataInputStream extends InputStream { private MCDataInput in; - - public MCDataInputStream(MCDataInput in) - { + + public MCDataInputStream(MCDataInput in) { this.in = in; } - + @Override - public int read() - { - return in.readByte()&0xFF; + public int read() { + return in.readByte() & 0xFF; } } diff --git a/src/main/java/codechicken/lib/data/MCDataOutput.java b/src/main/java/codechicken/lib/data/MCDataOutput.java index cf7cf89..34de499 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutput.java +++ b/src/main/java/codechicken/lib/data/MCDataOutput.java @@ -5,23 +5,38 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; -public interface MCDataOutput -{ +public interface MCDataOutput { public MCDataOutput writeLong(long l); + public MCDataOutput writeInt(int i); + public MCDataOutput writeShort(int s); + public MCDataOutput writeByte(int b); + public MCDataOutput writeDouble(double d); + public MCDataOutput writeFloat(float f); + public MCDataOutput writeBoolean(boolean b); + public MCDataOutput writeChar(char c); + public MCDataOutput writeVarInt(int i); + public MCDataOutput writeVarShort(int s); + public MCDataOutput writeByteArray(byte[] array); + public MCDataOutput writeString(String s); + public MCDataOutput writeCoord(int x, int y, int z); + public MCDataOutput writeCoord(BlockCoord coord); + public MCDataOutput writeNBTTagCompound(NBTTagCompound tag); + public MCDataOutput writeItemStack(ItemStack stack); + public MCDataOutput writeFluidStack(FluidStack liquid); } diff --git a/src/main/java/codechicken/lib/data/MCDataOutputStream.java b/src/main/java/codechicken/lib/data/MCDataOutputStream.java index bf929a5..1f425c6 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutputStream.java +++ b/src/main/java/codechicken/lib/data/MCDataOutputStream.java @@ -2,18 +2,15 @@ import java.io.OutputStream; -public class MCDataOutputStream extends OutputStream -{ +public class MCDataOutputStream extends OutputStream { private MCDataOutput out; - - public MCDataOutputStream(MCDataOutput out) - { + + public MCDataOutputStream(MCDataOutput out) { this.out = out; } - + @Override - public void write(int b) - { + public void write(int b) { out.writeByte(b); } } diff --git a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java index 89ea270..41ebbe3 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java +++ b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java @@ -3,6 +3,8 @@ import codechicken.lib.vec.BlockCoord; import com.google.common.base.Charsets; import cpw.mods.fml.common.network.ByteBufUtils; +import java.io.DataOutput; +import java.io.IOException; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; @@ -10,11 +12,7 @@ import net.minecraftforge.fluids.FluidStack; import org.apache.commons.lang3.Validate; -import java.io.DataOutput; -import java.io.IOException; - -public class MCDataOutputWrapper implements MCDataOutput -{ +public class MCDataOutputWrapper implements MCDataOutput { /** * Mimics ByteBufUtils * Write an integer using variable length encoding. @@ -41,11 +39,9 @@ public static void writeVarInt(DataOutput to, int i) throws IOException { public static void writeVarShort(DataOutput to, int s) throws IOException { int low = s & 0x7FFF; int high = (s & 0x7F8000) >> 15; - if (high != 0) - low |= 0x8000; + if (high != 0) low |= 0x8000; to.writeShort(low); - if (high != 0) - to.writeByte(high); + if (high != 0) to.writeByte(high); } /** @@ -57,7 +53,8 @@ public static void writeVarShort(DataOutput to, int s) throws IOException { */ public static void writeUTF8String(DataOutput to, String string) throws IOException { byte[] utf8Bytes = string.getBytes(Charsets.UTF_8); - Validate.isTrue(ByteBufUtils.varIntByteCount(utf8Bytes.length) < 3, "The string is too long for this encoding."); + Validate.isTrue( + ByteBufUtils.varIntByteCount(utf8Bytes.length) < 3, "The string is too long for this encoding."); writeVarInt(to, utf8Bytes.length); to.write(utf8Bytes); } @@ -203,10 +200,8 @@ public MCDataOutputWrapper writeItemStack(ItemStack stack, boolean large) { writeShort(-1); } else { writeShort(Item.getIdFromItem(stack.getItem())); - if (large) - writeInt(stack.stackSize); - else - writeByte(stack.stackSize); + if (large) writeInt(stack.stackSize); + else writeByte(stack.stackSize); writeShort(stack.getItemDamage()); writeNBTTagCompound(stack.stackTagCompound); } diff --git a/src/main/java/codechicken/lib/gui/Canvas9Seg.java b/src/main/java/codechicken/lib/gui/Canvas9Seg.java index 055bb42..4a35ad6 100644 --- a/src/main/java/codechicken/lib/gui/Canvas9Seg.java +++ b/src/main/java/codechicken/lib/gui/Canvas9Seg.java @@ -6,8 +6,7 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.ResourceLocation; -public class Canvas9Seg -{ +public class Canvas9Seg { public final ResourceLocation tex; public float[] seg_u = new float[4]; public float[] seg_v = new float[4]; @@ -24,12 +23,11 @@ private int[] readMarkers(TextureDataHolder data, int stride, int size) { int marker = 1; int prev_col = data.data[0]; - for(int i = 1; i < size; i++) { - if(data.data[i*stride] != prev_col) { + for (int i = 1; i < size; i++) { + if (data.data[i * stride] != prev_col) { markers[marker] = i; - prev_col = data.data[i*stride]; - if(++marker == 4) - break; + prev_col = data.data[i * stride]; + if (++marker == 4) break; } } @@ -40,10 +38,9 @@ private int[] readMarkers(TextureDataHolder data, int stride, int size) { private void parseMarkers(TextureDataHolder data, int stride, int size, int[] sizes, float[] texcoords) { int[] markers = readMarkers(data, stride, size); - for(int i = 0; i < 4; i++) { - texcoords[i] = markers[i]/(float)size; - if(i > 0) - sizes[i-1] = markers[i]-markers[i-1]; + for (int i = 0; i < 4; i++) { + texcoords[i] = markers[i] / (float) size; + if (i > 0) sizes[i - 1] = markers[i] - markers[i - 1]; } } @@ -55,11 +52,12 @@ private void load() { private void drawSeg(int[] sw, int[] sh, int seg) { Tessellator t = Tessellator.instance; - int u = seg%3; int v = seg/3; + int u = seg % 3; + int v = seg / 3; t.addVertexWithUV(sw[u], sh[v], 0, seg_u[u], seg_v[v]); - t.addVertexWithUV(sw[u], sh[v+1], 0, seg_u[u], seg_v[v+1]); - t.addVertexWithUV(sw[u+1], sh[v+1], 0, seg_u[u+1], seg_v[v+1]); - t.addVertexWithUV(sw[u+1], sh[v], 0, seg_u[u+1], seg_v[v]); + t.addVertexWithUV(sw[u], sh[v + 1], 0, seg_u[u], seg_v[v + 1]); + t.addVertexWithUV(sw[u + 1], sh[v + 1], 0, seg_u[u + 1], seg_v[v + 1]); + t.addVertexWithUV(sw[u + 1], sh[v], 0, seg_u[u + 1], seg_v[v]); } public void draw(int x, int y, int w, int h) { @@ -67,11 +65,10 @@ public void draw(int x, int y, int w, int h) { CCRenderState.reset(); CCRenderState.startDrawing(); - int[] sw = new int[]{x, x+seg_w[0], x+w-seg_w[2], x+w}; - int[] sh = new int[]{y, y+seg_h[0], y+h-seg_h[2], y+h}; + int[] sw = new int[] {x, x + seg_w[0], x + w - seg_w[2], x + w}; + int[] sh = new int[] {y, y + seg_h[0], y + h - seg_h[2], y + h}; - for(int seg = 0; seg < 9; seg++) - drawSeg(sw, sh, seg); + for (int seg = 0; seg < 9; seg++) drawSeg(sw, sh, seg); CCRenderState.draw(); } diff --git a/src/main/java/codechicken/lib/gui/GuiDraw.java b/src/main/java/codechicken/lib/gui/GuiDraw.java index bfb280d..a878d4b 100644 --- a/src/main/java/codechicken/lib/gui/GuiDraw.java +++ b/src/main/java/codechicken/lib/gui/GuiDraw.java @@ -2,27 +2,23 @@ import codechicken.lib.math.MathHelper; import codechicken.lib.render.CCRenderState; +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; -import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class GuiDraw -{ - public static class GuiHook extends Gui - { +public class GuiDraw { + public static class GuiHook extends Gui { public void setZLevel(float f) { zLevel = f; } @@ -58,10 +54,8 @@ public static void drawTexturedModalRect(int x, int y, int tx, int ty, int w, in } public static void drawString(String text, int x, int y, int colour, boolean shadow) { - if (shadow) - fontRenderer.drawStringWithShadow(text, x, y, colour); - else - fontRenderer.drawString(text, x, y, colour); + if (shadow) fontRenderer.drawStringWithShadow(text, x, y, colour); + else fontRenderer.drawString(text, x, y, colour); } public static void drawString(String text, int x, int y, int colour) { @@ -137,10 +131,10 @@ public static void drawTip(int x, int y, String text) { * Have a string in the tooltip list with TOOLTIP_HANDLER + getTipLineId(handler) for a custom handler */ public static final String TOOLTIP_HANDLER = "\u00A7x"; + private static List tipLineHandlers = new ArrayList(); - public static interface ITooltipLineHandler - { + public static interface ITooltipLineHandler { public Dimension getSize(); public void draw(int x, int y); @@ -148,12 +142,11 @@ public static interface ITooltipLineHandler public static int getTipLineId(ITooltipLineHandler handler) { tipLineHandlers.add(handler); - return tipLineHandlers.size()-1; + return tipLineHandlers.size() - 1; } public static ITooltipLineHandler getTipLine(String line) { - if(!line.startsWith(TOOLTIP_HANDLER)) - return null; + if (!line.startsWith(TOOLTIP_HANDLER)) return null; return tipLineHandlers.get(Integer.parseInt(line.substring(2))); } @@ -162,8 +155,7 @@ public static void drawMultilineTip(int x, int y, List list) { } public static void drawMultilineTip(FontRenderer font, int x, int y, List list) { - if (list.isEmpty()) - return; + if (list.isEmpty()) return; GL11.glDisable(GL12.GL_RESCALE_NORMAL); GL11.glDisable(GL11.GL_DEPTH_TEST); @@ -174,17 +166,19 @@ public static void drawMultilineTip(FontRenderer font, int x, int y, List displaySize().width - w - 8) { - x -= 24 + w;//flip side of cursor - if(x < 8) x = 8; + x -= 24 + w; // flip side of cursor + if (x < 8) x = 8; } y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h); @@ -192,11 +186,10 @@ else if (x > displaySize().width - w - 8) { drawTooltipBox(x - 4, y - 4, w + 7, h + 7); for (String s : list) { ITooltipLineHandler line = getTipLine(s); - if(line != null) { + if (line != null) { line.draw(x, y); y += line.getSize().height; - } - else { + } else { font.drawStringWithShadow(s, x, y, -1); y += s.endsWith(TOOLTIP_LINESPACE) ? 12 : 10; } @@ -214,7 +207,7 @@ public static void drawTooltipBox(int x, int y, int w, int h) { int bg = 0xf0100010; drawGradientRect(x + 1, y, w - 1, 1, bg, bg); drawGradientRect(x + 1, y + h, w - 1, 1, bg, bg); - drawGradientRect(x + 1, y + 1, w - 1, h - 1, bg, bg);//center + drawGradientRect(x + 1, y + 1, w - 1, h - 1, bg, bg); // center drawGradientRect(x, y + 1, 1, h - 1, bg, bg); drawGradientRect(x + w, y + 1, 1, h - 1, bg, bg); int grad1 = 0x505000ff; diff --git a/src/main/java/codechicken/lib/inventory/ContainerExtended.java b/src/main/java/codechicken/lib/inventory/ContainerExtended.java index 7c7cb15..c365c4c 100644 --- a/src/main/java/codechicken/lib/inventory/ContainerExtended.java +++ b/src/main/java/codechicken/lib/inventory/ContainerExtended.java @@ -1,22 +1,21 @@ package codechicken.lib.inventory; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - import codechicken.lib.packet.PacketCustom; import codechicken.lib.packet.PacketCustom.IClientPacketHandler; import codechicken.lib.packet.PacketCustom.IServerPacketHandler; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; import net.minecraft.client.Minecraft; -import net.minecraft.inventory.Container; -import net.minecraft.inventory.ICrafting; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.item.ItemStack; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ICrafting; import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; import net.minecraft.network.play.INetHandlerPlayClient; import net.minecraft.network.play.INetHandlerPlayServer; import org.apache.logging.log4j.LogManager; @@ -26,37 +25,30 @@ * Easy shift-click handling. * Hooks for slot clicks, large stack sizes and some networking. */ -public abstract class ContainerExtended extends Container implements ICrafting -{ +public abstract class ContainerExtended extends Container implements ICrafting { private static final String netChannel = "CCL:Container"; private static int nextNetworkID = 0; + static { - PacketCustom.assignHandler(netChannel, new IClientPacketHandler() - { + PacketCustom.assignHandler(netChannel, new IClientPacketHandler() { @Override public void handlePacket(PacketCustom packet, Minecraft mc, INetHandlerPlayClient handler) { Container cont = mc.thePlayer.openContainer; - if(!(cont instanceof ContainerExtended)) - return; - - ContainerExtended c = (ContainerExtended)cont; - if(packet.getType() == 1) - c.netID = packet.readInt(); - else if(c.netID == packet.readInt()) - c.handleClientPacket(packet); + if (!(cont instanceof ContainerExtended)) return; + + ContainerExtended c = (ContainerExtended) cont; + if (packet.getType() == 1) c.netID = packet.readInt(); + else if (c.netID == packet.readInt()) c.handleClientPacket(packet); } }); - PacketCustom.assignHandler(netChannel, new IServerPacketHandler() - { + PacketCustom.assignHandler(netChannel, new IServerPacketHandler() { @Override public void handlePacket(PacketCustom packet, EntityPlayerMP sender, INetHandlerPlayServer handler) { Container cont = sender.openContainer; - if(!(cont instanceof ContainerExtended)) - return; + if (!(cont instanceof ContainerExtended)) return; - ContainerExtended c = (ContainerExtended)cont; - if(c.netID == packet.readInt()) - c.handleServerPacket(packet); + ContainerExtended c = (ContainerExtended) cont; + if (c.netID == packet.readInt()) c.handleServerPacket(packet); } }); } @@ -66,8 +58,7 @@ public void handlePacket(PacketCustom packet, EntityPlayerMP sender, INetHandler public ContainerExtended() { crafters.add(this); - if(FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) - netID = ++nextNetworkID; + if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) netID = ++nextNetworkID; } @Override @@ -77,23 +68,18 @@ public void addCraftingToCrafters(ICrafting icrafting) { sendNetID((EntityPlayerMP) icrafting); sendContainerAndContentsToPlayer(this, getInventory(), Arrays.asList((EntityPlayerMP) icrafting)); detectAndSendChanges(); - } else - super.addCraftingToCrafters(icrafting); + } else super.addCraftingToCrafters(icrafting); } private void sendNetID(EntityPlayerMP player) { - if(netID == 0) - LogManager.getLogger("CodeChickenLib").error("Player added to container with 0 network ID"); - else - new PacketCustom(netChannel, 1).writeInt(netID).sendToPlayer(player); + if (netID == 0) LogManager.getLogger("CodeChickenLib").error("Player added to container with 0 network ID"); + else new PacketCustom(netChannel, 1).writeInt(netID).sendToPlayer(player); } @Override public void removeCraftingFromCrafters(ICrafting icrafting) { - if (icrafting instanceof EntityPlayerMP) - playerCrafters.remove(icrafting); - else - super.removeCraftingFromCrafters(icrafting); + if (icrafting instanceof EntityPlayerMP) playerCrafters.remove(icrafting); + else super.removeCraftingFromCrafters(icrafting); } @Override @@ -101,51 +87,43 @@ public void sendContainerAndContentsToPlayer(Container container, List list) { sendContainerAndContentsToPlayer(container, list, playerCrafters); } - public void sendContainerAndContentsToPlayer(Container container, List list, List playerCrafters) { + public void sendContainerAndContentsToPlayer( + Container container, List list, List playerCrafters) { LinkedList largeStacks = new LinkedList(); for (int i = 0; i < list.size(); i++) { ItemStack stack = list.get(i); if (stack != null && stack.stackSize > Byte.MAX_VALUE) { list.set(i, null); largeStacks.add(stack); - } else - largeStacks.add(null); + } else largeStacks.add(null); } - for (EntityPlayerMP player : playerCrafters) - player.sendContainerAndContentsToPlayer(container, list); + for (EntityPlayerMP player : playerCrafters) player.sendContainerAndContentsToPlayer(container, list); for (int i = 0; i < largeStacks.size(); i++) { ItemStack stack = largeStacks.get(i); - if (stack != null) - sendLargeStack(stack, i, playerCrafters); + if (stack != null) sendLargeStack(stack, i, playerCrafters); } } - public void sendLargeStack(ItemStack stack, int slot, List players) { - } + public void sendLargeStack(ItemStack stack, int slot, List players) {} @Override public void sendProgressBarUpdate(Container container, int i, int j) { - for (EntityPlayerMP player : playerCrafters) - player.sendProgressBarUpdate(container, i, j); + for (EntityPlayerMP player : playerCrafters) player.sendProgressBarUpdate(container, i, j); } @Override public void sendSlotContents(Container container, int slot, ItemStack stack) { - if (stack != null && stack.stackSize > Byte.MAX_VALUE) - sendLargeStack(stack, slot, playerCrafters); - else - for (EntityPlayerMP player : playerCrafters) - player.sendSlotContents(container, slot, stack); + if (stack != null && stack.stackSize > Byte.MAX_VALUE) sendLargeStack(stack, slot, playerCrafters); + else for (EntityPlayerMP player : playerCrafters) player.sendSlotContents(container, slot, stack); } @Override public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer player) { if (par1 >= 0 && par1 < inventorySlots.size()) { Slot slot = getSlot(par1); - if (slot instanceof SlotHandleClicks) - return ((SlotHandleClicks) slot).slotClick(this, player, par2, par3); + if (slot instanceof SlotHandleClicks) return ((SlotHandleClicks) slot).slotClick(this, player, par2, par3); } return super.slotClick(par1, par2, par3, player); } @@ -159,13 +137,10 @@ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int slotInde ItemStack stack = slot.getStack(); transferredStack = stack.copy(); - if (!doMergeStackAreas(slotIndex, stack)) - return null; + if (!doMergeStackAreas(slotIndex, stack)) return null; - if (stack.stackSize == 0) - slot.putStack(null); - else - slot.onSlotChanged(); + if (stack.stackSize == 0) slot.putStack(null); + else slot.onSlotChanged(); } return transferredStack; @@ -176,18 +151,18 @@ public boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boo boolean merged = false; int slotIndex = reverse ? endIndex - 1 : startIndex; - if (stack == null) - return false; + if (stack == null) return false; - if (stack.isStackable())//search for stacks to increase + if (stack.isStackable()) // search for stacks to increase { while (stack.stackSize > 0 && (reverse ? slotIndex >= startIndex : slotIndex < endIndex)) { Slot slot = (Slot) inventorySlots.get(slotIndex); ItemStack slotStack = slot.getStack(); - if (slotStack != null && slotStack.getItem() == stack.getItem() && - (!stack.getHasSubtypes() || stack.getItemDamage() == slotStack.getItemDamage()) && - ItemStack.areItemStackTagsEqual(stack, slotStack)) { + if (slotStack != null + && slotStack.getItem() == stack.getItem() + && (!stack.getHasSubtypes() || stack.getItemDamage() == slotStack.getItemDamage()) + && ItemStack.areItemStackTagsEqual(stack, slotStack)) { int totalStackSize = slotStack.stackSize + stack.stackSize; int maxStackSize = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit()); if (totalStackSize <= maxStackSize) { @@ -207,7 +182,7 @@ public boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boo } } - if (stack.stackSize > 0)//normal transfer :) + if (stack.stackSize > 0) // normal transfer :) { slotIndex = reverse ? endIndex - 1 : startIndex; @@ -253,8 +228,7 @@ protected void bindPlayerInventory(InventoryPlayer inventoryPlayer, int x, int y for (int row = 0; row < 3; row++) for (int col = 0; col < 9; col++) addSlotToContainer(new Slot(inventoryPlayer, col + row * 9 + 9, x + col * 18, y + row * 18)); - for (int slot = 0; slot < 9; slot++) - addSlotToContainer(new Slot(inventoryPlayer, slot, x + slot * 18, y + 58)); + for (int slot = 0; slot < 9; slot++) addSlotToContainer(new Slot(inventoryPlayer, slot, x + slot * 18, y + 58)); } @Override @@ -263,8 +237,7 @@ public boolean canInteractWith(EntityPlayer var1) { } public void sendContainerPacket(PacketCustom packet) { - for (EntityPlayerMP player : playerCrafters) - packet.sendToPlayer(player); + for (EntityPlayerMP player : playerCrafters) packet.sendToPlayer(player); } /** @@ -272,10 +245,11 @@ public void sendContainerPacket(PacketCustom packet) { * @return A packet on the CCL inventory channel that will be recieved by this container on the other network side */ public PacketCustom getPacket(int type) { - if(netID == 0) + if (netID == 0) LogManager.getLogger("CodeChickenLib").error("Tried to get packet for container with 0 network ID"); - if(type == 1) - throw new IllegalArgumentException("Packet type 1 is reserved for network synchronisation in ContainerExtended"); + if (type == 1) + throw new IllegalArgumentException( + "Packet type 1 is reserved for network synchronisation in ContainerExtended"); return new PacketCustom(netChannel, type).writeInt(netID); } @@ -291,7 +265,6 @@ public void handleClientPacket(PacketCustom packet) {} public void handleServerPacket(PacketCustom packet) {} public void sendProgressBarUpdate(int barID, int value) { - for (ICrafting crafting : (List) crafters) - crafting.sendProgressBarUpdate(this, barID, value); + for (ICrafting crafting : (List) crafters) crafting.sendProgressBarUpdate(this, barID, value); } } diff --git a/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java b/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java index f2fee59..5213416 100644 --- a/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java +++ b/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java @@ -1,17 +1,14 @@ package codechicken.lib.inventory; +import codechicken.lib.packet.PacketCustom; import java.util.ArrayList; import java.util.Collections; import java.util.List; - import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; -import codechicken.lib.packet.PacketCustom; - -public abstract class ContainerSynchronised extends ContainerExtended -{ +public abstract class ContainerSynchronised extends ContainerExtended { private ArrayList syncVars = new ArrayList(); /** @@ -39,7 +36,8 @@ public final void detectAndSendChanges() { } @Override - public void sendContainerAndContentsToPlayer(Container container, List list, List playerCrafters) { + public void sendContainerAndContentsToPlayer( + Container container, List list, List playerCrafters) { super.sendContainerAndContentsToPlayer(container, list, playerCrafters); for (int i = 0; i < syncVars.size(); i++) { IContainerSyncVar var = syncVars.get(i); @@ -47,8 +45,7 @@ public void sendContainerAndContentsToPlayer(Container container, List accessible.length) - { + if (lslot > accessible.length) { boolean[] l_accessible = new boolean[lslot]; ItemStack[] l_items = new ItemStack[lslot]; System.arraycopy(accessible, 0, l_accessible, 0, accessible.length); @@ -44,83 +37,66 @@ public InventoryCopy open(InventoryRange access) items = l_items; } - for(int slot : access.slots) - accessible[slot] = true; + for (int slot : access.slots) accessible[slot] = true; return this; } - + @Override - public int getSizeInventory() - { + public int getSizeInventory() { return items.length; } @Override - public ItemStack getStackInSlot(int slot) - { + public ItemStack getStackInSlot(int slot) { return items[slot]; } - public ItemStack decrStackSize(int slot, int amount) - { + public ItemStack decrStackSize(int slot, int amount) { return InventoryUtils.decrStackSize(this, slot, amount); } @Override - public ItemStack getStackInSlotOnClosing(int slot) - { + public ItemStack getStackInSlotOnClosing(int slot) { return InventoryUtils.getStackInSlotOnClosing(this, slot); } @Override - public void setInventorySlotContents(int slot, ItemStack stack) - { + public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; markDirty(); } @Override - public String getInventoryName() - { + public String getInventoryName() { return "copy"; } @Override - public boolean isUseableByPlayer(EntityPlayer player) - { + public boolean isUseableByPlayer(EntityPlayer player) { return true; } @Override - public void openInventory() - { - } + public void openInventory() {} @Override - public void closeInventory() - { - } + public void closeInventory() {} @Override - public int getInventoryStackLimit() - { + public int getInventoryStackLimit() { return 64; } - + @Override - public void markDirty() - { - } - + public void markDirty() {} + @Override - public boolean isItemValidForSlot(int i, ItemStack itemstack) - { + public boolean isItemValidForSlot(int i, ItemStack itemstack) { return inv.isItemValidForSlot(i, itemstack); } - + @Override - public boolean hasCustomInventoryName() - { + public boolean hasCustomInventoryName() { return true; } } diff --git a/src/main/java/codechicken/lib/inventory/InventoryNBT.java b/src/main/java/codechicken/lib/inventory/InventoryNBT.java index 45aa54f..1df5f0c 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryNBT.java +++ b/src/main/java/codechicken/lib/inventory/InventoryNBT.java @@ -8,103 +8,83 @@ /** * IInventory implementation which saves and loads from an NBT tag */ -public class InventoryNBT implements IInventory -{ +public class InventoryNBT implements IInventory { protected ItemStack[] items; protected NBTTagCompound tag; - - public InventoryNBT(int size, NBTTagCompound tag) - { + + public InventoryNBT(int size, NBTTagCompound tag) { this.tag = tag; items = new ItemStack[size]; readNBT(); } - - private void writeNBT() - { + + private void writeNBT() { tag.setTag("items", InventoryUtils.writeItemStacksToTag(items, getInventoryStackLimit())); } - - private void readNBT() - { - if(tag.hasKey("items")) - InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items", 10)); + + private void readNBT() { + if (tag.hasKey("items")) InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items", 10)); } - + @Override - public int getSizeInventory() - { + public int getSizeInventory() { return items.length; } @Override - public ItemStack getStackInSlot(int slot) - { + public ItemStack getStackInSlot(int slot) { return items[slot]; } @Override - public ItemStack decrStackSize(int slot, int amount) - { + public ItemStack decrStackSize(int slot, int amount) { return InventoryUtils.decrStackSize(this, slot, amount); } @Override - public ItemStack getStackInSlotOnClosing(int slot) - { + public ItemStack getStackInSlotOnClosing(int slot) { return InventoryUtils.getStackInSlotOnClosing(this, slot); } @Override - public void setInventorySlotContents(int slot, ItemStack stack) - { + public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; markDirty(); } @Override - public String getInventoryName() - { + public String getInventoryName() { return "NBT"; } @Override - public int getInventoryStackLimit() - { + public int getInventoryStackLimit() { return 64; } @Override - public void markDirty() - { + public void markDirty() { writeNBT(); } @Override - public boolean isUseableByPlayer(EntityPlayer var1) - { + public boolean isUseableByPlayer(EntityPlayer var1) { return true; } @Override - public void openInventory() - { - } + public void openInventory() {} @Override - public void closeInventory() - { - } - + public void closeInventory() {} + @Override - public boolean isItemValidForSlot(int i, ItemStack itemstack) - { + public boolean isItemValidForSlot(int i, ItemStack itemstack) { return true; } - + @Override - public boolean hasCustomInventoryName() - { + public boolean hasCustomInventoryName() { return true; } } diff --git a/src/main/java/codechicken/lib/inventory/InventoryRange.java b/src/main/java/codechicken/lib/inventory/InventoryRange.java index 9622325..d5c74b8 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryRange.java +++ b/src/main/java/codechicken/lib/inventory/InventoryRange.java @@ -7,68 +7,52 @@ /** * Inventory wrapper for unified ISided/IInventory access */ -public class InventoryRange -{ +public class InventoryRange { public IInventory inv; public int side; public ISidedInventory sidedInv; public int[] slots; - - public InventoryRange(IInventory inv, int side) - { + + public InventoryRange(IInventory inv, int side) { this.inv = inv; this.side = side; - if(inv instanceof ISidedInventory) - { - sidedInv = (ISidedInventory)inv; + if (inv instanceof ISidedInventory) { + sidedInv = (ISidedInventory) inv; slots = sidedInv.getAccessibleSlotsFromSide(side); - } - else - { + } else { slots = new int[inv.getSizeInventory()]; - for(int i = 0; i < slots.length; i++) - slots[i] = i; + for (int i = 0; i < slots.length; i++) slots[i] = i; } } - public InventoryRange(IInventory inv) - { + public InventoryRange(IInventory inv) { this(inv, 0); } - - public InventoryRange(IInventory inv, int fslot, int size) - { + + public InventoryRange(IInventory inv, int fslot, int size) { this.inv = inv; slots = new int[size]; - for(int i = 0; i < slots.length; i++) - slots[i] = fslot+i; + for (int i = 0; i < slots.length; i++) slots[i] = fslot + i; } - public InventoryRange(IInventory inv, InventoryRange access) - { + public InventoryRange(IInventory inv, InventoryRange access) { this.inv = inv; this.slots = access.slots; this.side = access.side; - if(inv instanceof ISidedInventory) - sidedInv = (ISidedInventory) inv; + if (inv instanceof ISidedInventory) sidedInv = (ISidedInventory) inv; } - public boolean canInsertItem(int slot, ItemStack item) - { + public boolean canInsertItem(int slot, ItemStack item) { return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canInsertItem(slot, item, side); } - - public boolean canExtractItem(int slot, ItemStack item) - { + + public boolean canExtractItem(int slot, ItemStack item) { return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canExtractItem(slot, item, side); } - public int lastSlot() - { + public int lastSlot() { int last = 0; - for(int slot : slots) - if(slot > last) - last = slot; + for (int slot : slots) if (slot > last) last = slot; return last; } } diff --git a/src/main/java/codechicken/lib/inventory/InventorySimple.java b/src/main/java/codechicken/lib/inventory/InventorySimple.java index 4481c23..487e393 100644 --- a/src/main/java/codechicken/lib/inventory/InventorySimple.java +++ b/src/main/java/codechicken/lib/inventory/InventorySimple.java @@ -7,127 +7,102 @@ /** * Simple IInventory implementation with an array of items, name and maximum stack size */ -public class InventorySimple implements IInventory -{ +public class InventorySimple implements IInventory { public ItemStack[] items; public int limit; public String name; - - public InventorySimple(ItemStack[] items, int limit, String name) - { + + public InventorySimple(ItemStack[] items, int limit, String name) { this.items = items; this.limit = limit; this.name = name; } - - public InventorySimple(ItemStack[] items, String name) - { + + public InventorySimple(ItemStack[] items, String name) { this(items, 64, name); } - - public InventorySimple(ItemStack[] items, int limit) - { + + public InventorySimple(ItemStack[] items, int limit) { this(items, limit, "inv"); } - - public InventorySimple(ItemStack[] items) - { + + public InventorySimple(ItemStack[] items) { this(items, 64, "inv"); } - public InventorySimple(int size, int limit, String name) - { + public InventorySimple(int size, int limit, String name) { this(new ItemStack[size], limit, name); } - - public InventorySimple(int size, int limit) - { + + public InventorySimple(int size, int limit) { this(size, limit, "inv"); } - - public InventorySimple(int size, String name) - { + + public InventorySimple(int size, String name) { this(size, 64, name); } - - public InventorySimple(int size) - { + + public InventorySimple(int size) { this(size, 64, "inv"); } @Override - public int getSizeInventory() - { + public int getSizeInventory() { return items.length; } @Override - public ItemStack getStackInSlot(int slot) - { + public ItemStack getStackInSlot(int slot) { return items[slot]; } @Override - public ItemStack decrStackSize(int slot, int amount) - { + public ItemStack decrStackSize(int slot, int amount) { return InventoryUtils.decrStackSize(this, slot, amount); } @Override - public ItemStack getStackInSlotOnClosing(int slot) - { + public ItemStack getStackInSlotOnClosing(int slot) { return InventoryUtils.getStackInSlotOnClosing(this, slot); } @Override - public void setInventorySlotContents(int slot, ItemStack stack) - { + public void setInventorySlotContents(int slot, ItemStack stack) { items[slot] = stack; markDirty(); } @Override - public String getInventoryName() - { + public String getInventoryName() { return name; } @Override - public int getInventoryStackLimit() - { + public int getInventoryStackLimit() { return limit; } @Override - public boolean isUseableByPlayer(EntityPlayer var1) - { + public boolean isUseableByPlayer(EntityPlayer var1) { return true; } @Override - public void openInventory() - { - } + public void openInventory() {} @Override - public void closeInventory() - { - } - + public void closeInventory() {} + @Override - public boolean isItemValidForSlot(int i, ItemStack itemstack) - { + public boolean isItemValidForSlot(int i, ItemStack itemstack) { return true; } - + @Override - public boolean hasCustomInventoryName() - { + public boolean hasCustomInventoryName() { return true; } - + @Override - public void markDirty() - { - } + public void markDirty() {} } diff --git a/src/main/java/codechicken/lib/inventory/InventoryUtils.java b/src/main/java/codechicken/lib/inventory/InventoryUtils.java index 757a1f6..17ac44f 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryUtils.java +++ b/src/main/java/codechicken/lib/inventory/InventoryUtils.java @@ -17,8 +17,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; -public class InventoryUtils -{ +public class InventoryUtils { /** * Constructor for ItemStack with tag */ @@ -48,10 +47,8 @@ public static ItemStack decrStackSize(IInventory inv, int slot, int size) { return item; } ItemStack itemstack1 = item.splitStack(size); - if (item.stackSize == 0) - inv.setInventorySlotContents(slot, null); - else - inv.setInventorySlotContents(slot, item); + if (item.stackSize == 0) inv.setInventorySlotContents(slot, null); + else inv.setInventorySlotContents(slot, item); inv.markDirty(); return itemstack1; @@ -72,8 +69,7 @@ public static ItemStack getStackInSlotOnClosing(IInventory inv, int slot) { * @return The quantity of items from addition that can be added to base */ public static int incrStackSize(ItemStack base, ItemStack addition) { - if (canStack(base, addition)) - return incrStackSize(base, addition.stackSize); + if (canStack(base, addition)) return incrStackSize(base, addition.stackSize); return 0; } @@ -84,10 +80,8 @@ public static int incrStackSize(ItemStack base, ItemStack addition) { public static int incrStackSize(ItemStack base, int addition) { int totalSize = base.stackSize + addition; - if (totalSize <= base.getMaxStackSize()) - return addition; - else if (base.stackSize < base.getMaxStackSize()) - return base.getMaxStackSize() - base.stackSize; + if (totalSize <= base.getMaxStackSize()) return addition; + else if (base.stackSize < base.getMaxStackSize()) return base.getMaxStackSize() - base.stackSize; return 0; } @@ -110,10 +104,8 @@ public static NBTTagList writeItemStacksToTag(ItemStack[] items, int maxQuantity tag.setShort("Slot", (short) i); items[i].writeToNBT(tag); - if (maxQuantity > Short.MAX_VALUE) - tag.setInteger("Quantity", items[i].stackSize); - else if (maxQuantity > Byte.MAX_VALUE) - tag.setShort("Quantity", (short) items[i].stackSize); + if (maxQuantity > Short.MAX_VALUE) tag.setInteger("Quantity", items[i].stackSize); + else if (maxQuantity > Byte.MAX_VALUE) tag.setShort("Quantity", (short) items[i].stackSize); tagList.appendTag(tag); } @@ -149,8 +141,7 @@ public static void dropItem(ItemStack stack, World world, Vector3 dropLocation) * Copies an itemstack with a new quantity */ public static ItemStack copyStack(ItemStack stack, int quantity) { - if (stack == null) - return null; + if (stack == null) return null; stack = stack.copy(); stack.stackSize = quantity; @@ -163,8 +154,7 @@ public static ItemStack copyStack(ItemStack stack, int quantity) { public static int getInsertibleQuantity(InventoryRange inv, ItemStack stack) { int quantity = 0; stack = copyStack(stack, Integer.MAX_VALUE); - for (int slot : inv.slots) - quantity += fitStackInSlot(inv, slot, stack); + for (int slot : inv.slots) quantity += fitStackInSlot(inv, slot, stack); return quantity; } @@ -175,10 +165,11 @@ public static int getInsertibleQuantity(IInventory inv, ItemStack stack) { public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) { ItemStack base = inv.inv.getStackInSlot(slot); - if (!canStack(base, stack) || !inv.canInsertItem(slot, stack)) - return 0; + if (!canStack(base, stack) || !inv.canInsertItem(slot, stack)) return 0; - int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit() - base.stackSize) : inv.inv.getInventoryStackLimit(); + int fit = base != null + ? incrStackSize(base, inv.inv.getInventoryStackLimit() - base.stackSize) + : inv.inv.getInventoryStackLimit(); return Math.min(fit, stack.stackSize); } @@ -195,11 +186,9 @@ public static int insertItem(InventoryRange inv, ItemStack stack, boolean simula for (int pass = 0; pass < 2; pass++) { for (int slot : inv.slots) { ItemStack base = inv.inv.getStackInSlot(slot); - if((pass == 0) == (base == null)) - continue; + if ((pass == 0) == (base == null)) continue; int fit = fitStackInSlot(inv, slot, stack); - if (fit == 0) - continue; + if (fit == 0) continue; if (base != null) { stack.stackSize -= fit; @@ -208,12 +197,10 @@ public static int insertItem(InventoryRange inv, ItemStack stack, boolean simula inv.inv.setInventorySlotContents(slot, base); } } else { - if (!simulate) - inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); + if (!simulate) inv.inv.setInventorySlotContents(slot, copyStack(stack, fit)); stack.stackSize -= fit; } - if (stack.stackSize == 0) - return 0; + if (stack.stackSize == 0) return 0; } } return stack.stackSize; @@ -228,8 +215,7 @@ public static int insertItem(IInventory inv, ItemStack stack, boolean simulate) */ public static ItemStack getExtractableStack(InventoryRange inv, int slot) { ItemStack stack = inv.inv.getStackInSlot(slot); - if (stack == null || !inv.canExtractItem(slot, stack)) - return null; + if (stack == null || !inv.canExtractItem(slot, stack)) return null; return stack; } @@ -239,8 +225,7 @@ public static ItemStack getExtractableStack(IInventory inv, int slot) { } public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { - if (stack1 == null || stack2 == null) - return stack1 == stack2; + if (stack1 == null || stack2 == null) return stack1 == stack2; return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() @@ -253,32 +238,42 @@ public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { */ public static IInventory getInventory(World world, int x, int y, int z) { TileEntity tile = world.getTileEntity(x, y, z); - if (!(tile instanceof IInventory)) - return null; + if (!(tile instanceof IInventory)) return null; - if (tile instanceof TileEntityChest) - return getChest((TileEntityChest) tile); + if (tile instanceof TileEntityChest) return getChest((TileEntityChest) tile); return (IInventory) tile; - } - public static final ForgeDirection[] chestSides = new ForgeDirection[]{ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; + public static final ForgeDirection[] chestSides = + new ForgeDirection[] {ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; public static IInventory getChest(TileEntityChest chest) { for (ForgeDirection fside : chestSides) { - if (chest.getWorldObj().getBlock(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ) == chest.getBlockType()) - return new InventoryLargeChest("container.chestDouble", - (TileEntityChest) chest.getWorldObj().getTileEntity(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ), chest); + if (chest.getWorldObj() + .getBlock( + chest.xCoord + fside.offsetX, + chest.yCoord + fside.offsetY, + chest.zCoord + fside.offsetZ) + == chest.getBlockType()) + return new InventoryLargeChest( + "container.chestDouble", + (TileEntityChest) chest.getWorldObj() + .getTileEntity( + chest.xCoord + fside.offsetX, + chest.yCoord + fside.offsetY, + chest.zCoord + fside.offsetZ), + chest); } return chest; } public static boolean canStack(ItemStack stack1, ItemStack stack2) { - return stack1 == null || stack2 == null || - (stack1.getItem() == stack2.getItem() && - (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) && - ItemStack.areItemStackTagsEqual(stack2, stack1)) && - stack1.isStackable(); + return stack1 == null + || stack2 == null + || (stack1.getItem() == stack2.getItem() + && (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) + && ItemStack.areItemStackTagsEqual(stack2, stack1)) + && stack1.isStackable(); } /** @@ -309,8 +304,7 @@ public static int stackSize(IInventory inv, int slot) { public static void dropOnClose(EntityPlayer player, IInventory inv) { for (int i = 0; i < inv.getSizeInventory(); i++) { ItemStack stack = inv.getStackInSlotOnClosing(i); - if (stack != null) - player.dropPlayerItemWithRandomChoice(stack, false); + if (stack != null) player.dropPlayerItemWithRandomChoice(stack, false); } } @@ -324,12 +318,11 @@ public static NBTTagCompound savePersistant(ItemStack stack, NBTTagCompound tag) public static ItemStack loadPersistant(NBTTagCompound tag) { String name = tag.getString("name"); Item item = (Item) Item.itemRegistry.getObject(name); - if(item == null) return null; + if (item == null) return null; int count = tag.hasKey("Count") ? tag.getByte("Count") : 1; int damage = tag.hasKey("Damage") ? tag.getShort("Damage") : 0; ItemStack stack = new ItemStack(item, count, damage); - if(tag.hasKey("tag", 10)) - stack.stackTagCompound = tag.getCompoundTag("tag"); + if (tag.hasKey("tag", 10)) stack.stackTagCompound = tag.getCompoundTag("tag"); return stack; } } diff --git a/src/main/java/codechicken/lib/inventory/ItemKey.java b/src/main/java/codechicken/lib/inventory/ItemKey.java index 71d3c50..d4b7d7e 100644 --- a/src/main/java/codechicken/lib/inventory/ItemKey.java +++ b/src/main/java/codechicken/lib/inventory/ItemKey.java @@ -1,18 +1,17 @@ package codechicken.lib.inventory; +import static codechicken.lib.inventory.InventoryUtils.actualDamage; + import com.google.common.base.Objects; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.oredict.OreDictionary; -import static codechicken.lib.inventory.InventoryUtils.actualDamage; - /** * Comparable ItemStack with a hashCode implementation. */ -public class ItemKey implements Comparable -{ +public class ItemKey implements Comparable { public ItemStack stack; private int hashcode = 0; @@ -35,18 +34,19 @@ public ItemKey(Item item, int damage, NBTTagCompound tag) { @Override public boolean equals(Object obj) { - if (!(obj instanceof ItemKey)) - return false; + if (!(obj instanceof ItemKey)) return false; ItemKey k = (ItemKey) obj; - return stack.getItem() == k.stack.getItem() && - actualDamage(stack) == actualDamage(k.stack) && - Objects.equal(stack.stackTagCompound, k.stack.stackTagCompound); + return stack.getItem() == k.stack.getItem() + && actualDamage(stack) == actualDamage(k.stack) + && Objects.equal(stack.stackTagCompound, k.stack.stackTagCompound); } @Override public int hashCode() { - return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(stack.getItem(), actualDamage(stack), stack.stackTagCompound)); + return hashcode != 0 + ? hashcode + : (hashcode = Objects.hashCode(stack.getItem(), actualDamage(stack), stack.stackTagCompound)); } public int compareInt(int a, int b) { @@ -57,8 +57,7 @@ public int compareInt(int a, int b) { public int compareTo(ItemKey o) { if (stack.getItem() != o.stack.getItem()) return compareInt(Item.getIdFromItem(stack.getItem()), Item.getIdFromItem(o.stack.getItem())); - if (actualDamage(stack) != actualDamage(o.stack)) - return compareInt(actualDamage(stack), actualDamage(o.stack)); + if (actualDamage(stack) != actualDamage(o.stack)) return compareInt(actualDamage(stack), actualDamage(o.stack)); return 0; } } diff --git a/src/main/java/codechicken/lib/inventory/SlotDummy.java b/src/main/java/codechicken/lib/inventory/SlotDummy.java index d72320c..a695e29 100644 --- a/src/main/java/codechicken/lib/inventory/SlotDummy.java +++ b/src/main/java/codechicken/lib/inventory/SlotDummy.java @@ -4,69 +4,51 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -public class SlotDummy extends SlotHandleClicks -{ +public class SlotDummy extends SlotHandleClicks { public final int stackLimit; - public SlotDummy(IInventory inv, int slot, int x, int y) - { + + public SlotDummy(IInventory inv, int slot, int x, int y) { this(inv, slot, x, y, 64); } - - public SlotDummy(IInventory inv, int slot, int x, int y, int limit) - { + + public SlotDummy(IInventory inv, int slot, int x, int y, int limit) { super(inv, slot, x, y); stackLimit = limit; } - + @Override - public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) - { + public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) { ItemStack held = player.inventory.getItemStack(); boolean shift = modifier == 1; slotClick(held, button, shift); return null; } - - public void slotClick(ItemStack held, int button, boolean shift) - { + + public void slotClick(ItemStack held, int button, boolean shift) { ItemStack tstack = getStack(); - if(held != null && (tstack == null || !InventoryUtils.canStack(held, tstack))) - { + if (held != null && (tstack == null || !InventoryUtils.canStack(held, tstack))) { int quantity = Math.min(held.stackSize, stackLimit); - if(shift) - quantity = Math.min(stackLimit, held.getMaxStackSize()*16); - if(button == 1) - quantity = 1; + if (shift) quantity = Math.min(stackLimit, held.getMaxStackSize() * 16); + if (button == 1) quantity = 1; putStack(InventoryUtils.copyStack(held, quantity)); - } - else if(tstack != null) - { + } else if (tstack != null) { int inc; - if(held != null) - { + if (held != null) { inc = button == 1 ? -held.stackSize : held.stackSize; - if(shift) - inc *= 16; - } - else - { + if (shift) inc *= 16; + } else { inc = button == 1 ? -1 : 1; - if(shift) - inc *= 16; + if (shift) inc *= 16; } - int quantity = tstack.stackSize+inc; - if(quantity <= 0) - putStack(null); - else - putStack(InventoryUtils.copyStack(tstack, quantity)); + int quantity = tstack.stackSize + inc; + if (quantity <= 0) putStack(null); + else putStack(InventoryUtils.copyStack(tstack, quantity)); } } - + @Override - public void putStack(ItemStack stack) - { - if(stack != null && stack.stackSize > stackLimit) - stack = InventoryUtils.copyStack(stack, stackLimit); + public void putStack(ItemStack stack) { + if (stack != null && stack.stackSize > stackLimit) stack = InventoryUtils.copyStack(stack, stackLimit); super.putStack(stack); } } diff --git a/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java b/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java index b8fab64..9b5d7e8 100644 --- a/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java +++ b/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java @@ -4,16 +4,13 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -public class SlotDummyOutput extends SlotHandleClicks -{ - public SlotDummyOutput(IInventory inv, int slot, int x, int y) - { +public class SlotDummyOutput extends SlotHandleClicks { + public SlotDummyOutput(IInventory inv, int slot, int x, int y) { super(inv, slot, x, y); } - + @Override - public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) - { + public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) { return null; } } diff --git a/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java b/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java index 7e56ddd..9a4b7f6 100644 --- a/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java +++ b/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java @@ -5,10 +5,8 @@ import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; -public abstract class SlotHandleClicks extends Slot -{ - public SlotHandleClicks(IInventory inv, int slot, int x, int y) - { +public abstract class SlotHandleClicks extends Slot { + public SlotHandleClicks(IInventory inv, int slot, int x, int y) { super(inv, slot, x, y); } diff --git a/src/main/java/codechicken/lib/lighting/LC.java b/src/main/java/codechicken/lib/lighting/LC.java index c2409fb..187d518 100644 --- a/src/main/java/codechicken/lib/lighting/LC.java +++ b/src/main/java/codechicken/lib/lighting/LC.java @@ -5,8 +5,7 @@ import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -public class LC implements Copyable -{ +public class LC implements Copyable { public int side; public float fa; public float fb; @@ -40,8 +39,7 @@ public LC set(LC lc) { public LC compute(Vector3 vec, Vector3 normal) { int side = CCModel.findSide(normal); - if (side < 0) - return set(12, 1, 0, 0, 0); + if (side < 0) return set(12, 1, 0, 0, 0); return compute(vec, side); } @@ -67,8 +65,7 @@ public LC compute(Vector3 vec, int side) { offset = vec.x >= 1; break; } - if (!offset) - side += 6; + if (!offset) side += 6; return computeO(vec, side); } @@ -86,4 +83,4 @@ public LC computeO(Vector3 vec, int side) { public LC copy() { return new LC(side, fa, fb, fc, fd); } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/lighting/LightMatrix.java b/src/main/java/codechicken/lib/lighting/LightMatrix.java index 1962eb0..30012cd 100644 --- a/src/main/java/codechicken/lib/lighting/LightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/LightMatrix.java @@ -10,8 +10,7 @@ /** * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> (x+1, y+1, z+1) */ -public class LightMatrix implements CCRenderState.IVertexOperation -{ +public class LightMatrix implements CCRenderState.IVertexOperation { public static final int operationIndex = CCRenderState.registerOperation(); public int computed = 0; @@ -28,30 +27,34 @@ public class LightMatrix implements CCRenderState.IVertexOperation /** * The 9 positions in the sample array for each side, sides >= 6 are centered on sample 13 (the block itself) */ - public static final int[][] ssamplem = new int[][]{ - { 0, 1, 2, 3, 4, 5, 6, 7, 8}, - {18,19,20,21,22,23,24,25,26}, - { 0, 9,18, 1,10,19, 2,11,20}, - { 6,15,24, 7,16,25, 8,17,26}, - { 0, 3, 6, 9,12,15,18,21,24}, - { 2, 5, 8,11,14,17,20,23,26}, - { 9,10,11,12,13,14,15,16,17}, - { 9,10,11,12,13,14,15,16,17}, - { 3,12,21, 4,13,22, 5,14,23}, - { 3,12,21, 4,13,22, 5,14,23}, - { 1, 4, 7,10,13,16,19,22,25}, - { 1, 4, 7,10,13,16,19,22,25}, - {13,13,13,13,13,13,13,13,13}}; - public static final int[][] qsamplem = new int[][]{//the positions in the side sample array for each corner - {0,1,3,4}, - {5,1,2,4}, - {6,7,3,4}, - {5,7,8,4}}; - public static final float[] sideao = new float[]{ + public static final int[][] ssamplem = new int[][] { + {0, 1, 2, 3, 4, 5, 6, 7, 8}, + {18, 19, 20, 21, 22, 23, 24, 25, 26}, + {0, 9, 18, 1, 10, 19, 2, 11, 20}, + {6, 15, 24, 7, 16, 25, 8, 17, 26}, + {0, 3, 6, 9, 12, 15, 18, 21, 24}, + {2, 5, 8, 11, 14, 17, 20, 23, 26}, + {9, 10, 11, 12, 13, 14, 15, 16, 17}, + {9, 10, 11, 12, 13, 14, 15, 16, 17}, + {3, 12, 21, 4, 13, 22, 5, 14, 23}, + {3, 12, 21, 4, 13, 22, 5, 14, 23}, + {1, 4, 7, 10, 13, 16, 19, 22, 25}, + {1, 4, 7, 10, 13, 16, 19, 22, 25}, + {13, 13, 13, 13, 13, 13, 13, 13, 13} + }; + + public static final int[][] qsamplem = new int[][] { // the positions in the side sample array for each corner + {0, 1, 3, 4}, + {5, 1, 2, 4}, + {6, 7, 3, 4}, + {5, 7, 8, 4} + }; + public static final float[] sideao = new float[] { 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, - 1F}; - + 1F + }; + /*static { int[][] os = new int[][]{ @@ -61,7 +64,7 @@ public class LightMatrix implements CCRenderState.IVertexOperation {0,0, 1}, {-1,0,0}, { 1,0,0}}; - + for(int s = 0; s < 12; s++) { int[] d0 = s < 6 ? new int[]{os[s][0]+1, os[s][1]+1, os[s][2]+1} : new int[]{1, 1, 1}; @@ -110,16 +113,18 @@ public void sideSample(int side) { int[] qsample = qsamplem[q]; if (Minecraft.isAmbientOcclusionEnabled()) interp(side, q, ssample[qsample[0]], ssample[qsample[1]], ssample[qsample[2]], ssample[qsample[3]]); - else - interp(side, q, ssample[4], ssample[4], ssample[4], ssample[4]); + else interp(side, q, ssample[4], ssample[4], ssample[4], ssample[4]); } computed |= 1 << side; } } private void interp(int s, int q, int a, int b, int c, int d) { - sample(a); sample(b); sample(c); sample(d); - ao[s][q] = interpAO(aSamples[a], aSamples[b], aSamples[c], aSamples[d])*sideao[s]; + sample(a); + sample(b); + sample(c); + sample(d); + ao[s][q] = interpAO(aSamples[a], aSamples[b], aSamples[c], aSamples[d]) * sideao[s]; brightness[s][q] = interpBrightness(bSamples[a], bSamples[b], bSamples[c], bSamples[d]); } @@ -128,19 +133,15 @@ public static float interpAO(float a, float b, float c, float d) { } public static int interpBrightness(int a, int b, int c, int d) { - if (a == 0) - a = d; - if (b == 0) - b = d; - if (c == 0) - c = d; + if (a == 0) a = d; + if (b == 0) b = d; + if (c == 0) c = d; return (a + b + c + d) >> 2 & 0xFF00FF; } @Override public boolean load() { - if(!CCRenderState.computeLighting) - return false; + if (!CCRenderState.computeLighting) return false; CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); @@ -161,4 +162,4 @@ public void operate() { public int operationID() { return operationIndex; } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java index eca2f9d..7867ff8 100644 --- a/src/main/java/codechicken/lib/lighting/LightModel.java +++ b/src/main/java/codechicken/lib/lighting/LightModel.java @@ -4,12 +4,10 @@ import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Vector3; -public class LightModel implements CCRenderState.IVertexOperation -{ +public class LightModel implements CCRenderState.IVertexOperation { public static final int operationIndex = CCRenderState.registerOperation(); - public static class Light - { + public static class Light { public Vector3 ambient = new Vector3(); public Vector3 diffuse = new Vector3(); public Vector3 position; @@ -28,17 +26,16 @@ public Light setAmbient(Vector3 vec) { return this; } } - + public static LightModel standardLightModel; + static { standardLightModel = new LightModel() .setAmbient(new Vector3(0.4, 0.4, 0.4)) - .addLight(new Light(new Vector3(0.2, 1, -0.7)) - .setDiffuse(new Vector3(0.6, 0.6, 0.6))) - .addLight(new Light(new Vector3(-0.2, 1, 0.7)) - .setDiffuse(new Vector3(0.6, 0.6, 0.6))); + .addLight(new Light(new Vector3(0.2, 1, -0.7)).setDiffuse(new Vector3(0.6, 0.6, 0.6))) + .addLight(new Light(new Vector3(-0.2, 1, 0.7)).setDiffuse(new Vector3(0.6, 0.6, 0.6))); } - + private Vector3 ambient = new Vector3(); private Light[] lights = new Light[8]; private int lightCount; @@ -69,21 +66,20 @@ public int apply(int colour, Vector3 normal) { n_colour.z += light.ambient.z + f * light.diffuse.z * n_l; } - if (n_colour.x > 1) - n_colour.x = 1; - if (n_colour.y > 1) - n_colour.y = 1; - if (n_colour.z > 1) - n_colour.z = 1; + if (n_colour.x > 1) n_colour.x = 1; + if (n_colour.y > 1) n_colour.y = 1; + if (n_colour.z > 1) n_colour.z = 1; n_colour.multiply((colour >>> 24) / 255D, (colour >> 16 & 0xFF) / 255D, (colour >> 8 & 0xFF) / 255D); - return (int) (n_colour.x * 255) << 24 | (int) (n_colour.y * 255) << 16 | (int) (n_colour.z * 255) << 8 | colour & 0xFF; + return (int) (n_colour.x * 255) << 24 + | (int) (n_colour.y * 255) << 16 + | (int) (n_colour.z * 255) << 8 + | colour & 0xFF; } @Override public boolean load() { - if(!CCRenderState.computeLighting) - return false; + if (!CCRenderState.computeLighting) return false; CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); @@ -102,8 +98,7 @@ public int operationID() { public PlanarLightModel reducePlanar() { int[] colours = new int[6]; - for (int i = 0; i < 6; i++) - colours[i] = apply(-1, Rotation.axes[i]); + for (int i = 0; i < 6; i++) colours[i] = apply(-1, Rotation.axes[i]); return new PlanarLightModel(colours); } } diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java index f557fe5..cbaed30 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java @@ -5,8 +5,7 @@ import net.minecraft.block.Block; import net.minecraft.world.IBlockAccess; -public class PlanarLightMatrix extends PlanarLightModel -{ +public class PlanarLightMatrix extends PlanarLightModel { public static final int operationIndex = CCRenderState.registerOperation(); public static PlanarLightMatrix instance = new PlanarLightMatrix(); @@ -28,9 +27,10 @@ public PlanarLightMatrix locate(IBlockAccess a, int x, int y, int z) { } public int brightness(int side) { - if((sampled & 1 << side) == 0) { + if ((sampled & 1 << side) == 0) { Block b = access.getBlock(pos.x, pos.y, pos.z); - brightness[side] = access.getLightBrightnessForSkyBlocks(pos.x, pos.y, pos.z, b.getLightValue(access, pos.x, pos.y, pos.z)); + brightness[side] = access.getLightBrightnessForSkyBlocks( + pos.x, pos.y, pos.z, b.getLightValue(access, pos.x, pos.y, pos.z)); sampled |= 1 << side; } return brightness[side]; diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java index 3923198..645eb45 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java @@ -6,8 +6,7 @@ /** * Faster precomputed version of LightModel that only works for axis planar sides */ -public class PlanarLightModel implements CCRenderState.IVertexOperation -{ +public class PlanarLightModel implements CCRenderState.IVertexOperation { public static PlanarLightModel standardLightModel = LightModel.standardLightModel.reducePlanar(); public int[] colours; @@ -18,8 +17,7 @@ public PlanarLightModel(int[] colours) { @Override public boolean load() { - if(!CCRenderState.computeLighting) - return false; + if (!CCRenderState.computeLighting) return false; CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); diff --git a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java index 942e1c3..5fa6fed 100644 --- a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java +++ b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java @@ -8,8 +8,7 @@ /** * Faster precomputed version of LightModel that only works for axis planar sides */ -public class SimpleBrightnessModel implements CCRenderState.IVertexOperation -{ +public class SimpleBrightnessModel implements CCRenderState.IVertexOperation { public static final int operationIndex = CCRenderState.registerOperation(); public static SimpleBrightnessModel instance = new SimpleBrightnessModel(); @@ -30,7 +29,8 @@ public int sample(int side) { if ((sampled & 1 << side) == 0) { c.set(pos).offset(side); Block block = access.getBlock(c.x, c.y, c.z); - samples[side] = access.getLightBrightnessForSkyBlocks(c.x, c.y, c.z, block.getLightValue(access, c.x, c.y, c.z)); + samples[side] = + access.getLightBrightnessForSkyBlocks(c.x, c.y, c.z, block.getLightValue(access, c.x, c.y, c.z)); sampled |= 1 << side; } return samples[side]; diff --git a/src/main/java/codechicken/lib/math/MathHelper.java b/src/main/java/codechicken/lib/math/MathHelper.java index 2da16b0..331398d 100644 --- a/src/main/java/codechicken/lib/math/MathHelper.java +++ b/src/main/java/codechicken/lib/math/MathHelper.java @@ -1,59 +1,49 @@ package codechicken.lib.math; -public class MathHelper -{ +public class MathHelper { public static final double phi = 1.618033988749894; public static final double pi = Math.PI; public static final double todeg = 57.29577951308232; public static final double torad = 0.017453292519943; public static final double sqrt2 = 1.414213562373095; - + public static double[] SIN_TABLE = new double[65536]; - static - { - for (int i = 0; i < 65536; ++i) - SIN_TABLE[i] = Math.sin(i / 65536D * 2 * Math.PI); - + + static { + for (int i = 0; i < 65536; ++i) SIN_TABLE[i] = Math.sin(i / 65536D * 2 * Math.PI); + SIN_TABLE[0] = 0; SIN_TABLE[16384] = 1; SIN_TABLE[32768] = 0; SIN_TABLE[49152] = 1; } - - public static double sin(double d) - { - return SIN_TABLE[(int)((float)d * 10430.378F) & 65535]; + + public static double sin(double d) { + return SIN_TABLE[(int) ((float) d * 10430.378F) & 65535]; } - - public static double cos(double d) - { - return SIN_TABLE[(int)((float)d * 10430.378F + 16384.0F) & 65535]; + + public static double cos(double d) { + return SIN_TABLE[(int) ((float) d * 10430.378F + 16384.0F) & 65535]; } - + /** * @param a The value * @param b The value to approach * @param max The maximum step * @return the closed value to b no less than max from a */ - public static float approachLinear(float a, float b, float max) - { - return (a > b) ? - (a - b < max ? b : a-max) : - (b - a < max ? b : a+max); + public static float approachLinear(float a, float b, float max) { + return (a > b) ? (a - b < max ? b : a - max) : (b - a < max ? b : a + max); } - + /** * @param a The value * @param b The value to approach * @param max The maximum step * @return the closed value to b no less than max from a */ - public static double approachLinear(double a, double b, double max) - { - return (a > b) ? - (a - b < max ? b : a-max) : - (b - a < max ? b : a+max); + public static double approachLinear(double a, double b, double max) { + return (a > b) ? (a - b < max ? b : a - max) : (b - a < max ? b : a + max); } /** @@ -62,9 +52,8 @@ public static double approachLinear(double a, double b, double max) * @param d The interpolation factor, between 0 and 1 * @return a+(b-a)*d */ - public static float interpolate(float a, float b, float d) - { - return a+(b-a)*d; + public static float interpolate(float a, float b, float d) { + return a + (b - a) * d; } /** @@ -73,20 +62,18 @@ public static float interpolate(float a, float b, float d) * @param d The interpolation factor, between 0 and 1 * @return a+(b-a)*d */ - public static double interpolate(double a, double b, double d) - { - return a+(b-a)*d; + public static double interpolate(double a, double b, double d) { + return a + (b - a) * d; } - + /** * @param a The value * @param b The value to approach * @param ratio The ratio to reduce the difference by * @return a+(b-a)*ratio */ - public static double approachExp(double a, double b, double ratio) - { - return a+(b-a)*ratio; + public static double approachExp(double a, double b, double ratio) { + return a + (b - a) * ratio; } /** @@ -96,12 +83,10 @@ public static double approachExp(double a, double b, double ratio) * @param cap The maximum amount to advance by * @return a+(b-a)*ratio */ - public static double approachExp(double a, double b, double ratio, double cap) - { - double d = (b-a)*ratio; - if(Math.abs(d) > cap) - d = Math.signum(d)*cap; - return a+d; + public static double approachExp(double a, double b, double ratio, double cap) { + double d = (b - a) * ratio; + if (Math.abs(d) > cap) d = Math.signum(d) * cap; + return a + d; } /** @@ -112,67 +97,55 @@ public static double approachExp(double a, double b, double ratio, double cap) * @param kick The difference when a == c * @return */ - public static double retreatExp(double a, double b, double c, double ratio, double kick) - { - double d = (Math.abs(c-a)+kick)*ratio; - if(d > Math.abs(b-a)) - return b; - return a+Math.signum(b-a)*d; + public static double retreatExp(double a, double b, double c, double ratio, double kick) { + double d = (Math.abs(c - a) + kick) * ratio; + if (d > Math.abs(b - a)) return b; + return a + Math.signum(b - a) * d; } /** - * + * * @param value The value * @param min The min value * @param max The max value * @return The clipped value between min and max */ - public static double clip(double value, double min, double max) - { - if(value > max) - value = max; - if(value < min) - value = min; + public static double clip(double value, double min, double max) { + if (value > max) value = max; + if (value < min) value = min; return value; } /** * @return a <= x <= b */ - public static boolean between(double a, double x, double b) - { + public static boolean between(double a, double x, double b) { return a <= x && x <= b; } - public static int approachExpI(int a, int b, double ratio) - { - int r = (int)Math.round(approachExp(a, b, ratio)); + public static int approachExpI(int a, int b, double ratio) { + int r = (int) Math.round(approachExp(a, b, ratio)); return r == a ? b : r; } - public static int retreatExpI(int a, int b, int c, double ratio, int kick) - { - int r = (int)Math.round(retreatExp(a, b, c, ratio, kick)); + public static int retreatExpI(int a, int b, int c, double ratio, int kick) { + int r = (int) Math.round(retreatExp(a, b, c, ratio, kick)); return r == a ? b : r; } - - public static int floor_double(double d) - { + + public static int floor_double(double d) { return net.minecraft.util.MathHelper.floor_double(d); } - - public static int roundAway(double d) - { + + public static int roundAway(double d) { return (int) (d < 0 ? Math.floor(d) : Math.ceil(d)); } - - public static int compare(int a, int b) - { + + public static int compare(int a, int b) { return a == b ? 0 : a < b ? -1 : 1; } - - public static int compare(double a, double b) - { + + public static int compare(double a, double b) { return a == b ? 0 : a < b ? -1 : 1; } } diff --git a/src/main/java/codechicken/lib/packet/ICustomPacketTile.java b/src/main/java/codechicken/lib/packet/ICustomPacketTile.java index d6832db..9bf9e03 100644 --- a/src/main/java/codechicken/lib/packet/ICustomPacketTile.java +++ b/src/main/java/codechicken/lib/packet/ICustomPacketTile.java @@ -1,6 +1,5 @@ package codechicken.lib.packet; -public interface ICustomPacketTile -{ +public interface ICustomPacketTile { public void handleDescriptionPacket(PacketCustom packet); } diff --git a/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java index 0d6bf2f..c87920e 100644 --- a/src/main/java/codechicken/lib/packet/PacketCustom.java +++ b/src/main/java/codechicken/lib/packet/PacketCustom.java @@ -1,6 +1,5 @@ package codechicken.lib.packet; - import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.vec.BlockCoord; @@ -19,6 +18,10 @@ import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.AttributeKey; +import java.util.EnumMap; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.Inflater; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -38,32 +41,21 @@ import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; -import java.util.EnumMap; -import java.util.List; -import java.util.zip.Deflater; -import java.util.zip.Inflater; - -public final class PacketCustom implements MCDataInput, MCDataOutput -{ - public static interface ICustomPacketHandler - { - } +public final class PacketCustom implements MCDataInput, MCDataOutput { + public static interface ICustomPacketHandler {} - public interface IClientPacketHandler extends ICustomPacketHandler - { + public interface IClientPacketHandler extends ICustomPacketHandler { public void handlePacket(PacketCustom packetCustom, Minecraft mc, INetHandlerPlayClient handler); } - public interface IServerPacketHandler extends ICustomPacketHandler - { + public interface IServerPacketHandler extends ICustomPacketHandler { public void handlePacket(PacketCustom packetCustom, EntityPlayerMP sender, INetHandlerPlayServer handler); } public static AttributeKey cclHandler = new AttributeKey("ccl:handler"); @ChannelHandler.Sharable - public static class CustomInboundHandler extends SimpleChannelInboundHandler - { + public static class CustomInboundHandler extends SimpleChannelInboundHandler { public EnumMap handlers = Maps.newEnumMap(Side.class); @Override @@ -75,19 +67,18 @@ public void handlerAdded(ChannelHandlerContext ctx) throws Exception { @Override protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception { handlers.get(ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get()) - .handle(ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(), + .handle( + ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(), ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get(), new PacketCustom(msg.payload())); } } - private static interface CustomHandler - { + private static interface CustomHandler { public void handle(INetHandler handler, String channel, PacketCustom packet) throws Exception; } - public static class ClientInboundHandler implements CustomHandler - { + public static class ClientInboundHandler implements CustomHandler { private IClientPacketHandler handler; public ClientInboundHandler(ICustomPacketHandler handler) { @@ -98,13 +89,11 @@ public ClientInboundHandler(ICustomPacketHandler handler) { public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { if (netHandler instanceof INetHandlerPlayClient) handler.handlePacket(packet, Minecraft.getMinecraft(), (INetHandlerPlayClient) netHandler); - else - System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); + else System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } - public static class ServerInboundHandler implements CustomHandler - { + public static class ServerInboundHandler implements CustomHandler { private IServerPacketHandler handler; public ServerInboundHandler(ICustomPacketHandler handler) { @@ -114,19 +103,17 @@ public ServerInboundHandler(ICustomPacketHandler handler) { @Override public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { if (netHandler instanceof NetHandlerPlayServer) - handler.handlePacket(packet, ((NetHandlerPlayServer) netHandler).playerEntity, (INetHandlerPlayServer) netHandler); - else - System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); + handler.handlePacket( + packet, ((NetHandlerPlayServer) netHandler).playerEntity, (INetHandlerPlayServer) netHandler); + else System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } - public static interface IHandshakeHandler - { + public static interface IHandshakeHandler { public void handshakeRecieved(NetHandlerPlayServer netHandler); } - public static class HandshakeInboundHandler extends ChannelInboundHandlerAdapter - { + public static class HandshakeInboundHandler extends ChannelInboundHandlerAdapter { public IHandshakeHandler handler; public HandshakeInboundHandler(IHandshakeHandler handler) { @@ -136,25 +123,27 @@ public HandshakeInboundHandler(IHandshakeHandler handler) { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof NetworkHandshakeEstablished) { - INetHandler netHandler = ((NetworkDispatcher) ctx.channel().attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).get()).getNetHandler(); + INetHandler netHandler = ((NetworkDispatcher) ctx.channel() + .attr(FMLOutboundHandler.FML_MESSAGETARGETARGS) + .get()) + .getNetHandler(); if (netHandler instanceof NetHandlerPlayServer) handler.handshakeRecieved((NetHandlerPlayServer) netHandler); - } else - ctx.fireUserEventTriggered(evt); + } else ctx.fireUserEventTriggered(evt); } } public static String channelName(Object channelKey) { - if (channelKey instanceof String) - return (String) channelKey; + if (channelKey instanceof String) return (String) channelKey; - ModContainer mc = channelKey instanceof ModContainer ? - (ModContainer) channelKey : - FMLCommonHandler.instance().findContainerFor(channelKey); + ModContainer mc = channelKey instanceof ModContainer + ? (ModContainer) channelKey + : FMLCommonHandler.instance().findContainerFor(channelKey); if (mc != null) { String s = mc.getModId(); - if(s.length() > 20) - throw new IllegalArgumentException("Mod ID ("+s+") too long for use as channel (20 chars). Use a string identifier"); + if (s.length() > 20) + throw new IllegalArgumentException( + "Mod ID (" + s + ") too long for use as channel (20 chars). Use a string identifier"); return s; } @@ -171,7 +160,10 @@ public static void assignHandler(Object channelKey, ICustomPacketHandler handler String channelName = channelName(channelKey); Side side = handler instanceof IServerPacketHandler ? Side.SERVER : Side.CLIENT; FMLEmbeddedChannel channel = getOrCreateChannel(channelName, side); - channel.attr(cclHandler).get().handlers.put(side, side == Side.SERVER ? new ServerInboundHandler(handler) : new ClientInboundHandler(handler)); + channel.attr(cclHandler) + .get() + .handlers + .put(side, side == Side.SERVER ? new ServerInboundHandler(handler) : new ClientInboundHandler(handler)); } public static void assignHandshakeHandler(Object channelKey, IHandshakeHandler handler) { @@ -187,8 +179,7 @@ public PacketCustom(ByteBuf payload) { byteBuf = payload; type = byteBuf.readUnsignedByte(); - if (type > 0x80) - decompress(); + if (type > 0x80) decompress(); type &= 0x7F; } @@ -233,8 +224,8 @@ private void do_compress() { deflater.finish(); ByteBuf out = Unpooled.buffer(len + 5); int clen = deflater.deflate(out.array(), 5, len); - if (clen >= len - 5 || !deflater.finished())//not worth compressing, gets larger - return; + if (clen >= len - 5 || !deflater.finished()) // not worth compressing, gets larger + return; out.setByte(0, type | 0x80); out.setInt(1, len); @@ -261,10 +252,8 @@ public ByteBuf getByteBuf() { } public PacketCustom compress() { - if (incoming()) - throw new IllegalStateException("Tried to compress an incoming packet"); - if ((type & 0x80) != 0) - throw new IllegalStateException("Packet already compressed"); + if (incoming()) throw new IllegalStateException("Tried to compress an incoming packet"); + if ((type & 0x80) != 0) throw new IllegalStateException("Packet already compressed"); type |= 0x80; return this; } @@ -354,10 +343,8 @@ public PacketCustom writeItemStack(ItemStack stack, boolean large) { writeShort(-1); } else { writeShort(Item.getIdFromItem(stack.getItem())); - if (large) - writeInt(stack.stackSize); - else - writeByte(stack.stackSize); + if (large) writeInt(stack.stackSize); + else writeByte(stack.stackSize); writeShort(stack.getItemDamage()); writeNBTTagCompound(stack.stackTagCompound); } @@ -468,20 +455,17 @@ public NBTTagCompound readNBTTagCompound() { public FluidStack readFluidStack() { Fluid fluid = FluidRegistry.getFluid(readShort()); - if(fluid == null) - fluid = FluidRegistry.WATER; + if (fluid == null) fluid = FluidRegistry.WATER; return new FluidStack(fluid, readVarInt(), readNBTTagCompound()); } public FMLProxyPacket toPacket() { - if (incoming()) - throw new IllegalStateException("Tried to write an incoming packet"); + if (incoming()) throw new IllegalStateException("Tried to write an incoming packet"); - if (byteBuf.readableBytes() > 32000 || (type & 0x80) != 0) - do_compress(); + if (byteBuf.readableBytes() > 32000 || (type & 0x80) != 0) do_compress(); - //FML packet impl returns the whole of the backing array, copy used portion of array to another ByteBuf + // FML packet impl returns the whole of the backing array, copy used portion of array to another ByteBuf return new FMLProxyPacket(byteBuf.copy(), channel); } @@ -490,10 +474,8 @@ public void sendToPlayer(EntityPlayer player) { } public static void sendToPlayer(Packet packet, EntityPlayer player) { - if (player == null) - sendToClients(packet); - else - ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet); + if (player == null) sendToClients(packet); + else ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet); } public void sendToClients() { @@ -525,10 +507,10 @@ public void sendToChunk(World world, int chunkX, int chunkZ) { } public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) { - PlayerManager playerManager = ((WorldServer)world).getPlayerManager(); - for (EntityPlayerMP player : (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) - if(playerManager.isPlayerWatchingChunk(player, chunkX, chunkZ)) - sendToPlayer(packet, player); + PlayerManager playerManager = ((WorldServer) world).getPlayerManager(); + for (EntityPlayerMP player : + (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + if (playerManager.isPlayerWatchingChunk(player, chunkX, chunkZ)) sendToPlayer(packet, player); /* Commented until forge accepts access tranformer request PlayerInstance p = ((WorldServer) world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); @@ -541,7 +523,8 @@ public void sendToOps() { } public static void sendToOps(Packet packet) { - for (EntityPlayerMP player : (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + for (EntityPlayerMP player : + (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) if (MinecraftServer.getServer().getConfigurationManager().func_152596_g(player.getGameProfile())) sendToPlayer(packet, player); } diff --git a/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java b/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java index ddff053..8ef8cf4 100644 --- a/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java +++ b/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java @@ -4,28 +4,24 @@ import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; -public class ExtendedMOP extends MovingObjectPosition implements Comparable -{ +public class ExtendedMOP extends MovingObjectPosition implements Comparable { public Object data; /** * The square distance from the start of the raytrace. */ public double dist; - - public ExtendedMOP(Entity entity, Object data) - { + + public ExtendedMOP(Entity entity, Object data) { super(entity); setData(data); } - - public ExtendedMOP(int x, int y, int z, int side, Vec3 hit, Object data) - { + + public ExtendedMOP(int x, int y, int z, int side, Vec3 hit, Object data) { super(x, y, z, side, hit); setData(data); } - - public ExtendedMOP(MovingObjectPosition mop, Object data, double dist) - { + + public ExtendedMOP(MovingObjectPosition mop, Object data, double dist) { super(0, 0, 0, 0, mop.hitVec); typeOfHit = mop.typeOfHit; blockX = mop.blockX; @@ -37,25 +33,20 @@ public ExtendedMOP(MovingObjectPosition mop, Object data, double dist) this.dist = dist; } - public void setData(Object data) - { - if(data instanceof Integer) - subHit = ((Integer) data).intValue(); + public void setData(Object data) { + if (data instanceof Integer) subHit = ((Integer) data).intValue(); this.data = data; } - + @SuppressWarnings("unchecked") - public static T getData(MovingObjectPosition mop) - { - if(mop instanceof ExtendedMOP) - return (T)((ExtendedMOP)mop).data; - - return (T)Integer.valueOf(mop.subHit); + public static T getData(MovingObjectPosition mop) { + if (mop instanceof ExtendedMOP) return (T) ((ExtendedMOP) mop).data; + + return (T) Integer.valueOf(mop.subHit); } - + @Override - public int compareTo(ExtendedMOP o) - { + public int compareTo(ExtendedMOP o) { return dist == o.dist ? 0 : dist < o.dist ? -1 : 1; } } diff --git a/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java b/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java index a585ac9..c38baf9 100644 --- a/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java +++ b/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java @@ -2,13 +2,11 @@ import codechicken.lib.vec.Cuboid6; -public class IndexedCuboid6 extends Cuboid6 -{ +public class IndexedCuboid6 extends Cuboid6 { public Object data; - - public IndexedCuboid6(Object data, Cuboid6 cuboid) - { + + public IndexedCuboid6(Object data, Cuboid6 cuboid) { super(cuboid); this.data = data; } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/raytracer/RayTracer.java b/src/main/java/codechicken/lib/raytracer/RayTracer.java index d648699..3eb9a8b 100644 --- a/src/main/java/codechicken/lib/raytracer/RayTracer.java +++ b/src/main/java/codechicken/lib/raytracer/RayTracer.java @@ -6,9 +6,9 @@ import codechicken.lib.vec.Vector3; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.util.List; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.MovingObjectPosition; @@ -16,10 +16,7 @@ import net.minecraft.util.Vec3; import net.minecraft.world.World; -import java.util.List; - -public class RayTracer -{ +public class RayTracer { private Vector3 vec = new Vector3(); private Vector3 vec2 = new Vector3(); @@ -27,23 +24,19 @@ public class RayTracer private double s_dist; private int s_side; private IndexedCuboid6 c_cuboid; - + private static ThreadLocal t_inst = new ThreadLocal(); - - public static RayTracer instance() - { + + public static RayTracer instance() { RayTracer inst = t_inst.get(); - if(inst == null) - t_inst.set(inst = new RayTracer()); + if (inst == null) t_inst.set(inst = new RayTracer()); return inst; } - - private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) - { + + private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) { vec.set(start); Vector3 hit = null; - switch(side) - { + switch (side) { case 0: hit = vec.XZintercept(end, cuboid.min.y); break; @@ -63,87 +56,78 @@ private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) hit = vec.YZintercept(end, cuboid.max.x); break; } - if(hit == null) - return; - - switch(side) - { + if (hit == null) return; + + switch (side) { case 0: case 1: - if(!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; + if (!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) + || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; break; case 2: case 3: - if(!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) || !MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y)) return; + if (!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) + || !MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y)) return; break; case 4: case 5: - if(!MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y) || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; + if (!MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y) + || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; break; } - + double dist = vec2.set(hit).subtract(start).magSquared(); - if(dist < s_dist) - { + if (dist < s_dist) { s_side = side; s_dist = dist; s_vec.set(vec); } } - - public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid) - { + + public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid) { s_dist = Double.MAX_VALUE; s_side = -1; - - for(int i = 0; i < 6; i++) - traceSide(i, start, end, cuboid); - - if(s_side < 0) - return null; - + + for (int i = 0; i < 6; i++) traceSide(i, start, end, cuboid); + + if (s_side < 0) return null; + MovingObjectPosition mop = new MovingObjectPosition(0, 0, 0, s_side, s_vec.toVec3D()); mop.typeOfHit = null; return mop; } - public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids) - { + public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids) { double c_dist = Double.MAX_VALUE; MovingObjectPosition c_hit = null; - - for(IndexedCuboid6 cuboid : cuboids) - { + + for (IndexedCuboid6 cuboid : cuboids) { MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); - if(mop != null && s_dist < c_dist) - { + if (mop != null && s_dist < c_dist) { mop = new ExtendedMOP(mop, cuboid.data, s_dist); c_dist = s_dist; c_hit = mop; c_cuboid = cuboid; } } - + return c_hit; } - public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids, BlockCoord pos, Block block) - { + public MovingObjectPosition rayTraceCuboids( + Vector3 start, Vector3 end, List cuboids, BlockCoord pos, Block block) { MovingObjectPosition mop = rayTraceCuboids(start, end, cuboids); - if(mop != null) - { + if (mop != null) { mop.typeOfHit = MovingObjectType.BLOCK; mop.blockX = pos.x; mop.blockY = pos.y; mop.blockZ = pos.z; - if(block != null) - c_cuboid.add(new Vector3(-pos.x, -pos.y, -pos.z)).setBlockBounds(block); + if (block != null) c_cuboid.add(new Vector3(-pos.x, -pos.y, -pos.z)).setBlockBounds(block); } return mop; } - public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) - { + public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) { Block block = world.getBlock(x, y, z); Vec3 headVec = getCorrectedHeadVec(player); @@ -153,56 +137,49 @@ public static MovingObjectPosition retraceBlock(World world, EntityPlayer player return block.collisionRayTrace(world, x, y, z, headVec, endVec); } - private static double getBlockReachDistance_server(EntityPlayerMP player) - { + private static double getBlockReachDistance_server(EntityPlayerMP player) { return player.theItemInWorldManager.getBlockReachDistance(); } @SideOnly(Side.CLIENT) - private static double getBlockReachDistance_client() - { + private static double getBlockReachDistance_client() { return Minecraft.getMinecraft().playerController.getBlockReachDistance(); } - - public static MovingObjectPosition reTrace(World world, EntityPlayer player) - { + + public static MovingObjectPosition reTrace(World world, EntityPlayer player) { return reTrace(world, player, getBlockReachDistance(player)); } - public static MovingObjectPosition reTrace(World world, EntityPlayer player, double reach) - { + public static MovingObjectPosition reTrace(World world, EntityPlayer player, double reach) { Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1); Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach); return world.func_147447_a(headVec, endVec, true, false, true); } - - public static Vec3 getCorrectedHeadVec(EntityPlayer player) - { + + public static Vec3 getCorrectedHeadVec(EntityPlayer player) { Vec3 v = Vec3.createVectorHelper(player.posX, player.posY, player.posZ); - if(player.worldObj.isRemote) { - v.yCoord+=player.getEyeHeight()-player.getDefaultEyeHeight();//compatibility with eye height changing mods + if (player.worldObj.isRemote) { + v.yCoord += + player.getEyeHeight() - player.getDefaultEyeHeight(); // compatibility with eye height changing mods } else { - v.yCoord+=player.getEyeHeight(); - if(player instanceof EntityPlayerMP && player.isSneaking()) - v.yCoord-=0.08; + v.yCoord += player.getEyeHeight(); + if (player instanceof EntityPlayerMP && player.isSneaking()) v.yCoord -= 0.08; } return v; } - - public static Vec3 getStartVec(EntityPlayer player) - { + + public static Vec3 getStartVec(EntityPlayer player) { return getCorrectedHeadVec(player); } - - public static double getBlockReachDistance(EntityPlayer player) - { - return player.worldObj.isRemote ? getBlockReachDistance_client() : - player instanceof EntityPlayerMP ? getBlockReachDistance_server((EntityPlayerMP) player) : 5D; + + public static double getBlockReachDistance(EntityPlayer player) { + return player.worldObj.isRemote + ? getBlockReachDistance_client() + : player instanceof EntityPlayerMP ? getBlockReachDistance_server((EntityPlayerMP) player) : 5D; } - - public static Vec3 getEndVec(EntityPlayer player) - { + + public static Vec3 getEndVec(EntityPlayer player) { Vec3 headVec = getCorrectedHeadVec(player); Vec3 lookVec = player.getLook(1.0F); double reach = getBlockReachDistance(player); diff --git a/src/main/java/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java index a408e97..d7563d6 100644 --- a/src/main/java/codechicken/lib/render/BlockRenderer.java +++ b/src/main/java/codechicken/lib/render/BlockRenderer.java @@ -4,12 +4,10 @@ import codechicken.lib.render.CCRenderState.VertexAttribute; import codechicken.lib.vec.Cuboid6; -public class BlockRenderer -{ - public static class BlockFace implements CCRenderState.IVertexSource - { - public Vertex5[] verts = new Vertex5[]{new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; - public LC[] lightCoords = new LC[]{new LC(), new LC(), new LC(), new LC()}; +public class BlockRenderer { + public static class BlockFace implements CCRenderState.IVertexSource { + public Vertex5[] verts = new Vertex5[] {new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; + public LC[] lightCoords = new LC[] {new LC(), new LC(), new LC(), new LC()}; public boolean lcComputed = false; public int side; @@ -20,7 +18,7 @@ public Vertex5[] getVertices() { @Override public T getAttributes(CCRenderState.VertexAttribute attr) { - return attr == CCRenderState.lightCoordAttrib && lcComputed ? (T)lightCoords : null; + return attr == CCRenderState.lightCoordAttrib && lcComputed ? (T) lightCoords : null; } @Override @@ -34,9 +32,8 @@ public void prepareVertex() { } public BlockFace computeLightCoords() { - if(!lcComputed) { - for (int i = 0; i < 4; i++) - lightCoords[i].compute(verts[i].vec, side); + if (!lcComputed) { + for (int i = 0; i < 4; i++) lightCoords[i].compute(verts[i].vec, side); lcComputed = true; } return this; @@ -49,54 +46,69 @@ public BlockFace loadCuboidFace(Cuboid6 c, int side) { double y2 = c.max.y; double z1 = c.min.z; double z2 = c.max.z; - double u1; double u2; double v1; double v2; + double u1; + double u2; + double v1; + double v2; this.side = side; lcComputed = false; - switch(side) { + switch (side) { case 0: - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; + u1 = x1; + v1 = z1; + u2 = x2; + v2 = z2; verts[0].set(x1, y1, z2, u1, v2, 0); verts[1].set(x1, y1, z1, u1, v1, 0); verts[2].set(x2, y1, z1, u2, v1, 0); verts[3].set(x2, y1, z2, u2, v2, 0); break; case 1: - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; + u1 = x1; + v1 = z1; + u2 = x2; + v2 = z2; verts[0].set(x2, y2, z2, u2, v2, 1); verts[1].set(x2, y2, z1, u2, v1, 1); verts[2].set(x1, y2, z1, u1, v1, 1); verts[3].set(x1, y2, z2, u1, v2, 1); break; case 2: - u1 = 1-x1; v1 = 1-y2; - u2 = 1-x2; v2 = 1-y1; + u1 = 1 - x1; + v1 = 1 - y2; + u2 = 1 - x2; + v2 = 1 - y1; verts[0].set(x1, y1, z1, u1, v2, 2); verts[1].set(x1, y2, z1, u1, v1, 2); verts[2].set(x2, y2, z1, u2, v1, 2); verts[3].set(x2, y1, z1, u2, v2, 2); break; case 3: - u1 = x1; v1 = 1-y2; - u2 = x2; v2 = 1-y1; + u1 = x1; + v1 = 1 - y2; + u2 = x2; + v2 = 1 - y1; verts[0].set(x2, y1, z2, u2, v2, 3); verts[1].set(x2, y2, z2, u2, v1, 3); verts[2].set(x1, y2, z2, u1, v1, 3); verts[3].set(x1, y1, z2, u1, v2, 3); break; case 4: - u1 = z1; v1 = 1-y2; - u2 = z2; v2 = 1-y1; + u1 = z1; + v1 = 1 - y2; + u2 = z2; + v2 = 1 - y1; verts[0].set(x1, y1, z2, u2, v2, 4); verts[1].set(x1, y2, z2, u2, v1, 4); verts[2].set(x1, y2, z1, u1, v1, 4); verts[3].set(x1, y1, z1, u1, v2, 4); break; case 5: - u1 = 1-z1; v1 = 1-y2; - u2 = 1-z2; v2 = 1-y1; + u1 = 1 - z1; + v1 = 1 - y2; + u2 = 1 - z2; + v2 = 1 - y1; verts[0].set(x2, y1, z1, u1, v2, 5); verts[1].set(x2, y2, z1, u1, v1, 5); verts[2].set(x2, y2, z2, u2, v1, 5); @@ -106,14 +118,12 @@ public BlockFace loadCuboidFace(Cuboid6 c, int side) { } } - public static class FullBlock implements CCRenderState.IVertexSource - { + public static class FullBlock implements CCRenderState.IVertexSource { public Vertex5[] verts = CCModel.quadModel(24).generateBlock(0, Cuboid6.full).verts; public LC[] lightCoords = new LC[24]; public FullBlock() { - for(int i = 0; i < 24; i++) - lightCoords[i] = new LC().compute(verts[i].vec, i/4); + for (int i = 0; i < 24; i++) lightCoords[i] = new LC().compute(verts[i].vec, i / 4); } @Override @@ -133,11 +143,12 @@ public boolean hasAttribute(VertexAttribute attr) { @Override public void prepareVertex() { - CCRenderState.side = CCRenderState.vertexIndex>>2; + CCRenderState.side = CCRenderState.vertexIndex >> 2; } } public static FullBlock fullBlock = new FullBlock(); + public static void renderFullBlock(int sideMask) { CCRenderState.setModel(fullBlock); renderFaces(sideMask); @@ -148,10 +159,10 @@ public static void renderFullBlock(int sideMask) { * @param sideMask A mask of faces not to render */ public static void renderFaces(int sideMask) { - if(sideMask == 0x3F) return; - for(int s = 0; s < 6; s++) - if((sideMask & 1< -{ - private static class PositionNormalEntry - { +public class CCModel implements CCRenderState.IVertexSource, Copyable { + private static class PositionNormalEntry { public Vector3 pos; public LinkedList normals = new LinkedList(); - public PositionNormalEntry(Vector3 position) - { + public PositionNormalEntry(Vector3 position) { pos = position; } - public boolean positionEqual(Vector3 v) - { + public boolean positionEqual(Vector3 v) { return pos.x == v.x && pos.y == v.y && pos.z == v.z; } - public PositionNormalEntry addNormal(Vector3 normal) - { + public PositionNormalEntry addNormal(Vector3 normal) { normals.add(normal); return this; } @@ -46,9 +40,8 @@ public PositionNormalEntry addNormal(Vector3 normal) public Vertex5[] verts; public ArrayList attributes = new ArrayList(); - protected CCModel(int vertexMode) - { - if(vertexMode != 7 && vertexMode != 4) + protected CCModel(int vertexMode) { + if (vertexMode != 7 && vertexMode != 4) throw new IllegalArgumentException("Models must be GL_QUADS or GL_TRIANGLES"); this.vertexMode = vertexMode; @@ -66,8 +59,7 @@ public Vertex5[] getVertices() { @Override public T getAttributes(CCRenderState.VertexAttribute attr) { - if(attr.attributeIndex < attributes.size()) - return (T) attributes.get(attr.attributeIndex); + if (attr.attributeIndex < attributes.size()) return (T) attributes.get(attr.attributeIndex); return null; } @@ -78,14 +70,12 @@ public boolean hasAttribute(CCRenderState.VertexAttribute attrib) { } @Override - public void prepareVertex() { - } + public void prepareVertex() {} public T getOrAllocate(CCRenderState.VertexAttribute attrib) { T array = getAttributes(attrib); - if(array == null) { - while(attributes.size() <= attrib.attributeIndex) - attributes.add(null); + if (array == null) { + while (attributes.size() <= attrib.attributeIndex) attributes.add(null); attributes.set(attrib.attributeIndex, array = attrib.newArray(verts.length)); } return array; @@ -107,57 +97,85 @@ public T getOrAllocate(CCRenderState.VertexAttribute attrib) { * @param f The scale of the model, pixels per block, normally 16 * @return The generated model */ - public CCModel generateBox(int i, double x1, double y1, double z1, double w, double h, double d, double tx, double ty, double tw, double th, double f) - { + public CCModel generateBox( + int i, + double x1, + double y1, + double z1, + double w, + double h, + double d, + double tx, + double ty, + double tw, + double th, + double f) { double u1, v1, u2, v2; - double x2 = x1+w; - double y2 = y1+h; - double z2 = z1+d; - x1 /= f; x2 /= f; y1 /= f; y2 /= f; z1 /= f; z2 /= f; - - //bottom face - u1 = (tx + d + w) / tw; v1 = (ty + d) / th; - u2 = (tx + d*2 + w) / tw; v2 = ty / th; + double x2 = x1 + w; + double y2 = y1 + h; + double z2 = z1 + d; + x1 /= f; + x2 /= f; + y1 /= f; + y2 /= f; + z1 /= f; + z2 /= f; + + // bottom face + u1 = (tx + d + w) / tw; + v1 = (ty + d) / th; + u2 = (tx + d * 2 + w) / tw; + v2 = ty / th; verts[i++] = new Vertex5(x1, y1, z2, u1, v2); verts[i++] = new Vertex5(x1, y1, z1, u1, v1); verts[i++] = new Vertex5(x2, y1, z1, u2, v1); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); - //top face - u1 = (tx + d) / tw; v1 = (ty + d) / th; - u2 = (tx + d + w) / tw; v2 = ty / th; + // top face + u1 = (tx + d) / tw; + v1 = (ty + d) / th; + u2 = (tx + d + w) / tw; + v2 = ty / th; verts[i++] = new Vertex5(x2, y2, z2, u2, v2); verts[i++] = new Vertex5(x2, y2, z1, u2, v1); verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y2, z2, u1, v2); - //front face - u1 = (tx + d + w) / tw; v1 = (ty + d) / th; - u2 = (tx + d) / tw; v2 = (ty + d + h) / th; + // front face + u1 = (tx + d + w) / tw; + v1 = (ty + d) / th; + u2 = (tx + d) / tw; + v2 = (ty + d + h) / th; verts[i++] = new Vertex5(x1, y2, z1, u2, v1); verts[i++] = new Vertex5(x2, y2, z1, u1, v1); verts[i++] = new Vertex5(x2, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y1, z1, u2, v2); - //back face - u1 = (tx + d*2 + w*2) / tw; v1 = (ty + d) / th; - u2 = (tx + d*2 + w) / tw; v2 = (ty + d + h) / th; + // back face + u1 = (tx + d * 2 + w * 2) / tw; + v1 = (ty + d) / th; + u2 = (tx + d * 2 + w) / tw; + v2 = (ty + d + h) / th; verts[i++] = new Vertex5(x1, y2, z2, u1, v1); verts[i++] = new Vertex5(x1, y1, z2, u1, v2); verts[i++] = new Vertex5(x2, y1, z2, u2, v2); verts[i++] = new Vertex5(x2, y2, z2, u2, v1); - //left face - u1 = (tx + d) / tw; v1 = (ty + d) / th; - u2 = (tx) / tw; v2 = (ty + d + h) / th; + // left face + u1 = (tx + d) / tw; + v1 = (ty + d) / th; + u2 = (tx) / tw; + v2 = (ty + d + h) / th; verts[i++] = new Vertex5(x1, y2, z2, u2, v1); verts[i++] = new Vertex5(x1, y2, z1, u1, v1); verts[i++] = new Vertex5(x1, y1, z1, u1, v2); verts[i++] = new Vertex5(x1, y1, z2, u2, v2); - //right face - u1 = (tx + d*2 + w) / tw; v1 = (ty + d) / th; - u2 = (tx + d + w) / tw; v2 = (ty + d + h) / th; + // right face + u1 = (tx + d * 2 + w) / tw; + v1 = (ty + d) / th; + u2 = (tx + d + w) / tw; + v2 = (ty + d + h) / th; verts[i++] = new Vertex5(x2, y1, z2, u1, v2); verts[i++] = new Vertex5(x2, y1, z1, u2, v2); verts[i++] = new Vertex5(x2, y2, z1, u2, v1); @@ -172,18 +190,16 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou * @param bounds The bounds of the block, 0 to 1 * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. */ - public CCModel generateBlock(int i, Cuboid6 bounds) - { + public CCModel generateBlock(int i, Cuboid6 bounds) { return generateBlock(i, bounds, 0); } - public CCModel generateBlock(int i, Cuboid6 bounds, int mask) - { - return generateBlock(i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z, mask); + public CCModel generateBlock(int i, Cuboid6 bounds, int mask) { + return generateBlock( + i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z, mask); } - public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) - { + public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) { return generateBlock(i, x1, y1, z1, x2, y2, z2, 0); } @@ -199,58 +215,69 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, * @param mask A bitmask of sides NOT to generate. I high bit at index s means side s will not be generated * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. */ - public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2, int mask) - { + public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2, int mask) { double u1, v1, u2, v2; - if((mask&1) == 0) {//bottom face - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; + if ((mask & 1) == 0) { // bottom face + u1 = x1; + v1 = z1; + u2 = x2; + v2 = z2; verts[i++] = new Vertex5(x1, y1, z2, u1, v2, 0); verts[i++] = new Vertex5(x1, y1, z1, u1, v1, 0); verts[i++] = new Vertex5(x2, y1, z1, u2, v1, 0); verts[i++] = new Vertex5(x2, y1, z2, u2, v2, 0); } - if((mask&2) == 0) {//top face - u1 = x1; v1 = z1; - u2 = x2; v2 = z2; + if ((mask & 2) == 0) { // top face + u1 = x1; + v1 = z1; + u2 = x2; + v2 = z2; verts[i++] = new Vertex5(x2, y2, z2, u2, v2, 1); verts[i++] = new Vertex5(x2, y2, z1, u2, v1, 1); verts[i++] = new Vertex5(x1, y2, z1, u1, v1, 1); verts[i++] = new Vertex5(x1, y2, z2, u1, v2, 1); } - if((mask&4) == 0) {//east face - u1 = 1-x1; v1 = 1-y2; - u2 = 1-x2; v2 = 1-y1; + if ((mask & 4) == 0) { // east face + u1 = 1 - x1; + v1 = 1 - y2; + u2 = 1 - x2; + v2 = 1 - y1; verts[i++] = new Vertex5(x1, y1, z1, u1, v2, 2); verts[i++] = new Vertex5(x1, y2, z1, u1, v1, 2); verts[i++] = new Vertex5(x2, y2, z1, u2, v1, 2); verts[i++] = new Vertex5(x2, y1, z1, u2, v2, 2); } - if((mask&8) == 0) {//west face - u1 = x1; v1 = 1-y2; - u2 = x2; v2 = 1-y1; + if ((mask & 8) == 0) { // west face + u1 = x1; + v1 = 1 - y2; + u2 = x2; + v2 = 1 - y1; verts[i++] = new Vertex5(x2, y1, z2, u2, v2, 3); verts[i++] = new Vertex5(x2, y2, z2, u2, v1, 3); verts[i++] = new Vertex5(x1, y2, z2, u1, v1, 3); verts[i++] = new Vertex5(x1, y1, z2, u1, v2, 3); } - if((mask&0x10) == 0) {//north face - u1 = z1; v1 = 1-y2; - u2 = z2; v2 = 1-y1; + if ((mask & 0x10) == 0) { // north face + u1 = z1; + v1 = 1 - y2; + u2 = z2; + v2 = 1 - y1; verts[i++] = new Vertex5(x1, y1, z2, u2, v2, 4); verts[i++] = new Vertex5(x1, y2, z2, u2, v1, 4); verts[i++] = new Vertex5(x1, y2, z1, u1, v1, 4); verts[i++] = new Vertex5(x1, y1, z1, u1, v2, 4); } - if((mask&0x20) == 0) {//south face - u1 = 1-z1; v1 = 1-y2; - u2 = 1-z2; v2 = 1-y1; + if ((mask & 0x20) == 0) { // south face + u1 = 1 - z1; + v1 = 1 - y2; + u2 = 1 - z2; + v2 = 1 - y1; verts[i++] = new Vertex5(x2, y1, z1, u1, v2, 5); verts[i++] = new Vertex5(x2, y2, z1, u1, v1, 5); verts[i++] = new Vertex5(x2, y2, z2, u2, v1, 5); @@ -260,8 +287,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, return this; } - public CCModel computeNormals() - { + public CCModel computeNormals() { return computeNormals(0, verts.length); } @@ -272,20 +298,17 @@ public CCModel computeNormals() * @param length The number of vertices to generate normals for. Note this must be a multiple of 3 for triangles or 4 for quads * @return The model */ - public CCModel computeNormals(int start, int length) - { - if(length%vp != 0 || start%vp != 0) + public CCModel computeNormals(int start, int length) { + if (length % vp != 0 || start % vp != 0) throw new IllegalArgumentException("Cannot generate normals across polygons"); Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib); - for(int k = 0; k < length; k+=vp) - { + for (int k = 0; k < length; k += vp) { int i = k + start; - Vector3 diff1 = verts[i+1].vec.copy().subtract(verts[i].vec); - Vector3 diff2 = verts[i+vp-1].vec.copy().subtract(verts[i].vec); + Vector3 diff1 = verts[i + 1].vec.copy().subtract(verts[i].vec); + Vector3 diff2 = verts[i + vp - 1].vec.copy().subtract(verts[i].vec); normals[i] = diff1.crossProduct(diff2).normalize(); - for(int d = 1; d < vp; d++) - normals[i+d] = normals[i].copy(); + for (int d = 1; d < vp; d++) normals[i + d] = normals[i].copy(); } return this; @@ -296,21 +319,18 @@ public CCModel computeNormals(int start, int length) * If the model is rotated, the lighting will no longer be valid * @return The model */ - public CCModel computeLighting(LightModel light) - { + public CCModel computeLighting(LightModel light) { Vector3[] normals = normals(); int[] colours = getAttributes(CCRenderState.lightingAttrib); - if(colours == null) { + if (colours == null) { colours = getOrAllocate(CCRenderState.lightingAttrib); Arrays.fill(colours, -1); } - for(int k = 0; k < verts.length; k++) - colours[k] = light.apply(colours[k], normals[k]); + for (int k = 0; k < verts.length; k++) colours[k] = light.apply(colours[k], normals[k]); return this; } - public CCModel setColour(int c) - { + public CCModel setColour(int c) { int[] colours = getOrAllocate(CCRenderState.colourAttrib); Arrays.fill(colours, c); return this; @@ -323,8 +343,7 @@ public CCModel setColour(int c) public CCModel computeLightCoords() { LC[] lcs = getOrAllocate(CCRenderState.lightCoordAttrib); Vector3[] normals = normals(); - for(int i = 0; i < verts.length; i++) - lcs[i] = new LC().compute(verts[i].vec, normals[i]); + for (int i = 0; i < verts.length; i++) lcs[i] = new LC().compute(verts[i].vec, normals[i]); return this; } @@ -332,16 +351,14 @@ public CCModel computeLightCoords() { * Averages all normals at the same position to produce a smooth lighting effect. * @return The model */ - public CCModel smoothNormals() - { + public CCModel smoothNormals() { ArrayList map = new ArrayList(); Vector3[] normals = normals(); - nextvert: for(int k = 0; k < verts.length; k++) - { + nextvert: + for (int k = 0; k < verts.length; k++) { Vector3 vec = verts[k].vec; - for(PositionNormalEntry e : map) - if(e.positionEqual(vec)) - { + for (PositionNormalEntry e : map) + if (e.positionEqual(vec)) { e.addNormal(normals[k]); continue nextvert; } @@ -349,72 +366,62 @@ public CCModel smoothNormals() map.add(new PositionNormalEntry(vec).addNormal(normals[k])); } - for(PositionNormalEntry e : map) - { - if(e.normals.size() <= 1) - continue; + for (PositionNormalEntry e : map) { + if (e.normals.size() <= 1) continue; Vector3 new_n = new Vector3(); - for(Vector3 n : e.normals) - new_n.add(n); + for (Vector3 n : e.normals) new_n.add(n); new_n.normalize(); - for(Vector3 n : e.normals) - n.set(new_n); + for (Vector3 n : e.normals) n.set(new_n); } return this; } - public CCModel apply(Transformation t) - { - for(int k = 0; k < verts.length; k++) - verts[k].apply(t); + public CCModel apply(Transformation t) { + for (int k = 0; k < verts.length; k++) verts[k].apply(t); Vector3[] normals = normals(); - if(normals != null) - for(int k = 0; k < normals.length; k++) - t.applyN(normals[k]); + if (normals != null) for (int k = 0; k < normals.length; k++) t.applyN(normals[k]); return this; } - public CCModel apply(UVTransformation uvt) - { - for(int k = 0; k < verts.length; k++) - verts[k].apply(uvt); + public CCModel apply(UVTransformation uvt) { + for (int k = 0; k < verts.length; k++) verts[k].apply(uvt); return this; } - public CCModel expand(int extraVerts) - { - int newLen = verts.length+extraVerts; + public CCModel expand(int extraVerts) { + int newLen = verts.length + extraVerts; verts = Arrays.copyOf(verts, newLen); - for(int i = 0; i < attributes.size(); i++) - if(attributes.get(i) != null) - attributes.set(i, CCRenderState.copyOf((CCRenderState.VertexAttribute)CCRenderState.getAttribute(i), attributes.get(i), newLen)); + for (int i = 0; i < attributes.size(); i++) + if (attributes.get(i) != null) + attributes.set( + i, + CCRenderState.copyOf( + (CCRenderState.VertexAttribute) CCRenderState.getAttribute(i), + attributes.get(i), + newLen)); return this; } - public void render(double x, double y, double z, double u, double v) - { + public void render(double x, double y, double z, double u, double v) { render(new Vector3(x, y, z).translation(), new UVTranslation(u, v)); } - public void render(double x, double y, double z, UVTransformation u) - { + public void render(double x, double y, double z, UVTransformation u) { render(new Vector3(x, y, z).translation(), u); } - public void render(Transformation t, double u, double v) - { + public void render(Transformation t, double u, double v) { render(t, new UVTranslation(u, v)); } - public void render(CCRenderState.IVertexOperation... ops) - { + public void render(CCRenderState.IVertexOperation... ops) { render(0, verts.length, ops); } @@ -424,52 +431,43 @@ public void render(CCRenderState.IVertexOperation... ops) * @param end The vertex index to render until * @param ops Operations to apply */ - public void render(int start, int end, CCRenderState.IVertexOperation... ops) - { + public void render(int start, int end, CCRenderState.IVertexOperation... ops) { CCRenderState.setPipeline(this, start, end, ops); CCRenderState.render(); } - public static CCModel quadModel(int numVerts) - { + public static CCModel quadModel(int numVerts) { return newModel(7, numVerts); } - public static CCModel triModel(int numVerts) - { + public static CCModel triModel(int numVerts) { return newModel(4, numVerts); } - public static CCModel newModel(int vertexMode, int numVerts) - { + public static CCModel newModel(int vertexMode, int numVerts) { CCModel model = newModel(vertexMode); model.verts = new Vertex5[numVerts]; return model; } - public static CCModel newModel(int vertexMode) - { + public static CCModel newModel(int vertexMode) { return new CCModel(vertexMode); } - public static double[] parseDoubles(String s, String token) - { + public static double[] parseDoubles(String s, String token) { String[] as = s.split(token); double[] values = new double[as.length]; - for(int i = 0; i < as.length; i++) - values[i] = Double.parseDouble(as[i]); + for (int i = 0; i < as.length; i++) values[i] = Double.parseDouble(as[i]); return values; } - public static void illegalAssert(boolean b, String err) - { - if(!b) throw new IllegalArgumentException(err); + public static void illegalAssert(boolean b, String err) { + if (!b) throw new IllegalArgumentException(err); } - public static void assertMatch(Matcher m, String s) - { + public static void assertMatch(Matcher m, String s) { m.reset(s); - illegalAssert(m.matches(), "Malformed line: "+s); + illegalAssert(m.matches(), "Malformed line: " + s); } private static final Pattern vertPattern = Pattern.compile("v(?: ([\\d\\.+-]+))+"); @@ -489,10 +487,9 @@ public static void assertMatch(Matcher m, String s) * @return A map of group names to models * @throws IOException */ - public static Map parseObjModels(InputStream input, int vertexMode, Transformation coordSystem) throws IOException - { - if(coordSystem == null) - coordSystem = new RedundantTransformation(); + public static Map parseObjModels(InputStream input, int vertexMode, Transformation coordSystem) + throws IOException { + if (coordSystem == null) coordSystem = new RedundantTransformation(); int vp = vertexMode == 7 ? 4 : 3; HashMap modelMap = new HashMap(); @@ -505,14 +502,11 @@ public static Map parseObjModels(InputStream input, int vertexM BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String line; - while((line = reader.readLine()) != null) - { + while ((line = reader.readLine()) != null) { line = line.replaceAll("\\s+", " ").trim(); - if(line.startsWith("#") || line.length() == 0) - continue; + if (line.startsWith("#") || line.length() == 0) continue; - if(line.startsWith("v ")) - { + if (line.startsWith("v ")) { assertMatch(vertMatcher, line); double[] values = parseDoubles(line.substring(2), " "); illegalAssert(values.length >= 3, "Vertices must have x, y and z components"); @@ -521,16 +515,14 @@ public static Map parseObjModels(InputStream input, int vertexM verts.add(vert); continue; } - if(line.startsWith("vt ")) - { + if (line.startsWith("vt ")) { assertMatch(uvwMatcher, line); double[] values = parseDoubles(line.substring(3), " "); illegalAssert(values.length >= 2, "Tex Coords must have u, and v components"); - uvs.add(new Vector3(values[0], 1-values[1], 0)); + uvs.add(new Vector3(values[0], 1 - values[1], 0)); continue; } - if(line.startsWith("vn ")) - { + if (line.startsWith("vn ")) { assertMatch(normalMatcher, line); double[] values = parseDoubles(line.substring(3), " "); illegalAssert(values.length >= 3, "Normals must have x, y and z components"); @@ -539,28 +531,21 @@ public static Map parseObjModels(InputStream input, int vertexM normals.add(norm); continue; } - if(line.startsWith("f ")) - { + if (line.startsWith("f ")) { assertMatch(polyMatcher, line); String[] av = line.substring(2).split(" "); illegalAssert(av.length >= 3, "Polygons must have at least 3 vertices"); int[][] polyVerts = new int[av.length][3]; - for(int i = 0; i < av.length; i++) - { + for (int i = 0; i < av.length; i++) { String[] as = av[i].split("/"); - for(int p = 0; p < as.length; p++) - if(as[p].length() > 0) - polyVerts[i][p] = Integer.parseInt(as[p]); + for (int p = 0; p < as.length; p++) + if (as[p].length() > 0) polyVerts[i][p] = Integer.parseInt(as[p]); } - if(vp == 3) - triangulate(polys, polyVerts); - else - quadulate(polys, polyVerts); + if (vp == 3) triangulate(polys, polyVerts); + else quadulate(polys, polyVerts); } - if(line.startsWith("g ")) - { - if(!polys.isEmpty()) - { + if (line.startsWith("g ")) { + if (!polys.isEmpty()) { modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); polys.clear(); } @@ -568,39 +553,31 @@ public static Map parseObjModels(InputStream input, int vertexM } } - if(!polys.isEmpty()) - modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); + if (!polys.isEmpty()) modelMap.put(modelName, createModel(verts, uvs, normals, vertexMode, polys)); return modelMap; } - public static void triangulate(List polys, int[][] polyVerts) - { - for(int i = 2; i < polyVerts.length; i++) - { + public static void triangulate(List polys, int[][] polyVerts) { + for (int i = 2; i < polyVerts.length; i++) { polys.add(polyVerts[0]); polys.add(polyVerts[i]); - polys.add(polyVerts[i-1]); + polys.add(polyVerts[i - 1]); } } - public static void quadulate(List polys, int[][] polyVerts) - { - if(polyVerts.length == 4) - { + public static void quadulate(List polys, int[][] polyVerts) { + if (polyVerts.length == 4) { polys.add(polyVerts[0]); polys.add(polyVerts[3]); polys.add(polyVerts[2]); polys.add(polyVerts[1]); - } - else - { - for(int i = 2; i < polyVerts.length; i++) - { + } else { + for (int i = 2; i < polyVerts.length; i++) { polys.add(polyVerts[0]); polys.add(polyVerts[i]); - polys.add(polyVerts[i-1]); - polys.add(polyVerts[i-1]); + polys.add(polyVerts[i - 1]); + polys.add(polyVerts[i - 1]); } } } @@ -610,8 +587,7 @@ public static void quadulate(List polys, int[][] polyVerts) * @param res The resource for the obj file * @return A map of group names to models */ - public static Map parseObjModels(ResourceLocation res) - { + public static Map parseObjModels(ResourceLocation res) { return parseObjModels(res, 4, null); } /** @@ -620,17 +596,17 @@ public static Map parseObjModels(ResourceLocation res) * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models */ - public static Map parseObjModels(ResourceLocation res, Transformation coordSystem) - { - try - { + public static Map parseObjModels(ResourceLocation res, Transformation coordSystem) { + try { return parseObjModels( - Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), - 4, coordSystem); - } - catch(IOException e) - { - throw new RuntimeException("failed to load model: "+res, e); + Minecraft.getMinecraft() + .getResourceManager() + .getResource(res) + .getInputStream(), + 4, + coordSystem); + } catch (IOException e) { + throw new RuntimeException("failed to load model: " + res, e); } } @@ -641,51 +617,47 @@ public static Map parseObjModels(ResourceLocation res, Transfor * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models */ - public static Map parseObjModels(ResourceLocation res, int vertexMode, Transformation coordSystem) - { - try - { + public static Map parseObjModels( + ResourceLocation res, int vertexMode, Transformation coordSystem) { + try { return parseObjModels( - Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), - vertexMode, coordSystem); - } - catch(Exception e) - { - throw new RuntimeException("failed to load model: "+res, e); + Minecraft.getMinecraft() + .getResourceManager() + .getResource(res) + .getInputStream(), + vertexMode, + coordSystem); + } catch (Exception e) { + throw new RuntimeException("failed to load model: " + res, e); } } - public static CCModel createModel(List verts, List uvs, List normals, int vertexMode, List polys) - { + public static CCModel createModel( + List verts, List uvs, List normals, int vertexMode, List polys) { int vp = vertexMode == 7 ? 4 : 3; - if(polys.size() < vp || polys.size()%vp != 0) - throw new IllegalArgumentException("Invalid number of vertices for model: "+polys.size()); + if (polys.size() < vp || polys.size() % vp != 0) + throw new IllegalArgumentException("Invalid number of vertices for model: " + polys.size()); boolean hasNormals = polys.get(0)[2] > 0; CCModel model = CCModel.newModel(vertexMode, polys.size()); - if(hasNormals) - model.getOrAllocate(CCRenderState.normalAttrib); + if (hasNormals) model.getOrAllocate(CCRenderState.normalAttrib); - for(int i = 0; i < polys.size(); i++) - { + for (int i = 0; i < polys.size(); i++) { int[] ai = polys.get(i); - Vector3 vert = verts.get(ai[0]-1).copy(); - Vector3 uv = ai[1] <= 0 ? new Vector3() : uvs.get(ai[1]-1).copy(); - if(ai[2] > 0 != hasNormals) - throw new IllegalArgumentException("Normals are an all or nothing deal here."); + Vector3 vert = verts.get(ai[0] - 1).copy(); + Vector3 uv = ai[1] <= 0 ? new Vector3() : uvs.get(ai[1] - 1).copy(); + if (ai[2] > 0 != hasNormals) throw new IllegalArgumentException("Normals are an all or nothing deal here."); model.verts[i] = new Vertex5(vert, uv.x, uv.y); - if(hasNormals) - model.normals()[i] = normals.get(ai[2]-1).copy(); + if (hasNormals) model.normals()[i] = normals.get(ai[2] - 1).copy(); } return model; } - private static int addIndex(List list, T elem) - { - int i = list.indexOf(elem)+1; - if(i == 0) { + private static int addIndex(List list, T elem) { + int i = list.indexOf(elem) + 1; + if (i == 0) { list.add(elem); i = list.size(); } @@ -693,17 +665,16 @@ private static int addIndex(List list, T elem) } private static String clean(double d) { - return d == (int) d ? Integer.toString((int)d) : Double.toString(d); + return d == (int) d ? Integer.toString((int) d) : Double.toString(d); } - public static void exportObj(Map models, PrintWriter p) - { + public static void exportObj(Map models, PrintWriter p) { List verts = new ArrayList(); List uvs = new ArrayList(); List normals = new ArrayList(); List polys = new ArrayList(); - for(Map.Entry e : models.entrySet()) { - p.println("g "+e.getKey()); + for (Map.Entry e : models.entrySet()) { + p.println("g " + e.getKey()); CCModel m = e.getValue(); int vStart = verts.size(); @@ -712,48 +683,43 @@ public static void exportObj(Map models, PrintWriter p) boolean hasNormals = m.normals() != null; polys.clear(); - for(int i = 0; i < m.verts.length; i++) { + for (int i = 0; i < m.verts.length; i++) { int[] ia = new int[hasNormals ? 3 : 2]; ia[0] = addIndex(verts, m.verts[i].vec); ia[1] = addIndex(uvs, m.verts[i].uv); - if(hasNormals) - ia[2] = addIndex(normals, m.normals()[i]); + if (hasNormals) ia[2] = addIndex(normals, m.normals()[i]); polys.add(ia); } - if(vStart < verts.size()) { + if (vStart < verts.size()) { p.println(); - for(int i = vStart; i < verts.size(); i++) { + for (int i = vStart; i < verts.size(); i++) { Vector3 v = verts.get(i); p.format("v %s %s %s\n", clean(v.x), clean(v.y), clean(v.z)); } } - if(uStart < uvs.size()) { + if (uStart < uvs.size()) { p.println(); - for(int i = uStart; i < uvs.size(); i++) { + for (int i = uStart; i < uvs.size(); i++) { UV uv = uvs.get(i); p.format("vt %s %s\n", clean(uv.u), clean(uv.v)); } } - if(nStart < normals.size()) { + if (nStart < normals.size()) { p.println(); - for(int i = nStart; i < normals.size(); i++) { + for (int i = nStart; i < normals.size(); i++) { Vector3 n = normals.get(i); p.format("vn %s %s %s\n", clean(n.x), clean(n.y), clean(n.z)); } } p.println(); - for(int i = 0; i < polys.size(); i++) { - if(i%m.vp == 0) - p.format("f"); + for (int i = 0; i < polys.size(); i++) { + if (i % m.vp == 0) p.format("f"); int[] ia = polys.get(i); - if(hasNormals) - p.format(" %d/%d/%d", ia[0], ia[1], ia[2]); - else - p.format(" %d/%d", ia[0], ia[1]); - if(i%m.vp == m.vp-1) - p.println(); + if (hasNormals) p.format(" %d/%d/%d", ia[0], ia[1], ia[2]); + else p.format(" %d/%d", ia[0], ia[1]); + if (i % m.vp == m.vp - 1) p.println(); } } } @@ -762,19 +728,15 @@ public static void exportObj(Map models, PrintWriter p) * Brings the UV coordinates of each face closer to the center UV by d. * Useful for fixing texture seams */ - public CCModel shrinkUVs(double d) - { - for(int k = 0; k < verts.length; k+=vp) - { + public CCModel shrinkUVs(double d) { + for (int k = 0; k < verts.length; k += vp) { UV uv = new UV(); - for(int i = 0; i < vp; i++) - { - uv.add(verts[k+i].uv); + for (int i = 0; i < vp; i++) { + uv.add(verts[k + i].uv); } - uv.multiply(1D/vp); - for(int i = 0; i < vp; i++) - { - Vertex5 vert = verts[k+i]; + uv.multiply(1D / vp); + for (int i = 0; i < vp; i++) { + Vertex5 vert = verts[k + i]; vert.uv.u += vert.uv.u < uv.u ? d : -d; vert.uv.v += vert.uv.v < uv.v ? d : -d; } @@ -788,22 +750,24 @@ public CCModel shrinkUVs(double d) * @param point The point to rotate around * @return A copy of this model rotated to the appropriate side */ - public CCModel sidedCopy(int side1, int side2, Vector3 point) - { + public CCModel sidedCopy(int side1, int side2, Vector3 point) { return copy().apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point)); } /** * Copies length vertices and normals */ - public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int length) - { - for(int k = 0; k < length; k++) - dst.verts[destpos+k] = src.verts[srcpos+k].copy(); - - for(int i = 0; i < src.attributes.size(); i++) - if(src.attributes.get(i) != null) - CCRenderState.arrayCopy(src.attributes.get(i), srcpos, dst.getOrAllocate(CCRenderState.getAttribute(i)), destpos, length); + public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int length) { + for (int k = 0; k < length; k++) dst.verts[destpos + k] = src.verts[srcpos + k].copy(); + + for (int i = 0; i < src.attributes.size(); i++) + if (src.attributes.get(i) != null) + CCRenderState.arrayCopy( + src.attributes.get(i), + srcpos, + dst.getOrAllocate(CCRenderState.getAttribute(i)), + destpos, + length); } /** @@ -812,12 +776,9 @@ public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int l * @param side The side of this model * @param point The rotation point */ - public static void generateSidedModels(CCModel[] models, int side, Vector3 point) - { - for(int s = 0; s < 6; s++) - { - if(s == side) - continue; + public static void generateSidedModels(CCModel[] models, int side, Vector3 point) { + for (int s = 0; s < 6; s++) { + if (s == side) continue; models[s] = models[side].sidedCopy(side, s, point); } @@ -829,19 +790,15 @@ public static void generateSidedModels(CCModel[] models, int side, Vector3 point * @param side The side of this model * @param point The rotation point */ - public static void generateSidedModelsH(CCModel[] models, int side, Vector3 point) - { - for(int s = 2; s < 6; s++) - { - if(s == side) - continue; + public static void generateSidedModelsH(CCModel[] models, int side, Vector3 point) { + for (int s = 2; s < 6; s++) { + if (s == side) continue; models[s] = models[side].sidedCopy(side, s, point); } } - public CCModel backfacedCopy() - { + public CCModel backfacedCopy() { return generateBackface(this, 0, copy(), 0, verts.length); } @@ -849,26 +806,24 @@ public CCModel backfacedCopy() * Generates copies of faces with clockwise vertices * @return The model */ - public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int destpos, int length) - { + public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int destpos, int length) { int vp = src.vp; - if(srcpos%vp != 0 || destpos%vp != 0 || length%vp != 0) + if (srcpos % vp != 0 || destpos % vp != 0 || length % vp != 0) throw new IllegalArgumentException("Vertices do not align with polygons"); - int[][] o = new int[][]{{0, 0}, {1, vp-1}, {2, vp-2}, {3, vp-3}}; - for(int i = 0; i < length; i++) - { - int b = (i/vp)*vp; - int d = i%vp; - int di = destpos+b+o[d][1]; - int si = srcpos+b+o[d][0]; + int[][] o = new int[][] {{0, 0}, {1, vp - 1}, {2, vp - 2}, {3, vp - 3}}; + for (int i = 0; i < length; i++) { + int b = (i / vp) * vp; + int d = i % vp; + int di = destpos + b + o[d][1]; + int si = srcpos + b + o[d][0]; dst.verts[di] = src.verts[si].copy(); - for(int a = 0; a < src.attributes.size(); a++) - if(src.attributes.get(a) != null) - CCRenderState.arrayCopy(src.attributes.get(a), si, dst.getOrAllocate(CCRenderState.getAttribute(a)), di, 1); + for (int a = 0; a < src.attributes.size(); a++) + if (src.attributes.get(a) != null) + CCRenderState.arrayCopy( + src.attributes.get(a), si, dst.getOrAllocate(CCRenderState.getAttribute(a)), di, 1); - if(dst.normals() != null && dst.normals()[di] != null) - dst.normals()[di].negate(); + if (dst.normals() != null && dst.normals()[di] != null) dst.normals()[di].negate(); } return dst; } @@ -877,18 +832,15 @@ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int * Generates sided copies of vertices into this model. * Assumes that your model has been generated at vertex side*(numVerts/6) */ - public CCModel generateSidedParts(int side, Vector3 point) - { - if(verts.length%(6*vp) != 0) + public CCModel generateSidedParts(int side, Vector3 point) { + if (verts.length % (6 * vp) != 0) throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); - int length = verts.length/6; + int length = verts.length / 6; - for(int s = 0; s < 6; s++) - { - if(s == side) - continue; + for (int s = 0; s < 6; s++) { + if (s == side) continue; - generateSidedPart(side, s, point, length*side, length*s, length); + generateSidedPart(side, s, point, length * side, length * s, length); } return this; @@ -898,18 +850,15 @@ public CCModel generateSidedParts(int side, Vector3 point) * Generates sided copies of vertices into this model. * Assumes that your model has been generated at vertex side*(numVerts/4) */ - public CCModel generateSidedPartsH(int side, Vector3 point) - { - if(verts.length%(4*vp) != 0) + public CCModel generateSidedPartsH(int side, Vector3 point) { + if (verts.length % (4 * vp) != 0) throw new IllegalArgumentException("Invalid number of vertices for sided part generation"); - int length = verts.length/4; + int length = verts.length / 4; - for(int s = 2; s < 6; s++) - { - if(s == side) - continue; + for (int s = 2; s < 6; s++) { + if (s == side) continue; - generateSidedPart(side, s, point, length*(side-2), length*(s-2), length); + generateSidedPart(side, s, point, length * (side - 2), length * (s - 2), length); } return this; @@ -918,69 +867,63 @@ public CCModel generateSidedPartsH(int side, Vector3 point) /** * Generates a sided copy of verts into this model */ - public CCModel generateSidedPart(int side1, int side2, Vector3 point, int srcpos, int destpos, int length) - { - return apply(new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point), srcpos, destpos, length); + public CCModel generateSidedPart(int side1, int side2, Vector3 point, int srcpos, int destpos, int length) { + return apply( + new TransformationList(sideRotations[side1].inverse(), sideRotations[side2]).at(point), + srcpos, + destpos, + length); } /** * Generates a rotated copy of verts into this model */ - public CCModel apply(Transformation t, int srcpos, int destpos, int length) - { - for(int k = 0; k < length; k++) - { - verts[destpos+k] = verts[srcpos+k].copy(); - verts[destpos+k].vec.apply(t); + public CCModel apply(Transformation t, int srcpos, int destpos, int length) { + for (int k = 0; k < length; k++) { + verts[destpos + k] = verts[srcpos + k].copy(); + verts[destpos + k].vec.apply(t); } Vector3[] normals = normals(); - if(normals != null) - for(int k = 0; k < length; k++) { - normals[destpos+k] = normals[srcpos+k].copy(); - t.applyN(normals[destpos+k]); + if (normals != null) + for (int k = 0; k < length; k++) { + normals[destpos + k] = normals[srcpos + k].copy(); + t.applyN(normals[destpos + k]); } return this; } - public static CCModel combine(Collection models) - { - if(models.isEmpty()) - return null; + public static CCModel combine(Collection models) { + if (models.isEmpty()) return null; int numVerts = 0; int vertexMode = -1; - for(CCModel model : models) - { - if(vertexMode == -1) - vertexMode = model.vertexMode; - if(vertexMode != model.vertexMode) + for (CCModel model : models) { + if (vertexMode == -1) vertexMode = model.vertexMode; + if (vertexMode != model.vertexMode) throw new IllegalArgumentException("Cannot combine models with different vertex modes"); - numVerts+=model.verts.length; + numVerts += model.verts.length; } CCModel c_model = newModel(vertexMode, numVerts); int i = 0; - for(CCModel model : models) - { + for (CCModel model : models) { copy(model, 0, c_model, i, model.verts.length); - i+=model.verts.length; + i += model.verts.length; } return c_model; } - public CCModel twoFacedCopy() - { - CCModel model = newModel(vertexMode, verts.length*2); + public CCModel twoFacedCopy() { + CCModel model = newModel(vertexMode, verts.length * 2); copy(this, 0, model, 0, verts.length); return generateBackface(model, 0, model, verts.length, verts.length); } - public CCModel copy() - { + public CCModel copy() { CCModel model = newModel(vertexMode, verts.length); copy(this, 0, model, 0, verts.length); return model; @@ -989,23 +932,18 @@ public CCModel copy() /** * @return The average of all vertices, for bones. */ - public Vector3 collapse() - { + public Vector3 collapse() { Vector3 v = new Vector3(); - for(Vertex5 vert : verts) - v.add(vert.vec); - v.multiply(1/(double)verts.length); + for (Vertex5 vert : verts) v.add(vert.vec); + v.multiply(1 / (double) verts.length); return v; } - public CCModel zOffset(Cuboid6 offsets) - { - for(int k = 0; k < verts.length; k++) - { + public CCModel zOffset(Cuboid6 offsets) { + for (int k = 0; k < verts.length; k++) { Vertex5 vert = verts[k]; Vector3 normal = normals()[k]; - switch(findSide(normal)) - { + switch (findSide(normal)) { case 0: vert.vec.y += offsets.min.y; break; @@ -1029,26 +967,23 @@ public CCModel zOffset(Cuboid6 offsets) return this; } - public static int findSide(Vector3 normal) - { - if(normal.y <=-0.99) return 0; - if(normal.y >= 0.99) return 1; - if(normal.z <=-0.99) return 2; - if(normal.z >= 0.99) return 3; - if(normal.x <=-0.99) return 4; - if(normal.x >= 0.99) return 5; + public static int findSide(Vector3 normal) { + if (normal.y <= -0.99) return 0; + if (normal.y >= 0.99) return 1; + if (normal.z <= -0.99) return 2; + if (normal.z >= 0.99) return 3; + if (normal.x <= -0.99) return 4; + if (normal.x >= 0.99) return 5; return -1; } /** * @return A Cuboid6 containing all the verts in this model */ - public Cuboid6 bounds() - { + public Cuboid6 bounds() { Vector3 vec1 = verts[0].vec; Cuboid6 c = new Cuboid6(vec1.copy(), vec1.copy()); - for(int i = 1; i < verts.length; i++) - c.enclose(verts[i].vec); + for (int i = 1; i < verts.length; i++) c.enclose(verts[i].vec); return c; } } diff --git a/src/main/java/codechicken/lib/render/CCModelLibrary.java b/src/main/java/codechicken/lib/render/CCModelLibrary.java index 0987aab..53f87a1 100644 --- a/src/main/java/codechicken/lib/render/CCModelLibrary.java +++ b/src/main/java/codechicken/lib/render/CCModelLibrary.java @@ -1,89 +1,91 @@ package codechicken.lib.render; -import codechicken.lib.vec.*; - import static codechicken.lib.math.MathHelper.phi; -public class CCModelLibrary -{ +import codechicken.lib.vec.*; + +public class CCModelLibrary { public static CCModel icosahedron4; public static CCModel icosahedron7; - + private static int i; - - static - { + + static { generateIcosahedron(); } - private static void generateIcosahedron() - { + private static void generateIcosahedron() { Vector3[] verts = new Vector3[12]; verts[0] = new Vector3(-1, phi, 0); - verts[1] = new Vector3( 1, phi, 0); - verts[2] = new Vector3( 1,-phi, 0); - verts[3] = new Vector3(-1,-phi, 0); + verts[1] = new Vector3(1, phi, 0); + verts[2] = new Vector3(1, -phi, 0); + verts[3] = new Vector3(-1, -phi, 0); - verts[4] = new Vector3(0,-1, phi); + verts[4] = new Vector3(0, -1, phi); verts[5] = new Vector3(0, 1, phi); - verts[6] = new Vector3(0, 1,-phi); - verts[7] = new Vector3(0,-1,-phi); + verts[6] = new Vector3(0, 1, -phi); + verts[7] = new Vector3(0, -1, -phi); - verts[8] = new Vector3( phi, 0,-1); - verts[9] = new Vector3( phi, 0, 1); + verts[8] = new Vector3(phi, 0, -1); + verts[9] = new Vector3(phi, 0, 1); verts[10] = new Vector3(-phi, 0, 1); - verts[11] = new Vector3(-phi, 0,-1); + verts[11] = new Vector3(-phi, 0, -1); + + Quat quat = Quat.aroundAxis(0, 0, 1, Math.atan(1 / phi)); + for (Vector3 vec : verts) quat.rotate(vec); - Quat quat = Quat.aroundAxis(0, 0, 1, Math.atan(1/phi)); - for(Vector3 vec : verts) - quat.rotate(vec); - icosahedron4 = CCModel.newModel(4, 60); icosahedron7 = CCModel.newModel(7, 80); i = 0; - //top + // top addIcosahedronTriangle(verts[1], 0.5, 0, verts[0], 0, 0.25, verts[5], 1, 0.25); addIcosahedronTriangle(verts[1], 0.5, 0, verts[5], 0, 0.25, verts[9], 1, 0.25); addIcosahedronTriangle(verts[1], 0.5, 0, verts[9], 0, 0.25, verts[8], 1, 0.25); addIcosahedronTriangle(verts[1], 0.5, 0, verts[8], 0, 0.25, verts[6], 1, 0.25); addIcosahedronTriangle(verts[1], 0.5, 0, verts[6], 0, 0.25, verts[0], 1, 0.25); - //centre 1vert top - addIcosahedronTriangle(verts[0], 0.5, 0.25, verts[11],0, 0.75, verts[10],1, 0.75); - addIcosahedronTriangle(verts[5], 0.5, 0.25, verts[10],0, 0.75, verts[4], 1, 0.75); + // centre 1vert top + addIcosahedronTriangle(verts[0], 0.5, 0.25, verts[11], 0, 0.75, verts[10], 1, 0.75); + addIcosahedronTriangle(verts[5], 0.5, 0.25, verts[10], 0, 0.75, verts[4], 1, 0.75); addIcosahedronTriangle(verts[9], 0.5, 0.25, verts[4], 0, 0.75, verts[2], 1, 0.75); addIcosahedronTriangle(verts[8], 0.5, 0.25, verts[2], 0, 0.75, verts[7], 1, 0.75); - addIcosahedronTriangle(verts[6], 0.5, 0.25, verts[7], 0, 0.75, verts[11],1, 0.75); - //centre 1vert bottom + addIcosahedronTriangle(verts[6], 0.5, 0.25, verts[7], 0, 0.75, verts[11], 1, 0.75); + // centre 1vert bottom addIcosahedronTriangle(verts[2], 0.5, 0.75, verts[8], 0, 0.25, verts[9], 1, 0.25); addIcosahedronTriangle(verts[7], 0.5, 0.75, verts[6], 0, 0.25, verts[8], 1, 0.25); - addIcosahedronTriangle(verts[11],0.5, 0.75, verts[0], 0, 0.25, verts[6], 1, 0.25); - addIcosahedronTriangle(verts[10],0.5, 0.75, verts[5], 0, 0.25, verts[0], 1, 0.25); + addIcosahedronTriangle(verts[11], 0.5, 0.75, verts[0], 0, 0.25, verts[6], 1, 0.25); + addIcosahedronTriangle(verts[10], 0.5, 0.75, verts[5], 0, 0.25, verts[0], 1, 0.25); addIcosahedronTriangle(verts[4], 0.5, 0.75, verts[9], 0, 0.25, verts[5], 1, 0.25); - //bottom + // bottom addIcosahedronTriangle(verts[3], 0.5, 1, verts[2], 0, 0.75, verts[4], 1, 0.75); addIcosahedronTriangle(verts[3], 0.5, 1, verts[7], 0, 0.75, verts[2], 1, 0.75); - addIcosahedronTriangle(verts[3], 0.5, 1, verts[11],0, 0.75, verts[7], 1, 0.75); - addIcosahedronTriangle(verts[3], 0.5, 1, verts[10],0, 0.75, verts[11],1, 0.75); - addIcosahedronTriangle(verts[3], 0.5, 1, verts[4], 0, 0.75, verts[10],1, 0.75); - + addIcosahedronTriangle(verts[3], 0.5, 1, verts[11], 0, 0.75, verts[7], 1, 0.75); + addIcosahedronTriangle(verts[3], 0.5, 1, verts[10], 0, 0.75, verts[11], 1, 0.75); + addIcosahedronTriangle(verts[3], 0.5, 1, verts[4], 0, 0.75, verts[10], 1, 0.75); + icosahedron4.computeNormals().smoothNormals(); icosahedron7.computeNormals().smoothNormals(); } - private static void addIcosahedronTriangle(Vector3 vec1, double u1, double v1, - Vector3 vec2, double u2, double v2, - Vector3 vec3, double u3, double v3) - { - icosahedron4.verts[i*3] = icosahedron7.verts[i*4] = new Vertex5(vec1, u1, v1); - icosahedron4.verts[i*3+1] = icosahedron7.verts[i*4+1] = new Vertex5(vec2, u2, v2); - icosahedron4.verts[i*3+2] = icosahedron7.verts[i*4+2] = icosahedron7.verts[i*4+3] = new Vertex5(vec3, u3, v3); + private static void addIcosahedronTriangle( + Vector3 vec1, + double u1, + double v1, + Vector3 vec2, + double u2, + double v2, + Vector3 vec3, + double u3, + double v3) { + icosahedron4.verts[i * 3] = icosahedron7.verts[i * 4] = new Vertex5(vec1, u1, v1); + icosahedron4.verts[i * 3 + 1] = icosahedron7.verts[i * 4 + 1] = new Vertex5(vec2, u2, v2); + icosahedron4.verts[i * 3 + 2] = + icosahedron7.verts[i * 4 + 2] = icosahedron7.verts[i * 4 + 3] = new Vertex5(vec3, u3, v3); i++; } - - public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) - { + + public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) { return new Matrix4().translate(position).apply(new Scale(scale)).apply(rotation); } } diff --git a/src/main/java/codechicken/lib/render/CCRenderPipeline.java b/src/main/java/codechicken/lib/render/CCRenderPipeline.java index 72fb2b3..79d965e 100644 --- a/src/main/java/codechicken/lib/render/CCRenderPipeline.java +++ b/src/main/java/codechicken/lib/render/CCRenderPipeline.java @@ -2,21 +2,17 @@ import codechicken.lib.render.CCRenderState.IVertexOperation; import codechicken.lib.render.CCRenderState.VertexAttribute; - import java.util.ArrayList; -public class CCRenderPipeline -{ - public class PipelineBuilder - { +public class CCRenderPipeline { + public class PipelineBuilder { public PipelineBuilder add(IVertexOperation op) { ops.add(op); return this; } public PipelineBuilder add(IVertexOperation... ops) { - for(int i = 0; i < ops.length; i++) - CCRenderPipeline.this.ops.add(ops[i]); + for (int i = 0; i < ops.length; i++) CCRenderPipeline.this.ops.add(ops[i]); return this; } @@ -30,17 +26,14 @@ public void render() { } } - private class PipelineNode - { + private class PipelineNode { public ArrayList deps = new ArrayList(); public IVertexOperation op; public void add() { - if(op == null) - return; + if (op == null) return; - for(int i = 0; i < deps.size(); i++) - deps.get(i).add(); + for (int i = 0; i < deps.size(); i++) deps.get(i).add(); deps.clear(); sorted.add(op); op = null; @@ -56,8 +49,7 @@ public void add() { public void setPipeline(IVertexOperation... ops) { this.ops.clear(); - for(int i = 0; i < ops.length; i++) - this.ops.add(ops[i]); + for (int i = 0; i < ops.length; i++) this.ops.add(ops[i]); rebuild(); } @@ -67,44 +59,34 @@ public void reset() { } private void unbuild() { - for(int i = 0; i < attribs.size(); i++) - attribs.get(i).active = false; + for (int i = 0; i < attribs.size(); i++) attribs.get(i).active = false; attribs.clear(); sorted.clear(); } public void rebuild() { - if(ops.isEmpty() || CCRenderState.model == null) - return; + if (ops.isEmpty() || CCRenderState.model == null) return; - //ensure enough nodes for all ops - while(nodes.size() < CCRenderState.operationCount()) - nodes.add(new PipelineNode()); + // ensure enough nodes for all ops + while (nodes.size() < CCRenderState.operationCount()) nodes.add(new PipelineNode()); unbuild(); - if(CCRenderState.useNormals) - addAttribute(CCRenderState.normalAttrib); - if(CCRenderState.useColour) - addAttribute(CCRenderState.colourAttrib); - if(CCRenderState.computeLighting) - addAttribute(CCRenderState.lightingAttrib); + if (CCRenderState.useNormals) addAttribute(CCRenderState.normalAttrib); + if (CCRenderState.useColour) addAttribute(CCRenderState.colourAttrib); + if (CCRenderState.computeLighting) addAttribute(CCRenderState.lightingAttrib); - for(int i = 0; i < ops.size(); i++) { + for (int i = 0; i < ops.size(); i++) { IVertexOperation op = ops.get(i); loading = nodes.get(op.operationID()); boolean loaded = op.load(); - if(loaded) - loading.op = op; - - if(op instanceof VertexAttribute) - if(loaded) - attribs.add((VertexAttribute)op); - else - ((VertexAttribute)op).active = false; + if (loaded) loading.op = op; + + if (op instanceof VertexAttribute) + if (loaded) attribs.add((VertexAttribute) op); + else ((VertexAttribute) op).active = false; } - for(int i = 0; i < nodes.size(); i++) - nodes.get(i).add(); + for (int i = 0; i < nodes.size(); i++) nodes.get(i).add(); } public void addRequirement(int opRef) { @@ -117,15 +99,14 @@ public void addDependency(VertexAttribute attrib) { } public void addAttribute(VertexAttribute attrib) { - if(!attrib.active) { + if (!attrib.active) { ops.add(attrib); attrib.active = true; } } public void operate() { - for(int i = 0; i < sorted.size(); i++) - sorted.get(i).operate(); + for (int i = 0; i < sorted.size(); i++) sorted.get(i).operate(); } public PipelineBuilder builder() { diff --git a/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java index 952f01f..51c92ec 100644 --- a/src/main/java/codechicken/lib/render/CCRenderState.java +++ b/src/main/java/codechicken/lib/render/CCRenderState.java @@ -7,20 +7,18 @@ import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; +import java.util.ArrayList; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.ResourceLocation; import net.minecraft.world.IBlockAccess; -import java.util.ArrayList; - /** * The core of the CodeChickenLib render system. * Rendering operations are written to avoid object allocations by reusing static variables. */ -public class CCRenderState -{ +public class CCRenderState { private static int nextOperationIndex; public static int registerOperation() { @@ -34,8 +32,7 @@ public static int operationCount() { /** * Represents an operation to be run for each vertex that operates on and modifies the current state */ - public static interface IVertexOperation - { + public static interface IVertexOperation { /** * Load any required references and add dependencies to the pipeline based on the current model (may be null) * Return false if this operation is redundant in the pipeline with the given model @@ -55,9 +52,10 @@ public static interface IVertexOperation } private static ArrayList> vertexAttributes = new ArrayList>(); + private static int registerVertexAttribute(VertexAttribute attr) { vertexAttributes.add(attr); - return vertexAttributes.size()-1; + return vertexAttributes.size() - 1; } public static VertexAttribute getAttribute(int index) { @@ -69,8 +67,7 @@ public static VertexAttribute getAttribute(int index) { * This class should handle the loading of the attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others * @param The array type for this attrute eg. int[], Vector3[] */ - public static abstract class VertexAttribute implements IVertexOperation - { + public abstract static class VertexAttribute implements IVertexOperation { public final int attributeIndex = registerVertexAttribute(this); private final int operationIndex = registerOperation(); /** @@ -91,23 +88,20 @@ public int operationID() { public static void arrayCopy(Object src, int srcPos, Object dst, int destPos, int length) { System.arraycopy(src, srcPos, dst, destPos, length); - if(dst instanceof Copyable[]) { - Object[] oa = (Object[])dst; - Copyable[] c = (Copyable[])dst; - for(int i = destPos; i < destPos+length; i++) - if(c[i] != null) - oa[i] = c[i].copy(); + if (dst instanceof Copyable[]) { + Object[] oa = (Object[]) dst; + Copyable[] c = (Copyable[]) dst; + for (int i = destPos; i < destPos + length; i++) if (c[i] != null) oa[i] = c[i].copy(); } } public static T copyOf(VertexAttribute attr, T src, int length) { T dst = attr.newArray(length); - arrayCopy(src, 0, dst, 0, ((Object[])src).length); + arrayCopy(src, 0, dst, 0, ((Object[]) src).length); return dst; } - public static interface IVertexSource - { + public static interface IVertexSource { public Vertex5[] getVertices(); /** @@ -140,22 +134,20 @@ public Vector3[] newArray(int length) { @Override public boolean load() { normalRef = model.getAttributes(this); - if(model.hasAttribute(this)) - return normalRef != null; + if (model.hasAttribute(this)) return normalRef != null; - if(model.hasAttribute(sideAttrib)) { + if (model.hasAttribute(sideAttrib)) { pipeline.addDependency(sideAttrib); return true; } - throw new IllegalStateException("Normals requested but neither normal or side attrutes are provided by the model"); + throw new IllegalStateException( + "Normals requested but neither normal or side attrutes are provided by the model"); } @Override public void operate() { - if(normalRef != null) - setNormal(normalRef[vertexIndex]); - else - setNormal(Rotation.axes[side]); + if (normalRef != null) setNormal(normalRef[vertexIndex]); + else setNormal(Rotation.axes[side]); } }; public static VertexAttribute colourAttrib = new VertexAttribute() { @@ -174,10 +166,8 @@ public boolean load() { @Override public void operate() { - if(colourRef != null) - setColour(ColourRGBA.multiply(baseColour, colourRef[vertexIndex])); - else - setColour(baseColour); + if (colourRef != null) setColour(ColourRGBA.multiply(baseColour, colourRef[vertexIndex])); + else setColour(baseColour); } }; public static VertexAttribute lightingAttrib = new VertexAttribute() { @@ -190,11 +180,10 @@ public int[] newArray(int length) { @Override public boolean load() { - if(!computeLighting || !useColour || !model.hasAttribute(this)) - return false; + if (!computeLighting || !useColour || !model.hasAttribute(this)) return false; colourRef = model.getAttributes(this); - if(colourRef != null) { + if (colourRef != null) { pipeline.addDependency(colourAttrib); return true; } @@ -217,8 +206,7 @@ public int[] newArray(int length) { @Override public boolean load() { sideRef = model.getAttributes(this); - if(model.hasAttribute(this)) - return sideRef != null; + if (model.hasAttribute(this)) return sideRef != null; pipeline.addDependency(normalAttrib); return true; @@ -226,10 +214,8 @@ public boolean load() { @Override public void operate() { - if(sideRef != null) - side = sideRef[vertexIndex]; - else - side = CCModel.findSide(normal); + if (sideRef != null) side = sideRef[vertexIndex]; + else side = CCModel.findSide(normal); } }; /** @@ -237,7 +223,7 @@ public void operate() { */ public static VertexAttribute lightCoordAttrib = new VertexAttribute() { private LC[] lcRef; - private Vector3 vec = new Vector3();//for computation + private Vector3 vec = new Vector3(); // for computation private Vector3 pos = new Vector3(); @Override @@ -248,8 +234,7 @@ public LC[] newArray(int length) { @Override public boolean load() { lcRef = model.getAttributes(this); - if(model.hasAttribute(this)) - return lcRef != null; + if (model.hasAttribute(this)) return lcRef != null; pos.set(lightMatrix.pos.x, lightMatrix.pos.y, lightMatrix.pos.z); pipeline.addDependency(sideAttrib); @@ -259,21 +244,19 @@ public boolean load() { @Override public void operate() { - if(lcRef != null) - lc.set(lcRef[vertexIndex]); - else - lc.compute(vec.set(vert.vec).sub(pos), side); + if (lcRef != null) lc.set(lcRef[vertexIndex]); + else lc.compute(vec.set(vert.vec).sub(pos), side); } }; - //pipeline state + // pipeline state public static IVertexSource model; public static int firstVertexIndex; public static int lastVertexIndex; public static int vertexIndex; public static CCRenderPipeline pipeline = new CCRenderPipeline(); - //context + // context public static int baseColour; public static int alphaOverride; public static boolean useNormals; @@ -281,7 +264,7 @@ public void operate() { public static boolean useColour; public static LightMatrix lightMatrix = new LightMatrix(); - //vertex outputs + // vertex outputs public static Vertex5 vert = new Vertex5(); public static boolean hasNormal; public static Vector3 normal = new Vector3(); @@ -290,7 +273,7 @@ public void operate() { public static boolean hasBrightness; public static int brightness; - //attrute storage + // attrute storage public static int side; public static LC lc = new LC(); @@ -313,7 +296,7 @@ public static void setPipeline(IVertexSource model, int start, int end, IVertexO } public static void bindModel(IVertexSource model) { - if(CCRenderState.model != model) { + if (CCRenderState.model != model) { CCRenderState.model = model; pipeline.rebuild(); } @@ -340,7 +323,7 @@ public static void render(IVertexOperation... ops) { public static void render() { Vertex5[] verts = model.getVertices(); - for(vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) { + for (vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) { model.prepareVertex(); vert.set(verts[vertexIndex]); runPipeline(); @@ -353,12 +336,14 @@ public static void runPipeline() { } public static void writeVert() { - if(hasNormal) - Tessellator.instance.setNormal((float)normal.x, (float)normal.y, (float)normal.z); - if(hasColour) - Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); - if(hasBrightness) - Tessellator.instance.setBrightness(brightness); + if (hasNormal) Tessellator.instance.setNormal((float) normal.x, (float) normal.y, (float) normal.z); + if (hasColour) + Tessellator.instance.setColorRGBA( + colour >>> 24, + colour >> 16 & 0xFF, + colour >> 8 & 0xFF, + alphaOverride >= 0 ? alphaOverride : colour & 0xFF); + if (hasBrightness) Tessellator.instance.setBrightness(brightness); Tessellator.instance.addVertexWithUV(vert.vec.x, vert.vec.y, vert.vec.z, vert.uv.u, vert.uv.v); } @@ -387,7 +372,7 @@ public static void setBrightness(IBlockAccess world, int x, int y, int z) { } public static void pullLightmap() { - setBrightness((int)OpenGlHelper.lastBrightnessY << 16 | (int)OpenGlHelper.lastBrightnessX); + setBrightness((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX); } public static void pushLightmap() { @@ -416,10 +401,13 @@ public static void startDrawing() { public static void startDrawing(int mode) { Tessellator.instance.startDrawing(mode); - if(hasColour) - Tessellator.instance.setColorRGBA(colour>>>24, colour>>16 & 0xFF, colour>>8 & 0xFF, alphaOverride >= 0 ? alphaOverride : colour & 0xFF); - if(hasBrightness) - Tessellator.instance.setBrightness(brightness); + if (hasColour) + Tessellator.instance.setColorRGBA( + colour >>> 24, + colour >> 16 & 0xFF, + colour >> 8 & 0xFF, + alphaOverride >= 0 ? alphaOverride : colour & 0xFF); + if (hasBrightness) Tessellator.instance.setBrightness(brightness); } public static void draw() { diff --git a/src/main/java/codechicken/lib/render/ColourMultiplier.java b/src/main/java/codechicken/lib/render/ColourMultiplier.java index 71e3228..cf3a0db 100644 --- a/src/main/java/codechicken/lib/render/ColourMultiplier.java +++ b/src/main/java/codechicken/lib/render/ColourMultiplier.java @@ -2,8 +2,7 @@ import codechicken.lib.colour.ColourRGBA; -public class ColourMultiplier implements CCRenderState.IVertexOperation -{ +public class ColourMultiplier implements CCRenderState.IVertexOperation { private static ColourMultiplier instance = new ColourMultiplier(-1); public static ColourMultiplier instance(int colour) { @@ -20,7 +19,7 @@ public ColourMultiplier(int colour) { @Override public boolean load() { - if(colour == -1) { + if (colour == -1) { CCRenderState.setColour(-1); return false; } diff --git a/src/main/java/codechicken/lib/render/EntityDigIconFX.java b/src/main/java/codechicken/lib/render/EntityDigIconFX.java index e0e7571..1712859 100644 --- a/src/main/java/codechicken/lib/render/EntityDigIconFX.java +++ b/src/main/java/codechicken/lib/render/EntityDigIconFX.java @@ -8,23 +8,20 @@ import net.minecraft.util.IIcon; import net.minecraft.world.World; -public class EntityDigIconFX extends EntityFX -{ - public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) - { +public class EntityDigIconFX extends EntityFX { + public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) { super(world, x, y, z, dx, dy, dz); particleIcon = icon; particleGravity = 1; particleRed = particleGreen = particleBlue = 0.6F; particleScale /= 2.0F; } - + @Override - public int getFXLayer() - { + public int getFXLayer() { return 1; } - + public void setScale(float scale) { particleScale = scale; } @@ -32,91 +29,94 @@ public void setScale(float scale) { public float getScale() { return particleScale; } - - public void setMaxAge(int age){ + + public void setMaxAge(int age) { particleMaxAge = age; } - - public int getMaxAge(){ + + public int getMaxAge() { return particleMaxAge; } - + /** * copy pasted from EntityDiggingFX */ @Override - public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7) - { + public void renderParticle( + Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7) { float f6 = (particleTextureIndexX + particleTextureJitterX / 4.0F) / 16.0F; float f7 = f6 + 0.015609375F; float f8 = (particleTextureIndexY + particleTextureJitterY / 4.0F) / 16.0F; float f9 = f8 + 0.015609375F; float f10 = 0.1F * particleScale; - if (particleIcon != null) - { + if (particleIcon != null) { f6 = particleIcon.getInterpolatedU(particleTextureJitterX / 4.0F * 16.0F); f7 = particleIcon.getInterpolatedU((particleTextureJitterX + 1.0F) / 4.0F * 16.0F); f8 = particleIcon.getInterpolatedV(particleTextureJitterY / 4.0F * 16.0F); f9 = particleIcon.getInterpolatedV((particleTextureJitterY + 1.0F) / 4.0F * 16.0F); } - float f11 = (float)(prevPosX + (posX - prevPosX) * par2 - interpPosX); - float f12 = (float)(prevPosY + (posY - prevPosY) * par2 - interpPosY); - float f13 = (float)(prevPosZ + (posZ - prevPosZ) * par2 - interpPosZ); + float f11 = (float) (prevPosX + (posX - prevPosX) * par2 - interpPosX); + float f12 = (float) (prevPosY + (posY - prevPosY) * par2 - interpPosY); + float f13 = (float) (prevPosZ + (posZ - prevPosZ) * par2 - interpPosZ); float f14 = 1.0F; par1Tessellator.setColorOpaque_F(f14 * particleRed, f14 * particleGreen, f14 * particleBlue); - par1Tessellator.addVertexWithUV(f11 - par3 * f10 - par6 * f10, f12 - par4 * f10, f13 - par5 * f10 - par7 * f10, f6, f9); - par1Tessellator.addVertexWithUV(f11 - par3 * f10 + par6 * f10, f12 + par4 * f10, f13 - par5 * f10 + par7 * f10, f6, f8); - par1Tessellator.addVertexWithUV(f11 + par3 * f10 + par6 * f10, f12 + par4 * f10, f13 + par5 * f10 + par7 * f10, f7, f8); - par1Tessellator.addVertexWithUV(f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10, f7, f9); + par1Tessellator.addVertexWithUV( + f11 - par3 * f10 - par6 * f10, f12 - par4 * f10, f13 - par5 * f10 - par7 * f10, f6, f9); + par1Tessellator.addVertexWithUV( + f11 - par3 * f10 + par6 * f10, f12 + par4 * f10, f13 - par5 * f10 + par7 * f10, f6, f8); + par1Tessellator.addVertexWithUV( + f11 + par3 * f10 + par6 * f10, f12 + par4 * f10, f13 + par5 * f10 + par7 * f10, f7, f8); + par1Tessellator.addVertexWithUV( + f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10, f7, f9); } - - public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, EffectRenderer effectRenderer) - { + + public static void addBlockHitEffects( + World world, Cuboid6 bounds, int side, IIcon icon, EffectRenderer effectRenderer) { float border = 0.1F; - Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2*border); - diff.x*=world.rand.nextDouble(); - diff.y*=world.rand.nextDouble(); - diff.z*=world.rand.nextDouble(); + Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2 * border); + diff.x *= world.rand.nextDouble(); + diff.y *= world.rand.nextDouble(); + diff.z *= world.rand.nextDouble(); Vector3 pos = diff.add(bounds.min).add(border); - - if (side == 0) - diff.y = bounds.min.y - border; - if (side == 1) - diff.y = bounds.max.y + border; - if (side == 2) - diff.z = bounds.min.z - border; - if (side == 3) - diff.z = bounds.max.z + border; - if (side == 4) - diff.x = bounds.min.x - border; - if (side == 5) - diff.x = bounds.max.x + border; - - effectRenderer.addEffect( - new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon) - .multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F)); + + if (side == 0) diff.y = bounds.min.y - border; + if (side == 1) diff.y = bounds.max.y + border; + if (side == 2) diff.z = bounds.min.z - border; + if (side == 3) diff.z = bounds.max.z + border; + if (side == 4) diff.x = bounds.min.x - border; + if (side == 5) diff.x = bounds.max.x + border; + + effectRenderer.addEffect(new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon) + .multiplyVelocity(0.2F) + .multipleParticleScaleBy(0.6F)); } - - public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, EffectRenderer effectRenderer) - { + + public static void addBlockDestroyEffects( + World world, Cuboid6 bounds, IIcon[] icons, EffectRenderer effectRenderer) { Vector3 diff = bounds.max.copy().subtract(bounds.min); Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); Vector3 density = diff.copy().multiply(4); density.x = Math.ceil(density.x); density.y = Math.ceil(density.y); density.z = Math.ceil(density.z); - + for (int i = 0; i < density.x; ++i) for (int j = 0; j < density.y; ++j) - for (int k = 0; k < density.z; ++k) - { - double x = bounds.min.x+(i+0.5)*diff.x/density.x; - double y = bounds.min.y+(j+0.5)*diff.y/density.y; - double z = bounds.min.z+(k+0.5)*diff.z/density.z; - effectRenderer.addEffect( - new EntityDigIconFX(world, x, y, z, x-center.x, y-center.y, z-center.z, icons[world.rand.nextInt(icons.length)])); + for (int k = 0; k < density.z; ++k) { + double x = bounds.min.x + (i + 0.5) * diff.x / density.x; + double y = bounds.min.y + (j + 0.5) * diff.y / density.y; + double z = bounds.min.z + (k + 0.5) * diff.z / density.z; + effectRenderer.addEffect(new EntityDigIconFX( + world, + x, + y, + z, + x - center.x, + y - center.y, + z - center.z, + icons[world.rand.nextInt(icons.length)])); } } } diff --git a/src/main/java/codechicken/lib/render/FontUtils.java b/src/main/java/codechicken/lib/render/FontUtils.java index b927046..bada7cb 100644 --- a/src/main/java/codechicken/lib/render/FontUtils.java +++ b/src/main/java/codechicken/lib/render/FontUtils.java @@ -5,62 +5,53 @@ import net.minecraft.item.ItemStack; import org.lwjgl.opengl.GL11; -public class FontUtils -{ +public class FontUtils { public static FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; - - public static void drawCenteredString(String s, int xCenter, int y, int colour) - { - fontRenderer.drawString(s, xCenter-fontRenderer.getStringWidth(s)/2, y, colour); + + public static void drawCenteredString(String s, int xCenter, int y, int colour) { + fontRenderer.drawString(s, xCenter - fontRenderer.getStringWidth(s) / 2, y, colour); } - - public static void drawRightString(String s, int xRight, int y, int colour) - { - fontRenderer.drawString(s, xRight-fontRenderer.getStringWidth(s), y, colour); + + public static void drawRightString(String s, int xRight, int y, int colour) { + fontRenderer.drawString(s, xRight - fontRenderer.getStringWidth(s), y, colour); } - - public static final String[] prefixes = new String[]{"K", "M", "G"}; - public static void drawItemQuantity(int x, int y, ItemStack item, String quantity, int mode) - { - if(item == null || (quantity == null && item.stackSize <= 1)) - return; - - if(quantity == null) - { - switch(mode) - { + + public static final String[] prefixes = new String[] {"K", "M", "G"}; + + public static void drawItemQuantity(int x, int y, ItemStack item, String quantity, int mode) { + if (item == null || (quantity == null && item.stackSize <= 1)) return; + + if (quantity == null) { + switch (mode) { case 2: int q = item.stackSize; String postfix = ""; - for(int p = 0; p < 3 && q > 1000; p++) - { - q/=1000; + for (int p = 0; p < 3 && q > 1000; p++) { + q /= 1000; postfix = prefixes[p]; } - quantity = Integer.toString(q)+postfix; + quantity = Integer.toString(q) + postfix; case 1: quantity = ""; - if(item.stackSize/64 > 0) - quantity+=item.stackSize/64 + "s"; - if(item.stackSize%64 > 0) - quantity+=item.stackSize%64; - break; + if (item.stackSize / 64 > 0) quantity += item.stackSize / 64 + "s"; + if (item.stackSize % 64 > 0) quantity += item.stackSize % 64; + break; default: quantity = Integer.toString(item.stackSize); - break; + break; } } - + double scale = quantity.length() > 2 ? 0.5 : 1; - double sheight = 8*scale; - double swidth = fontRenderer.getStringWidth(quantity)*scale; + double sheight = 8 * scale; + double swidth = fontRenderer.getStringWidth(quantity) * scale; GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glPushMatrix(); - GL11.glTranslated(x+16-swidth, y+16-sheight, 0); - GL11.glScaled(scale, scale, 1); - fontRenderer.drawStringWithShadow(quantity, 0, 0, 0xFFFFFF); + GL11.glTranslated(x + 16 - swidth, y + 16 - sheight, 0); + GL11.glScaled(scale, scale, 1); + fontRenderer.drawStringWithShadow(quantity, 0, 0, 0xFFFFFF); GL11.glPopMatrix(); GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_DEPTH_TEST); diff --git a/src/main/java/codechicken/lib/render/IFaceRenderer.java b/src/main/java/codechicken/lib/render/IFaceRenderer.java index d2ed2b4..891b8f9 100644 --- a/src/main/java/codechicken/lib/render/IFaceRenderer.java +++ b/src/main/java/codechicken/lib/render/IFaceRenderer.java @@ -1,6 +1,5 @@ package codechicken.lib.render; -public interface IFaceRenderer -{ +public interface IFaceRenderer { public void renderFace(Vertex5[] face, int side); } diff --git a/src/main/java/codechicken/lib/render/ManagedTextureFX.java b/src/main/java/codechicken/lib/render/ManagedTextureFX.java index ed1166d..602dbe0 100644 --- a/src/main/java/codechicken/lib/render/ManagedTextureFX.java +++ b/src/main/java/codechicken/lib/render/ManagedTextureFX.java @@ -1,29 +1,23 @@ package codechicken.lib.render; -public class ManagedTextureFX extends TextureFX -{ +public class ManagedTextureFX extends TextureFX { public boolean changed; - - public ManagedTextureFX(int size, String name) - { + + public ManagedTextureFX(int size, String name) { super(size, name); - imageData = new int[size*size]; + imageData = new int[size * size]; } - + @Override - public void setup() - { - } - - public void setData(int[] data) - { + public void setup() {} + + public void setData(int[] data) { System.arraycopy(data, 0, imageData, 0, imageData.length); changed = true; } - + @Override - public boolean changed() - { + public boolean changed() { boolean r = changed; changed = false; return r; diff --git a/src/main/java/codechicken/lib/render/PlaceholderTexture.java b/src/main/java/codechicken/lib/render/PlaceholderTexture.java index b909375..96aef9a 100644 --- a/src/main/java/codechicken/lib/render/PlaceholderTexture.java +++ b/src/main/java/codechicken/lib/render/PlaceholderTexture.java @@ -4,8 +4,7 @@ import net.minecraft.client.resources.IResourceManager; import net.minecraft.util.ResourceLocation; -public class PlaceholderTexture extends TextureAtlasSprite -{ +public class PlaceholderTexture extends TextureAtlasSprite { protected PlaceholderTexture(String par1) { super(par1); } diff --git a/src/main/java/codechicken/lib/render/QBImporter.java b/src/main/java/codechicken/lib/render/QBImporter.java index 712036b..64efeac 100644 --- a/src/main/java/codechicken/lib/render/QBImporter.java +++ b/src/main/java/codechicken/lib/render/QBImporter.java @@ -5,20 +5,17 @@ import codechicken.lib.vec.*; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.*; +import javax.imageio.ImageIO; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.*; -import java.util.*; - -public class QBImporter -{ - private static class ImagePackNode - { +public class QBImporter { + private static class ImagePackNode { Rectangle4i rect; ImagePackNode child1; ImagePackNode child2; @@ -29,59 +26,49 @@ public ImagePackNode(int x, int y, int w, int h) { } public boolean pack(QBImage img) { - if(child1 != null) - return child1.pack(img) || child2.pack(img); + if (child1 != null) return child1.pack(img) || child2.pack(img); - if(packed != null) - return false; + if (packed != null) return false; int fit = getFit(img.width(), img.height()); - if(fit == 0) - return false; + if (fit == 0) return false; - if((fit & 2) != 0) {//exact fit + if ((fit & 2) != 0) { // exact fit packed = img; img.packSlot = rect; - img.packT = new ImageTransform((fit&1)<<2); + img.packT = new ImageTransform((fit & 1) << 2); return true; } int w = (fit & 1) == 0 ? img.width() : img.height(); int h = (fit & 1) == 0 ? img.height() : img.width(); - if(rect.w - w > rect.h - h) {//create split with biggest leftover space + if (rect.w - w > rect.h - h) { // create split with biggest leftover space child1 = new ImagePackNode(rect.x, rect.y, w, rect.h); - child2 = new ImagePackNode(rect.x+w, rect.y, rect.w-w, rect.h); + child2 = new ImagePackNode(rect.x + w, rect.y, rect.w - w, rect.h); } else { child1 = new ImagePackNode(rect.x, rect.y, rect.w, h); - child2 = new ImagePackNode(rect.x, rect.y+h, rect.w, rect.h-h); + child2 = new ImagePackNode(rect.x, rect.y + h, rect.w, rect.h - h); } return child1.pack(img); } private int getFit(int w, int h) { - if(w == rect.w && h == rect.h) - return 2; - if(w == rect.h && h == rect.w) - return 3; - if(rect.w >= w && rect.h >= h) - return 4; - if(rect.w >= h && rect.h >= w) - return 5; + if (w == rect.w && h == rect.h) return 2; + if (w == rect.h && h == rect.w) return 3; + if (rect.w >= w && rect.h >= h) return 4; + if (rect.w >= h && rect.h >= w) return 5; return 0; } private static void nextSize(Rectangle4i rect, boolean square) { - if(square) { + if (square) { rect.w <<= 1; rect.h <<= 1; - } - else { - if(rect.w == rect.h) - rect.w *= 2; - else - rect.h *= 2; + } else { + if (rect.w == rect.h) rect.w *= 2; + else rect.h *= 2; } } @@ -89,23 +76,20 @@ public static ImagePackNode pack(List images, boolean square) { Collections.sort(images); int area = 0; - for(QBImage img : images) - area+=img.area(); + for (QBImage img : images) area += img.area(); ImagePackNode node = new ImagePackNode(0, 0, 2, 2); - while(node.rect.area() < area) - nextSize(node.rect, square); + while (node.rect.area() < area) nextSize(node.rect, square); - while(true) { + while (true) { boolean packed = true; - for(QBImage img : images) - if(!node.pack(img)) { + for (QBImage img : images) + if (!node.pack(img)) { packed = false; break; } - if(packed) - return node; + if (packed) return node; node.child1 = node.child2 = null; nextSize(node.rect, square); @@ -119,23 +103,21 @@ public BufferedImage toImage() { } private void write(BufferedImage img) { - if(child1 != null) { + if (child1 != null) { child1.write(img); child2.write(img); - } - else if(packed != null) { + } else if (packed != null) { ImageTransform t = packed.packT; - for(int u = 0; u < rect.w; u++) - for(int v = 0; v < rect.h; v++) { + for (int u = 0; u < rect.w; u++) + for (int v = 0; v < rect.h; v++) { int rgba = t.access(packed, u, v); - img.setRGB(u+rect.x, v+rect.y, rgba>>>8 | rgba<<24); + img.setRGB(u + rect.x, v + rect.y, rgba >>> 8 | rgba << 24); } } } } - private static class ImageTransform - { + private static class ImageTransform { int transform; public ImageTransform(int i) { @@ -147,44 +129,43 @@ public ImageTransform() { } public boolean transpose() { - return (transform&4) != 0; + return (transform & 4) != 0; } public boolean flipU() { - return (transform&1) != 0; + return (transform & 1) != 0; } public boolean flipV() { - return (transform&2) != 0; + return (transform & 2) != 0; } public int access(QBImage img, int u, int v) { - if(transpose()) { - int tmp = u; u = v; v = tmp; + if (transpose()) { + int tmp = u; + u = v; + v = tmp; } - if(flipU()) - u = img.width()-1-u; - if(flipV()) - v = img.height()-1-v; + if (flipU()) u = img.width() - 1 - u; + if (flipV()) v = img.height() - 1 - v; return img.data[u][v]; } public UV transform(UV uv) { - if(transpose()) { - double tmp = uv.u; uv.u = uv.v; uv.v = tmp; + if (transpose()) { + double tmp = uv.u; + uv.u = uv.v; + uv.v = tmp; } - if(flipU()) - uv.u = 1-uv.u; - if(flipV()) - uv.v = 1-uv.v; + if (flipU()) uv.u = 1 - uv.u; + if (flipV()) uv.v = 1 - uv.v; return uv; } } - public static class QBImage implements Comparable - { + public static class QBImage implements Comparable { int[][] data; ImageTransform packT; Rectangle4i packSlot; @@ -198,57 +179,54 @@ public int height() { } public int area() { - return width()*height(); + return width() * height(); } @Override public int compareTo(QBImage o) { - int a = area(); int b = o.area(); + int a = area(); + int b = o.area(); return a > b ? -1 : a == b ? 0 : 1; } public ImageTransform transformTo(QBImage img) { - if(width() == img.width() && height() == img.height()) - for(int i = 0; i < 4; i++) { + if (width() == img.width() && height() == img.height()) + for (int i = 0; i < 4; i++) { ImageTransform t = new ImageTransform(i); - if(equals(img, t)) - return t; + if (equals(img, t)) return t; } - if(width() == img.height() && height() == img.width()) - for(int i = 4; i < 8; i++) { + if (width() == img.height() && height() == img.width()) + for (int i = 4; i < 8; i++) { ImageTransform t = new ImageTransform(i); - if(equals(img, t)) - return t; + if (equals(img, t)) return t; } return null; } public boolean equals(QBImage img, ImageTransform t) { - for(int u = 0; u < img.width(); u++) - for(int v = 0; v < img.height(); v++) - if(t.access(this, u, v) != img.data[u][v]) - return false; + for (int u = 0; u < img.width(); u++) + for (int v = 0; v < img.height(); v++) if (t.access(this, u, v) != img.data[u][v]) return false; return true; } public void transform(UV uv) { packT.transform(uv); - uv.u*=packSlot.w; - uv.v*=packSlot.h; - uv.u+=packSlot.x; - uv.v+=packSlot.y; + uv.u *= packSlot.w; + uv.v *= packSlot.h; + uv.u += packSlot.x; + uv.v += packSlot.y; } } - private static final int[][] vertOrder = new int[][] {//clockwise because MC is left handed - {3, 0}, - {1, 0}, - {1, 2}, - {3, 2}}; + private static final int[][] vertOrder = new int[][] { // clockwise because MC is left handed + {3, 0}, + {1, 0}, + {1, 2}, + {3, 2} + }; - public static class QBQuad - { + public static class QBQuad { public Vertex5[] verts = new Vertex5[4]; public QBImage image = new QBImage(); public ImageTransform t = new ImageTransform(); @@ -259,24 +237,24 @@ public QBQuad(int side) { } public void applyImageT() { - for(Vertex5 vert : verts) { + for (Vertex5 vert : verts) { t.transform(vert.uv); image.transform(vert.uv); } } - public static QBQuad restore(Rectangle4i flat, int side, double d, QBImage img) { QBQuad quad = new QBQuad(side); quad.image = img; - Transformation t = new Scale(-1, 1, -1).with(Rotation.sideOrientation(side, 0)).with(new Translation(new Vector3().setSide(side, d))); + Transformation t = new Scale(-1, 1, -1) + .with(Rotation.sideOrientation(side, 0)) + .with(new Translation(new Vector3().setSide(side, d))); quad.verts[0] = new Vertex5(flat.x, 0, flat.y, 0, 0); - quad.verts[1] = new Vertex5(flat.x+flat.w, 0, flat.y, 1, 0); - quad.verts[2] = new Vertex5(flat.x+flat.w, 0, flat.y+flat.h, 1, 1); - quad.verts[3] = new Vertex5(flat.x, 0, flat.y+flat.h, 0, 1); - for(Vertex5 vert : quad.verts) - vert.apply(t); + quad.verts[1] = new Vertex5(flat.x + flat.w, 0, flat.y, 1, 0); + quad.verts[2] = new Vertex5(flat.x + flat.w, 0, flat.y + flat.h, 1, 1); + quad.verts[3] = new Vertex5(flat.x, 0, flat.y + flat.h, 0, 1); + for (Vertex5 vert : quad.verts) vert.apply(t); return quad; } @@ -285,12 +263,11 @@ public Rectangle4i flatten() { Transformation t = Rotation.sideOrientation(side, 0).inverse().with(new Scale(-1, 0, -1)); Vector3 vmin = verts[0].vec.copy().apply(t); Vector3 vmax = verts[2].vec.copy().apply(t); - return new Rectangle4i((int)vmin.x, (int)vmin.z, (int)(vmax.x-vmin.x), (int)(vmax.z-vmin.z)); + return new Rectangle4i((int) vmin.x, (int) vmin.z, (int) (vmax.x - vmin.x), (int) (vmax.z - vmin.z)); } } - public static class QBCuboid - { + public static class QBCuboid { public QBMatrix mat; public CuboidCoord c; public int sides; @@ -304,16 +281,16 @@ public QBCuboid(QBMatrix mat, CuboidCoord c) { public static boolean intersects(QBCuboid a, QBCuboid b) { CuboidCoord c = a.c; CuboidCoord d = b.c; - return c.min.x <= d.max.x && - d.min.x <= c.max.x && - c.min.y <= d.max.y && - d.min.y <= c.max.y && - c.min.z <= d.max.z && - d.min.z <= c.max.z; + return c.min.x <= d.max.x + && d.min.x <= c.max.x + && c.min.y <= d.max.y + && d.min.y <= c.max.y + && c.min.z <= d.max.z + && d.min.z <= c.max.z; } public static void clip(QBCuboid a, QBCuboid b) { - if(intersects(a, b)) { + if (intersects(a, b)) { a.clip(b); b.clip(a); } @@ -321,22 +298,21 @@ public static void clip(QBCuboid a, QBCuboid b) { public void clip(QBCuboid o) { CuboidCoord d = o.c; - for(int a = 0; a < 6; a+=2) - { - int a1 = (a+2)%6; - int a2 = (a+4)%6; - if(c.getSide(a1+1) <= d.getSide(a1+1) && - c.getSide(a1) >= d.getSide(a1) && - c.getSide(a2+1) <= d.getSide(a2+1) && - c.getSide(a2) >= d.getSide(a2)) { - - if(c.getSide(a) <= d.getSide(a+1) && c.getSide(a) >= d.getSide(a)) { + for (int a = 0; a < 6; a += 2) { + int a1 = (a + 2) % 6; + int a2 = (a + 4) % 6; + if (c.getSide(a1 + 1) <= d.getSide(a1 + 1) + && c.getSide(a1) >= d.getSide(a1) + && c.getSide(a2 + 1) <= d.getSide(a2 + 1) + && c.getSide(a2) >= d.getSide(a2)) { + + if (c.getSide(a) <= d.getSide(a + 1) && c.getSide(a) >= d.getSide(a)) { c.setSide(a, d.getSide(a + 1) + 1); - sides|=1<= d.getSide(a) && c.getSide(a+1) <= d.getSide(a+1)) { + if (c.getSide(a + 1) >= d.getSide(a) && c.getSide(a + 1) <= d.getSide(a + 1)) { c.setSide(a + 1, d.getSide(a) - 1); - sides|=2< quads) { Cuboid6 box = c.bounds(); - for(int s = 0; s < 6; s++) - if((sides & 1<>1] = box.getSide(side); + da[side >> 1] = box.getSide(side); QBQuad quad = new QBQuad(side); - for(int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { int rU = vertOrder[i][0]; int rV = vertOrder[i][1]; int sideU = Rotation.rotateSide(side, rU); int sideV = Rotation.rotateSide(side, rV); - da[sideU>>1] = box.getSide(sideU); - da[sideV>>1] = box.getSide(sideV); - quad.verts[i] = new Vertex5(Vector3.fromAxes(da), (3-rU)/2, rV/2); + da[sideU >> 1] = box.getSide(sideU); + da[sideV >> 1] = box.getSide(sideV); + quad.verts[i] = new Vertex5(Vector3.fromAxes(da), (3 - rU) / 2, rV / 2); } int sideU = Rotation.rotateSide(side, 1); @@ -370,47 +344,44 @@ private QBQuad extractQuad(int side, Cuboid6 box) { QBImage image = quad.image; int[] ia = new int[3]; - ia[side>>1] = c.getSide(side); ia[sideU>>1] = c.getSide(sideU^1); ia[sideV>>1] = c.getSide(sideV^1); + ia[side >> 1] = c.getSide(side); + ia[sideU >> 1] = c.getSide(sideU ^ 1); + ia[sideV >> 1] = c.getSide(sideV ^ 1); BlockCoord b = BlockCoord.fromAxes(ia); BlockCoord bU = BlockCoord.sideOffsets[sideU]; BlockCoord bV = BlockCoord.sideOffsets[sideV]; - for(int u = 0; u < image.width(); u++) - for(int v = 0; v < image.height(); v++) - image.data[u][v] = mat.matrix[b.x+bU.x*u+bV.x*v][b.y+bU.y*u+bV.y*v][b.z+bU.z*u+bV.z*v]; + for (int u = 0; u < image.width(); u++) + for (int v = 0; v < image.height(); v++) + image.data[u][v] = + mat.matrix[b.x + bU.x * u + bV.x * v][b.y + bU.y * u + bV.y * v][b.z + bU.z * u + bV.z * v]; return quad; } } - public static class QBMatrix - { + public static class QBMatrix { public String name; public BlockCoord pos; public BlockCoord size; public int[][][] matrix; public void readMatrix(DataInputStream din, boolean compressed) throws IOException { - if(compressed) { + if (compressed) { int z = 0; - while (z < size.z) - { + while (z < size.z) { int index = 0; - while (true) - { + while (true) { int data = din.readInt(); - if (data == NEXTSLICEFLAG) - break; + if (data == NEXTSLICEFLAG) break; if (data == CODEFLAG) { int count = readTni(din); data = din.readInt(); - for(int j = 0; j < count; j++, index++) - matrix[index % size.x][index / size.x][z] = data; - } - else { + for (int j = 0; j < count; j++, index++) matrix[index % size.x][index / size.x][z] = data; + } else { matrix[index % size.x][index / size.x][z] = data; index++; } @@ -418,28 +389,23 @@ public void readMatrix(DataInputStream din, boolean compressed) throws IOExcepti z++; } } else { - for(int z = 0; z < size.z; z++) - for(int y = 0; y < size.y; y++) - for(int x = 0; x < size.x; x++) - matrix[x][y][z] = din.readInt(); + for (int z = 0; z < size.z; z++) + for (int y = 0; y < size.y; y++) for (int x = 0; x < size.x; x++) matrix[x][y][z] = din.readInt(); } } public void convertBGRAtoRGBA() { - for(int z = 0; z < size.z; z++) - for(int y = 0; y < size.y; y++) - for(int x = 0; x < size.x; x++) { + for (int z = 0; z < size.z; z++) + for (int y = 0; y < size.y; y++) + for (int x = 0; x < size.x; x++) { int i = matrix[x][y][z]; - matrix[x][y][z] = Integer.reverseBytes(i>>>8)|i&0xFF; + matrix[x][y][z] = Integer.reverseBytes(i >>> 8) | i & 0xFF; } } private boolean voxelFull(boolean[][][] solid, CuboidCoord c) { - for(BlockCoord b : c) - if(matrix[b.x][b.y][b.z] == 0) - return false; - for(BlockCoord b : c) - solid[b.x][b.y][b.z] = false; + for (BlockCoord b : c) if (matrix[b.x][b.y][b.z] == 0) return false; + for (BlockCoord b : c) solid[b.x][b.y][b.z] = false; return true; } @@ -447,14 +413,13 @@ private QBCuboid expand(boolean[][][] solid, BlockCoord b) { CuboidCoord c = new CuboidCoord(b); solid[b.x][b.y][b.z] = false; - for(int s = 0; s < 6; s++) { + for (int s = 0; s < 6; s++) { CuboidCoord slice = c.copy(); - slice.expand(s^1, -(slice.size(s)-1)); + slice.expand(s ^ 1, -(slice.size(s) - 1)); slice.expand(s, 1); - while(slice.getSide(s) >= 0 && slice.getSide(s) < size.getSide(s)) { - if(!voxelFull(solid, slice)) - break; + while (slice.getSide(s) >= 0 && slice.getSide(s) < size.getSide(s)) { + if (!voxelFull(solid, slice)) break; slice.expand(s ^ 1, -1); slice.expand(s, 1); c.expand(s, 1); @@ -466,105 +431,93 @@ private QBCuboid expand(boolean[][][] solid, BlockCoord b) { public List rectangulate() { List list = new ArrayList(); boolean[][][] solid = new boolean[size.x][size.y][size.z]; - for(int z = 0; z < size.z; z++) - for(int y = 0; y < size.y; y++) - for(int x = 0; x < size.x; x++) - solid[x][y][z] = matrix[x][y][z] != 0; + for (int z = 0; z < size.z; z++) + for (int y = 0; y < size.y; y++) for (int x = 0; x < size.x; x++) solid[x][y][z] = matrix[x][y][z] != 0; - for(int x = 0; x < size.x; x++) - for(int z = 0; z < size.z; z++) - for(int y = 0; y < size.y; y++) - if(solid[x][y][z]) - list.add(expand(solid, new BlockCoord(x, y, z))); + for (int x = 0; x < size.x; x++) + for (int z = 0; z < size.z; z++) + for (int y = 0; y < size.y; y++) + if (solid[x][y][z]) list.add(expand(solid, new BlockCoord(x, y, z))); - for(int i = 0; i < list.size(); i++) - for(int j = i+1; j < list.size(); j++) - QBCuboid.clip(list.get(i), list.get(j)); + for (int i = 0; i < list.size(); i++) + for (int j = i + 1; j < list.size(); j++) QBCuboid.clip(list.get(i), list.get(j)); return list; } public List extractQuads(boolean texturePlanes) { List quads = new LinkedList(); - for(QBCuboid c : rectangulate()) - c.extractQuads(quads); + for (QBCuboid c : rectangulate()) c.extractQuads(quads); - if(texturePlanes) - optimisePlanes(quads); + if (texturePlanes) optimisePlanes(quads); return quads; } private void optimisePlanes(List quads) { Multimap map = HashMultimap.create(); - for(QBQuad quad : quads) - map.put(quad.side | ((int)quad.verts[0].vec.getSide(quad.side))<<3, quad); + for (QBQuad quad : quads) map.put(quad.side | ((int) quad.verts[0].vec.getSide(quad.side)) << 3, quad); quads.clear(); - for(Integer key : map.keySet()) { + for (Integer key : map.keySet()) { Collection plane = map.get(key); - if(plane.size() == 1) { + if (plane.size() == 1) { quads.add(plane.iterator().next()); continue; } - int side = key&7; + int side = key & 7; Rectangle4i rect = null; - for(QBQuad q : plane) - if(rect == null) - rect = q.flatten(); - else - rect.include(q.flatten()); + for (QBQuad q : plane) + if (rect == null) rect = q.flatten(); + else rect.include(q.flatten()); QBImage img = new QBImage(); img.data = new int[rect.w][rect.h]; - for(QBQuad q : plane) { + for (QBQuad q : plane) { QBImage from = q.image; Rectangle4i r = q.flatten(); - int du = r.x-rect.x; - int dv = r.y-rect.y; - for(int u = 0; u < from.width(); u++) - for(int v = 0; v < from.height(); v++) - img.data[du+u][dv+v] = from.data[u][v]; + int du = r.x - rect.x; + int dv = r.y - rect.y; + for (int u = 0; u < from.width(); u++) + for (int v = 0; v < from.height(); v++) img.data[du + u][dv + v] = from.data[u][v]; } - quads.add(QBQuad.restore(rect, side, key>>3, img)); + quads.add(QBQuad.restore(rect, side, key >> 3, img)); } } public CCModel buildModel(List quads, BufferedImage img, boolean scaleMC) { - CCModel m = CCModel.quadModel(quads.size()*4); + CCModel m = CCModel.quadModel(quads.size() * 4); int i = 0; - for(QBQuad quad : quads) { + for (QBQuad quad : quads) { quad.applyImageT(); m.verts[i++] = quad.verts[0]; m.verts[i++] = quad.verts[1]; m.verts[i++] = quad.verts[2]; m.verts[i++] = quad.verts[3]; } - m.apply(new UVScale(1D/img.getWidth(), 1D/img.getHeight())); + m.apply(new UVScale(1D / img.getWidth(), 1D / img.getHeight())); m.apply(new Translation(pos.x, pos.y, pos.z)); - if(scaleMC) - m.apply(new Scale(1/16D)); + if (scaleMC) m.apply(new Scale(1 / 16D)); m.computeNormals(); return m; } private static void addImages(List quads, List images) { - for(QBQuad q : quads) { + for (QBQuad q : quads) { QBImage img = q.image; boolean matched = false; - for(QBImage img2 : images) { + for (QBImage img2 : images) { ImageTransform t = img.transformTo(img2); - if(t != null) { + if (t != null) { q.t = t; q.image = img2; matched = true; break; } } - if(!matched) - images.add(img); + if (!matched) images.add(img); } } } @@ -573,8 +526,8 @@ private static void addImages(List quads, List images) { public static final int SQUARETEXTURE = 2; public static final int MERGETEXTURES = 4; public static final int SCALEMC = 8; - public static class QBModel - { + + public static class QBModel { public QBMatrix[] matrices; public boolean rightHanded; @@ -588,21 +541,21 @@ public RasterisedModel toRasterisedModel(int flags) { boolean mergeTextures = (flags & MERGETEXTURES) != 0; boolean scaleMC = (flags & SCALEMC) != 0; - for(QBMatrix mat : matrices) { + for (QBMatrix mat : matrices) { List quads = mat.extractQuads(texturePlanes); modelQuads.add(quads); QBMatrix.addImages(quads, qbImages); - if(!mergeTextures) { + if (!mergeTextures) { images.add(ImagePackNode.pack(qbImages, squareTextures).toImage()); qbImages.clear(); } } - if(mergeTextures) + if (mergeTextures) images.add(ImagePackNode.pack(qbImages, squareTextures).toImage()); RasterisedModel m = new RasterisedModel(images); - for(int i = 0; i < matrices.length; i++) { + for (int i = 0; i < matrices.length; i++) { QBMatrix mat = matrices[i]; BufferedImage img = images.get(mergeTextures ? 0 : i); m.add(mat.name, mat.buildModel(modelQuads.get(i), img, scaleMC)); @@ -611,8 +564,7 @@ public RasterisedModel toRasterisedModel(int flags) { } } - public static class RasterisedModel - { + public static class RasterisedModel { private class Holder { CCModel m; int img; @@ -633,7 +585,7 @@ public RasterisedModel(List images) { } public void add(String name, CCModel m) { - map.put(name, new Holder(m, Math.min(map.size(), images.size()-1))); + map.put(name, new Holder(m, Math.min(map.size(), images.size() - 1))); } public CCModel getModel(String key) { @@ -642,41 +594,37 @@ public CCModel getModel(String key) { public IIcon getIcon(String key, IIconRegister r, String iconName) { int img = map.get(key).img; - if(icons[img] != null && !iconName.equals(icons[img])) - throw new IllegalArgumentException("Attempted to get a previously registered icon by a different name: "+icons[img]+", "+iconName); - if(icons[img] != null) - return r.registerIcon(iconName); + if (icons[img] != null && !iconName.equals(icons[img])) + throw new IllegalArgumentException("Attempted to get a previously registered icon by a different name: " + + icons[img] + ", " + iconName); + if (icons[img] != null) return r.registerIcon(iconName); icons[img] = iconName; return TextureUtils.getTextureSpecial(r, iconName).addTexture(new TextureDataHolder(images.get(img))); } private void exportImg(BufferedImage img, File imgFile) throws IOException { - if(!imgFile.exists()) - imgFile.createNewFile(); + if (!imgFile.exists()) imgFile.createNewFile(); ImageIO.write(img, "PNG", imgFile); } public void export(File objFile, File imgDir) { try { - if(!objFile.exists()) - objFile.createNewFile(); - if(!imgDir.exists()) - imgDir.mkdirs(); + if (!objFile.exists()) objFile.createNewFile(); + if (!imgDir.exists()) imgDir.mkdirs(); Map modelMap = new HashMap(); - for(Map.Entry e : map.entrySet()) - modelMap.put(e.getKey(), e.getValue().m); + for (Map.Entry e : map.entrySet()) modelMap.put(e.getKey(), e.getValue().m); PrintWriter p = new PrintWriter(objFile); CCModel.exportObj(modelMap, p); p.close(); - if(images.size() < map.size()) + if (images.size() < map.size()) exportImg(images.get(0), new File(imgDir, objFile.getName().replaceAll("(.+)\\..+", "$1.png"))); else - for(Map.Entry e : map.entrySet()) - exportImg(images.get(e.getValue().img), new File(imgDir, e.getKey()+".png")); + for (Map.Entry e : map.entrySet()) + exportImg(images.get(e.getValue().img), new File(imgDir, e.getKey() + ".png")); } catch (IOException e) { throw new RuntimeException(e); @@ -685,7 +633,7 @@ public void export(File objFile, File imgDir) { } private static String readAsciiString(DataInputStream din) throws IOException { - byte[] bytes = new byte[din.readByte()&0xFF]; + byte[] bytes = new byte[din.readByte() & 0xFF]; din.readFully(bytes); return new String(bytes, "US-ASCII"); } @@ -696,6 +644,7 @@ private static int readTni(DataInputStream din) throws IOException { private static final int CODEFLAG = Integer.reverseBytes(2); private static final int NEXTSLICEFLAG = Integer.reverseBytes(6); + public static QBModel loadQB(InputStream input) throws IOException { DataInputStream din = new DataInputStream(input); @@ -706,11 +655,10 @@ public static QBModel loadQB(InputStream input) throws IOException { boolean compressed = din.readInt() != 0; boolean visEncoded = din.readInt() != 0; - if(visEncoded) - throw new IllegalArgumentException("Encoded Visiblity States not supported"); + if (visEncoded) throw new IllegalArgumentException("Encoded Visiblity States not supported"); m.matrices = new QBMatrix[readTni(din)]; - for(int i = 0; i < m.matrices.length; i++) { + for (int i = 0; i < m.matrices.length; i++) { QBMatrix mat = new QBMatrix(); m.matrices[i] = mat; mat.name = readAsciiString(din); @@ -718,8 +666,7 @@ public static QBModel loadQB(InputStream input) throws IOException { mat.pos = new BlockCoord(readTni(din), readTni(din), readTni(din)); mat.matrix = new int[mat.size.x][mat.size.y][mat.size.z]; mat.readMatrix(din, compressed); - if(colorFormat == 1) - mat.convertBGRAtoRGBA(); + if (colorFormat == 1) mat.convertBGRAtoRGBA(); } return m; @@ -727,9 +674,12 @@ public static QBModel loadQB(InputStream input) throws IOException { public static QBModel loadQB(ResourceLocation res) { try { - return loadQB(Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream()); - } catch(Exception e) { - throw new RuntimeException("failed to load model: "+res, e); + return loadQB(Minecraft.getMinecraft() + .getResourceManager() + .getResource(res) + .getInputStream()); + } catch (Exception e) { + throw new RuntimeException("failed to load model: " + res, e); } } @@ -741,8 +691,8 @@ public static QBModel loadQB(File file) { } finally { fin.close(); } - } catch(Exception e) { - throw new RuntimeException("failed to load model: "+file.getPath(), e); + } catch (Exception e) { + throw new RuntimeException("failed to load model: " + file.getPath(), e); } } } diff --git a/src/main/java/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java index d878113..b5327c3 100644 --- a/src/main/java/codechicken/lib/render/RenderUtils.java +++ b/src/main/java/codechicken/lib/render/RenderUtils.java @@ -1,5 +1,8 @@ package codechicken.lib.render; +import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; +import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; + import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Rectangle4i; import codechicken.lib.vec.Vector3; @@ -19,35 +22,32 @@ import net.minecraftforge.fluids.FluidStack; import org.lwjgl.opengl.GL11; -import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; -import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; - -public class RenderUtils -{ +public class RenderUtils { static Vector3[] vectors = new Vector3[8]; - static RenderItem uniformRenderItem = new RenderItem() - { - public boolean shouldBob() - { + static RenderItem uniformRenderItem = new RenderItem() { + public boolean shouldBob() { return false; } }; static EntityItem entityItem; - - static - { - for(int i = 0; i < vectors.length; i++) - vectors[i] = new Vector3(); - + + static { + for (int i = 0; i < vectors.length; i++) vectors[i] = new Vector3(); + uniformRenderItem.setRenderManager(RenderManager.instance); - + entityItem = new EntityItem(null); entityItem.hoverStart = 0; } - public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, double res) - { - renderFluidQuad(point2, vectors[0].set(point4).subtract(point1), vectors[1].set(point1).subtract(point2), icon, res); + public static void renderFluidQuad( + Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, double res) { + renderFluidQuad( + point2, + vectors[0].set(point4).subtract(point1), + vectors[1].set(point1).subtract(point2), + icon, + res); } /** @@ -57,60 +57,60 @@ public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point * @param high The left side of the quad * @param res Units per icon */ - public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) - { + public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) { Tessellator t = Tessellator.instance; double u1 = icon.getMinU(); - double du = icon.getMaxU()-icon.getMinU(); + double du = icon.getMaxU() - icon.getMinU(); double v2 = icon.getMaxV(); - double dv = icon.getMaxV()-icon.getMinV(); + double dv = icon.getMaxV() - icon.getMinV(); double wlen = wide.mag(); double hlen = high.mag(); - + double x = 0; - while(x < wlen) - { + while (x < wlen) { double rx = wlen - x; - if(rx > res) - rx = res; + if (rx > res) rx = res; double y = 0; - while(y < hlen) - { - double ry = hlen-y; - if(ry > res) - ry = res; - - Vector3 dx1 = vectors[2].set(wide).multiply(x/wlen); - Vector3 dx2 = vectors[3].set(wide).multiply((x+rx)/wlen); - Vector3 dy1 = vectors[4].set(high).multiply(y/hlen); - Vector3 dy2 = vectors[5].set(high).multiply((y+ry)/hlen); - - t.addVertexWithUV(base.x+dx1.x+dy2.x, base.y+dx1.y+dy2.y, base.z+dx1.z+dy2.z, u1, v2-ry/res*dv); - t.addVertexWithUV(base.x+dx1.x+dy1.x, base.y+dx1.y+dy1.y, base.z+dx1.z+dy1.z, u1, v2); - t.addVertexWithUV(base.x+dx2.x+dy1.x, base.y+dx2.y+dy1.y, base.z+dx2.z+dy1.z, u1+rx/res*du, v2); - t.addVertexWithUV(base.x+dx2.x+dy2.x, base.y+dx2.y+dy2.y, base.z+dx2.z+dy2.z, u1+rx/res*du, v2-ry/res*dv); - - y+=ry; + while (y < hlen) { + double ry = hlen - y; + if (ry > res) ry = res; + + Vector3 dx1 = vectors[2].set(wide).multiply(x / wlen); + Vector3 dx2 = vectors[3].set(wide).multiply((x + rx) / wlen); + Vector3 dy1 = vectors[4].set(high).multiply(y / hlen); + Vector3 dy2 = vectors[5].set(high).multiply((y + ry) / hlen); + + t.addVertexWithUV( + base.x + dx1.x + dy2.x, base.y + dx1.y + dy2.y, base.z + dx1.z + dy2.z, u1, v2 - ry / res * dv); + t.addVertexWithUV(base.x + dx1.x + dy1.x, base.y + dx1.y + dy1.y, base.z + dx1.z + dy1.z, u1, v2); + t.addVertexWithUV( + base.x + dx2.x + dy1.x, base.y + dx2.y + dy1.y, base.z + dx2.z + dy1.z, u1 + rx / res * du, v2); + t.addVertexWithUV( + base.x + dx2.x + dy2.x, + base.y + dx2.y + dy2.y, + base.z + dx2.z + dy2.z, + u1 + rx / res * du, + v2 - ry / res * dv); + + y += ry; } - - x+=rx; + + x += rx; } } - - public static void translateToWorldCoords(Entity entity, float frame) - { + + public static void translateToWorldCoords(Entity entity, float frame) { double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame; double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame; double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame; - + GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ); } - - public static void drawCuboidOutline(Cuboid6 c) - { + + public static void drawCuboidOutline(Cuboid6 c) { Tessellator var2 = Tessellator.instance; var2.startDrawing(3); var2.addVertex(c.min.x, c.min.y, c.min.z); @@ -137,130 +137,130 @@ public static void drawCuboidOutline(Cuboid6 c) var2.addVertex(c.min.x, c.max.y, c.max.z); var2.draw(); } - - public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) - { - renderFluidQuad(//bottom + + public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { + renderFluidQuad( // bottom new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), - new Vector3(bound.min.x, bound.min.y, bound.max.z), - tex, res); - renderFluidQuad(//top + new Vector3(bound.min.x, bound.min.y, bound.max.z), + tex, + res); + renderFluidQuad( // top new Vector3(bound.min.x, bound.max.y, bound.min.z), new Vector3(bound.min.x, bound.max.y, bound.max.z), new Vector3(bound.max.x, bound.max.y, bound.max.z), - new Vector3(bound.max.x, bound.max.y, bound.min.z), - tex, res); - renderFluidQuad(//-x + new Vector3(bound.max.x, bound.max.y, bound.min.z), + tex, + res); + renderFluidQuad( // -x new Vector3(bound.min.x, bound.max.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), - new Vector3(bound.min.x, bound.max.y, bound.max.z), - tex, res); - renderFluidQuad(//+x + new Vector3(bound.min.x, bound.max.y, bound.max.z), + tex, + res); + renderFluidQuad( // +x new Vector3(bound.max.x, bound.max.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), - new Vector3(bound.max.x, bound.max.y, bound.min.z), - tex, res); - renderFluidQuad(//-z + new Vector3(bound.max.x, bound.max.y, bound.min.z), + tex, + res); + renderFluidQuad( // -z new Vector3(bound.max.x, bound.max.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.min.z), - new Vector3(bound.min.x, bound.max.y, bound.min.z), - tex, res); - renderFluidQuad(//+z + new Vector3(bound.min.x, bound.max.y, bound.min.z), + tex, + res); + renderFluidQuad( // +z new Vector3(bound.min.x, bound.max.y, bound.max.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), - new Vector3(bound.max.x, bound.max.y, bound.max.z), - tex, res); + new Vector3(bound.max.x, bound.max.y, bound.max.z), + tex, + res); } - - public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1, double ty2) - { - double[] points = new double[]{x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009}; + + public static void renderBlockOverlaySide( + int x, int y, int z, int side, double tx1, double tx2, double ty1, double ty2) { + double[] points = new double[] {x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009}; Tessellator tessellator = Tessellator.instance; - switch(side) - { + switch (side) { case 0: tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty1); tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty1); tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2); tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2); - break; + break; case 1: tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1); tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1); tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty2); tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty2); - break; + break; case 2: tessellator.addVertexWithUV(points[0], points[3], points[4], tx2, ty1); tessellator.addVertexWithUV(points[1], points[3], points[4], tx1, ty1); tessellator.addVertexWithUV(points[1], points[2], points[4], tx1, ty2); tessellator.addVertexWithUV(points[0], points[2], points[4], tx2, ty2); - break; + break; case 3: tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty1); tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty1); tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2); tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2); - break; + break; case 4: tessellator.addVertexWithUV(points[0], points[3], points[5], tx2, ty1); tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1); tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty2); tessellator.addVertexWithUV(points[0], points[2], points[5], tx2, ty2); - break; + break; case 5: tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1); tessellator.addVertexWithUV(points[1], points[3], points[5], tx1, ty1); tessellator.addVertexWithUV(points[1], points[2], points[5], tx1, ty2); tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty2); - break; + break; } } - public static boolean shouldRenderFluid(FluidStack stack) - { + public static boolean shouldRenderFluid(FluidStack stack) { return stack.amount > 0 && stack.getFluid() != null; } - + /** * @param stack The fluid stack to render * @return The icon of the fluid */ - public static IIcon prepareFluidRender(FluidStack stack, int alpha) - { + public static IIcon prepareFluidRender(FluidStack stack, int alpha) { GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - + Fluid fluid = stack.getFluid(); - CCRenderState.setColour(fluid.getColor(stack)<<8|alpha); + CCRenderState.setColour(fluid.getColor(stack) << 8 | alpha); TextureUtils.bindAtlas(fluid.getSpriteNumber()); return TextureUtils.safeIcon(fluid.getIcon(stack)); } - + /** * Re-enables lighting and disables blending. */ - public static void postFluidRender() - { + public static void postFluidRender() { GL11.glEnable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_BLEND); } - - public static double fluidDensityToAlpha(double density) - { + + public static double fluidDensityToAlpha(double density) { return Math.pow(density, 0.4); } /** - * Renders a fluid within a bounding box. + * Renders a fluid within a bounding box. * If the fluid is a liquid it will render as a normal tank with height equal to density/bound.height. * If the fluid is a gas, it will render the full box with an alpha equal to density. * Warning, bound will be mutated if the fluid is a liquid @@ -269,50 +269,43 @@ public static double fluidDensityToAlpha(double density) * @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids this determines the height. * @param res The resolution to render at. */ - public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) - { - if(!shouldRenderFluid(stack)) - return; - + public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { + if (!shouldRenderFluid(stack)) return; + int alpha = 255; - if(stack.getFluid().isGaseous()) - alpha = (int) (fluidDensityToAlpha(density)*255); - else - bound.max.y = bound.min.y+(bound.max.y-bound.min.y)*density; - + if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255); + else bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * density; + IIcon tex = prepareFluidRender(stack, alpha); CCRenderState.startDrawing(); renderFluidCuboid(bound, tex, res); CCRenderState.draw(); postFluidRender(); } - - public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) - { - if(!shouldRenderFluid(stack)) - return; - + + public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) { + if (!shouldRenderFluid(stack)) return; + int alpha = 255; - if(stack.getFluid().isGaseous()) - alpha = (int) (fluidDensityToAlpha(density)*255); - else - { - int height = (int) (rect.h*density); - rect.y +=rect.h-height; + if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255); + else { + int height = (int) (rect.h * density); + rect.y += rect.h - height; rect.h = height; } - + IIcon tex = prepareFluidRender(stack, alpha); CCRenderState.startDrawing(); renderFluidQuad( - new Vector3(rect.x, rect.y+rect.h, 0), - new Vector3(rect.w,0, 0), - new Vector3(0, -rect.h, 0), tex, res); + new Vector3(rect.x, rect.y + rect.h, 0), + new Vector3(rect.w, 0, 0), + new Vector3(0, -rect.h, 0), + tex, + res); CCRenderState.draw(); postFluidRender(); } - /** * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately */ @@ -324,33 +317,29 @@ public static void renderItemUniform(ItemStack item) { * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately * @param spin The spin angle of the item around the y axis in degrees */ - public static void renderItemUniform(ItemStack item, double spin) - { + public static void renderItemUniform(ItemStack item, double spin) { IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, ENTITY); boolean is3D = customRenderer != null && customRenderer.shouldUseRenderHelper(ENTITY, item, BLOCK_3D); boolean larger = false; - if (item.getItem() instanceof ItemBlock && RenderBlocks.renderItemIn3d(Block.getBlockFromItem(item.getItem()).getRenderType())) - { + if (item.getItem() instanceof ItemBlock + && RenderBlocks.renderItemIn3d( + Block.getBlockFromItem(item.getItem()).getRenderType())) { int renderType = Block.getBlockFromItem(item.getItem()).getRenderType(); larger = !(renderType == 1 || renderType == 19 || renderType == 12 || renderType == 2); - } - else if(is3D) - { + } else if (is3D) { larger = true; } - + double d = 2; - double d1 = 1/d; - if(larger) - GL11.glScaled(d, d, d); + double d1 = 1 / d; + if (larger) GL11.glScaled(d, d, d); GL11.glColor4f(1, 1, 1, 1); - + entityItem.setEntityItemStack(item); - uniformRenderItem.doRender(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float)(spin*9/Math.PI)); - - if(larger) - GL11.glScaled(d1, d1, d1); + uniformRenderItem.doRender(entityItem, 0, larger ? 0.09 : 0.06, 0, 0, (float) (spin * 9 / Math.PI)); + + if (larger) GL11.glScaled(d1, d1, d1); } } diff --git a/src/main/java/codechicken/lib/render/ShaderProgram.java b/src/main/java/codechicken/lib/render/ShaderProgram.java index d813ffa..efd1783 100644 --- a/src/main/java/codechicken/lib/render/ShaderProgram.java +++ b/src/main/java/codechicken/lib/render/ShaderProgram.java @@ -1,137 +1,109 @@ package codechicken.lib.render; -import org.lwjgl.opengl.ARBShaderObjects; -import org.lwjgl.opengl.ARBVertexShader; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.vector.Matrix4f; +import static org.lwjgl.opengl.ARBShaderObjects.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import org.lwjgl.opengl.ARBShaderObjects; +import org.lwjgl.opengl.ARBVertexShader; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Matrix4f; -import static org.lwjgl.opengl.ARBShaderObjects.*; - -public class ShaderProgram -{ +public class ShaderProgram { int programID; - - public ShaderProgram() - { + + public ShaderProgram() { programID = glCreateProgramObjectARB(); - if(programID == 0) - throw new RuntimeException("Unable to allocate shader program object."); + if (programID == 0) throw new RuntimeException("Unable to allocate shader program object."); } - - public void attach(int shaderType, String resource) - { + + public void attach(int shaderType, String resource) { InputStream stream = ShaderProgram.class.getResourceAsStream(resource); - if(stream == null) - throw new RuntimeException("Unable to locate resource: "+resource); - + if (stream == null) throw new RuntimeException("Unable to locate resource: " + resource); + attach(shaderType, stream); } - - public void use() - { + + public void use() { glUseProgramObjectARB(programID); } - - public static void restore() - { + + public static void restore() { glUseProgramObjectARB(0); } - - public void link() - { + + public void link() { glLinkProgramARB(programID); - if(glGetObjectParameteriARB(programID, GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) - throw new RuntimeException("Error linking program: "+getInfoLog(programID)); - + if (glGetObjectParameteriARB(programID, GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) + throw new RuntimeException("Error linking program: " + getInfoLog(programID)); + glValidateProgramARB(programID); - if(glGetObjectParameteriARB(programID, GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) - throw new RuntimeException("Error validating program: "+getInfoLog(programID)); - + if (glGetObjectParameteriARB(programID, GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) + throw new RuntimeException("Error validating program: " + getInfoLog(programID)); + use(); onLink(); restore(); } - - public void attach(int shaderType, InputStream stream) - { - if(stream == null) - throw new RuntimeException("Invalid shader inputstream"); - + + public void attach(int shaderType, InputStream stream) { + if (stream == null) throw new RuntimeException("Invalid shader inputstream"); + int shaderID = 0; - try - { + try { shaderID = glCreateShaderObjectARB(shaderType); - if(shaderID == 0) - throw new RuntimeException("Unable to allocate shader object."); - - try - { + if (shaderID == 0) throw new RuntimeException("Unable to allocate shader object."); + + try { glShaderSourceARB(shaderID, asString(stream)); - } - catch(IOException e) - { + } catch (IOException e) { throw new RuntimeException("Error reading inputstream.", e); } - + glCompileShaderARB(shaderID); - if(glGetObjectParameteriARB(shaderID, GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) - throw new RuntimeException("Error compiling shader: "+getInfoLog(shaderID)); - + if (glGetObjectParameteriARB(shaderID, GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) + throw new RuntimeException("Error compiling shader: " + getInfoLog(shaderID)); + glAttachObjectARB(programID, shaderID); - } - catch(RuntimeException e) - { + } catch (RuntimeException e) { glDeleteObjectARB(shaderID); throw e; - } + } } - public static String asString(InputStream stream) throws IOException - { + public static String asString(InputStream stream) throws IOException { StringBuilder sb = new StringBuilder(); BufferedReader bin = new BufferedReader(new InputStreamReader(stream)); String line; - while((line = bin.readLine()) != null) - sb.append(line).append('\n'); + while ((line = bin.readLine()) != null) sb.append(line).append('\n'); stream.close(); return sb.toString(); } - - private static String getInfoLog(int shaderID) - { + + private static String getInfoLog(int shaderID) { return glGetInfoLogARB(shaderID, glGetObjectParameteriARB(shaderID, GL_OBJECT_INFO_LOG_LENGTH_ARB)); } - - public int getUniformLoc(String name) - { + + public int getUniformLoc(String name) { return ARBShaderObjects.glGetUniformLocationARB(programID, name); } - public int getAttribLoc(String name) - { + public int getAttribLoc(String name) { return ARBVertexShader.glGetAttribLocationARB(programID, name); } - public void uniformTexture(String name, int textureIndex) - { + public void uniformTexture(String name, int textureIndex) { ARBShaderObjects.glUniform1iARB(getUniformLoc(name), textureIndex); } - - public void onLink() - { - - } - - public void glVertexAttributeMat4(int loc, Matrix4f matrix) - { - ARBVertexShader.glVertexAttrib4fARB(loc , matrix.m00, matrix.m01, matrix.m02, matrix.m03); - ARBVertexShader.glVertexAttrib4fARB(loc+1, matrix.m10, matrix.m11, matrix.m12, matrix.m13); - ARBVertexShader.glVertexAttrib4fARB(loc+2, matrix.m20, matrix.m21, matrix.m22, matrix.m23); - ARBVertexShader.glVertexAttrib4fARB(loc+3, matrix.m30, matrix.m31, matrix.m32, matrix.m33); + + public void onLink() {} + + public void glVertexAttributeMat4(int loc, Matrix4f matrix) { + ARBVertexShader.glVertexAttrib4fARB(loc, matrix.m00, matrix.m01, matrix.m02, matrix.m03); + ARBVertexShader.glVertexAttrib4fARB(loc + 1, matrix.m10, matrix.m11, matrix.m12, matrix.m13); + ARBVertexShader.glVertexAttrib4fARB(loc + 2, matrix.m20, matrix.m21, matrix.m22, matrix.m23); + ARBVertexShader.glVertexAttrib4fARB(loc + 3, matrix.m30, matrix.m31, matrix.m32, matrix.m33); } } diff --git a/src/main/java/codechicken/lib/render/SpriteSheetManager.java b/src/main/java/codechicken/lib/render/SpriteSheetManager.java index 2b6a4af..e0ebcf9 100644 --- a/src/main/java/codechicken/lib/render/SpriteSheetManager.java +++ b/src/main/java/codechicken/lib/render/SpriteSheetManager.java @@ -3,19 +3,16 @@ import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.util.ArrayList; +import java.util.HashMap; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; -import java.util.ArrayList; -import java.util.HashMap; - -public class SpriteSheetManager -{ +public class SpriteSheetManager { @SideOnly(Side.CLIENT) - public static class SpriteSheet implements IIconSelfRegister - { + public static class SpriteSheet implements IIconSelfRegister { private int tilesX; private int tilesY; private ArrayList newSprites = new ArrayList(); @@ -24,119 +21,106 @@ public static class SpriteSheet implements IIconSelfRegister private TextureDataHolder texture; private int spriteWidth; private int spriteHeight; - + public int atlasIndex; - - private SpriteSheet(int tilesX, int tilesY, ResourceLocation textureFile) - { + + private SpriteSheet(int tilesX, int tilesY, ResourceLocation textureFile) { this.tilesX = tilesX; this.tilesY = tilesY; this.resource = textureFile; - sprites = new TextureSpecial[tilesX*tilesY]; + sprites = new TextureSpecial[tilesX * tilesY]; } - - public void requestIndicies(int... indicies) - { - for(int i : indicies) - setupSprite(i); + + public void requestIndicies(int... indicies) { + for (int i : indicies) setupSprite(i); } - - public void registerIcons(IIconRegister register) - { - TextureMap textureMap = (TextureMap)register; - - if(TextureUtils.refreshTexture(textureMap, resource.getResourcePath())) - { + + public void registerIcons(IIconRegister register) { + TextureMap textureMap = (TextureMap) register; + + if (TextureUtils.refreshTexture(textureMap, resource.getResourcePath())) { reloadTexture(); for (TextureSpecial sprite : sprites) - if (sprite != null) - textureMap.setTextureEntry(sprite.getIconName(), sprite); - } - else - { - for(int i : newSprites) - textureMap.setTextureEntry(sprites[i].getIconName(), sprites[i]); + if (sprite != null) textureMap.setTextureEntry(sprite.getIconName(), sprite); + } else { + for (int i : newSprites) textureMap.setTextureEntry(sprites[i].getIconName(), sprites[i]); } newSprites.clear(); } - - public TextureSpecial setupSprite(int i) - { - if(sprites[i] == null) - { - String name = resource+"_"+i; + + public TextureSpecial setupSprite(int i) { + if (sprites[i] == null) { + String name = resource + "_" + i; sprites[i] = new TextureSpecial(name).baseFromSheet(this, i); newSprites.add(i); } return sprites[i]; } - private void reloadTexture() - { + private void reloadTexture() { texture = TextureUtils.loadTexture(resource); - spriteWidth = texture.width/tilesX; - spriteHeight = texture.height/tilesY; + spriteWidth = texture.width / tilesX; + spriteHeight = texture.height / tilesY; } - public IIcon getSprite(int index) - { + public IIcon getSprite(int index) { IIcon i = sprites[index]; - if(i == null) - throw new IllegalArgumentException("Sprite at index: "+index+" from texture file "+resource+" was not preloaded."); + if (i == null) + throw new IllegalArgumentException( + "Sprite at index: " + index + " from texture file " + resource + " was not preloaded."); return i; } - public TextureDataHolder createSprite(int spriteIndex) - { - int sx = spriteIndex%tilesX; - int sy = spriteIndex/tilesX; + public TextureDataHolder createSprite(int spriteIndex) { + int sx = spriteIndex % tilesX; + int sy = spriteIndex / tilesX; TextureDataHolder sprite = new TextureDataHolder(spriteWidth, spriteHeight); - TextureUtils.copySubImg(texture.data, texture.width, sx*spriteWidth, sy*spriteHeight, - spriteWidth, spriteHeight, - sprite.data, spriteWidth, 0, 0); + TextureUtils.copySubImg( + texture.data, + texture.width, + sx * spriteWidth, + sy * spriteHeight, + spriteWidth, + spriteHeight, + sprite.data, + spriteWidth, + 0, + 0); return sprite; } - public int spriteWidth() - { + public int spriteWidth() { return spriteWidth; } - - public int spriteHeight() - { + + public int spriteHeight() { return spriteHeight; } - public TextureSpecial bindTextureFX(int i, TextureFX textureFX) - { + public TextureSpecial bindTextureFX(int i, TextureFX textureFX) { return setupSprite(i).addTextureFX(textureFX); } - public SpriteSheet selfRegister(int atlas) - { + public SpriteSheet selfRegister(int atlas) { TextureUtils.addIconRegistrar(this); return this; } - + @Override - public int atlasIndex() - { + public int atlasIndex() { return atlasIndex; } } - + private static HashMap spriteSheets = new HashMap(); - - public static SpriteSheet getSheet(ResourceLocation resource) - { + + public static SpriteSheet getSheet(ResourceLocation resource) { return getSheet(16, 16, resource); } - public static SpriteSheet getSheet(int tilesX, int tilesY, ResourceLocation resource) - { + public static SpriteSheet getSheet(int tilesX, int tilesY, ResourceLocation resource) { SpriteSheet sheet = spriteSheets.get(resource.toString()); - if(sheet == null) - spriteSheets.put(resource.toString(), sheet = new SpriteSheet(tilesX, tilesY, resource)); + if (sheet == null) spriteSheets.put(resource.toString(), sheet = new SpriteSheet(tilesX, tilesY, resource)); return sheet; - } + } } diff --git a/src/main/java/codechicken/lib/render/TextureDataHolder.java b/src/main/java/codechicken/lib/render/TextureDataHolder.java index e945c08..3632787 100644 --- a/src/main/java/codechicken/lib/render/TextureDataHolder.java +++ b/src/main/java/codechicken/lib/render/TextureDataHolder.java @@ -2,34 +2,29 @@ import java.awt.image.BufferedImage; -public class TextureDataHolder -{ +public class TextureDataHolder { public int width; public int height; public int[] data; - - public TextureDataHolder(int width, int height) - { + + public TextureDataHolder(int width, int height) { this.width = width; this.height = height; - data = new int[width*height]; + data = new int[width * height]; } - public TextureDataHolder(int[] data, int width) - { + public TextureDataHolder(int[] data, int width) { this.data = data; this.width = width; - height = data.length/width; + height = data.length / width; } - public TextureDataHolder(BufferedImage img) - { + public TextureDataHolder(BufferedImage img) { this(img.getWidth(), img.getHeight()); img.getRGB(0, 0, width, height, data, 0, width); } - public TextureDataHolder copyData() - { + public TextureDataHolder copyData() { int[] copy = new int[data.length]; System.arraycopy(data, 0, copy, 0, data.length); data = copy; diff --git a/src/main/java/codechicken/lib/render/TextureFX.java b/src/main/java/codechicken/lib/render/TextureFX.java index c46ebeb..364683f 100644 --- a/src/main/java/codechicken/lib/render/TextureFX.java +++ b/src/main/java/codechicken/lib/render/TextureFX.java @@ -6,8 +6,7 @@ import net.minecraft.client.Minecraft; @SideOnly(Side.CLIENT) -public class TextureFX -{ +public class TextureFX { public int[] imageData; public int tileSizeBase = 16; public int tileSizeSquare = 256; @@ -50,8 +49,7 @@ public void update() { onTick(); } - public void onTick() { - } + public void onTick() {} public boolean changed() { return true; diff --git a/src/main/java/codechicken/lib/render/TextureSpecial.java b/src/main/java/codechicken/lib/render/TextureSpecial.java index 6f71410..d69c398 100644 --- a/src/main/java/codechicken/lib/render/TextureSpecial.java +++ b/src/main/java/codechicken/lib/render/TextureSpecial.java @@ -1,10 +1,11 @@ package codechicken.lib.render; -import codechicken.lib.asm.ObfMapping; import codechicken.lib.render.SpriteSheetManager.SpriteSheet; import codechicken.lib.render.TextureUtils.IIconSelfRegister; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.awt.image.BufferedImage; +import java.util.ArrayList; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -15,16 +16,13 @@ import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; -import java.awt.image.BufferedImage; -import java.util.ArrayList; - @SideOnly(Side.CLIENT) public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegister { - //sprite sheet fields + // sprite sheet fields private int spriteIndex; private SpriteSheet spriteSheet; - //textureFX fields + // textureFX fields private TextureFX textureFX; private int mipmapLevels; private int rawWidth; @@ -41,8 +39,7 @@ protected TextureSpecial(String par1) { } public TextureSpecial addTexture(TextureDataHolder t) { - if (baseTextures == null) - baseTextures = new ArrayList(); + if (baseTextures == null) baseTextures = new ArrayList(); baseTextures.add(t); return this; } @@ -61,8 +58,7 @@ public TextureSpecial addTextureFX(TextureFX fx) { @Override public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) { super.initSprite(sheetWidth, sheetHeight, originX, originY, rotated); - if (textureFX != null) - textureFX.onTextureDimensionsUpdate(rawWidth, rawHeight); + if (textureFX != null) textureFX.onTextureDimensionsUpdate(rawWidth, rawHeight); } @Override @@ -79,25 +75,19 @@ public void updateAnimation() { } } - /** * Copy paste mojang code because it's private, and CCL can't have access transformers or reflection */ public int[][] prepareAnisotropicFiltering(int[][] mipmaps) { - if (Minecraft.getMinecraft().gameSettings.anisotropicFiltering <= 1) - { + if (Minecraft.getMinecraft().gameSettings.anisotropicFiltering <= 1) { return mipmaps; - } - else - { + } else { int[][] aint1 = new int[mipmaps.length][]; - for (int k = 0; k < mipmaps.length; ++k) - { + for (int k = 0; k < mipmaps.length; ++k) { int[] aint2 = mipmaps[k]; - if (aint2 != null) - { + if (aint2 != null) { int[] aint3 = new int[(rawWidth + 16 >> k) * (rawHeight + 16 >> k)]; System.arraycopy(aint2, 0, aint3, 0, aint2.length); aint1[k] = TextureUtil.prepareAnisotropicData(aint3, rawWidth >> k, rawHeight >> k, 8 >> k); @@ -109,7 +99,8 @@ public int[][] prepareAnisotropicFiltering(int[][] mipmaps) { } @Override - public void loadSprite(BufferedImage[] images, AnimationMetadataSection animationMeta, boolean anisotropicFiltering) { + public void loadSprite( + BufferedImage[] images, AnimationMetadataSection animationMeta, boolean anisotropicFiltering) { rawWidth = images[0].getWidth(); rawHeight = images[0].getHeight(); super.loadSprite(images, animationMeta, anisotropicFiltering); @@ -128,7 +119,7 @@ public boolean hasCustomLoader(IResourceManager manager, ResourceLocation locati public void addFrame(int[] data, int width, int height) { GameSettings settings = Minecraft.getMinecraft().gameSettings; - BufferedImage[] images = new BufferedImage[settings.mipmapLevels+1]; + BufferedImage[] images = new BufferedImage[settings.mipmapLevels + 1]; images[0] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); images[0].setRGB(0, 0, width, height, data, 0, width); @@ -138,19 +129,15 @@ public void addFrame(int[] data, int width, int height) { @Override public boolean load(IResourceManager manager, ResourceLocation location) { if (baseTextures != null) { - for (TextureDataHolder tex : baseTextures) - addFrame(tex.data, tex.width, tex.height); - } - else if (spriteSheet != null) { + for (TextureDataHolder tex : baseTextures) addFrame(tex.data, tex.width, tex.height); + } else if (spriteSheet != null) { TextureDataHolder tex = spriteSheet.createSprite(spriteIndex); addFrame(tex.data, tex.width, tex.height); - } - else if (blankSize > 0) { + } else if (blankSize > 0) { addFrame(new int[blankSize * blankSize], blankSize, blankSize); } - if (framesTextureData.isEmpty()) - throw new RuntimeException("No base frame for texture: " + getIconName()); + if (framesTextureData.isEmpty()) throw new RuntimeException("No base frame for texture: " + getIconName()); return false; } @@ -162,8 +149,7 @@ public boolean hasAnimationMetadata() { @Override public int getFrameCount() { - if (textureFX != null) - return 1; + if (textureFX != null) return 1; return super.getFrameCount(); } @@ -181,8 +167,7 @@ public TextureSpecial selfRegister() { @Override public void registerIcons(IIconRegister register) { - if (selfRegister) - ((TextureMap) register).setTextureEntry(getIconName(), this); + if (selfRegister) ((TextureMap) register).setTextureEntry(getIconName(), this); } @Override diff --git a/src/main/java/codechicken/lib/render/TextureUtils.java b/src/main/java/codechicken/lib/render/TextureUtils.java index 0ccaa70..6e90960 100644 --- a/src/main/java/codechicken/lib/render/TextureUtils.java +++ b/src/main/java/codechicken/lib/render/TextureUtils.java @@ -3,6 +3,11 @@ import codechicken.lib.colour.Colour; import codechicken.lib.colour.ColourARGB; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import javax.imageio.ImageIO; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureManager; @@ -14,16 +19,8 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; - -public class TextureUtils -{ - public static interface IIconSelfRegister - { +public class TextureUtils { + public static interface IIconSelfRegister { public void registerIcons(IIconRegister register); public int atlasIndex(); @@ -42,8 +39,7 @@ public static void addIconRegistrar(IIconSelfRegister registrar) { @SubscribeEvent public void textureLoad(TextureStitchEvent.Pre event) { for (IIconSelfRegister reg : iconRegistrars) - if (reg.atlasIndex() == event.map.getTextureType()) - reg.registerIcons(event.map); + if (reg.atlasIndex() == event.map.getTextureType()) reg.registerIcons(event.map); } /** @@ -56,13 +52,15 @@ public static int[] loadTextureData(ResourceLocation resource) { public static Colour[] loadTextureColours(ResourceLocation resource) { int[] idata = loadTextureData(resource); Colour[] data = new Colour[idata.length]; - for (int i = 0; i < data.length; i++) - data[i] = new ColourARGB(idata[i]); + for (int i = 0; i < data.length; i++) data[i] = new ColourARGB(idata[i]); return data; } public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException { - return Minecraft.getMinecraft().getResourceManager().getResource(textureFile).getInputStream(); + return Minecraft.getMinecraft() + .getResourceManager() + .getResource(textureFile) + .getInputStream(); } public static BufferedImage loadBufferedImage(ResourceLocation textureFile) { @@ -85,7 +83,17 @@ public static TextureManager engine() { return Minecraft.getMinecraft().renderEngine; } - public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) { + public static void copySubImg( + int[] fromTex, + int fromWidth, + int fromX, + int fromY, + int width, + int height, + int[] toTex, + int toWidth, + int toX, + int toY) { for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { int fp = (y + fromY) * fromWidth + x + fromX; @@ -112,8 +120,7 @@ public static IIcon getBlankIcon(int size, IIconRegister iconRegister) { public static TextureSpecial getTextureSpecial(IIconRegister iconRegister, String name) { TextureMap textureMap = (TextureMap) iconRegister; IIcon entry = textureMap.getTextureExtry(name); - if (entry != null) - throw new IllegalStateException("Texture: " + name + " is already registered"); + if (entry != null) throw new IllegalStateException("Texture: " + name + " is already registered"); TextureSpecial icon = new TextureSpecial(name); textureMap.setTextureEntry(name, icon); @@ -136,8 +143,7 @@ public static void prepareTexture(int target, int texture, int min_mag_filter, i public static TextureDataHolder loadTexture(ResourceLocation resource) { BufferedImage img = loadBufferedImage(resource); - if (img == null) - throw new RuntimeException("Texture not found: " + resource); + if (img == null) throw new RuntimeException("Texture not found: " + resource); return new TextureDataHolder(img); } @@ -160,8 +166,7 @@ public static IIcon safeIcon(IIcon icon) { } public static boolean isMissing(IIcon icon, ResourceLocation atlas) { - if(icon == null) - return true; + if (icon == null) return true; IIcon missing = ((TextureMap) engine().getTexture(atlas)).getAtlasSprite("missingno"); return icon.getMinU() == missing.getMinU() && icon.getMinV() == missing.getMinV(); diff --git a/src/main/java/codechicken/lib/render/Vertex5.java b/src/main/java/codechicken/lib/render/Vertex5.java index 7c66822..37e0827 100644 --- a/src/main/java/codechicken/lib/render/Vertex5.java +++ b/src/main/java/codechicken/lib/render/Vertex5.java @@ -5,13 +5,11 @@ import codechicken.lib.util.Copyable; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -public class Vertex5 implements Copyable -{ +public class Vertex5 implements Copyable { public Vector3 vec; public UV uv; @@ -64,8 +62,9 @@ public Vertex5 copy() { public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Vertex: (" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ") " + - "(" + new BigDecimal(uv.u, cont) + ", " + new BigDecimal(uv.v, cont) + ") ("+uv.tex+")"; + return "Vertex: (" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + + new BigDecimal(vec.z, cont) + ") " + "(" + new BigDecimal(uv.u, cont) + ", " + + new BigDecimal(uv.v, cont) + ") (" + uv.tex + ")"; } public Vertex5 apply(Transformation t) { diff --git a/src/main/java/codechicken/lib/render/uv/UV.java b/src/main/java/codechicken/lib/render/uv/UV.java index 708b243..1ca2956 100644 --- a/src/main/java/codechicken/lib/render/uv/UV.java +++ b/src/main/java/codechicken/lib/render/uv/UV.java @@ -1,7 +1,6 @@ package codechicken.lib.render.uv; import codechicken.lib.util.Copyable; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -11,8 +10,7 @@ public class UV implements Copyable { public double v; public int tex; - public UV() { - } + public UV() {} public UV(double u, double v) { this(u, v, 0); @@ -71,9 +69,8 @@ public UV apply(UVTransformation t) { @Override public boolean equals(Object o) { - if (!(o instanceof UV)) - return false; + if (!(o instanceof UV)) return false; UV uv = (UV) o; return u == uv.u && v == uv.v; } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/render/uv/UVRotation.java b/src/main/java/codechicken/lib/render/uv/UVRotation.java index e57ee3f..02cf97f 100644 --- a/src/main/java/codechicken/lib/render/uv/UVRotation.java +++ b/src/main/java/codechicken/lib/render/uv/UVRotation.java @@ -1,13 +1,11 @@ package codechicken.lib.render.uv; import codechicken.lib.math.MathHelper; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -public class UVRotation extends UVTransformation -{ +public class UVRotation extends UVTransformation { public double angle; /** @@ -21,8 +19,8 @@ public UVRotation(double angle) { public void apply(UV uv) { double c = MathHelper.cos(angle); double s = MathHelper.sin(angle); - double u2 = c*uv.u + s*uv.v; - uv.v = - s*uv.u + c*uv.v; + double u2 = c * uv.u + s * uv.v; + uv.v = -s * uv.u + c * uv.v; uv.u = u2; } @@ -33,8 +31,7 @@ public UVTransformation inverse() { @Override public UVTransformation merge(UVTransformation next) { - if(next instanceof UVRotation) - return new UVRotation(angle+((UVRotation)next).angle); + if (next instanceof UVRotation) return new UVRotation(angle + ((UVRotation) next).angle); return null; } @@ -45,8 +42,7 @@ public boolean isRedundant() { } @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); return "UVRotation(" + new BigDecimal(angle, cont) + ")"; } diff --git a/src/main/java/codechicken/lib/render/uv/UVTransformation.java b/src/main/java/codechicken/lib/render/uv/UVTransformation.java index 0d9afd2..066da2a 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTransformation.java +++ b/src/main/java/codechicken/lib/render/uv/UVTransformation.java @@ -6,12 +6,13 @@ /** * Abstract supertype for any UV transformation */ -public abstract class UVTransformation extends ITransformation implements CCRenderState.IVertexOperation -{ +public abstract class UVTransformation extends ITransformation + implements CCRenderState.IVertexOperation { public static final int operationIndex = CCRenderState.registerOperation(); public UVTransformation at(UV point) { - return new UVTransformationList(new UVTranslation(-point.u, -point.v), this, new UVTranslation(point.u, point.v)); + return new UVTransformationList( + new UVTranslation(-point.u, -point.v), this, new UVTranslation(point.u, point.v)); } public UVTransformationList with(UVTransformation t) { @@ -33,5 +34,3 @@ public int operationID() { return operationIndex; } } - - diff --git a/src/main/java/codechicken/lib/render/uv/UVTransformationList.java b/src/main/java/codechicken/lib/render/uv/UVTransformationList.java index ec69ae9..149a943 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTransformationList.java +++ b/src/main/java/codechicken/lib/render/uv/UVTransformationList.java @@ -3,52 +3,38 @@ import java.util.ArrayList; import java.util.Iterator; -public class UVTransformationList extends UVTransformation -{ +public class UVTransformationList extends UVTransformation { private ArrayList transformations = new ArrayList(); - public UVTransformationList(UVTransformation... transforms) - { - for(UVTransformation t : transforms) - if(t instanceof UVTransformationList) - transformations.addAll(((UVTransformationList)t).transformations); - else - transformations.add(t); + public UVTransformationList(UVTransformation... transforms) { + for (UVTransformation t : transforms) + if (t instanceof UVTransformationList) transformations.addAll(((UVTransformationList) t).transformations); + else transformations.add(t); compact(); } @Override - public void apply(UV uv) - { - for(int i = 0; i < transformations.size(); i++) - transformations.get(i).apply(uv); + public void apply(UV uv) { + for (int i = 0; i < transformations.size(); i++) transformations.get(i).apply(uv); } @Override - public UVTransformationList with(UVTransformation t) - { - if(t.isRedundant()) - return this; + public UVTransformationList with(UVTransformation t) { + if (t.isRedundant()) return this; - if(t instanceof UVTransformationList) - transformations.addAll(((UVTransformationList)t).transformations); - else - transformations.add(t); + if (t instanceof UVTransformationList) transformations.addAll(((UVTransformationList) t).transformations); + else transformations.add(t); compact(); return this; } - public UVTransformationList prepend(UVTransformation t) - { - if(t.isRedundant()) - return this; + public UVTransformationList prepend(UVTransformation t) { + if (t.isRedundant()) return this; - if(t instanceof UVTransformationList) - transformations.addAll(0, ((UVTransformationList)t).transformations); - else - transformations.add(0, t); + if (t instanceof UVTransformationList) transformations.addAll(0, ((UVTransformationList) t).transformations); + else transformations.add(0, t); compact(); return this; @@ -58,27 +44,21 @@ private void compact() { ArrayList newList = new ArrayList(transformations.size()); Iterator iterator = transformations.iterator(); UVTransformation prev = null; - while(iterator.hasNext()) { + while (iterator.hasNext()) { UVTransformation t = iterator.next(); - if(t.isRedundant()) - continue; + if (t.isRedundant()) continue; - if(prev != null) { + if (prev != null) { UVTransformation m = prev.merge(t); - if(m == null) - newList.add(prev); - else if(m.isRedundant()) - t = null; - else - t = m; + if (m == null) newList.add(prev); + else if (m.isRedundant()) t = null; + else t = m; } prev = t; } - if(prev != null) - newList.add(prev); + if (prev != null) newList.add(prev); - if(newList.size() < transformations.size()) - transformations = newList; + if (newList.size() < transformations.size()) transformations = newList; } @Override @@ -87,20 +67,17 @@ public boolean isRedundant() { } @Override - public UVTransformation inverse() - { + public UVTransformation inverse() { UVTransformationList rev = new UVTransformationList(); - for(int i = transformations.size()-1; i >= 0; i--) + for (int i = transformations.size() - 1; i >= 0; i--) rev.with(transformations.get(i).inverse()); return rev; } @Override - public String toString() - { + public String toString() { String s = ""; - for(UVTransformation t : transformations) - s+="\n"+t.toString(); + for (UVTransformation t : transformations) s += "\n" + t.toString(); return s.trim(); } } diff --git a/src/main/java/codechicken/lib/render/uv/UVTranslation.java b/src/main/java/codechicken/lib/render/uv/UVTranslation.java index cd87544..69851eb 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTranslation.java +++ b/src/main/java/codechicken/lib/render/uv/UVTranslation.java @@ -1,7 +1,6 @@ package codechicken.lib.render.uv; import codechicken.lib.math.MathHelper; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -34,8 +33,8 @@ public UVTransformation inverse() { @Override public UVTransformation merge(UVTransformation next) { if (next instanceof UVTranslation) { - UVTranslation t = (UVTranslation)next; - return new UVTranslation(du+t.du, dv+t.dv); + UVTranslation t = (UVTranslation) next; + return new UVTranslation(du + t.du, dv + t.dv); } return null; diff --git a/src/main/java/codechicken/lib/tool/LibDownloader.java b/src/main/java/codechicken/lib/tool/LibDownloader.java index dc77c10..b09ca04 100644 --- a/src/main/java/codechicken/lib/tool/LibDownloader.java +++ b/src/main/java/codechicken/lib/tool/LibDownloader.java @@ -11,64 +11,56 @@ import java.util.LinkedList; import java.util.List; -public class LibDownloader -{ +public class LibDownloader { private static String[] libs = new String[] { - "org/ow2/asm/asm-debug-all/5.0.3/asm-debug-all-5.0.3.jar", - "com/google/guava/guava/14.0/guava-14.0.jar", - "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", - "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", - "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar"}; + "org/ow2/asm/asm-debug-all/5.0.3/asm-debug-all-5.0.3.jar", + "com/google/guava/guava/14.0/guava-14.0.jar", + "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", + "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", + "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar" + }; private static File libDir = new File("lib"); private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); public static void load() { - if(!libDir.exists()) - libDir.mkdir(); - if(!libDir.isDirectory()) - throw new RuntimeException("/lib is not a directory"); + if (!libDir.exists()) libDir.mkdir(); + if (!libDir.isDirectory()) throw new RuntimeException("/lib is not a directory"); List missing = checkExists(); - for(String lib : missing) - download(lib); + for (String lib : missing) download(lib); addPaths(libs); } private static void addPaths(String[] libs) { try { URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); - Method m_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); + Method m_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] {URL.class}); m_addURL.setAccessible(true); - for(String lib : libs) + for (String lib : libs) m_addURL.invoke(cl, new File(libDir, fileName(lib)).toURI().toURL()); - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException("Failed to add libraries to classpath", e); } } private static void download(String lib) { File libFile = new File(libDir, fileName(lib)); - try - { - URL libDownload = new URL("http://repo1.maven.org/maven2/"+lib); + try { + URL libDownload = new URL("http://repo1.maven.org/maven2/" + lib); URLConnection connection = libDownload.openConnection(); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); connection.setRequestProperty("User-Agent", "CodeChickenLib Downloader"); int sizeGuess = connection.getContentLength(); download(connection.getInputStream(), sizeGuess, libFile); - } - catch (Exception e) - { + } catch (Exception e) { libFile.delete(); throw new RuntimeException("A download error occured", e); } } - private static void download(InputStream is, int sizeGuess, File target) throws Exception - { + private static void download(InputStream is, int sizeGuess, File target) throws Exception { String name = target.getName(); if (sizeGuess > downloadBuffer.capacity()) throw new Exception(String.format("The file %s is too large to be downloaded", name)); @@ -88,8 +80,7 @@ private static void download(InputStream is, int sizeGuess, File target) throws is.close(); downloadBuffer.limit(fullLength); - if(!target.exists()) - target.createNewFile(); + if (!target.exists()) target.createNewFile(); downloadBuffer.position(0); FileOutputStream fos = new FileOutputStream(target); @@ -103,12 +94,10 @@ private static String fileName(String lib) { private static List checkExists() { LinkedList list = new LinkedList(); - for(String lib : libs) { + for (String lib : libs) { File file = new File(libDir, fileName(lib)); - if(!file.exists()) - list.add(lib); + if (!file.exists()) list.add(lib); } return list; } - } diff --git a/src/main/java/codechicken/lib/tool/MCStripTransformer.java b/src/main/java/codechicken/lib/tool/MCStripTransformer.java index 11edf66..8114ae5 100644 --- a/src/main/java/codechicken/lib/tool/MCStripTransformer.java +++ b/src/main/java/codechicken/lib/tool/MCStripTransformer.java @@ -1,6 +1,7 @@ package codechicken.lib.tool; import codechicken.lib.asm.ASMHelper; +import java.util.Iterator; import org.objectweb.asm.ClassReader; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -9,16 +10,13 @@ import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; -import java.util.Iterator; - public class MCStripTransformer { public static class ReferenceDetector extends Remapper { boolean found = false; @Override public String map(String typeName) { - if(typeName.startsWith("net/minecraft") || !typeName.contains("/")) - found = true; + if (typeName.startsWith("net/minecraft") || !typeName.contains("/")) found = true; return typeName; } } @@ -28,17 +26,16 @@ public static byte[] transform(byte[] bytes) { boolean changed = false; Iterator it = cnode.methods.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { MethodNode mnode = it.next(); ReferenceDetector r = new ReferenceDetector(); mnode.accept(new RemappingMethodAdapter(mnode.access, mnode.desc, new MethodVisitor(Opcodes.ASM4) {}, r)); - if(r.found) { + if (r.found) { it.remove(); changed = true; } } - if(changed) - bytes = ASMHelper.createBytes(cnode, 0); + if (changed) bytes = ASMHelper.createBytes(cnode, 0); return bytes; } } diff --git a/src/main/java/codechicken/lib/tool/Main.java b/src/main/java/codechicken/lib/tool/Main.java index 083db03..29dbac3 100644 --- a/src/main/java/codechicken/lib/tool/Main.java +++ b/src/main/java/codechicken/lib/tool/Main.java @@ -1,12 +1,11 @@ package codechicken.lib.tool; -public class Main -{ +public class Main { public static void main(String[] args) { LibDownloader.load(); try { Class c_toolMain = new StripClassLoader().loadClass("codechicken.lib.tool.ToolMain"); - c_toolMain.getDeclaredMethod("main", String[].class).invoke(null, new Object[]{args}); + c_toolMain.getDeclaredMethod("main", String[].class).invoke(null, new Object[] {args}); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/codechicken/lib/tool/StripClassLoader.java b/src/main/java/codechicken/lib/tool/StripClassLoader.java index 51bf15a..f3de755 100644 --- a/src/main/java/codechicken/lib/tool/StripClassLoader.java +++ b/src/main/java/codechicken/lib/tool/StripClassLoader.java @@ -6,27 +6,24 @@ import java.net.URL; import java.net.URLClassLoader; -public class StripClassLoader extends URLClassLoader -{ +public class StripClassLoader extends URLClassLoader { public StripClassLoader() { super(new URL[0], StripClassLoader.class.getClassLoader()); } @Override public Class loadClass(String name) throws ClassNotFoundException { - if(!name.startsWith("codechicken.lib")) - return super.loadClass(name); + if (!name.startsWith("codechicken.lib")) return super.loadClass(name); try { - String resName = name.replace('.', '/')+".class"; + String resName = name.replace('.', '/') + ".class"; InputStream res = getResourceAsStream(resName); - if(res == null) - throw new ClassNotFoundException("Could not find resource: "+resName); + if (res == null) throw new ClassNotFoundException("Could not find resource: " + resName); byte[] bytes = readFully(res); bytes = transform(bytes); return defineClass(name, bytes, 0, bytes.length); - } catch(IOException e) { + } catch (IOException e) { throw new ClassNotFoundException(name, e); } } @@ -36,8 +33,7 @@ public static byte[] readFully(InputStream is) throws IOException { int read; byte[] data = new byte[16384]; - while ((read = is.read(data, 0, data.length)) > 0) - buffer.write(data, 0, read); + while ((read = is.read(data, 0, data.length)) > 0) buffer.write(data, 0, read); return buffer.toByteArray(); } diff --git a/src/main/java/codechicken/lib/tool/ToolMain.java b/src/main/java/codechicken/lib/tool/ToolMain.java index 24dee52..3d49f88 100644 --- a/src/main/java/codechicken/lib/tool/ToolMain.java +++ b/src/main/java/codechicken/lib/tool/ToolMain.java @@ -2,38 +2,36 @@ import codechicken.lib.tool.module.ModuleQBConverter; -public class ToolMain -{ +public class ToolMain { public static interface Module { public void main(String[] args); + public String name(); + public void printHelp(); } - public static Module[] modules = new Module[]{ - new ModuleQBConverter() - }; + public static Module[] modules = new Module[] {new ModuleQBConverter()}; private static void printHelp() { System.out.println("Usage: [module] [args]"); System.out.println(" Modules: "); - for(Module m : modules) - System.out.println(" - "+m.name()); + for (Module m : modules) System.out.println(" - " + m.name()); System.out.println("-h [module] for module help"); } public static void main(String[] args) { - if(args.length > 0) { - for(Module m : modules) - if(args[0].equals(m.name())) { - String[] args2 = new String[args.length-1]; + if (args.length > 0) { + for (Module m : modules) + if (args[0].equals(m.name())) { + String[] args2 = new String[args.length - 1]; System.arraycopy(args, 1, args2, 0, args2.length); m.main(args2); return; } - if(args[0].equals("-h") && args.length >= 2) { - for(Module m : modules) - if(args[1].equals(m.name())) { + if (args[0].equals("-h") && args.length >= 2) { + for (Module m : modules) + if (args[1].equals(m.name())) { m.printHelp(); return; } diff --git a/src/main/java/codechicken/lib/tool/module/JOptModule.java b/src/main/java/codechicken/lib/tool/module/JOptModule.java index f67e920..9e72b81 100644 --- a/src/main/java/codechicken/lib/tool/module/JOptModule.java +++ b/src/main/java/codechicken/lib/tool/module/JOptModule.java @@ -1,36 +1,28 @@ package codechicken.lib.tool.module; import codechicken.lib.tool.ToolMain; +import java.io.IOException; import joptsimple.OptionException; import joptsimple.OptionParser; import joptsimple.OptionSet; -import java.io.IOException; - -public abstract class JOptModule implements ToolMain.Module -{ +public abstract class JOptModule implements ToolMain.Module { OptionParser parser = new OptionParser(); @Override public void main(String[] args) { OptionSet options; - try - { + try { options = parser.parse(args); - } - catch(OptionException ex) - { + } catch (OptionException ex) { System.err.println(ex.getLocalizedMessage()); System.exit(-1); return; } - try - { + try { main(parser, options); - } - catch(Exception e) - { + } catch (Exception e) { throw new RuntimeException(e); } } diff --git a/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java index c4ae0c0..57bbfae 100644 --- a/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java +++ b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java @@ -1,22 +1,26 @@ package codechicken.lib.tool.module; +import static java.util.Arrays.asList; + import codechicken.lib.render.QBImporter; +import java.io.File; import joptsimple.OptionParser; import joptsimple.OptionSet; -import java.io.File; - -import static java.util.Arrays.asList; - -public class ModuleQBConverter extends JOptModule -{ +public class ModuleQBConverter extends JOptModule { public ModuleQBConverter() { parser.acceptsAll(asList("?", "h", "help"), "Show the help"); parser.acceptsAll(asList("i", "input"), "comma separated list of paths to models (.qb or directories)") - .withRequiredArg().ofType(File.class).withValuesSeparatedBy(',').required(); + .withRequiredArg() + .ofType(File.class) + .withValuesSeparatedBy(',') + .required(); parser.acceptsAll(asList("o", "out"), "Output Directory") - .withRequiredArg().ofType(File.class); - parser.acceptsAll(asList("o2", "textureplanes"), "2nd level optimisation. Merges coplanar polygons. Increases texture size"); + .withRequiredArg() + .ofType(File.class); + parser.acceptsAll( + asList("o2", "textureplanes"), + "2nd level optimisation. Merges coplanar polygons. Increases texture size"); parser.acceptsAll(asList("s", "squaretextures"), "Produce square textures"); parser.acceptsAll(asList("t", "mergetextures"), "Use the same texture for all models"); parser.acceptsAll(asList("r", "scalemc"), "Resize model to mc standard (shrink by factor of 16)"); @@ -24,41 +28,35 @@ public ModuleQBConverter() { protected void main(OptionParser parser, OptionSet options) { int flags = 0; - if(options.has("o2")) flags |= QBImporter.TEXTUREPLANES; - if(options.has("s")) flags |= QBImporter.SQUARETEXTURE; - if(options.has("t")) flags |= QBImporter.MERGETEXTURES; - if(options.has("r")) flags |= QBImporter.SCALEMC; + if (options.has("o2")) flags |= QBImporter.TEXTUREPLANES; + if (options.has("s")) flags |= QBImporter.SQUARETEXTURE; + if (options.has("t")) flags |= QBImporter.MERGETEXTURES; + if (options.has("r")) flags |= QBImporter.SCALEMC; File[] input = options.valuesOf("input").toArray(new File[0]); File[] outDir = new File[input.length]; - if(options.has("out")) { - File output = (File)options.valueOf("out"); - if(output.isFile()) - throw new RuntimeException("Output Path is not a directory"); - if(!output.exists()) - output.mkdirs(); + if (options.has("out")) { + File output = (File) options.valueOf("out"); + if (output.isFile()) throw new RuntimeException("Output Path is not a directory"); + if (!output.exists()) output.mkdirs(); - for(int i = 0; i < input.length; i++) - outDir[i] = output; + for (int i = 0; i < input.length; i++) outDir[i] = output; } else { - for(int i = 0; i < input.length; i++) + for (int i = 0; i < input.length; i++) outDir[i] = input[i].isDirectory() ? input[i] : input[i].getParentFile(); } - for(int i = 0; i < input.length; i++) { + for (int i = 0; i < input.length; i++) { File file = input[i]; - if(file.isDirectory()) { - for(File file2 : file.listFiles()) - if(file2.getName().endsWith(".qb")) - convert(file2, outDir[i], flags); - } - else - convert(file, outDir[i], flags); + if (file.isDirectory()) { + for (File file2 : file.listFiles()) + if (file2.getName().endsWith(".qb")) convert(file2, outDir[i], flags); + } else convert(file, outDir[i], flags); } } private void convert(File in, File outDir, int flags) { - System.out.println("Converting: "+in.getName()); + System.out.println("Converting: " + in.getName()); QBImporter.RasterisedModel m = QBImporter.loadQB(in).toRasterisedModel(flags); m.export(new File(outDir, in.getName().replace(".qb", ".obj")), outDir); } diff --git a/src/main/java/codechicken/lib/util/LangProxy.java b/src/main/java/codechicken/lib/util/LangProxy.java index 287b0a7..a29cf8c 100644 --- a/src/main/java/codechicken/lib/util/LangProxy.java +++ b/src/main/java/codechicken/lib/util/LangProxy.java @@ -2,19 +2,18 @@ import net.minecraft.util.StatCollector; -public class LangProxy -{ +public class LangProxy { public final String namespace; public LangProxy(String namespace) { - this.namespace = namespace+"."; + this.namespace = namespace + "."; } public String translate(String key) { - return StatCollector.translateToLocal(namespace+key); + return StatCollector.translateToLocal(namespace + key); } public String format(String key, Object... params) { - return StatCollector.translateToLocalFormatted(namespace+key, params); + return StatCollector.translateToLocalFormatted(namespace + key, params); } } diff --git a/src/main/java/codechicken/lib/vec/AxisCycle.java b/src/main/java/codechicken/lib/vec/AxisCycle.java index 5a0a526..2de5767 100644 --- a/src/main/java/codechicken/lib/vec/AxisCycle.java +++ b/src/main/java/codechicken/lib/vec/AxisCycle.java @@ -1,21 +1,39 @@ package codechicken.lib.vec; -public class AxisCycle -{ - public static Transformation[] cycles = new Transformation[]{ +public class AxisCycle { + public static Transformation[] cycles = new Transformation[] { new RedundantTransformation(), - new VariableTransformation(new Matrix4(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d0 = vec.x; double d1 = vec.y; double d2 = vec.z; - vec.x = d2; vec.y = d0; vec.z = d1; - } @Override public Transformation inverse(){ + new VariableTransformation(new Matrix4(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + double d2 = vec.z; + vec.x = d2; + vec.y = d0; + vec.z = d1; + } + + @Override + public Transformation inverse() { return cycles[2]; - }}, - new VariableTransformation(new Matrix4(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d0 = vec.x; double d1 = vec.y; double d2 = vec.z; - vec.x = d1; vec.y = d2; vec.z = d0; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + double d2 = vec.z; + vec.x = d1; + vec.y = d2; + vec.z = d0; + } + + @Override + public Transformation inverse() { return cycles[1]; - }}}; + } + } + }; } diff --git a/src/main/java/codechicken/lib/vec/BlockCoord.java b/src/main/java/codechicken/lib/vec/BlockCoord.java index 4299400..bc64997 100644 --- a/src/main/java/codechicken/lib/vec/BlockCoord.java +++ b/src/main/java/codechicken/lib/vec/BlockCoord.java @@ -4,157 +4,131 @@ import codechicken.lib.util.Copyable; import net.minecraft.tileentity.TileEntity; -public class BlockCoord implements Comparable, Copyable -{ +public class BlockCoord implements Comparable, Copyable { public int x; public int y; public int z; - public BlockCoord(int x, int y, int z) - { + public BlockCoord(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } - public BlockCoord(Vector3 v) - { + public BlockCoord(Vector3 v) { this(MathHelper.floor_double(v.x), MathHelper.floor_double(v.y), MathHelper.floor_double(v.z)); } - public BlockCoord(TileEntity tile) - { + public BlockCoord(TileEntity tile) { this(tile.xCoord, tile.yCoord, tile.zCoord); } - public BlockCoord(int[] ia) - { + public BlockCoord(int[] ia) { this(ia[0], ia[1], ia[2]); } - public BlockCoord() - { - } + public BlockCoord() {} - public static BlockCoord fromAxes(int[] ia) - { + public static BlockCoord fromAxes(int[] ia) { return new BlockCoord(ia[2], ia[0], ia[1]); } @Override - public boolean equals(Object obj) - { - if(!(obj instanceof BlockCoord)) - return false; - BlockCoord o2 = (BlockCoord)obj; + public boolean equals(Object obj) { + if (!(obj instanceof BlockCoord)) return false; + BlockCoord o2 = (BlockCoord) obj; return x == o2.x && y == o2.y && z == o2.z; } @Override - public int hashCode() - { - return (x^z)*31 + y; + public int hashCode() { + return (x ^ z) * 31 + y; } - public int compareTo(BlockCoord o) - { - if(x != o.x)return x < o.x ? 1 : -1; - if(y != o.y)return y < o.y ? 1 : -1; - if(z != o.z)return z < o.z ? 1 : -1; + public int compareTo(BlockCoord o) { + if (x != o.x) return x < o.x ? 1 : -1; + if (y != o.y) return y < o.y ? 1 : -1; + if (z != o.z) return z < o.z ? 1 : -1; return 0; } - public Vector3 toVector3Centered() - { - return new Vector3(x+0.5, y+0.5, z+0.5); + public Vector3 toVector3Centered() { + return new Vector3(x + 0.5, y + 0.5, z + 0.5); } - public BlockCoord multiply(int i) - { - x*=i; - y*=i; - z*=i; + public BlockCoord multiply(int i) { + x *= i; + y *= i; + z *= i; return this; } - public double mag() - { - return Math.sqrt(x*x+y*y+z*z); + public double mag() { + return Math.sqrt(x * x + y * y + z * z); } - public int mag2() - { - return x*x+y*y+z*z; + public int mag2() { + return x * x + y * y + z * z; } - public boolean isZero() - { + public boolean isZero() { return x == 0 && y == 0 && z == 0; } - public boolean isAxial() - { + public boolean isAxial() { return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); } - public BlockCoord add(BlockCoord coord2) - { - x+=coord2.x; - y+=coord2.y; - z+=coord2.z; + public BlockCoord add(BlockCoord coord2) { + x += coord2.x; + y += coord2.y; + z += coord2.z; return this; } - public BlockCoord add(int i, int j, int k) - { - x+=i; - y+=j; - z+=k; + public BlockCoord add(int i, int j, int k) { + x += i; + y += j; + z += k; return this; } - public BlockCoord sub(BlockCoord coord2) - { - x-=coord2.x; - y-=coord2.y; - z-=coord2.z; + public BlockCoord sub(BlockCoord coord2) { + x -= coord2.x; + y -= coord2.y; + z -= coord2.z; return this; } - public BlockCoord sub(int i, int j, int k) - { - x-=i; - y-=j; - z-=k; + public BlockCoord sub(int i, int j, int k) { + x -= i; + y -= j; + z -= k; return this; } - public BlockCoord offset(int side) - { + public BlockCoord offset(int side) { return offset(side, 1); } - public BlockCoord offset(int side, int amount) - { + public BlockCoord offset(int side, int amount) { BlockCoord offset = sideOffsets[side]; - x+=offset.x*amount; - y+=offset.y*amount; - z+=offset.z*amount; + x += offset.x * amount; + y += offset.y * amount; + z += offset.z * amount; return this; } - public BlockCoord inset(int side) - { + public BlockCoord inset(int side) { return inset(side, 1); } - public BlockCoord inset(int side, int amount) - { + public BlockCoord inset(int side, int amount) { return offset(side, -amount); } public int getSide(int side) { - switch(side) { + switch (side) { case 0: case 1: return y; @@ -168,54 +142,55 @@ public int getSide(int side) { throw new IndexOutOfBoundsException("Switch Falloff"); } - public BlockCoord setSide(int s, int v) - { - switch(s) - { + public BlockCoord setSide(int s, int v) { + switch (s) { case 0: - case 1: y = v; break; + case 1: + y = v; + break; case 2: - case 3: z = v; break; + case 3: + z = v; + break; case 4: - case 5: x = v; break; - default: throw new IndexOutOfBoundsException("Switch Falloff"); + case 5: + x = v; + break; + default: + throw new IndexOutOfBoundsException("Switch Falloff"); } return this; } - public static final BlockCoord[] sideOffsets = new BlockCoord[]{ - new BlockCoord( 0,-1, 0), - new BlockCoord( 0, 1, 0), - new BlockCoord( 0, 0,-1), - new BlockCoord( 0, 0, 1), + public static final BlockCoord[] sideOffsets = new BlockCoord[] { + new BlockCoord(0, -1, 0), + new BlockCoord(0, 1, 0), + new BlockCoord(0, 0, -1), + new BlockCoord(0, 0, 1), new BlockCoord(-1, 0, 0), - new BlockCoord( 1, 0, 0)}; + new BlockCoord(1, 0, 0) + }; - public int[] intArray() - { - return new int[]{x, y, z}; + public int[] intArray() { + return new int[] {x, y, z}; } - public BlockCoord copy() - { + public BlockCoord copy() { return new BlockCoord(x, y, z); } - public BlockCoord set(int i, int j, int k) - { + public BlockCoord set(int i, int j, int k) { x = i; y = j; z = k; return this; } - public BlockCoord set(BlockCoord coord) - { + public BlockCoord set(BlockCoord coord) { return set(coord.x, coord.y, coord.z); } - public BlockCoord set(int[] ia) - { + public BlockCoord set(int[] ia) { return set(ia[0], ia[1], ia[2]); } @@ -223,28 +198,23 @@ public BlockCoord set(TileEntity tile) { return set(tile.xCoord, tile.yCoord, tile.zCoord); } - public int toSide() - { - if(!isAxial()) return -1; - if(y < 0) return 0; - if(y > 0) return 1; - if(z < 0) return 2; - if(z > 0) return 3; - if(x < 0) return 4; - if(x > 0) return 5; + public int toSide() { + if (!isAxial()) return -1; + if (y < 0) return 0; + if (y > 0) return 1; + if (z < 0) return 2; + if (z > 0) return 3; + if (x < 0) return 4; + if (x > 0) return 5; return -1; } - public int absSum() - { - return (x < 0 ? -x : x) + - (y < 0 ? -y : y) + - (z < 0 ? -z : z); + public int absSum() { + return (x < 0 ? -x : x) + (y < 0 ? -y : y) + (z < 0 ? -z : z); } - public String toString() - { - return "("+x+", "+y+", "+z+")"; + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/Cuboid6.java b/src/main/java/codechicken/lib/vec/Cuboid6.java index 4b4fa14..66f0f28 100644 --- a/src/main/java/codechicken/lib/vec/Cuboid6.java +++ b/src/main/java/codechicken/lib/vec/Cuboid6.java @@ -1,51 +1,43 @@ package codechicken.lib.vec; import codechicken.lib.util.Copyable; -import net.minecraft.block.Block; -import net.minecraft.util.AxisAlignedBB; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import net.minecraft.block.Block; +import net.minecraft.util.AxisAlignedBB; -public class Cuboid6 implements Copyable -{ +public class Cuboid6 implements Copyable { public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); - + public Vector3 min; public Vector3 max; - - public Cuboid6(Vector3 min, Vector3 max) - { + + public Cuboid6(Vector3 min, Vector3 max) { this.min = min; this.max = max; } - public Cuboid6(AxisAlignedBB aabb) - { + public Cuboid6(AxisAlignedBB aabb) { min = new Vector3(aabb.minX, aabb.minY, aabb.minZ); - max = new Vector3(aabb.maxX, aabb.maxY, aabb.maxZ); + max = new Vector3(aabb.maxX, aabb.maxY, aabb.maxZ); } - - public Cuboid6(Cuboid6 cuboid) - { + + public Cuboid6(Cuboid6 cuboid) { min = cuboid.min.copy(); max = cuboid.max.copy(); } - public Cuboid6(double minx, double miny, double minz, double maxx, double maxy, double maxz) - { + public Cuboid6(double minx, double miny, double minz, double maxx, double maxy, double maxz) { min = new Vector3(minx, miny, minz); max = new Vector3(maxx, maxy, maxz); } - public AxisAlignedBB toAABB() - { + public AxisAlignedBB toAABB() { return AxisAlignedBB.getBoundingBox(min.x, min.y, min.z, max.x, max.y, max.z); } - - public Cuboid6 copy() - { + + public Cuboid6 copy() { return new Cuboid6(this); } @@ -65,127 +57,144 @@ public Cuboid6 set(double minx, double miny, double minz, double maxx, double ma return this; } - public Cuboid6 add(Vector3 vec) - { + public Cuboid6 add(Vector3 vec) { min.add(vec); max.add(vec); return this; } - - public Cuboid6 sub(Vector3 vec) - { + + public Cuboid6 sub(Vector3 vec) { min.subtract(vec); max.subtract(vec); return this; } - - public Cuboid6 expand(double d) - { + + public Cuboid6 expand(double d) { return expand(new Vector3(d, d, d)); } - - public Cuboid6 expand(Vector3 vec) - { + + public Cuboid6 expand(Vector3 vec) { min.sub(vec); max.add(vec); return this; } - public void setBlockBounds(Block block) - { - block.setBlockBounds((float)min.x, (float)min.y, (float)min.z, (float)max.x, (float)max.y, (float)max.z); + public void setBlockBounds(Block block) { + block.setBlockBounds((float) min.x, (float) min.y, (float) min.z, (float) max.x, (float) max.y, (float) max.z); } - public boolean intersects(Cuboid6 b) - { - return max.x-1E-5 > b.min.x && - b.max.x-1E-5 > min.x && - max.y-1E-5 > b.min.y && - b.max.y-1E-5 > min.y && - max.z-1E-5 > b.min.z && - b.max.z-1E-5 > min.z; + public boolean intersects(Cuboid6 b) { + return max.x - 1E-5 > b.min.x + && b.max.x - 1E-5 > min.x + && max.y - 1E-5 > b.min.y + && b.max.y - 1E-5 > min.y + && max.z - 1E-5 > b.min.z + && b.max.z - 1E-5 > min.z; } - - public Cuboid6 offset(Cuboid6 o) - { + + public Cuboid6 offset(Cuboid6 o) { min.add(o.min); max.add(o.max); return this; } - - public Vector3 center() - { + + public Vector3 center() { return min.copy().add(max).multiply(0.5); } - - public static boolean intersects(Cuboid6 a, Cuboid6 b) - { + + public static boolean intersects(Cuboid6 a, Cuboid6 b) { return a != null && b != null && a.intersects(b); } - - public String toString() - { + + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Cuboid: ("+new BigDecimal(min.x, cont)+", "+new BigDecimal(min.y, cont)+", "+new BigDecimal(min.z, cont)+") -> ("+ - new BigDecimal(max.x, cont)+", "+new BigDecimal(max.y, cont)+", "+new BigDecimal(max.z, cont)+")"; - } - - public Cuboid6 enclose(Vector3 vec) - { - if(min.x > vec.x) min.x = vec.x; - if(min.y > vec.y) min.y = vec.y; - if(min.z > vec.z) min.z = vec.z; - if(max.x < vec.x) max.x = vec.x; - if(max.y < vec.y) max.y = vec.y; - if(max.z < vec.z) max.z = vec.z; + return "Cuboid: (" + new BigDecimal(min.x, cont) + ", " + new BigDecimal(min.y, cont) + ", " + + new BigDecimal(min.z, cont) + ") -> (" + new BigDecimal(max.x, cont) + ", " + + new BigDecimal(max.y, cont) + ", " + new BigDecimal(max.z, cont) + ")"; + } + + public Cuboid6 enclose(Vector3 vec) { + if (min.x > vec.x) min.x = vec.x; + if (min.y > vec.y) min.y = vec.y; + if (min.z > vec.z) min.z = vec.z; + if (max.x < vec.x) max.x = vec.x; + if (max.y < vec.y) max.y = vec.y; + if (max.z < vec.z) max.z = vec.z; return this; } - - public Cuboid6 enclose(Cuboid6 c) - { - if(min.x > c.min.x) min.x = c.min.x; - if(min.y > c.min.y) min.y = c.min.y; - if(min.z > c.min.z) min.z = c.min.z; - if(max.x < c.max.x) max.x = c.max.x; - if(max.y < c.max.y) max.y = c.max.y; - if(max.z < c.max.z) max.z = c.max.z; + + public Cuboid6 enclose(Cuboid6 c) { + if (min.x > c.min.x) min.x = c.min.x; + if (min.y > c.min.y) min.y = c.min.y; + if (min.z > c.min.z) min.z = c.min.z; + if (max.x < c.max.x) max.x = c.max.x; + if (max.y < c.max.y) max.y = c.max.y; + if (max.z < c.max.z) max.z = c.max.z; return this; } - - public Cuboid6 apply(Transformation t) - { + + public Cuboid6 apply(Transformation t) { t.apply(min); t.apply(max); double temp; - if(min.x > max.x) {temp = min.x; min.x = max.x; max.x = temp;} - if(min.y > max.y) {temp = min.y; min.y = max.y; max.y = temp;} - if(min.z > max.z) {temp = min.z; min.z = max.z; max.z = temp;} + if (min.x > max.x) { + temp = min.x; + min.x = max.x; + max.x = temp; + } + if (min.y > max.y) { + temp = min.y; + min.y = max.y; + max.y = temp; + } + if (min.z > max.z) { + temp = min.z; + min.z = max.z; + max.z = temp; + } return this; } - - public double getSide(int s) - { - switch(s) { - case 0: return min.y; - case 1: return max.y; - case 2: return min.z; - case 3: return max.z; - case 4: return min.x; - case 5: return max.x; + + public double getSide(int s) { + switch (s) { + case 0: + return min.y; + case 1: + return max.y; + case 2: + return min.z; + case 3: + return max.z; + case 4: + return min.x; + case 5: + return max.x; } throw new IndexOutOfBoundsException("Switch Falloff"); } - - public Cuboid6 setSide(int s, double d) - { - switch(s) { - case 0: min.y = d; break; - case 1: max.y = d; break; - case 2: min.z = d; break; - case 3: max.z = d; break; - case 4: min.x = d; break; - case 5: max.x = d; break; - default: throw new IndexOutOfBoundsException("Switch Falloff"); + + public Cuboid6 setSide(int s, double d) { + switch (s) { + case 0: + min.y = d; + break; + case 1: + max.y = d; + break; + case 2: + min.z = d; + break; + case 3: + max.z = d; + break; + case 4: + min.x = d; + break; + case 5: + max.x = d; + break; + default: + throw new IndexOutOfBoundsException("Switch Falloff"); } return this; } diff --git a/src/main/java/codechicken/lib/vec/CuboidCoord.java b/src/main/java/codechicken/lib/vec/CuboidCoord.java index ef05e75..0348a29 100644 --- a/src/main/java/codechicken/lib/vec/CuboidCoord.java +++ b/src/main/java/codechicken/lib/vec/CuboidCoord.java @@ -1,12 +1,10 @@ package codechicken.lib.vec; import codechicken.lib.util.Copyable; -import net.minecraft.util.AxisAlignedBB; - import java.util.Iterator; +import net.minecraft.util.AxisAlignedBB; -public class CuboidCoord implements Iterable, Copyable -{ +public class CuboidCoord implements Iterable, Copyable { public BlockCoord min; public BlockCoord max; @@ -43,10 +41,9 @@ public CuboidCoord expand(int x, int y, int z) { } public CuboidCoord expand(int side, int amount) { - if (side % 2 == 0)//negative side - min = min.offset(side, amount); - else - max = max.offset(side, amount); + if (side % 2 == 0) // negative side + min = min.offset(side, amount); + else max = max.offset(side, amount); return this; } @@ -61,58 +58,78 @@ public CuboidCoord offset(int x, int y, int z) { max.add(x, y, z); return this; } - + public int size(int s) { - switch(s) { + switch (s) { case 0: case 1: - return max.y - min.y+1; + return max.y - min.y + 1; case 2: case 3: - return max.z - min.z+1; + return max.z - min.z + 1; case 4: case 5: - return max.x - min.x+1; + return max.x - min.x + 1; default: return 0; } } public int getSide(int s) { - switch(s) { - case 0: return min.y; - case 1: return max.y; - case 2: return min.z; - case 3: return max.z; - case 4: return min.x; - case 5: return max.x; + switch (s) { + case 0: + return min.y; + case 1: + return max.y; + case 2: + return min.z; + case 3: + return max.z; + case 4: + return min.x; + case 5: + return max.x; } throw new IndexOutOfBoundsException("Switch Falloff"); } public CuboidCoord setSide(int s, int v) { - switch(s) { - case 0: min.y = v; break; - case 1: max.y = v; break; - case 2: min.z = v; break; - case 3: max.z = v; break; - case 4: min.x = v; break; - case 5: max.x = v; break; - default: throw new IndexOutOfBoundsException("Switch Falloff"); + switch (s) { + case 0: + min.y = v; + break; + case 1: + max.y = v; + break; + case 2: + min.z = v; + break; + case 3: + max.z = v; + break; + case 4: + min.x = v; + break; + case 5: + max.x = v; + break; + default: + throw new IndexOutOfBoundsException("Switch Falloff"); } return this; } public int getVolume() { - return (max.x-min.x+1)*(max.y-min.y+1)*(max.z-min.z+1); + return (max.x - min.x + 1) * (max.y - min.y + 1) * (max.z - min.z + 1); } public Vector3 getCenterVec() { - return new Vector3(min.x+(max.x-min.x+1)/2D, min.y+(max.y-min.y+1)/2D, min.z+(max.z-min.z+1)/2D); + return new Vector3( + min.x + (max.x - min.x + 1) / 2D, min.y + (max.y - min.y + 1) / 2D, min.z + (max.z - min.z + 1) / 2D); } public BlockCoord getCenter(BlockCoord store) { - store.set(min.x+(max.x-min.x)/2, min.y+(max.y-min.y)/2, min.z+(max.z-min.z)/2); + store.set(min.x + (max.x - min.x) / 2, min.y + (max.y - min.y) / 2, min.z + (max.z - min.z) / 2); return store; } @@ -121,13 +138,11 @@ public boolean contains(BlockCoord coord) { } public boolean contains(int x, int y, int z) { - return x >= min.x && x <= max.x - && y >= min.y && y <= max.y - && z >= min.z && z <= max.z; + return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z; } public int[] intArray() { - return new int[]{min.x, min.y, min.z, max.x, max.y, max.z}; + return new int[] {min.x, min.y, min.z, max.x, max.y, max.z}; } public CuboidCoord copy() { @@ -171,12 +186,12 @@ public CuboidCoord include(BlockCoord coord) { } public CuboidCoord include(int x, int y, int z) { - if(x < min.x) min.x = x; - else if(x > max.x) max.x = x; - if(y < min.y) min.y = y; - else if(y > max.y) max.y = y; - if(z < min.z) min.z = z; - else if(z > max.z) max.z = z; + if (x < min.x) min.x = x; + else if (x > max.x) max.x = x; + if (y < min.y) min.y = y; + else if (y > max.y) max.y = y; + if (z < min.z) min.z = z; + else if (z > max.z) max.z = z; return this; } @@ -189,15 +204,12 @@ public boolean hasNext() { } public BlockCoord next() { - if(b == null) - b = min.copy(); + if (b == null) b = min.copy(); else { - if(b.z != max.z) - b.z++; + if (b.z != max.z) b.z++; else { b.z = min.z; - if(b.y != max.y) - b.y++; + if (b.y != max.y) b.y++; else { b.y = min.y; b.x++; diff --git a/src/main/java/codechicken/lib/vec/ITransformation.java b/src/main/java/codechicken/lib/vec/ITransformation.java index ab823f0..06f2819 100644 --- a/src/main/java/codechicken/lib/vec/ITransformation.java +++ b/src/main/java/codechicken/lib/vec/ITransformation.java @@ -5,8 +5,7 @@ * @param The vector type * @param The transformation type */ -public abstract class ITransformation -{ +public abstract class ITransformation { /** * Applies this transformation to vec */ diff --git a/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java b/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java index 015add0..7cb6361 100644 --- a/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java +++ b/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java @@ -1,18 +1,15 @@ package codechicken.lib.vec; @SuppressWarnings("serial") -public class IrreversibleTransformationException extends RuntimeException -{ +public class IrreversibleTransformationException extends RuntimeException { public ITransformation t; - - public IrreversibleTransformationException(ITransformation t) - { + + public IrreversibleTransformationException(ITransformation t) { this.t = t; } - + @Override - public String getMessage() - { - return "The following transformation is irreversible:\n"+t; + public String getMessage() { + return "The following transformation is irreversible:\n" + t; } } diff --git a/src/main/java/codechicken/lib/vec/Line3.java b/src/main/java/codechicken/lib/vec/Line3.java index 90b428c..850e016 100644 --- a/src/main/java/codechicken/lib/vec/Line3.java +++ b/src/main/java/codechicken/lib/vec/Line3.java @@ -1,27 +1,22 @@ package codechicken.lib.vec; - -public class Line3 -{ +public class Line3 { public static final double tol = 0.0001D; - + public Vector3 pt1; public Vector3 pt2; - - public Line3(Vector3 pt1, Vector3 pt2) - { + + public Line3(Vector3 pt1, Vector3 pt2) { this.pt1 = pt1; this.pt2 = pt2; } - public Line3() - { + public Line3() { this(new Vector3(), new Vector3()); } - public static boolean intersection2D(Line3 line1, Line3 line2, Vector3 store) - { - // calculate differences + public static boolean intersection2D(Line3 line1, Line3 line2, Vector3 store) { + // calculate differences double xD1 = line1.pt2.x - line1.pt1.x; double zD1 = line1.pt2.z - line1.pt1.z; double xD2 = line2.pt2.x - line2.pt1.x; @@ -29,18 +24,21 @@ public static boolean intersection2D(Line3 line1, Line3 line2, Vector3 store) double xD3 = line1.pt1.x - line2.pt1.x; double zD3 = line1.pt1.z - line2.pt1.z; - + double div = zD2 * xD1 - xD2 * zD1; - if(div == 0)//lines are parallel - return false; + if (div == 0) // lines are parallel + return false; double ua = (xD2 * zD3 - zD2 * xD3) / div; store.set(line1.pt1.x + ua * xD1, 0, line1.pt1.z + ua * zD1); - if(store.x >= Math.min(line1.pt1.x, line1.pt2.x)-tol && store.x >= Math.min(line2.pt1.x, line2.pt2.x)-tol - && store.z >= Math.min(line1.pt1.z, line1.pt2.z)-tol && store.z >= Math.min(line2.pt1.z, line2.pt2.z)-tol - && store.x <= Math.max(line1.pt1.x, line1.pt2.x)+tol && store.x <= Math.max(line2.pt1.x, line2.pt2.x)+tol - && store.z <= Math.max(line1.pt1.z, line1.pt2.z)+tol && store.z <= Math.max(line2.pt1.z, line2.pt2.z)+tol) - return true; + if (store.x >= Math.min(line1.pt1.x, line1.pt2.x) - tol + && store.x >= Math.min(line2.pt1.x, line2.pt2.x) - tol + && store.z >= Math.min(line1.pt1.z, line1.pt2.z) - tol + && store.z >= Math.min(line2.pt1.z, line2.pt2.z) - tol + && store.x <= Math.max(line1.pt1.x, line1.pt2.x) + tol + && store.x <= Math.max(line2.pt1.x, line2.pt2.x) + tol + && store.z <= Math.max(line1.pt1.z, line1.pt2.z) + tol + && store.z <= Math.max(line2.pt1.z, line2.pt2.z) + tol) return true; return false; } diff --git a/src/main/java/codechicken/lib/vec/Matrix4.java b/src/main/java/codechicken/lib/vec/Matrix4.java index 5d85a13..fab8e52 100644 --- a/src/main/java/codechicken/lib/vec/Matrix4.java +++ b/src/main/java/codechicken/lib/vec/Matrix4.java @@ -3,32 +3,42 @@ import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import org.lwjgl.opengl.GL11; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.DoubleBuffer; +import org.lwjgl.opengl.GL11; -public class Matrix4 extends Transformation implements Copyable -{ - private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16*8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); - - //m +public class Matrix4 extends Transformation implements Copyable { + private static DoubleBuffer glBuf = + ByteBuffer.allocateDirect(16 * 8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); + + // m public double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; - - public Matrix4() - { + + public Matrix4() { m00 = m11 = m22 = m33 = 1; } - - public Matrix4(double d00, double d01, double d02, double d03, - double d10, double d11, double d12, double d13, - double d20, double d21, double d22, double d23, - double d30, double d31, double d32, double d33) - { + + public Matrix4( + double d00, + double d01, + double d02, + double d03, + double d10, + double d11, + double d12, + double d13, + double d20, + double d21, + double d22, + double d23, + double d30, + double d31, + double d32, + double d33) { m00 = d00; m01 = d01; m02 = d02; @@ -46,32 +56,28 @@ public Matrix4(double d00, double d01, double d02, double d03, m32 = d32; m33 = d33; } - - public Matrix4(Matrix4 mat) - { + + public Matrix4(Matrix4 mat) { set(mat); } - - public Matrix4 setIdentity() - { + + public Matrix4 setIdentity() { m00 = m11 = m22 = m33 = 1; m01 = m02 = m03 = m10 = m12 = m13 = m20 = m21 = m23 = m30 = m31 = m32 = 0; - + return this; } - - public Matrix4 translate(Vector3 vec) - { + + public Matrix4 translate(Vector3 vec) { m03 += m00 * vec.x + m01 * vec.y + m02 * vec.z; m13 += m10 * vec.x + m11 * vec.y + m12 * vec.z; m23 += m20 * vec.x + m21 * vec.y + m22 * vec.z; m33 += m30 * vec.x + m31 * vec.y + m32 * vec.z; - + return this; } - - public Matrix4 scale(Vector3 vec) - { + + public Matrix4 scale(Vector3 vec) { m00 *= vec.x; m10 *= vec.x; m20 *= vec.x; @@ -84,33 +90,32 @@ public Matrix4 scale(Vector3 vec) m12 *= vec.z; m22 *= vec.z; m32 *= vec.z; - + return this; } - - public Matrix4 rotate(double angle, Vector3 axis) - { + + public Matrix4 rotate(double angle, Vector3 axis) { double c = Math.cos(angle); double s = Math.sin(angle); double mc = 1.0f - c; - double xy = axis.x*axis.y; - double yz = axis.y*axis.z; - double xz = axis.x*axis.z; - double xs = axis.x*s; - double ys = axis.y*s; - double zs = axis.z*s; - - double f00 = axis.x*axis.x*mc+c; - double f10 = xy*mc+zs; - double f20 = xz*mc-ys; - - double f01 = xy*mc-zs; - double f11 = axis.y*axis.y*mc+c; - double f21 = yz*mc+xs; - - double f02 = xz*mc+ys; - double f12 = yz*mc-xs; - double f22 = axis.z*axis.z*mc+c; + double xy = axis.x * axis.y; + double yz = axis.y * axis.z; + double xz = axis.x * axis.z; + double xs = axis.x * s; + double ys = axis.y * s; + double zs = axis.z * s; + + double f00 = axis.x * axis.x * mc + c; + double f10 = xy * mc + zs; + double f20 = xz * mc - ys; + + double f01 = xy * mc - zs; + double f11 = axis.y * axis.y * mc + c; + double f21 = yz * mc + xs; + + double f02 = xz * mc + ys; + double f12 = yz * mc - xs; + double f22 = axis.z * axis.z * mc + c; double t00 = m00 * f00 + m01 * f10 + m02 * f20; double t10 = m10 * f00 + m11 * f10 + m12 * f20; @@ -132,18 +137,16 @@ public Matrix4 rotate(double angle, Vector3 axis) m11 = t11; m21 = t21; m31 = t31; - + return this; } - - public Matrix4 rotate(Rotation rotation) - { + + public Matrix4 rotate(Rotation rotation) { rotation.apply(this); return this; } - - public Matrix4 leftMultiply(Matrix4 mat) - { + + public Matrix4 leftMultiply(Matrix4 mat) { double n00 = m00 * mat.m00 + m10 * mat.m01 + m20 * mat.m02 + m30 * mat.m03; double n01 = m01 * mat.m00 + m11 * mat.m01 + m21 * mat.m02 + m31 * mat.m03; double n02 = m02 * mat.m00 + m12 * mat.m01 + m22 * mat.m02 + m32 * mat.m03; @@ -177,12 +180,11 @@ public Matrix4 leftMultiply(Matrix4 mat) m31 = n31; m32 = n32; m33 = n33; - + return this; } - - public Matrix4 multiply(Matrix4 mat) - { + + public Matrix4 multiply(Matrix4 mat) { double n00 = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20 + m03 * mat.m30; double n01 = m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21 + m03 * mat.m31; double n02 = m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22 + m03 * mat.m32; @@ -216,12 +218,11 @@ public Matrix4 multiply(Matrix4 mat) m31 = n31; m32 = n32; m33 = n33; - + return this; } - - public Matrix4 transpose() - { + + public Matrix4 transpose() { double n00 = m00; double n10 = m01; double n20 = m02; @@ -255,17 +256,15 @@ public Matrix4 transpose() m31 = n31; m32 = n32; m33 = n33; - + return this; } - - public Matrix4 copy() - { + + public Matrix4 copy() { return new Matrix4(this); } - - public Matrix4 set(Matrix4 mat) - { + + public Matrix4 set(Matrix4 mat) { m00 = mat.m00; m01 = mat.m01; m02 = mat.m02; @@ -282,72 +281,80 @@ public Matrix4 set(Matrix4 mat) m31 = mat.m31; m32 = mat.m32; m33 = mat.m33; - + return this; } - + @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.multiply(this); } - - private void mult3x3(Vector3 vec) - { + + private void mult3x3(Vector3 vec) { double x = m00 * vec.x + m01 * vec.y + m02 * vec.z; double y = m10 * vec.x + m11 * vec.y + m12 * vec.z; double z = m20 * vec.x + m21 * vec.y + m22 * vec.z; - + vec.x = x; vec.y = y; vec.z = z; } - + @Override - public void apply(Vector3 vec) - { + public void apply(Vector3 vec) { mult3x3(vec); vec.add(m03, m13, m23); } - + @Override - public void applyN(Vector3 vec) - { + public void applyN(Vector3 vec) { mult3x3(vec); vec.normalize(); } - + @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "["+new BigDecimal(m00, cont)+","+new BigDecimal(m01, cont)+","+new BigDecimal(m02, cont)+","+new BigDecimal(m03, cont)+"]\n"+ - "["+new BigDecimal(m10, cont)+","+new BigDecimal(m11, cont)+","+new BigDecimal(m12, cont)+","+new BigDecimal(m13, cont)+"]\n"+ - "["+new BigDecimal(m20, cont)+","+new BigDecimal(m21, cont)+","+new BigDecimal(m22, cont)+","+new BigDecimal(m23, cont)+"]\n"+ - "["+new BigDecimal(m30, cont)+","+new BigDecimal(m31, cont)+","+new BigDecimal(m32, cont)+","+new BigDecimal(m33, cont)+"]"; + return "[" + new BigDecimal(m00, cont) + "," + new BigDecimal(m01, cont) + "," + new BigDecimal(m02, cont) + "," + + new BigDecimal(m03, cont) + "]\n" + "[" + + new BigDecimal(m10, cont) + "," + new BigDecimal(m11, cont) + "," + new BigDecimal(m12, cont) + "," + + new BigDecimal(m13, cont) + "]\n" + "[" + + new BigDecimal(m20, cont) + "," + new BigDecimal(m21, cont) + "," + new BigDecimal(m22, cont) + "," + + new BigDecimal(m23, cont) + "]\n" + "[" + + new BigDecimal(m30, cont) + "," + new BigDecimal(m31, cont) + "," + new BigDecimal(m32, cont) + "," + + new BigDecimal(m33, cont) + "]"; } - - public Matrix4 apply(Transformation t) - { + + public Matrix4 apply(Transformation t) { t.apply(this); return this; } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { - glBuf.put(m00).put(m10).put(m20).put(m30) - .put(m01).put(m11).put(m21).put(m31) - .put(m02).put(m12).put(m22).put(m32) - .put(m03).put(m13).put(m23).put(m33); + public void glApply() { + glBuf.put(m00) + .put(m10) + .put(m20) + .put(m30) + .put(m01) + .put(m11) + .put(m21) + .put(m31) + .put(m02) + .put(m12) + .put(m22) + .put(m32) + .put(m03) + .put(m13) + .put(m23) + .put(m33); glBuf.flip(); GL11.glMultMatrix(glBuf); } - + @Override - public Transformation inverse() - { - throw new IrreversibleTransformationException(this);//Don't waste your cpu with matrix inverses + public Transformation inverse() { + throw new IrreversibleTransformationException(this); // Don't waste your cpu with matrix inverses } } diff --git a/src/main/java/codechicken/lib/vec/Quat.java b/src/main/java/codechicken/lib/vec/Quat.java index b938c2e..0bcf88e 100644 --- a/src/main/java/codechicken/lib/vec/Quat.java +++ b/src/main/java/codechicken/lib/vec/Quat.java @@ -2,86 +2,74 @@ import codechicken.lib.math.MathHelper; import codechicken.lib.util.Copyable; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -public class Quat implements Copyable -{ +public class Quat implements Copyable { public double x; public double y; public double z; public double s; - public Quat() - { + public Quat() { s = 1; x = 0; y = 0; z = 0; } - public Quat(Quat quat) - { + public Quat(Quat quat) { x = quat.x; y = quat.y; z = quat.z; s = quat.s; } - public Quat(double d, double d1, double d2, double d3) - { + public Quat(double d, double d1, double d2, double d3) { x = d1; y = d2; z = d3; s = d; } - public Quat set(Quat quat) - { + public Quat set(Quat quat) { x = quat.x; y = quat.y; z = quat.z; s = quat.s; - + return this; } - public Quat set(double d, double d1, double d2, double d3) - { + public Quat set(double d, double d1, double d2, double d3) { x = d1; y = d2; z = d3; s = d; - + return this; } - - public static Quat aroundAxis(double ax, double ay, double az, double angle) - { + + public static Quat aroundAxis(double ax, double ay, double az, double angle) { return new Quat().setAroundAxis(ax, ay, az, angle); } - public static Quat aroundAxis(Vector3 axis, double angle) - { + public static Quat aroundAxis(Vector3 axis, double angle) { return aroundAxis(axis.x, axis.y, axis.z, angle); } - - public Quat setAroundAxis(double ax, double ay, double az, double angle) - { + + public Quat setAroundAxis(double ax, double ay, double az, double angle) { angle *= 0.5; double d4 = MathHelper.sin(angle); return set(MathHelper.cos(angle), ax * d4, ay * d4, az * d4); } - - public Quat setAroundAxis(Vector3 axis, double angle) - { + + public Quat setAroundAxis(Vector3 axis, double angle) { return setAroundAxis(axis.x, axis.y, axis.z, angle); } - public Quat multiply(Quat quat) - { + public Quat multiply(Quat quat) { double d = s * quat.s - x * quat.x - y * quat.y - z * quat.z; double d1 = s * quat.x + x * quat.s - y * quat.z + z * quat.y; double d2 = s * quat.y + x * quat.z + y * quat.s - z * quat.x; @@ -90,12 +78,11 @@ public Quat multiply(Quat quat) x = d1; y = d2; z = d3; - + return this; } - public Quat rightMultiply(Quat quat) - { + public Quat rightMultiply(Quat quat) { double d = s * quat.s - x * quat.x - y * quat.y - z * quat.z; double d1 = s * quat.x + x * quat.s + y * quat.z - z * quat.y; double d2 = s * quat.y - x * quat.z + y * quat.s + z * quat.x; @@ -104,37 +91,32 @@ public Quat rightMultiply(Quat quat) x = d1; y = d2; z = d3; - + return this; } - public double mag() - { + public double mag() { return Math.sqrt(x * x + y * y + z * z + s * s); } - public Quat normalize() - { + public Quat normalize() { double d = mag(); - if(d != 0) - { + if (d != 0) { d = 1 / d; x *= d; y *= d; z *= d; s *= d; } - + return this; } - public Quat copy() - { + public Quat copy() { return new Quat(this); } - public void rotate(Vector3 vec) - { + public void rotate(Vector3 vec) { double d = -x * vec.x - y * vec.y - z * vec.z; double d1 = s * vec.x + y * vec.z - z * vec.y; double d2 = s * vec.y - x * vec.z + z * vec.x; @@ -144,14 +126,13 @@ public void rotate(Vector3 vec) vec.z = d3 * s - d * z - d1 * y + d2 * x; } - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Quat("+new BigDecimal(s, cont)+", "+new BigDecimal(x, cont)+", "+new BigDecimal(y, cont)+", "+new BigDecimal(z, cont)+")"; + return "Quat(" + new BigDecimal(s, cont) + ", " + new BigDecimal(x, cont) + ", " + new BigDecimal(y, cont) + + ", " + new BigDecimal(z, cont) + ")"; } - public Rotation rotation() - { + public Rotation rotation() { return new Rotation(this); } } diff --git a/src/main/java/codechicken/lib/vec/Rectangle4i.java b/src/main/java/codechicken/lib/vec/Rectangle4i.java index 49058c7..9c9f942 100644 --- a/src/main/java/codechicken/lib/vec/Rectangle4i.java +++ b/src/main/java/codechicken/lib/vec/Rectangle4i.java @@ -1,18 +1,14 @@ package codechicken.lib.vec; -public class Rectangle4i -{ +public class Rectangle4i { public int x; public int y; public int w; public int h; - - public Rectangle4i() - { - } - - public Rectangle4i(int x, int y, int w, int h) - { + + public Rectangle4i() {} + + public Rectangle4i(int x, int y, int w, int h) { this.x = x; this.y = y; this.w = w; @@ -28,11 +24,11 @@ public int y1() { } public int x2() { - return x+w-1; + return x + w - 1; } public int y2() { - return y+h-1; + return y + h - 1; } public void set(int x, int y, int w, int h) { @@ -41,25 +37,23 @@ public void set(int x, int y, int w, int h) { this.w = w; this.h = h; } - - public Rectangle4i offset(int dx, int dy) - { - x+=dx; - y+=dy; + + public Rectangle4i offset(int dx, int dy) { + x += dx; + y += dy; return this; } @Deprecated - public Rectangle4i with(int px, int py) - { + public Rectangle4i with(int px, int py) { return include(px, py); } public Rectangle4i include(int px, int py) { - if(px < x) expand(px-x, 0); - if(px >= x+w) expand(px-x-w+1, 0); - if(py < y) expand(0, py-y); - if(py >= y+h) expand(0, py-y-h+1); + if (px < x) expand(px - x, 0); + if (px >= x + w) expand(px - x - w + 1, 0); + if (py < y) expand(0, py - y); + if (py >= y + h) expand(0, py - y - h + 1); return this; } @@ -69,32 +63,25 @@ public Rectangle4i include(Rectangle4i r) { } public Rectangle4i expand(int px, int py) { - if(px > 0) - w+=px; + if (px > 0) w += px; else { - x+=px; - w-=px; + x += px; + w -= px; } - if(py > 0) - h+=py; + if (py > 0) h += py; else { - y+=py; - h-=py; + y += py; + h -= py; } return this; } - - public boolean contains(int px, int py) - { - return x <= px && px < x+w && y <= py && py < y+h; + + public boolean contains(int px, int py) { + return x <= px && px < x + w && y <= py && py < y + h; } - - public boolean intersects(Rectangle4i r) - { - return r.x+r.w > x && - r.x < x+w && - r.y+r.h > y && - r.y < y+h; + + public boolean intersects(Rectangle4i r) { + return r.x + r.w > x && r.x < x + w && r.y + r.h > y && r.y < y + h; } public int area() { diff --git a/src/main/java/codechicken/lib/vec/RedundantTransformation.java b/src/main/java/codechicken/lib/vec/RedundantTransformation.java index be2e87e..664467c 100644 --- a/src/main/java/codechicken/lib/vec/RedundantTransformation.java +++ b/src/main/java/codechicken/lib/vec/RedundantTransformation.java @@ -3,46 +3,42 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public class RedundantTransformation extends Transformation -{ +public class RedundantTransformation extends Transformation { @Override - public void apply(Vector3 vec){} + public void apply(Vector3 vec) {} @Override - public void apply(Matrix4 mat){} - + public void apply(Matrix4 mat) {} + @Override - public void applyN(Vector3 normal){} - + public void applyN(Vector3 normal) {} + @Override - public Transformation at(Vector3 point) - { + public Transformation at(Vector3 point) { return this; } - + @Override @SideOnly(Side.CLIENT) - public void glApply(){} - + public void glApply() {} + @Override - public Transformation inverse() - { + public Transformation inverse() { return this; } - + @Override public Transformation merge(Transformation next) { return next; } - + @Override public boolean isRedundant() { return true; } - + @Override - public String toString() - { + public String toString() { return "Nothing()"; } } diff --git a/src/main/java/codechicken/lib/vec/Rotation.java b/src/main/java/codechicken/lib/vec/Rotation.java index 0dd0b9f..5890fa5 100644 --- a/src/main/java/codechicken/lib/vec/Rotation.java +++ b/src/main/java/codechicken/lib/vec/Rotation.java @@ -3,123 +3,171 @@ import codechicken.lib.math.MathHelper; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import org.lwjgl.opengl.GL11; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import org.lwjgl.opengl.GL11; -public class Rotation extends Transformation -{ +public class Rotation extends Transformation { /** * Clockwise pi/2 about y looking down */ - public static Transformation[] quarterRotations = new Transformation[]{ + public static Transformation[] quarterRotations = new Transformation[] { new RedundantTransformation(), - new VariableTransformation(new Matrix4(0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d1 = vec.x; double d2 = vec.z; - vec.x = -d2; vec.z = d1; - } @Override public Transformation inverse(){ + new VariableTransformation(new Matrix4(0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d1 = vec.x; + double d2 = vec.z; + vec.x = -d2; + vec.z = d1; + } + + @Override + public Transformation inverse() { return quarterRotations[3]; - }}, - new VariableTransformation(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - vec.x = -vec.x; vec.z = -vec.z; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + vec.x = -vec.x; + vec.z = -vec.z; + } + + @Override + public Transformation inverse() { return this; - }}, - new VariableTransformation(new Matrix4(0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d1 = vec.x; double d2 = vec.z; - vec.x = d2; vec.z = -d1; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d1 = vec.x; + double d2 = vec.z; + vec.x = d2; + vec.z = -d1; + } + + @Override + public Transformation inverse() { return quarterRotations[1]; - }} - }; - - public static Transformation[] sideRotations = new Transformation[]{ + } + } + }; + + public static Transformation[] sideRotations = new Transformation[] { new RedundantTransformation(), - new VariableTransformation(new Matrix4(1, 0, 0, 0, 0,-1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - vec.y = -vec.y; vec.z = -vec.z; - } @Override public Transformation inverse(){ + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + vec.y = -vec.y; + vec.z = -vec.z; + } + + @Override + public Transformation inverse() { return this; - }}, - new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d1 = vec.y; double d2 = vec.z; - vec.y = -d2; vec.z = d1; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d1 = vec.y; + double d2 = vec.z; + vec.y = -d2; + vec.z = d1; + } + + @Override + public Transformation inverse() { return sideRotations[3]; - }}, - new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d1 = vec.y; double d2 = vec.z; - vec.y = d2; vec.z = -d1; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d1 = vec.y; + double d2 = vec.z; + vec.y = d2; + vec.z = -d1; + } + + @Override + public Transformation inverse() { return sideRotations[2]; - }}, - new VariableTransformation(new Matrix4(0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d0 = vec.x; double d1 = vec.y; - vec.x = d1; vec.y = -d0; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + vec.x = d1; + vec.y = -d0; + } + + @Override + public Transformation inverse() { return sideRotations[5]; - }}, - new VariableTransformation(new Matrix4(0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)){ - @Override public void apply(Vector3 vec){ - double d0 = vec.x; double d1 = vec.y; - vec.x = -d1; vec.y = d0; - } @Override public Transformation inverse(){ + } + }, + new VariableTransformation(new Matrix4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) { + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + vec.x = -d1; + vec.y = d0; + } + + @Override + public Transformation inverse() { return sideRotations[4]; - }} - }; - - public static Vector3[] axes = new Vector3[]{ - new Vector3( 0,-1, 0), - new Vector3( 0, 1, 0), - new Vector3( 0, 0,-1), - new Vector3( 0, 0, 1), + } + } + }; + + public static Vector3[] axes = new Vector3[] { + new Vector3(0, -1, 0), + new Vector3(0, 1, 0), + new Vector3(0, 0, -1), + new Vector3(0, 0, 1), new Vector3(-1, 0, 0), - new Vector3( 1, 0, 0)}; - - public static int[] sideRotMap = new int[]{ - 3,4,2,5, - 3,5,2,4, - 1,5,0,4, - 1,4,0,5, - 1,2,0,3, - 1,3,0,2}; - - public static int[] rotSideMap = new int[]{ - -1,-1, 2, 0, 1, 3, - -1,-1, 2, 0, 3, 1, - 2, 0,-1,-1, 3, 1, - 2, 0,-1,-1, 1, 3, - 2, 0, 1, 3,-1,-1, - 2, 0, 3, 1,-1,-1}; - + new Vector3(1, 0, 0) + }; + + public static int[] sideRotMap = new int[] { + 3, 4, 2, 5, + 3, 5, 2, 4, + 1, 5, 0, 4, + 1, 4, 0, 5, + 1, 2, 0, 3, + 1, 3, 0, 2 + }; + + public static int[] rotSideMap = new int[] { + -1, -1, 2, 0, 1, 3, -1, -1, 2, 0, 3, 1, 2, 0, -1, -1, 3, 1, 2, 0, -1, -1, 1, 3, 2, 0, 1, 3, -1, -1, 2, 0, 3, 1, + -1, -1 + }; + /** * Rotate pi/2 * this offset for [side] about y axis before rotating to the side for the rotation indicies to line up */ - public static int[] sideRotOffsets = new int[]{0, 2, 2, 0, 1, 3}; + public static int[] sideRotOffsets = new int[] {0, 2, 2, 0, 1, 3}; - public static int rotateSide(int s, int r) - { - return sideRotMap[s<<2|r]; + public static int rotateSide(int s, int r) { + return sideRotMap[s << 2 | r]; } - + /** * Reverse of rotateSide */ - public static int rotationTo(int s1, int s2) - { - if((s1&6) == (s2&6)) - throw new IllegalArgumentException("Faces "+s1+" and "+s2+" are opposites"); - return rotSideMap[s1*6+s2]; + public static int rotationTo(int s1, int s2) { + if ((s1 & 6) == (s2 & 6)) throw new IllegalArgumentException("Faces " + s1 + " and " + s2 + " are opposites"); + return rotSideMap[s1 * 6 + s2]; } /** @@ -127,147 +175,126 @@ public static int rotationTo(int s1, int s2) * @param side The side of the block being placed on * @return The rotation for the face == side^1 */ - public static int getSidedRotation(EntityPlayer player, int side) - { + public static int getSidedRotation(EntityPlayer player, int side) { Vector3 look = new Vector3(player.getLook(1)); double max = 0; int maxr = 0; - for(int r = 0; r < 4; r++) - { - Vector3 axis = Rotation.axes[rotateSide(side^1, r)]; + for (int r = 0; r < 4; r++) { + Vector3 axis = Rotation.axes[rotateSide(side ^ 1, r)]; double d = look.scalarProject(axis); - if(d > max) - { + if (d > max) { max = d; maxr = r; } } return maxr; } - + /** * @return The rotation quat for side 0 and rotation 0 to side s with rotation r */ - public static Transformation sideOrientation(int s, int r) - { - return quarterRotations[(r+sideRotOffsets[s])%4].with(sideRotations[s]); + public static Transformation sideOrientation(int s, int r) { + return quarterRotations[(r + sideRotOffsets[s]) % 4].with(sideRotations[s]); } /** * @param entity The placing entity, used for obtaining the look vector * @return The side towards which the entity is most directly looking. */ - public static int getSideFromLookAngle(EntityLivingBase entity) - { + public static int getSideFromLookAngle(EntityLivingBase entity) { Vector3 look = new Vector3(entity.getLook(1)); double max = 0; int maxs = 0; - for(int s = 0; s < 6; s++) { + for (int s = 0; s < 6; s++) { double d = look.scalarProject(axes[s]); - if(d > max) { + if (d > max) { max = d; maxs = s; } } return maxs; } - + public double angle; public Vector3 axis; - + private Quat quat; - - public Rotation(double angle, Vector3 axis) - { + + public Rotation(double angle, Vector3 axis) { this.angle = angle; this.axis = axis; } - - public Rotation(double angle, double x, double y, double z) - { + + public Rotation(double angle, double x, double y, double z) { this(angle, new Vector3(x, y, z)); } - - public Rotation(Quat quat) - { + + public Rotation(Quat quat) { this.quat = quat; - - angle = Math.acos(quat.s)*2; - if(angle == 0) - { + + angle = Math.acos(quat.s) * 2; + if (angle == 0) { axis = new Vector3(0, 1, 0); - } - else - { - double sa = Math.sin(angle*0.5); - axis = new Vector3(quat.x/sa, quat.y/sa, quat.z/sa); + } else { + double sa = Math.sin(angle * 0.5); + axis = new Vector3(quat.x / sa, quat.y / sa, quat.z / sa); } } @Override - public void apply(Vector3 vec) - { - if(quat == null) - quat = Quat.aroundAxis(axis, angle); - + public void apply(Vector3 vec) { + if (quat == null) quat = Quat.aroundAxis(axis, angle); + vec.rotate(quat); } - + @Override - public void applyN(Vector3 normal) - { + public void applyN(Vector3 normal) { apply(normal); } @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.rotate(angle, axis); } - - public Quat toQuat() - { - if(quat == null) - quat = Quat.aroundAxis(axis, angle); + + public Quat toQuat() { + if (quat == null) quat = Quat.aroundAxis(axis, angle); return quat; } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { - GL11.glRotatef((float)(angle*MathHelper.todeg), (float)axis.x, (float)axis.y, (float)axis.z); + public void glApply() { + GL11.glRotatef((float) (angle * MathHelper.todeg), (float) axis.x, (float) axis.y, (float) axis.z); } - + @Override - public Transformation inverse() - { + public Transformation inverse() { return new Rotation(-angle, axis); } @Override public Transformation merge(Transformation next) { - if(next instanceof Rotation) { - Rotation r = (Rotation)next; - if(r.axis.equalsT(axis)) - return new Rotation(angle+r.angle, axis); - + if (next instanceof Rotation) { + Rotation r = (Rotation) next; + if (r.axis.equalsT(axis)) return new Rotation(angle + r.angle, axis); + return new Rotation(toQuat().copy().multiply(r.toQuat())); } - + return null; } - + @Override public boolean isRedundant() { return MathHelper.between(-1E-5, angle, 1E-5); } - + @Override - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Rotation("+new BigDecimal(angle, cont)+", "+new BigDecimal(axis.x, cont)+", "+ - new BigDecimal(axis.y, cont)+", "+new BigDecimal(axis.z, cont)+")"; + return "Rotation(" + new BigDecimal(angle, cont) + ", " + new BigDecimal(axis.x, cont) + ", " + + new BigDecimal(axis.y, cont) + ", " + new BigDecimal(axis.z, cont) + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/Scale.java b/src/main/java/codechicken/lib/vec/Scale.java index 922755c..8428d57 100644 --- a/src/main/java/codechicken/lib/vec/Scale.java +++ b/src/main/java/codechicken/lib/vec/Scale.java @@ -2,11 +2,10 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import org.lwjgl.opengl.GL11; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import org.lwjgl.opengl.GL11; public class Scale extends Transformation { public Vector3 factor; @@ -29,8 +28,7 @@ public void apply(Vector3 vec) { } @Override - public void applyN(Vector3 normal) { - } + public void applyN(Vector3 normal) {} @Override public void apply(Matrix4 mat) { @@ -50,8 +48,7 @@ public Transformation inverse() { @Override public Transformation merge(Transformation next) { - if (next instanceof Scale) - return new Scale(factor.copy().multiply(((Scale) next).factor)); + if (next instanceof Scale) return new Scale(factor.copy().multiply(((Scale) next).factor)); return null; } @@ -64,6 +61,7 @@ public boolean isRedundant() { @Override public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Scale(" + new BigDecimal(factor.x, cont) + ", " + new BigDecimal(factor.y, cont) + ", " + new BigDecimal(factor.z, cont) + ")"; + return "Scale(" + new BigDecimal(factor.x, cont) + ", " + new BigDecimal(factor.y, cont) + ", " + + new BigDecimal(factor.z, cont) + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/SwapYZ.java b/src/main/java/codechicken/lib/vec/SwapYZ.java index d4524d4..0f965e6 100644 --- a/src/main/java/codechicken/lib/vec/SwapYZ.java +++ b/src/main/java/codechicken/lib/vec/SwapYZ.java @@ -1,27 +1,19 @@ package codechicken.lib.vec; -public class SwapYZ extends VariableTransformation -{ - public SwapYZ() - { - super(new Matrix4( - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, 1, 0, 0, - 0, 0, 0, 1)); +public class SwapYZ extends VariableTransformation { + public SwapYZ() { + super(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1)); } - + @Override - public void apply(Vector3 vec) - { + public void apply(Vector3 vec) { double vz = vec.z; vec.z = vec.y; vec.y = vz; } - + @Override - public Transformation inverse() - { + public Transformation inverse() { return this; } } diff --git a/src/main/java/codechicken/lib/vec/Transformation.java b/src/main/java/codechicken/lib/vec/Transformation.java index 8b323df..9302109 100644 --- a/src/main/java/codechicken/lib/vec/Transformation.java +++ b/src/main/java/codechicken/lib/vec/Transformation.java @@ -7,8 +7,8 @@ /** * Abstract supertype for any 3D vector transformation */ -public abstract class Transformation extends ITransformation implements CCRenderState.IVertexOperation -{ +public abstract class Transformation extends ITransformation + implements CCRenderState.IVertexOperation { public static final int operationIndex = CCRenderState.registerOperation(); /** @@ -43,8 +43,7 @@ public boolean load() { @Override public void operate() { apply(CCRenderState.vert.vec); - if(CCRenderState.normalAttrib.active) - applyN(CCRenderState.normal); + if (CCRenderState.normalAttrib.active) applyN(CCRenderState.normal); } @Override diff --git a/src/main/java/codechicken/lib/vec/TransformationList.java b/src/main/java/codechicken/lib/vec/TransformationList.java index b9cee64..12f4f5c 100644 --- a/src/main/java/codechicken/lib/vec/TransformationList.java +++ b/src/main/java/codechicken/lib/vec/TransformationList.java @@ -2,138 +2,110 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; - import java.util.ArrayList; import java.util.Iterator; -public class TransformationList extends Transformation -{ +public class TransformationList extends Transformation { private ArrayList transformations = new ArrayList(); private Matrix4 mat; - - public TransformationList(Transformation... transforms) - { - for(Transformation t : transforms) - if(t instanceof TransformationList) - transformations.addAll(((TransformationList)t).transformations); - else - transformations.add(t); - + + public TransformationList(Transformation... transforms) { + for (Transformation t : transforms) + if (t instanceof TransformationList) transformations.addAll(((TransformationList) t).transformations); + else transformations.add(t); + compact(); } - - public Matrix4 compile() - { - if(mat == null) - { + + public Matrix4 compile() { + if (mat == null) { mat = new Matrix4(); - for(int i = transformations.size()-1; i >= 0; i--) + for (int i = transformations.size() - 1; i >= 0; i--) transformations.get(i).apply(mat); } return mat; } - + /** * Returns a global space matrix as opposed to an object space matrix (reverse application order) * @return */ - public Matrix4 reverseCompile() - { + public Matrix4 reverseCompile() { Matrix4 mat = new Matrix4(); - for(Transformation t : transformations) - t.apply(mat); + for (Transformation t : transformations) t.apply(mat); return mat; } - + @Override - public void apply(Vector3 vec) - { - if(mat != null) - mat.apply(vec); + public void apply(Vector3 vec) { + if (mat != null) mat.apply(vec); else - for(int i = 0; i < transformations.size(); i++) + for (int i = 0; i < transformations.size(); i++) transformations.get(i).apply(vec); } - + @Override - public void applyN(Vector3 normal) - { - if(mat != null) - mat.applyN(normal); + public void applyN(Vector3 normal) { + if (mat != null) mat.applyN(normal); else - for(int i = 0; i < transformations.size(); i++) + for (int i = 0; i < transformations.size(); i++) transformations.get(i).applyN(normal); } @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.multiply(compile()); } - + @Override - public TransformationList with(Transformation t) - { - if(t.isRedundant()) - return this; - - mat = null;//matrix invalid - if(t instanceof TransformationList) - transformations.addAll(((TransformationList)t).transformations); - else - transformations.add(t); - + public TransformationList with(Transformation t) { + if (t.isRedundant()) return this; + + mat = null; // matrix invalid + if (t instanceof TransformationList) transformations.addAll(((TransformationList) t).transformations); + else transformations.add(t); + compact(); return this; } - - public TransformationList prepend(Transformation t) - { - if(t.isRedundant()) - return this; - - mat = null;//matrix invalid - if(t instanceof TransformationList) - transformations.addAll(0, ((TransformationList)t).transformations); - else - transformations.add(0, t); - + + public TransformationList prepend(Transformation t) { + if (t.isRedundant()) return this; + + mat = null; // matrix invalid + if (t instanceof TransformationList) transformations.addAll(0, ((TransformationList) t).transformations); + else transformations.add(0, t); + compact(); return this; } - + private void compact() { ArrayList newList = new ArrayList(transformations.size()); Iterator iterator = transformations.iterator(); Transformation prev = null; - while(iterator.hasNext()) { + while (iterator.hasNext()) { Transformation t = iterator.next(); - if(t.isRedundant()) - continue; - - if(prev != null) { + if (t.isRedundant()) continue; + + if (prev != null) { Transformation m = prev.merge(t); - if(m == null) - newList.add(prev); - else if(m.isRedundant()) - t = null; - else - t = m; + if (m == null) newList.add(prev); + else if (m.isRedundant()) t = null; + else t = m; } prev = t; } - if(prev != null) - newList.add(prev); - - if(newList.size() < transformations.size()) { + if (prev != null) newList.add(prev); + + if (newList.size() < transformations.size()) { transformations = newList; mat = null; } - - if(transformations.size() > 3 && mat == null) - compile(); + + if (transformations.size() > 3 && mat == null) compile(); } - + @Override public boolean isRedundant() { return transformations.size() == 0; @@ -141,27 +113,23 @@ public boolean isRedundant() { @Override @SideOnly(Side.CLIENT) - public void glApply() - { - for(int i = transformations.size()-1; i >= 0; i--) + public void glApply() { + for (int i = transformations.size() - 1; i >= 0; i--) transformations.get(i).glApply(); } - + @Override - public Transformation inverse() - { + public Transformation inverse() { TransformationList rev = new TransformationList(); - for(int i = transformations.size()-1; i >= 0; i--) + for (int i = transformations.size() - 1; i >= 0; i--) rev.with(transformations.get(i).inverse()); return rev; } - + @Override - public String toString() - { + public String toString() { String s = ""; - for(Transformation t : transformations) - s+="\n"+t.toString(); + for (Transformation t : transformations) s += "\n" + t.toString(); return s.trim(); } } diff --git a/src/main/java/codechicken/lib/vec/Translation.java b/src/main/java/codechicken/lib/vec/Translation.java index 9ef8286..3e29216 100644 --- a/src/main/java/codechicken/lib/vec/Translation.java +++ b/src/main/java/codechicken/lib/vec/Translation.java @@ -2,11 +2,10 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import org.lwjgl.opengl.GL11; - import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import org.lwjgl.opengl.GL11; public class Translation extends Transformation { public Vector3 vec; @@ -25,8 +24,7 @@ public void apply(Vector3 vec) { } @Override - public void applyN(Vector3 normal) { - } + public void applyN(Vector3 normal) {} @Override public void apply(Matrix4 mat) { @@ -51,8 +49,7 @@ public Transformation inverse() { @Override public Transformation merge(Transformation next) { - if (next instanceof Translation) - return new Translation(vec.copy().add(((Translation) next).vec)); + if (next instanceof Translation) return new Translation(vec.copy().add(((Translation) next).vec)); return null; } @@ -65,6 +62,7 @@ public boolean isRedundant() { @Override public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Translation(" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ")"; + return "Translation(" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + + new BigDecimal(vec.z, cont) + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/VariableTransformation.java b/src/main/java/codechicken/lib/vec/VariableTransformation.java index 9e8ec89..bab385b 100644 --- a/src/main/java/codechicken/lib/vec/VariableTransformation.java +++ b/src/main/java/codechicken/lib/vec/VariableTransformation.java @@ -3,31 +3,26 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -public abstract class VariableTransformation extends Transformation -{ +public abstract class VariableTransformation extends Transformation { public Matrix4 mat; - - public VariableTransformation(Matrix4 mat) - { + + public VariableTransformation(Matrix4 mat) { this.mat = mat; } - + @Override - public void applyN(Vector3 normal) - { + public void applyN(Vector3 normal) { apply(normal); } @Override - public void apply(Matrix4 mat) - { + public void apply(Matrix4 mat) { mat.multiply(this.mat); } - + @Override @SideOnly(Side.CLIENT) - public void glApply() - { + public void glApply() { mat.glApply(); } -} \ No newline at end of file +} diff --git a/src/main/java/codechicken/lib/vec/Vector3.java b/src/main/java/codechicken/lib/vec/Vector3.java index 8a690df..e5cba67 100644 --- a/src/main/java/codechicken/lib/vec/Vector3.java +++ b/src/main/java/codechicken/lib/vec/Vector3.java @@ -4,6 +4,9 @@ import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; @@ -11,97 +14,77 @@ import org.lwjgl.util.vector.Vector3f; import org.lwjgl.util.vector.Vector4f; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - -public class Vector3 implements Copyable -{ +public class Vector3 implements Copyable { public static Vector3 zero = new Vector3(); public static Vector3 one = new Vector3(1, 1, 1); public static Vector3 center = new Vector3(0.5, 0.5, 0.5); - + public double x; public double y; public double z; - public Vector3() - { - } + public Vector3() {} - public Vector3(double d, double d1, double d2) - { + public Vector3(double d, double d1, double d2) { x = d; y = d1; z = d2; } - public Vector3(Vector3 vec) - { + public Vector3(Vector3 vec) { x = vec.x; y = vec.y; z = vec.z; } - public Vector3(double[] da) - { + public Vector3(double[] da) { this(da[0], da[1], da[2]); } - public Vector3(Vec3 vec) - { + public Vector3(Vec3 vec) { x = vec.xCoord; y = vec.yCoord; z = vec.zCoord; } - public Vector3(BlockCoord coord) - { + public Vector3(BlockCoord coord) { x = coord.x; y = coord.y; z = coord.z; } - public Vector3 copy() - { + public Vector3 copy() { return new Vector3(this); } - - public static Vector3 fromEntity(Entity e) - { + + public static Vector3 fromEntity(Entity e) { return new Vector3(e.posX, e.posY, e.posZ); } - - public static Vector3 fromEntityCenter(Entity e) - { - return new Vector3(e.posX, e.posY - e.yOffset + e.height/2, e.posZ); + + public static Vector3 fromEntityCenter(Entity e) { + return new Vector3(e.posX, e.posY - e.yOffset + e.height / 2, e.posZ); } - public static Vector3 fromTileEntity(TileEntity e) - { + public static Vector3 fromTileEntity(TileEntity e) { return new Vector3(e.xCoord, e.yCoord, e.zCoord); } - - public static Vector3 fromTileEntityCenter(TileEntity e) - { + + public static Vector3 fromTileEntityCenter(TileEntity e) { return new Vector3(e.xCoord + 0.5, e.yCoord + 0.5, e.zCoord + 0.5); } - public static Vector3 fromAxes(double[] da) - { + public static Vector3 fromAxes(double[] da) { return new Vector3(da[2], da[0], da[1]); } - public Vector3 set(double d, double d1, double d2) - { + public Vector3 set(double d, double d1, double d2) { x = d; y = d1; z = d2; return this; } - public Vector3 set(Vector3 vec) - { + public Vector3 set(Vector3 vec) { x = vec.x; y = vec.y; z = vec.z; @@ -109,7 +92,7 @@ public Vector3 set(Vector3 vec) } public double getSide(int side) { - switch(side) { + switch (side) { case 0: case 1: return y; @@ -123,39 +106,39 @@ public double getSide(int side) { throw new IndexOutOfBoundsException("Switch Falloff"); } - public Vector3 setSide(int s, double v) - { - switch(s) - { + public Vector3 setSide(int s, double v) { + switch (s) { case 0: - case 1: y = v; break; + case 1: + y = v; + break; case 2: - case 3: z = v; break; + case 3: + z = v; + break; case 4: - case 5: x = v; break; - default: throw new IndexOutOfBoundsException("Switch Falloff"); + case 5: + x = v; + break; + default: + throw new IndexOutOfBoundsException("Switch Falloff"); } return this; } - public double dotProduct(Vector3 vec) - { + public double dotProduct(Vector3 vec) { double d = vec.x * x + vec.y * y + vec.z * z; - - if(d > 1 && d < 1.00001) - d = 1; - else if(d < -1 && d > -1.00001) - d = -1; + + if (d > 1 && d < 1.00001) d = 1; + else if (d < -1 && d > -1.00001) d = -1; return d; } - public double dotProduct(double d, double d1, double d2) - { + public double dotProduct(double d, double d1, double d2) { return d * x + d1 * y + d2 * z; } - public Vector3 crossProduct(Vector3 vec) - { + public Vector3 crossProduct(Vector3 vec) { double d = y * vec.z - z * vec.y; double d1 = z * vec.x - x * vec.z; double d2 = x * vec.y - y * vec.x; @@ -165,107 +148,91 @@ public Vector3 crossProduct(Vector3 vec) return this; } - public Vector3 add(double d, double d1, double d2) - { + public Vector3 add(double d, double d1, double d2) { x += d; y += d1; z += d2; return this; } - public Vector3 add(Vector3 vec) - { + public Vector3 add(Vector3 vec) { x += vec.x; y += vec.y; z += vec.z; return this; } - - public Vector3 add(double d) - { + + public Vector3 add(double d) { return add(d, d, d); } - public Vector3 sub(Vector3 vec) - { + public Vector3 sub(Vector3 vec) { return subtract(vec); } - - public Vector3 subtract(Vector3 vec) - { + + public Vector3 subtract(Vector3 vec) { x -= vec.x; y -= vec.y; z -= vec.z; return this; } - public Vector3 negate(Vector3 vec) - { + public Vector3 negate(Vector3 vec) { x = -x; y = -y; z = -z; return this; } - - public Vector3 multiply(double d) - { + + public Vector3 multiply(double d) { x *= d; y *= d; z *= d; return this; } - public Vector3 multiply(Vector3 f) - { + public Vector3 multiply(Vector3 f) { x *= f.x; y *= f.y; z *= f.z; return this; } - - public Vector3 multiply(double fx, double fy, double fz) - { + + public Vector3 multiply(double fx, double fy, double fz) { x *= fx; y *= fy; z *= fz; return this; } - public double mag() - { + public double mag() { return Math.sqrt(x * x + y * y + z * z); } - public double magSquared() - { + public double magSquared() { return x * x + y * y + z * z; } - public Vector3 normalize() - { + public Vector3 normalize() { double d = mag(); - if(d != 0) - { + if (d != 0) { multiply(1 / d); } return this; } - public String toString() - { + public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Vector3("+new BigDecimal(x, cont)+", "+new BigDecimal(y, cont)+", "+new BigDecimal(z, cont)+")"; + return "Vector3(" + new BigDecimal(x, cont) + ", " + new BigDecimal(y, cont) + ", " + new BigDecimal(z, cont) + + ")"; } - - public Vector3 perpendicular() - { - if(z == 0) - return zCrossProduct(); + + public Vector3 perpendicular() { + if (z == 0) return zCrossProduct(); return xCrossProduct(); } - - public Vector3 xCrossProduct() - { + + public Vector3 xCrossProduct() { double d = z; double d1 = -y; x = 0; @@ -273,9 +240,8 @@ public Vector3 xCrossProduct() z = d1; return this; } - - public Vector3 zCrossProduct() - { + + public Vector3 zCrossProduct() { double d = y; double d1 = -x; x = d; @@ -283,9 +249,8 @@ public Vector3 zCrossProduct() z = 0; return this; } - - public Vector3 yCrossProduct() - { + + public Vector3 yCrossProduct() { double d = -z; double d1 = x; x = d; @@ -293,217 +258,180 @@ public Vector3 yCrossProduct() z = d1; return this; } - - public Vector3 rotate(double angle, Vector3 axis){ + + public Vector3 rotate(double angle, Vector3 axis) { Quat.aroundAxis(axis.copy().normalize(), angle).rotate(this); return this; } - - public Vector3 rotate(Quat rotator) - { + + public Vector3 rotate(Quat rotator) { rotator.rotate(this); return this; } - public Vec3 toVec3D() - { + public Vec3 toVec3D() { return Vec3.createVectorHelper(x, y, z); } - public double angle(Vector3 vec) - { + public double angle(Vector3 vec) { return Math.acos(copy().normalize().dotProduct(vec.copy().normalize())); } - public boolean isZero() - { + public boolean isZero() { return x == 0 && y == 0 && z == 0; } - public boolean isAxial() - { + public boolean isAxial() { return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); } @SideOnly(Side.CLIENT) - public Vector3f vector3f() - { - return new Vector3f((float)x, (float)y, (float)z); + public Vector3f vector3f() { + return new Vector3f((float) x, (float) y, (float) z); } @SideOnly(Side.CLIENT) - public Vector4f vector4f() - { - return new Vector4f((float)x, (float)y, (float)z, 1); + public Vector4f vector4f() { + return new Vector4f((float) x, (float) y, (float) z, 1); } - + @SideOnly(Side.CLIENT) - public void glVertex() - { + public void glVertex() { GL11.glVertex3d(x, y, z); } - public Vector3 YZintercept(Vector3 end, double px) - { + public Vector3 YZintercept(Vector3 end, double px) { double dx = end.x - x; double dy = end.y - y; double dz = end.z - z; - if (dx == 0) - return null; - + if (dx == 0) return null; + double d = (px - x) / dx; - if(MathHelper.between(-1E-5, d, 1E-5)) - return this; - - if(!MathHelper.between(0, d, 1)) - return null; - + if (MathHelper.between(-1E-5, d, 1E-5)) return this; + + if (!MathHelper.between(0, d, 1)) return null; + x = px; - y += d*dy; - z += d*dz; + y += d * dy; + z += d * dz; return this; } - public Vector3 XZintercept(Vector3 end, double py) - { + public Vector3 XZintercept(Vector3 end, double py) { double dx = end.x - x; double dy = end.y - y; double dz = end.z - z; - if (dy == 0) - return null; - + if (dy == 0) return null; + double d = (py - y) / dy; - if(MathHelper.between(-1E-5, d, 1E-5)) - return this; - - if(!MathHelper.between(0, d, 1)) - return null; - - x += d*dx; + if (MathHelper.between(-1E-5, d, 1E-5)) return this; + + if (!MathHelper.between(0, d, 1)) return null; + + x += d * dx; y = py; - z += d*dz; + z += d * dz; return this; } - public Vector3 XYintercept(Vector3 end, double pz) - { + public Vector3 XYintercept(Vector3 end, double pz) { double dx = end.x - x; double dy = end.y - y; double dz = end.z - z; - if (dz == 0) - return null; - + if (dz == 0) return null; + double d = (pz - z) / dz; - if(MathHelper.between(-1E-5, d, 1E-5)) - return this; - - if(!MathHelper.between(0, d, 1)) - return null; - - x += d*dx; - y += d*dy; - z = pz; + if (MathHelper.between(-1E-5, d, 1E-5)) return this; + + if (!MathHelper.between(0, d, 1)) return null; + + x += d * dx; + y += d * dy; + z = pz; return this; } - public Vector3 negate() - { + public Vector3 negate() { x = -x; y = -y; z = -z; return this; } - public Translation translation() - { + public Translation translation() { return new Translation(this); } - public double scalarProject(Vector3 b) - { + public double scalarProject(Vector3 b) { double l = b.mag(); - return l == 0 ? 0 : dotProduct(b)/l; + return l == 0 ? 0 : dotProduct(b) / l; } - - public Vector3 project(Vector3 b) - { + + public Vector3 project(Vector3 b) { double l = b.magSquared(); - if(l == 0) - { + if (l == 0) { set(0, 0, 0); return this; } - double m = dotProduct(b)/l; + double m = dotProduct(b) / l; set(b).multiply(m); return this; } - + @Override - public boolean equals(Object o) - { - if(!(o instanceof Vector3)) - return false; - Vector3 v = (Vector3)o; + public boolean equals(Object o) { + if (!(o instanceof Vector3)) return false; + Vector3 v = (Vector3) o; return x == v.x && y == v.y && z == v.z; } - + /** * Equals method with tolerance * @return true if this is equal to v within +-1E-5 */ - public boolean equalsT(Vector3 v) - { - return MathHelper.between(x-1E-5, v.x, x+1E-5) && - MathHelper.between(y-1E-5, v.y, y+1E-5) && - MathHelper.between(z-1E-5, v.z, z+1E-5); + public boolean equalsT(Vector3 v) { + return MathHelper.between(x - 1E-5, v.x, x + 1E-5) + && MathHelper.between(y - 1E-5, v.y, y + 1E-5) + && MathHelper.between(z - 1E-5, v.z, z + 1E-5); } - public Vector3 apply(Transformation t) - { + public Vector3 apply(Transformation t) { t.apply(this); return this; } - public Vector3 $tilde() - { + public Vector3 $tilde() { return normalize(); } - public Vector3 unary_$tilde() - { + public Vector3 unary_$tilde() { return normalize(); } - - public Vector3 $plus(Vector3 v) - { + + public Vector3 $plus(Vector3 v) { return add(v); } - - public Vector3 $minus(Vector3 v) - { + + public Vector3 $minus(Vector3 v) { return subtract(v); } - - public Vector3 $times(double d) - { + + public Vector3 $times(double d) { return multiply(d); } - - public Vector3 $div(double d) - { - return multiply(1/d); + + public Vector3 $div(double d) { + return multiply(1 / d); } - - public Vector3 $times(Vector3 v) - { + + public Vector3 $times(Vector3 v) { return crossProduct(v); } - public double $dot$times(Vector3 v) - { + public double $dot$times(Vector3 v) { return dotProduct(v); } } diff --git a/src/main/java/codechicken/lib/world/ChunkExtension.java b/src/main/java/codechicken/lib/world/ChunkExtension.java index c3f17b7..6b830d1 100644 --- a/src/main/java/codechicken/lib/world/ChunkExtension.java +++ b/src/main/java/codechicken/lib/world/ChunkExtension.java @@ -1,85 +1,62 @@ package codechicken.lib.world; +import java.util.HashSet; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.Packet; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.chunk.Chunk; -import java.util.HashSet; - -public abstract class ChunkExtension -{ +public abstract class ChunkExtension { public final Chunk chunk; public final ChunkCoordIntPair coord; public final WorldExtension world; public HashSet watchedPlayers; - - public ChunkExtension(Chunk chunk, WorldExtension world) - { + + public ChunkExtension(Chunk chunk, WorldExtension world) { this.chunk = chunk; coord = chunk.getChunkCoordIntPair(); this.world = world; watchedPlayers = new HashSet(); } - - public void loadData(NBTTagCompound tag) - { - } - - public void saveData(NBTTagCompound tag) - { - } - - public void load() - { - } - - public void unload() - { - } - - public final void sendPacketToPlayers(Packet packet) - { - for(EntityPlayerMP player : watchedPlayers) - player.playerNetServerHandler.sendPacket(packet); + + public void loadData(NBTTagCompound tag) {} + + public void saveData(NBTTagCompound tag) {} + + public void load() {} + + public void unload() {} + + public final void sendPacketToPlayers(Packet packet) { + for (EntityPlayerMP player : watchedPlayers) player.playerNetServerHandler.sendPacket(packet); } - public final void watchPlayer(EntityPlayerMP player) - { + public final void watchPlayer(EntityPlayerMP player) { watchedPlayers.add(player); onWatchPlayer(player); } - - public void onWatchPlayer(EntityPlayerMP player) - { - } - public final void unwatchPlayer(EntityPlayerMP player) - { + public void onWatchPlayer(EntityPlayerMP player) {} + + public final void unwatchPlayer(EntityPlayerMP player) { watchedPlayers.remove(player); onUnWatchPlayer(player); } - - public void onUnWatchPlayer(EntityPlayerMP player) - { - } - public void sendUpdatePackets() - { - } - + public void onUnWatchPlayer(EntityPlayerMP player) {} + + public void sendUpdatePackets() {} + @Override - public int hashCode() - { + public int hashCode() { return coord.chunkXPos ^ coord.chunkZPos; } - + @Override - public boolean equals(Object o) - { - return (o instanceof ChunkExtension && ((ChunkExtension)o).coord.equals(coord)) || - (o instanceof ChunkCoordIntPair && coord.equals(o)) || - (o instanceof Long && (Long)o == (((long)coord.chunkXPos)<<32 | coord.chunkZPos)); + public boolean equals(Object o) { + return (o instanceof ChunkExtension && ((ChunkExtension) o).coord.equals(coord)) + || (o instanceof ChunkCoordIntPair && coord.equals(o)) + || (o instanceof Long && (Long) o == (((long) coord.chunkXPos) << 32 | coord.chunkZPos)); } } diff --git a/src/main/java/codechicken/lib/world/IChunkLoadTile.java b/src/main/java/codechicken/lib/world/IChunkLoadTile.java index 5739102..8e53c76 100644 --- a/src/main/java/codechicken/lib/world/IChunkLoadTile.java +++ b/src/main/java/codechicken/lib/world/IChunkLoadTile.java @@ -6,7 +6,6 @@ * Be sure to call TileChunkLoadHook.init() from your mod during initialisation * You could easily implement this in your own mod, but providing it here reduces the number of times the chunkTileEntityMap needs to be iterated */ -public interface IChunkLoadTile -{ +public interface IChunkLoadTile { public void onChunkLoad(); } diff --git a/src/main/java/codechicken/lib/world/TileChunkLoadHook.java b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java index e080c2e..7e75cbd 100644 --- a/src/main/java/codechicken/lib/world/TileChunkLoadHook.java +++ b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java @@ -1,18 +1,17 @@ package codechicken.lib.world; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import java.util.ArrayList; +import java.util.List; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.ChunkEvent; -import java.util.ArrayList; -import java.util.List; - -public class TileChunkLoadHook -{ +public class TileChunkLoadHook { private static boolean init; + public static void init() { - if(init) return; + if (init) return; init = true; MinecraftForge.EVENT_BUS.register(new TileChunkLoadHook()); @@ -20,9 +19,8 @@ public static void init() { @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { - List list = new ArrayList(event.getChunk().chunkTileEntityMap.values()); - for(TileEntity t : list) - if(t instanceof IChunkLoadTile) - ((IChunkLoadTile)t).onChunkLoad(); + List list = + new ArrayList(event.getChunk().chunkTileEntityMap.values()); + for (TileEntity t : list) if (t instanceof IChunkLoadTile) ((IChunkLoadTile) t).onChunkLoad(); } } diff --git a/src/main/java/codechicken/lib/world/WorldExtension.java b/src/main/java/codechicken/lib/world/WorldExtension.java index b4cfe0e..b074e46 100644 --- a/src/main/java/codechicken/lib/world/WorldExtension.java +++ b/src/main/java/codechicken/lib/world/WorldExtension.java @@ -1,99 +1,73 @@ package codechicken.lib.world; +import java.util.HashMap; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -import java.util.HashMap; - -public abstract class WorldExtension -{ +public abstract class WorldExtension { public final World world; public HashMap chunkMap = new HashMap(); - - public WorldExtension(World world) - { + + public WorldExtension(World world) { this.world = world; } - - public void load() - { - } - - public void unload() - { - } - - public void save() - { - } - - public void preTick() - { - } - - public void postTick() - { - } - - protected final void addChunk(ChunkExtension extension) - { + + public void load() {} + + public void unload() {} + + public void save() {} + + public void preTick() {} + + public void postTick() {} + + protected final void addChunk(ChunkExtension extension) { chunkMap.put(extension.chunk, extension); } - - protected final void loadChunk(Chunk chunk) - { + + protected final void loadChunk(Chunk chunk) { chunkMap.get(chunk).load(); } - - protected final void unloadChunk(Chunk chunk) - { + + protected final void unloadChunk(Chunk chunk) { if (chunkMap.get(chunk) != null) chunkMap.get(chunk).unload(); } - - protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) - { + + protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) { chunkMap.get(chunk).loadData(tag); } - - protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) - { + + protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) { chunkMap.get(chunk).saveData(tag); } - - protected final void remChunk(Chunk chunk) - { + + protected final void remChunk(Chunk chunk) { chunkMap.remove(chunk); } - protected final void watchChunk(Chunk chunk, EntityPlayerMP player) - { + protected final void watchChunk(Chunk chunk, EntityPlayerMP player) { chunkMap.get(chunk).watchPlayer(player); } - protected final void unwatchChunk(Chunk chunk, EntityPlayerMP player) - { + protected final void unwatchChunk(Chunk chunk, EntityPlayerMP player) { ChunkExtension extension = chunkMap.get(chunk); - if(extension != null) - extension.unwatchPlayer(player); + if (extension != null) extension.unwatchPlayer(player); } - protected final void sendChunkUpdates(Chunk chunk) - { + protected final void sendChunkUpdates(Chunk chunk) { chunkMap.get(chunk).sendUpdatePackets(); } - public boolean containsChunk(Chunk chunk) - { + public boolean containsChunk(Chunk chunk) { return chunkMap.containsKey(chunk); } - public ChunkExtension getChunkExtension(int chunkXPos, int chunkZPos) - { - if(!world.blockExists(chunkXPos<<4, 128, chunkZPos<<4)) - return null; - + public ChunkExtension getChunkExtension(int chunkXPos, int chunkZPos) { + if (!world.blockExists(chunkXPos << 4, 128, chunkZPos << 4)) return null; + return chunkMap.get(world.getChunkFromChunkCoords(chunkXPos, chunkZPos)); } } diff --git a/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java index 23431b0..fbd93ea 100644 --- a/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java +++ b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java @@ -3,15 +3,14 @@ import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -public abstract class WorldExtensionInstantiator -{ +public abstract class WorldExtensionInstantiator { public int instantiatorID; - + public abstract WorldExtension createWorldExtension(World world); + public abstract ChunkExtension createChunkExtension(Chunk chunk, WorldExtension world); - - public WorldExtension getExtension(World world) - { + + public WorldExtension getExtension(World world) { return WorldExtensionManager.getWorldExtension(world, instantiatorID); } } diff --git a/src/main/java/codechicken/lib/world/WorldExtensionManager.java b/src/main/java/codechicken/lib/world/WorldExtensionManager.java index b8ec2b4..a121379 100644 --- a/src/main/java/codechicken/lib/world/WorldExtensionManager.java +++ b/src/main/java/codechicken/lib/world/WorldExtensionManager.java @@ -5,6 +5,8 @@ import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.util.ArrayList; +import java.util.HashMap; import net.minecraft.client.Minecraft; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -16,186 +18,143 @@ import net.minecraftforge.event.world.ChunkWatchEvent.Watch; import net.minecraftforge.event.world.WorldEvent; -import java.util.ArrayList; -import java.util.HashMap; - -public class WorldExtensionManager -{ - public static class WorldExtensionEventHandler - { +public class WorldExtensionManager { + public static class WorldExtensionEventHandler { @SubscribeEvent - public void onChunkDataLoad(ChunkDataEvent.Load event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - + public void onChunkDataLoad(ChunkDataEvent.Load event) { + if (!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); + createChunkExtension(event.world, event.getChunk()); - for(WorldExtension extension : worldMap.get(event.world)) + for (WorldExtension extension : worldMap.get(event.world)) extension.loadChunkData(event.getChunk(), event.getData()); } @SubscribeEvent - public void onChunkDataSave(ChunkDataEvent.Save event) - { - for(WorldExtension extension : worldMap.get(event.world)) + public void onChunkDataSave(ChunkDataEvent.Save event) { + for (WorldExtension extension : worldMap.get(event.world)) extension.saveChunkData(event.getChunk(), event.getData()); - - if(!event.getChunk().isChunkLoaded) - removeChunk(event.world, event.getChunk()); + + if (!event.getChunk().isChunkLoaded) removeChunk(event.world, event.getChunk()); } - + @SubscribeEvent - public void onChunkLoad(ChunkEvent.Load event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - + public void onChunkLoad(ChunkEvent.Load event) { + if (!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); + createChunkExtension(event.world, event.getChunk()); - - for(WorldExtension extension : worldMap.get(event.world)) - extension.loadChunk(event.getChunk()); + + for (WorldExtension extension : worldMap.get(event.world)) extension.loadChunk(event.getChunk()); } @SubscribeEvent - public void onChunkUnLoad(ChunkEvent.Unload event) - { - if(event.getChunk() instanceof EmptyChunk) - return; - - for(WorldExtension extension : worldMap.get(event.world)) - extension.unloadChunk(event.getChunk()); - - if(event.world.isRemote) - removeChunk(event.world, event.getChunk()); + public void onChunkUnLoad(ChunkEvent.Unload event) { + if (event.getChunk() instanceof EmptyChunk) return; + + for (WorldExtension extension : worldMap.get(event.world)) extension.unloadChunk(event.getChunk()); + + if (event.world.isRemote) removeChunk(event.world, event.getChunk()); } @SubscribeEvent - public void onWorldSave(WorldEvent.Save event) - { - if(worldMap.containsKey(event.world)) - for(WorldExtension extension : worldMap.get(event.world)) - extension.save(); + public void onWorldSave(WorldEvent.Save event) { + if (worldMap.containsKey(event.world)) + for (WorldExtension extension : worldMap.get(event.world)) extension.save(); } @SubscribeEvent - public void onWorldLoad(WorldEvent.Load event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); + public void onWorldLoad(WorldEvent.Load event) { + if (!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); } @SubscribeEvent - public void onWorldUnLoad(WorldEvent.Unload event) - { - if(worldMap.containsKey(event.world))//because force closing unloads a world twice - for(WorldExtension extension : worldMap.remove(event.world)) - extension.unload(); + public void onWorldUnLoad(WorldEvent.Unload event) { + if (worldMap.containsKey(event.world)) // because force closing unloads a world twice + for (WorldExtension extension : worldMap.remove(event.world)) extension.unload(); } - + @SubscribeEvent - public void onChunkWatch(Watch event) - { + public void onChunkWatch(Watch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); - for(WorldExtension extension : worldMap.get(event.player.worldObj)) + for (WorldExtension extension : worldMap.get(event.player.worldObj)) extension.watchChunk(chunk, event.player); } @SubscribeEvent @SideOnly(Side.CLIENT) - public void onChunkUnWatch(UnWatch event) - { + public void onChunkUnWatch(UnWatch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); - for(WorldExtension extension : worldMap.get(event.player.worldObj)) + for (WorldExtension extension : worldMap.get(event.player.worldObj)) extension.unwatchChunk(chunk, event.player); } @SubscribeEvent @SideOnly(Side.CLIENT) - public void clientTick(TickEvent.ClientTickEvent event) - { + public void clientTick(TickEvent.ClientTickEvent event) { World world = Minecraft.getMinecraft().theWorld; if (worldMap.containsKey(world)) - if (event.phase == TickEvent.Phase.START) - preTick(world); - else - postTick(world); + if (event.phase == TickEvent.Phase.START) preTick(world); + else postTick(world); } @SubscribeEvent - public void serverTick(TickEvent.WorldTickEvent event) - { - if(!worldMap.containsKey(event.world)) - WorldExtensionManager.onWorldLoad(event.world); - - if(event.phase == TickEvent.Phase.START) - preTick(event.world); - else - postTick(event.world); + public void serverTick(TickEvent.WorldTickEvent event) { + if (!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); + + if (event.phase == TickEvent.Phase.START) preTick(event.world); + else postTick(event.world); } } - + private static boolean initialised; - private static ArrayList extensionIntialisers = new ArrayList(); - - public static void registerWorldExtension(WorldExtensionInstantiator init) - { - if(!initialised) - init(); - + private static ArrayList extensionIntialisers = + new ArrayList(); + + public static void registerWorldExtension(WorldExtensionInstantiator init) { + if (!initialised) init(); + init.instantiatorID = extensionIntialisers.size(); extensionIntialisers.add(init); } - private static void init() - { + private static void init() { initialised = true; MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); } private static HashMap worldMap = new HashMap(); - - private static void onWorldLoad(World world) - { + + private static void onWorldLoad(World world) { WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()]; - for(int i = 0; i < extensions.length; i++) + for (int i = 0; i < extensions.length; i++) extensions[i] = extensionIntialisers.get(i).createWorldExtension(world); - + worldMap.put(world, extensions); - - for(WorldExtension extension : extensions) - extension.load(); + + for (WorldExtension extension : extensions) extension.load(); } - private static void createChunkExtension(World world, Chunk chunk) - { + private static void createChunkExtension(World world, Chunk chunk) { WorldExtension[] extensions = worldMap.get(world); - for(int i = 0; i < extensionIntialisers.size(); i++) - if(!extensions[i].containsChunk(chunk)) + for (int i = 0; i < extensionIntialisers.size(); i++) + if (!extensions[i].containsChunk(chunk)) extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); } - - private static void removeChunk(World world, Chunk chunk) - { - for(WorldExtension extension : worldMap.get(world)) - extension.remChunk(chunk); + + private static void removeChunk(World world, Chunk chunk) { + for (WorldExtension extension : worldMap.get(world)) extension.remChunk(chunk); } - - private static void preTick(World world) - { - for(WorldExtension extension : worldMap.get(world)) - extension.preTick(); + + private static void preTick(World world) { + for (WorldExtension extension : worldMap.get(world)) extension.preTick(); } - - private static void postTick(World world) - { - for(WorldExtension extension : worldMap.get(world)) - extension.postTick(); + + private static void postTick(World world) { + for (WorldExtension extension : worldMap.get(world)) extension.postTick(); } - public static WorldExtension getWorldExtension(World world, int instantiatorID) - { + public static WorldExtension getWorldExtension(World world, int instantiatorID) { return worldMap.get(world)[instantiatorID]; } } From acdf6d754f0f6a0bee8553103c6edf5be2fbc11e Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Thu, 5 Jan 2023 12:09:05 +0000 Subject: [PATCH 162/219] Update buildscript (#9) * Update buildscript * Bump CCL --- build.gradle | 258 ++++++++++++++++++++++++++++++++++---------- dependencies.gradle | 2 +- 2 files changed, 204 insertions(+), 56 deletions(-) diff --git a/build.gradle b/build.gradle index 997b94d..fa88ae1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,17 @@ -//version: 1661114848 +//version: 1671313514 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. - Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. + Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/build.gradle for updates. */ import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.matthewprenger.cursegradle.CurseArtifact +import com.matthewprenger.cursegradle.CurseRelation +import com.modrinth.minotaur.dependencies.ModDependency +import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory @@ -27,7 +31,7 @@ buildscript { url 'https://maven.minecraftforge.net' } maven { - // GTNH ForgeGradle Fork + // GTNH ForgeGradle and ASM Fork name = "GTNH Maven" url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" } @@ -41,7 +45,9 @@ buildscript { } } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.9' + //Overwrite the current ASM version to fix shading newer than java 8 applicatations. + classpath 'org.ow2.asm:asm-debug-all-custom:5.0.3' + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.13' } } plugins { @@ -59,6 +65,8 @@ plugins { id 'de.undercouch.download' version '5.0.1' id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false id 'com.diffplug.spotless' version '6.7.2' apply false + id 'com.modrinth.minotaur' version '2.+' apply false + id 'com.matthewprenger.cursegradle' version '1.4.0' apply false } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -127,26 +135,35 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false -boolean usesMixinDebug = project.hasProperty('usesMixinDebug') ?: project.usesMixins.toBoolean() -boolean forceEnableMixins = project.hasProperty('forceEnableMixins') ? project.forceEnableMixins.toBoolean() : false -String channel = project.hasProperty('channel') ? project.channel : 'stable' -String mappingsVersion = project.hasProperty('mappingsVersion') ? project.mappingsVersion : '12' +propertyDefaultIfUnset("noPublishedSources", false) +propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) +propertyDefaultIfUnset("forceEnableMixins", false) +propertyDefaultIfUnset("channel", "stable") +propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("modrinthProjectId", "") +propertyDefaultIfUnset("modrinthRelations", "") +propertyDefaultIfUnset("curseForgeProjectId", "") +propertyDefaultIfUnset("curseForgeRelations", "") + String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" -String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") -String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") -String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + +final String modGroupPath = modGroup.toString().replaceAll("\\.", "/") +final String apiPackagePath = apiPackage.toString().replaceAll("\\.", "/") + +String targetPackageJava = javaSourceDir + modGroupPath +String targetPackageScala = scalaSourceDir + modGroupPath +String targetPackageKotlin = kotlinSourceDir + modGroupPath if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } if (apiPackage) { - targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + targetPackageJava = javaSourceDir + modGroupPath + "/" + apiPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath + targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } @@ -160,31 +177,36 @@ if (accessTransformersFile) { } if (usesMixins.toBoolean()) { - if (mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { - throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!") + if (mixinsPackage.isEmpty()) { + throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") } + final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/") + final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/") - targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath + targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } - String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt" - if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { - throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) + if (!mixinPlugin.isEmpty()) { + String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" + String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" + String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".kt" + if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { + throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) + } } } if (coreModClass) { - String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt" + final String coreModPath = coreModClass.toString().replaceAll("\\.", "/") + String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java" + String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java" + String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".kt" if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) } @@ -240,7 +262,7 @@ if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { def arguments = [] def jvmArguments = [] -if (usesMixins.toBoolean() || forceEnableMixins) { +if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { arguments += [ "--tweakClass org.spongepowered.asm.launch.MixinTweaker" ] @@ -258,7 +280,9 @@ minecraft { runDir = 'run' if (replaceGradleTokenInFile) { - replaceIn replaceGradleTokenInFile + for (f in replaceGradleTokenInFile.split(',')) { + replaceIn f + } if (gradleTokenModId) { replace gradleTokenModId, modId } @@ -305,13 +329,16 @@ repositories { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' } - if (usesMixins.toBoolean() || forceEnableMixins) { + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { maven { - name 'sponge' - url 'https://repo.spongepowered.org/repository/maven-public' + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" } - maven { - url 'https://jitpack.io' + if (usesMixinDebug.toBoolean()) { + maven { + name = "Fabric Maven" + url = "https://maven.fabricmc.net/" + } } } } @@ -321,19 +348,13 @@ dependencies { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') annotationProcessor('com.google.guava:guava:24.1.1-jre') annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT') - } - if (usesMixins.toBoolean() || forceEnableMixins) { - // using 0.8 to workaround a issue in 0.7 which fails mixin application - compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') { - // Mixin includes a lot of dependencies that are too up-to-date - exclude module: 'launchwrapper' - exclude module: 'guava' - exclude module: 'gson' - exclude module: 'commons-io' - exclude module: 'log4j-core' + annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.3:processor') + if (usesMixinDebug.toBoolean()) { + runtimeOnly('org.jetbrains:intellij-fernflower:1.2.1.16') } - compile('com.github.GTNewHorizons:SpongeMixins:1.5.0') + } + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + compile('com.gtnewhorizon:gtnhmixins:2.1.3') } } @@ -345,13 +366,18 @@ def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if (usesMixins.toBoolean()) { - def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json"); + def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") if (!mixinConfigFile.exists()) { + def mixinPluginLine = "" + if(!mixinPlugin.isEmpty()) { + // We might not have a mixin plugin if we're using early/late mixins + mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ + } + mixinConfigFile.text = """{ "required": true, - "minVersion": "0.7.11", - "package": "${modGroup}.${mixinsPackage}", - "plugin": "${modGroup}.${mixinPlugin}", + "minVersion": "0.8.5-GTNH", + "package": "${modGroup}.${mixinsPackage}",${mixinPluginLine} "refmap": "${mixingConfigRefMap}", "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_8", @@ -563,11 +589,11 @@ task devJar(type: Jar) { task apiJar(type: Jar) { from(sourceSets.main.allSource) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' + include modGroupPath + "/" + apiPackagePath + '/**' } from(sourceSets.main.output) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' + include modGroupPath + "/" + apiPackagePath + '/**' } from(sourceSets.main.resources.srcDirs) { @@ -651,6 +677,113 @@ publishing { } } +if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { + apply plugin: 'com.modrinth.minotaur' + + File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") + + modrinth { + token = System.getenv("MODRINTH_TOKEN") + projectId = modrinthProjectId + versionNumber = identifiedVersion + versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" + changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" + uploadFile = jar + additionalFiles = getSecondaryArtifacts() + gameVersions = [minecraftVersion] + loaders = ["forge"] + debugMode = false + } + + if (modrinthRelations.size() != 0) { + String[] deps = modrinthRelations.split(";") + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(":") + String[] qual = parts[0].split("-") + addModrinthDep(qual[0], qual[1], parts[1]) + } + } + if (usesMixins.toBoolean()) { + addModrinthDep("required", "project", "gtnhmixins") + } + tasks.modrinth.dependsOn(build) + tasks.publish.dependsOn(tasks.modrinth) +} + +if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) { + apply plugin: 'com.matthewprenger.cursegradle' + + File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") + + curseforge { + apiKey = System.getenv("CURSEFORGE_TOKEN") + project { + id = curseForgeProjectId + if (changelogFile.exists()) { + changelogType = "markdown" + changelog = changelogFile + } + releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" + addGameVersion minecraftVersion + addGameVersion "Forge" + mainArtifact jar + for (artifact in getSecondaryArtifacts()) addArtifact artifact + } + + options { + javaIntegration = false + forgeGradleIntegration = false + debug = false + } + } + + if (curseForgeRelations.size() != 0) { + String[] deps = curseForgeRelations.split(";") + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(":") + addCurseForgeRelation(parts[0], parts[1]) + } + } + if (usesMixins.toBoolean()) { + addCurseForgeRelation("requiredDependency", "gtnhmixins") + } + tasks.curseforge.dependsOn(build) + tasks.publish.dependsOn(tasks.curseforge) +} + +def addModrinthDep(scope, type, name) { + com.modrinth.minotaur.dependencies.Dependency dep; + if (!(scope in ["required", "optional", "incompatible", "embedded"])) { + throw new Exception("Invalid modrinth dependency scope: " + scope) + } + switch (type) { + case "project": + dep = new ModDependency(name, scope) + break + case "version": + dep = new VersionDependency(name, scope) + break + default: + throw new Exception("Invalid modrinth dependency type: " + type) + } + project.modrinth.dependencies.add(dep) +} + +def addCurseForgeRelation(type, name) { + if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { + throw new Exception("Invalid CurseForge relation type: " + type) + } + CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact + CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation())) + rel."$type"(name) +} + // Updating task updateBuildScript { doLast { @@ -963,6 +1096,21 @@ def checkPropertyExists(String propertyName) { } } +def propertyDefaultIfUnset(String propertyName, defaultValue) { + if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { + project.ext.setProperty(propertyName, defaultValue) + } +} + def getFile(String relativePath) { return new File(projectDir, relativePath) } + +def getSecondaryArtifacts() { + // Because noPublishedSources from the beginning of the script is somehow not visible here... + boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false + def secondaryArtifacts = [devJar] + if (!noPublishedSources) secondaryArtifacts += [sourcesJar] + if (apiPackage) secondaryArtifacts += [apiJar] + return secondaryArtifacts +} diff --git a/dependencies.gradle b/dependencies.gradle index 5dc55d7..1ea2ad8 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ // Add your dependencies here dependencies { - compile('com.github.GTNewHorizons:CodeChickenLib:1.1.5.3:dev') + compile('com.github.GTNewHorizons:CodeChickenLib:1.1.5.6:dev') } From f6102d56ec78e69efcbf434b83a6b904a31e46ea Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Wed, 11 Jan 2023 21:05:45 +0000 Subject: [PATCH 163/219] Add GradleStart-injected property for obf mapping discovery (for RFG compatibility) --- src/main/java/codechicken/lib/asm/ObfMapping.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java index 39d1167..d7fea04 100644 --- a/src/main/java/codechicken/lib/asm/ObfMapping.java +++ b/src/main/java/codechicken/lib/asm/ObfMapping.java @@ -110,7 +110,7 @@ public static File[] getConfFiles() { throw new RuntimeException("Failed to select mappings directory, set it manually in the config"); } - private static final int DIR_GUESSES = 5; + private static final int DIR_GUESSES = 6; private static final int DIR_ASKS = 3; public static File confDirectoryGuess(int i, ConfigTag tag) { @@ -132,6 +132,9 @@ public static File confDirectoryGuess(int i, ConfigTag tag) { System.getProperty("user.home"), ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + "-" + ForgeVersion.getVersion() + "-" + FMLInjectionData.data()[4] + "/unpacked/conf"); + case 5: + final String gradleCsvDir = System.getProperty("net.minecraftforge.gradle.GradleStart.csvDir"); + return gradleCsvDir != null ? new File(gradleCsvDir) : null; default: JFileChooser fc = new JFileChooser(mcDir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); From 318c107957f71b40c7378986d1cc86ca6afc14de Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 10:33:45 +0000 Subject: [PATCH 164/219] [ci skip] Update buildscript to RetroFuturaGradle --- build.gradle | 837 ++++++++++++++--------- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 272 +++++--- gradlew.bat | 38 +- settings.gradle | 24 +- 6 files changed, 697 insertions(+), 477 deletions(-) diff --git a/build.gradle b/build.gradle index fa88ae1..78caf98 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1671313514 +//version: 1675074449 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,24 +6,27 @@ */ +import com.diffplug.blowdryer.Blowdryer import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory +import org.jetbrains.gradle.ext.* import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit import java.util.zip.ZipEntry -import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream buildscript { repositories { + mavenLocal() mavenCentral() maven { @@ -31,9 +34,10 @@ buildscript { url 'https://maven.minecraftforge.net' } maven { - // GTNH ForgeGradle and ASM Fork - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + // GTNH RetroFuturaGradle and ASM Fork + name "GTNH Maven" + url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true } maven { name 'sonatype' @@ -44,76 +48,41 @@ buildscript { url 'https://repo1.maven.org/maven2/' } } - dependencies { - //Overwrite the current ASM version to fix shading newer than java 8 applicatations. - classpath 'org.ow2.asm:asm-debug-all-custom:5.0.3' - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.13' - } } plugins { id 'java-library' - id 'idea' + id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" id 'eclipse' id 'scala' id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false - id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false - id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false - id 'org.ajoberstar.grgit' version '4.1.1' - id 'com.github.johnrengelman.shadow' version '4.0.4' - id 'com.palantir.git-version' version '0.13.0' apply false - id 'de.undercouch.download' version '5.0.1' - id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false + id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false + id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false + id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false + id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '7.1.2' apply false + id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version + id 'de.undercouch.download' version '5.3.0' + id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle id 'com.diffplug.spotless' version '6.7.2' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false + id 'com.gtnewhorizons.retrofuturagradle' version '1.0.18' } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -dependencies { - implementation 'com.diffplug:blowdryer:1.6.0' -} - -apply plugin: 'com.diffplug.blowdryer' - if (project.file('.git/HEAD').isFile()) { apply plugin: 'com.palantir.git-version' } def out = services.get(StyledTextOutputFactory).create('an-output') -apply plugin: 'forge' - def projectJavaVersion = JavaLanguageVersion.of(8) -java { - toolchain { - languageVersion.set(projectJavaVersion) - } -} - -idea { - module { - inheritOutputDirs = true - downloadJavadoc = true - downloadSources = true - } -} - boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false -if (!disableSpotless) { - apply plugin: 'com.diffplug.spotless' - apply from: Blowdryer.file('spotless.gradle') -} - -if (JavaVersion.current() != JavaVersion.VERSION_1_8) { - throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) -} - checkPropertyExists("modName") checkPropertyExists("modId") checkPropertyExists("modGroup") @@ -121,10 +90,7 @@ checkPropertyExists("autoUpdateBuildScript") checkPropertyExists("minecraftVersion") checkPropertyExists("forgeVersion") checkPropertyExists("replaceGradleTokenInFile") -checkPropertyExists("gradleTokenModId") -checkPropertyExists("gradleTokenModName") checkPropertyExists("gradleTokenVersion") -checkPropertyExists("gradleTokenGroupName") checkPropertyExists("apiPackage") checkPropertyExists("accessTransformersFile") checkPropertyExists("usesMixins") @@ -135,6 +101,8 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") +propertyDefaultIfUnset("generateGradleTokenClass", "") +propertyDefaultIfUnset("includeWellKnownRepositories", true) propertyDefaultIfUnset("noPublishedSources", false) propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) @@ -144,14 +112,107 @@ propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") propertyDefaultIfUnset("curseForgeRelations", "") +propertyDefaultIfUnset("minimizeShadowedDependencies", true) +propertyDefaultIfUnset("relocateShadowedDependencies", true) +// Deprecated properties (kept for backwards compat) +propertyDefaultIfUnset("gradleTokenModId", "") +propertyDefaultIfUnset("gradleTokenModName", "") +propertyDefaultIfUnset("gradleTokenGroupName", "") + +propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only +propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only + +project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +if (!disableSpotless) { + apply plugin: 'com.diffplug.spotless' + apply from: Blowdryer.file('spotless.gradle') +} String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" +if (usesShadowedDependencies.toBoolean()) { + apply plugin: "com.github.johnrengelman.shadow" +} -final String modGroupPath = modGroup.toString().replaceAll("\\.", "/") -final String apiPackagePath = apiPackage.toString().replaceAll("\\.", "/") +java { + toolchain { + if (enableModernJavaSyntax.toBoolean()) { + languageVersion.set(JavaLanguageVersion.of(17)) + } else { + languageVersion.set(projectJavaVersion) + } + vendor.set(JvmVendorSpec.ADOPTIUM) + } + if (!noPublishedSources) { + withSourcesJar() + } +} + +pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { + // If Kotlin is enabled in the project + kotlin { + jvmToolchain(8) + } + // Kotlin hacks our source sets, so we hack Kotlin's tasks + def disabledKotlinTaskList = [ + "kaptGenerateStubsMcLauncherKotlin", + "kaptGenerateStubsPatchedMcKotlin", + "kaptGenerateStubsInjectedTagsKotlin", + "compileMcLauncherKotlin", + "compilePatchedMcKotlin", + "compileInjectedTagsKotlin", + "kaptMcLauncherKotlin", + "kaptPatchedMcKotlin", + "kaptInjectedTagsKotlin", + ] + tasks.configureEach { task -> + if (task.name in disabledKotlinTaskList) { + task.enabled = false + } + } +} + +configurations { + create("runtimeOnlyNonPublishable") { + description = "Runtime only dependencies that are not published alongside the jar" + canBeConsumed = false + canBeResolved = false + } +} + +if (enableModernJavaSyntax.toBoolean()) { + dependencies { + annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { + transitive = false // We only care about the 1 annotation class + } + } + + tasks.withType(JavaCompile).configureEach { + if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) { + return + } + sourceCompatibility = 17 // for the IDE support + options.release.set(8) + + javaCompiler.set(javaToolchains.compilerFor { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.ADOPTIUM) + }) + } +} + +eclipse { + classpath { + downloadSources = true + downloadJavadoc = true + } +} + +final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char) +final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char) String targetPackageJava = javaSourceDir + modGroupPath String targetPackageScala = scalaSourceDir + modGroupPath @@ -174,6 +235,27 @@ if (accessTransformersFile) { if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) +} else { + boolean atsFound = false + for (File at : sourceSets.getByName("main").resources.files) { + if (at.name.toLowerCase().endsWith("_at.cfg")) { + atsFound = true + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) + } + } + for (File at : sourceSets.getByName("api").resources.files) { + if (at.name.toLowerCase().endsWith("_at.cfg")) { + atsFound = true + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) + } + } + if (atsFound) { + logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name") + } } if (usesMixins.toBoolean()) { @@ -212,7 +294,7 @@ if (coreModClass) { } } -configurations.all { +configurations.configureEach { resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) // Make sure GregTech build won't time out @@ -243,7 +325,7 @@ catch (Exception ignored) { versionOverride = 'NO-GIT-TAG-SET' identifiedVersion = versionOverride } -version = minecraftVersion + '-' + identifiedVersion +version = identifiedVersion ext { modVersion = identifiedVersion } @@ -259,56 +341,72 @@ if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = modId } -def arguments = [] -def jvmArguments = [] - -if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - arguments += [ - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - if (usesMixinDebug.toBoolean()) { - jvmArguments += [ - "-Dmixin.debug.countInjections=true", - "-Dmixin.debug.verbose=true", - "-Dmixin.debug.export=true" - ] - } -} minecraft { - version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion - runDir = 'run' - if (replaceGradleTokenInFile) { for (f in replaceGradleTokenInFile.split(',')) { - replaceIn f + tagReplacementFiles.add f } - if (gradleTokenModId) { - replace gradleTokenModId, modId - } - if (gradleTokenModName) { - replace gradleTokenModName, modName - } - if (gradleTokenVersion) { - replace gradleTokenVersion, modVersion - } - if (gradleTokenGroupName) { - replace gradleTokenGroupName, modGroup + } + if (gradleTokenModId) { + injectedTags.put gradleTokenModId, modId + } + if (gradleTokenModName) { + injectedTags.put gradleTokenModName, modName + } + if (gradleTokenVersion) { + injectedTags.put gradleTokenVersion, modVersion + } + if (gradleTokenGroupName) { + injectedTags.put gradleTokenGroupName, modGroup + } + if (enableGenericInjection.toBoolean()) { + injectMissingGenerics.set(true) + } + + // Enable assertions in the current mod + extraRunJvmArguments.add("-ea:${modGroup}") + + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") + + if (usesMixinDebug.toBoolean()) { + extraRunJvmArguments.addAll([ + "-Dmixin.debug.countInjections=true", + "-Dmixin.debug.verbose=true", + "-Dmixin.debug.export=true" + ]) } } - clientIntellijRun { - args(arguments) - jvmArgs(jvmArguments) + // Blowdryer is present in some old mod builds, do not propagate it further as a dependency + // IC2 has no reobf jars in its Maven + groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"]) +} + +if (generateGradleTokenClass) { + tasks.injectTags.outputClassName.set(generateGradleTokenClass) +} - if (developmentEnvironmentUserName) { - args("--username", developmentEnvironmentUserName) +// Custom reobf auto-mappings +configurations.configureEach { + dependencies.configureEach { dep -> + if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) { + if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") { + // https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971 + project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971") + } } } +} - serverIntellijRun { - args(arguments) - jvmArgs(jvmArguments) +// Ensure tests have access to minecraft classes +sourceSets { + test { + java { + compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output + runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output + } } } @@ -316,24 +414,66 @@ if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// Allow unsafe repos but warn +repositories.configureEach { repo -> + if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { + if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) { + logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'") + repo.allowInsecureProtocol = true + } + } +} + apply from: 'repositories.gradle' configurations { - implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored - implementation.extendsFrom(shadowCompile) - implementation.extendsFrom(shadeCompile) + for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { + config.extendsFrom(runtimeOnlyNonPublishable) + if (usesShadowedDependencies.toBoolean()) { + config.extendsFrom(shadowImplementation) + // TODO: remove Compile after all uses are refactored to Implementation + config.extendsFrom(shadeCompile) + config.extendsFrom(shadowCompile) + } + } + // A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api" + create("compile") { + description = "Deprecated: use api or implementation instead, gets put in api" + canBeConsumed = false + canBeResolved = false + visible = false + } + create("testCompile") { + description = "Deprecated: use testImplementation instead" + canBeConsumed = false + canBeResolved = false + visible = false + } + api.extendsFrom(compile) + testImplementation.extendsFrom(testCompile) +} + +afterEvaluate { + if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) { + logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`") + logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle") + } } repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' + mavenContent { + excludeGroup("net.minecraftforge") // missing the `universal` artefact + } + } + maven { + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true } if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - } if (usesMixinDebug.toBoolean()) { maven { name = "Fabric Maven" @@ -341,6 +481,35 @@ repositories { } } } + if (includeWellKnownRepositories.toBoolean()) { + maven { + name "CurseMaven" + url "https://cursemaven.com" + content { + includeGroup "curse.maven" + } + } + maven { + name = "ic2" + url = "https://maven.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + name = "ic2-mirror" + url = "https://maven2.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + name "MMD Maven" + url "https://maven.mcmoddev.com/" + } + } } dependencies { @@ -348,30 +517,42 @@ dependencies { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') annotationProcessor('com.google.guava:guava:24.1.1-jre') annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.3:processor') + annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.10:processor') if (usesMixinDebug.toBoolean()) { - runtimeOnly('org.jetbrains:intellij-fernflower:1.2.1.16') + runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') } } if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - compile('com.gtnewhorizon:gtnhmixins:2.1.3') + implementation('com.gtnewhorizon:gtnhmixins:2.1.10') + } +} + +pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { + if (usesMixins.toBoolean()) { + dependencies { + kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + } } } apply from: 'dependencies.gradle' def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' -def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap -def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" - -task generateAssets { - if (usesMixins.toBoolean()) { +def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' +def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap +def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" + +tasks.register('generateAssets') { + group = "GTNH Buildscript" + description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" + onlyIf { usesMixins.toBoolean() } + doLast { def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") if (!mixinConfigFile.exists()) { def mixinPluginLine = "" - if(!mixinPlugin.isEmpty()) { + if (!mixinPlugin.isEmpty()) { // We might not have a mixin plugin if we're using early/late mixins - mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ + mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ } mixinConfigFile.text = """{ @@ -390,105 +571,58 @@ task generateAssets { } } -task relocateShadowJar(type: ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" -} - -shadowJar { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' - } +if (usesMixins.toBoolean()) { + tasks.named("reobfJar", ReobfuscatedJar).configure { + extraSrgFiles.from(mixinSrg) } - manifest { - attributes(getManifestAttributes()) + tasks.named("processResources").configure { + dependsOn("generateAssets") } - minimize() // This will only allow shading for actually used classes - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile - ] - dependsOn(relocateShadowJar) -} - -jar { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' + tasks.named("compileJava", JavaCompile).configure { + doFirst { + new File(mixinTmpDir).mkdirs() } + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" + ] } - manifest { - attributes(getManifestAttributes()) - } - - if (usesShadowedDependencies.toBoolean()) { - dependsOn(shadowJar) - enabled = false - } -} - -reobf { - if (usesMixins.toBoolean()) { - addExtraSrgFile mixinSrg - } -} - -afterEvaluate { - if (usesMixins.toBoolean()) { - tasks.compileJava { - options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobf.srg}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", - // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code - "-XDenableSunApiLintControl", - "-XDignore.symbol.file" - ] + pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { + kapt { + correctErrorTypes = true + javacOptions { + option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") + option("-AoutSrgFile=$mixinSrg") + option("-AoutRefMapFile=$refMap") + } + } + tasks.configureEach { task -> + if (task.name == "kaptKotlin") { + task.doFirst { + new File(mixinTmpDir).mkdirs() + } + } } - } -} - -runClient { - if (developmentEnvironmentUserName) { - arguments += [ - "--username", - developmentEnvironmentUserName - ] } - args(arguments) - jvmArgs(jvmArguments) } -runServer { - args(arguments) - jvmArgs(jvmArguments) -} - -tasks.withType(JavaExec).configureEach { - javaLauncher.set( - javaToolchains.launcherFor { - languageVersion = projectJavaVersion - } - ) -} - -processResources { +tasks.named("processResources", ProcessResources).configure { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version + inputs.property "mcversion", project.minecraft.mcVersion exclude("spotless.gradle") - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - - // replace modVersion and minecraftVersion - expand "minecraftVersion": project.minecraft.version, + // replace stuff in mcmod.info, nothing else. replaces ${key} with value in text + filesMatching("mcmod.info") { + expand "minecraftVersion": project.minecraft.mcVersion, "modVersion": modVersion, "modId": modId, "modName": modName @@ -497,12 +631,6 @@ processResources { if (usesMixins.toBoolean()) { from refMap } - - // copy everything else that's not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - exclude 'spotless.gradle' - } } def getManifestAttributes() { @@ -529,65 +657,71 @@ def getManifestAttributes() { return manifestAttributes } -task sourcesJar(type: Jar) { - from(sourceSets.main.allSource) - from(file("$projectDir/LICENSE")) - getArchiveClassifier().set('sources') -} - -task shadowDevJar(type: ShadowJar) { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' - } - } - - from sourceSets.main.output - getArchiveClassifier().set("dev") - +tasks.named("jar", Jar).configure { manifest { attributes(getManifestAttributes()) } - - minimize() // This will only allow shading for actually used classes - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile - ] -} - -task relocateShadowDevJar(type: ConfigureShadowRelocation) { - target = tasks.shadowDevJar - prefix = modGroup + ".shadow" } -task circularResolverJar(type: Jar) { - dependsOn(relocateShadowDevJar) - dependsOn(shadowDevJar) - enabled = false -} +if (usesShadowedDependencies.toBoolean()) { + tasks.register('relocateShadowJar', ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" + enabled = minimizeShadowedDependencies.toBoolean() + } + tasks.named("shadowJar", ShadowJar).configure { + manifest { + attributes(getManifestAttributes()) + } -task devJar(type: Jar) { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' + if (minimizeShadowedDependencies.toBoolean()) { + minimize() // This will only allow shading for actually used classes + } + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile, + project.configurations.shadeCompile + ] + archiveClassifier.set('dev') + if (minimizeShadowedDependencies.toBoolean()) { + dependsOn(relocateShadowJar) } } - - from sourceSets.main.output - getArchiveClassifier().set("dev") - - manifest { - attributes(getManifestAttributes()) + configurations.runtimeElements.outgoing.artifacts.clear() + configurations.apiElements.outgoing.artifacts.clear() + configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) + configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) + tasks.named("jar", Jar) { + enabled = false + finalizedBy(tasks.shadowJar) + } + tasks.named("reobfJar", ReobfuscatedJar) { + inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) } + AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") + javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { + skip() + } + for (runTask in ["runClient", "runServer"]) { + tasks.named(runTask).configure { + dependsOn("shadowJar") + } + } +} +ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar +ext.publishableObfJar = tasks.reobfJar - if (usesShadowedDependencies.toBoolean()) { - dependsOn(circularResolverJar) - enabled = false +tasks.named('extractForgeUserdev', Copy).configure { efu -> + doLast { + // Fix CoFH-repackaged CCL not finding mappings + project.copy { + from(mcpTasks.userdevDir("conf")) + into(new File(project.buildDir, "unpacked/conf")) + } } } -task apiJar(type: Jar) { +tasks.register('apiJar', Jar) { from(sourceSets.main.allSource) { include modGroupPath + "/" + apiPackagePath + '/**' } @@ -605,18 +739,78 @@ task apiJar(type: Jar) { artifacts { if (!noPublishedSources) { - archives sourcesJar + archives tasks.named("sourcesJar") } - archives devJar if (apiPackage) { - archives apiJar + archives tasks.named("apiJar") } } -// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), -// and isn't strictly needed with the POM so just disable it. -tasks.withType(GenerateModuleMetadata) { - enabled = false +idea { + module { + downloadJavadoc = true + downloadSources = true + } + project { + settings { + runConfigurations { + "1. Run Client"(Gradle) { + taskNames = ["runClient"] + } + "2. Run Server"(Gradle) { + taskNames = ["runServer"] + } + "3. Run Obfuscated Client"(Gradle) { + taskNames = ["runObfClient"] + } + "4. Run Obfuscated Server"(Gradle) { + taskNames = ["runObfServer"] + } + if (!disableSpotless) { + "5. Apply spotless"(Gradle) { + taskNames = ["spotlessApply"] + } + } + def coreModArgs = "" + if (coreModClass) { + coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"' + } + "Run Client (IJ Native)"(Application) { + mainClass = "GradleStart" + moduleName = project.name + ".main" + afterEvaluate { + workingDirectory = tasks.runClient.workingDir.absolutePath + programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') + jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + + ' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + + coreModArgs + } + } + "Run Server (IJ Native)"(Application) { + mainClass = "GradleStartServer" + moduleName = project.name + ".main" + afterEvaluate { + workingDirectory = tasks.runServer.workingDir.absolutePath + programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') + jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + + ' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + + coreModArgs + } + } + } + compiler.javac { + afterEvaluate { + moduleJavacAdditionalOptions = [ + (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') + ] + } + } + } + } +} + +tasks.named("processIdeaSettings").configure { + dependsOn("injectTags") } // workaround variable hiding in pom processing @@ -624,51 +818,24 @@ def projectConfigs = project.configurations publishing { publications { - maven(MavenPublication) { + create("maven", MavenPublication) { from components.java - if (usesShadowedDependencies.toBoolean()) { - artifact source: shadowJar, classifier: "" - } - if (!noPublishedSources) { - artifact source: sourcesJar, classifier: "sources" - } - artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" + if (apiPackage) { - artifact source: apiJar, classifier: "api" + artifact apiJar } groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - - // remove extra garbage from minecraft and minecraftDeps configuration - pom.withXml { - def badArtifacts = [:].withDefault { [] as Set } - for (configuration in [ - projectConfigs.minecraft, - projectConfigs.minecraftDeps - ]) { - for (dependency in configuration.allDependencies) { - badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name - } - } - // example for specifying extra stuff to ignore - // badArtifacts["org.example.group"] += "artifactName" - - Node pomNode = asNode() - pomNode.dependencies.'*'.findAll() { - badArtifacts[it.groupId.text()].contains(it.artifactId.text()) - }.each() { - it.parent().remove(it) - } - } } } repositories { maven { url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" + allowInsecureProtocol = true credentials { username = System.getenv("MAVEN_USER") ?: "NONE" password = System.getenv("MAVEN_PASSWORD") ?: "NONE" @@ -688,7 +855,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { versionNumber = identifiedVersion versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" - uploadFile = jar + uploadFile = publishableObfJar additionalFiles = getSecondaryArtifacts() gameVersions = [minecraftVersion] loaders = ["forge"] @@ -729,7 +896,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" addGameVersion minecraftVersion addGameVersion "Forge" - mainArtifact jar + mainArtifact publishableObfJar for (artifact in getSecondaryArtifacts()) addArtifact artifact } @@ -757,7 +924,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null tasks.publish.dependsOn(tasks.curseforge) } -def addModrinthDep(scope, type, name) { +def addModrinthDep(String scope, String type, String name) { com.modrinth.minotaur.dependencies.Dependency dep; if (!(scope in ["required", "optional", "incompatible", "embedded"])) { throw new Exception("Invalid modrinth dependency scope: " + scope) @@ -775,7 +942,7 @@ def addModrinthDep(scope, type, name) { project.modrinth.dependencies.add(dep) } -def addCurseForgeRelation(type, name) { +def addCurseForgeRelation(String type, String name) { if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { throw new Exception("Invalid CurseForge relation type: " + type) } @@ -785,17 +952,20 @@ def addCurseForgeRelation(type, name) { } // Updating -task updateBuildScript { +tasks.register('updateBuildScript') { + group = 'GTNH Buildscript' + description = 'Updates the build script to the latest version' + doLast { - if (performBuildScriptUpdate(projectDir.toString())) return + if (performBuildScriptUpdate()) return print("Build script already up-to-date!") } } -if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) { +if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) { if (autoUpdateBuildScript.toBoolean()) { - performBuildScriptUpdate(projectDir.toString()) + performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") } @@ -838,10 +1008,11 @@ boolean verifySettingsGradle() { return false } -boolean performBuildScriptUpdate(String projectDir) { - if (isNewBuildScriptVersionAvailable(projectDir)) { +boolean performBuildScriptUpdate() { + if (isNewBuildScriptVersionAvailable()) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } + def out = services.get(StyledTextOutputFactory).create('buildscript-update-output') out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -852,7 +1023,7 @@ boolean performBuildScriptUpdate(String projectDir) { return false } -boolean isNewBuildScriptVersionAvailable(String projectDir) { +boolean isNewBuildScriptVersionAvailable() { Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] String currentBuildScript = getFile("build.gradle").getText() @@ -872,15 +1043,12 @@ static String getVersionHash(String buildScriptContent) { return "" } -configure(updateBuildScript) { - group = 'forgegradle' - description = 'Updates the build script to the latest version' -} - // Parameter Deobfuscation -task deobfParams { - doLast { +tasks.register('deobfParams') { + group = 'GTNH Buildscript' + description = 'Rename all obfuscated parameter names inherited from Minecraft classes' + doLast { // TODO String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" @@ -894,7 +1062,10 @@ task deobfParams { if (!file(paramsCSV).exists()) { println("Extracting MCP archive ...") - unzip(mcpZIP, mcpDir) + copy { + from(zipTree(mcpZIP)) + into(mcpDir) + } } println("Parsing params.csv ...") @@ -937,42 +1108,6 @@ static int replaceParams(File file, Map params) { return 0 } -// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681) -static unzip(String zipFileName, String outputDir) { - byte[] buffer = new byte[16384] - ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName)) - ZipEntry zipEntry = zis.getNextEntry() - while (zipEntry != null) { - File newFile = new File(outputDir + File.separator, zipEntry.name) - if (zipEntry.isDirectory()) { - if (!newFile.isDirectory() && !newFile.mkdirs()) { - throw new IOException("Failed to create directory $newFile") - } - } else { - // fix for Windows-created archives - File parent = newFile.parentFile - if (!parent.isDirectory() && !parent.mkdirs()) { - throw new IOException("Failed to create directory $parent") - } - // write file content - FileOutputStream fos = new FileOutputStream(newFile) - int len = 0 - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len) - } - fos.close() - } - zipEntry = zis.getNextEntry() - } - zis.closeEntry() - zis.close() -} - -configure(deobfParams) { - group = 'forgegradle' - description = 'Rename all obfuscated parameter names inherited from Minecraft classes' -} - // Dependency Deobfuscation def deobf(String sourceURL) { @@ -999,11 +1134,29 @@ def deobf(String sourceURL) { hostName = String.join(".", parts) return deobf(sourceURL, "$hostName/$fileName") - } catch (Exception e) { + } catch (Exception ignored) { return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } } +def deobfMaven(String repoURL, String mavenDep) { + if (!repoURL.endsWith("/")) { + repoURL += "/" + } + String[] parts = mavenDep.split(":") + parts[0] = parts[0].replace('.', '/') + def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" + return deobf(jarURL) +} + +def deobfCurse(String curseDep) { + try { + return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") + } catch (Exception ignored) { + out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") + } +} + // The method above is to be preferred. Use this method if the filename is not at the end of the URL. def deobf(String sourceURL, String rawFileName) { String bon2Version = "2.5.1" @@ -1109,7 +1262,7 @@ def getFile(String relativePath) { def getSecondaryArtifacts() { // Because noPublishedSources from the beginning of the script is somehow not visible here... boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - def secondaryArtifacts = [devJar] + def secondaryArtifacts = [publishableDevJar] if (!noPublishedSources) secondaryArtifacts += [sourcesJar] if (apiPackage) secondaryArtifacts += [apiJar] return secondaryArtifacts diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 42198 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%0Dx9&DJ+=*NrOLFNd~jpXIl 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 OOi;9)pb#jaQ2zt%fx@f+ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ab0b72..f398c33 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acf..79a61d4 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # 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"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +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 - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || 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 @@ -105,84 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +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=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=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -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" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +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 - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + 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 - i=$((i+1)) + # 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 - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +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 -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# 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. +# -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +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 index 9618d8d..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,14 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +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" @@ -37,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :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 %CMD_LINE_ARGS% +"%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%"=="0" goto mainEnd +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! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +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 diff --git a/settings.gradle b/settings.gradle index 93c852a..01ea5f1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,28 @@ + +pluginManagement { + repositories { + maven { + // RetroFuturaGradle + name "GTNH Maven" + url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true + mavenContent { + includeGroup("com.gtnewhorizons.retrofuturagradle") + } + } + gradlePluginPortal() + mavenCentral() + mavenLocal() + } +} + plugins { id 'com.diffplug.blowdryerSetup' version '1.6.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' // Provides java toolchains } -apply plugin: 'com.diffplug.blowdryerSetup' - blowdryerSetup { - github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.5') + repoSubfolder 'gtnhShared' + github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0') //devLocal '.' // Use this when testing config updates locally } From a4515fbef8382f0f961ade90ca82c85d924fc06d Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 10:33:49 +0000 Subject: [PATCH 165/219] [ci skip] spotlessApply with the new settings --- .../java/codechicken/lib/asm/ASMBlock.java | 42 +-- .../java/codechicken/lib/asm/ASMHelper.java | 114 ++++--- .../java/codechicken/lib/asm/ASMInit.java | 1 + .../java/codechicken/lib/asm/ASMReader.java | 6 +- .../codechicken/lib/asm/CC_ClassWriter.java | 1 + .../lib/asm/ClassHeirachyManager.java | 22 +- .../lib/asm/ImportantInsnVisitor.java | 2 + .../codechicken/lib/asm/InsnComparator.java | 17 +- .../codechicken/lib/asm/InsnListSection.java | 57 ++-- .../lib/asm/LocalVariablesSorterVisitor.java | 2 + .../lib/asm/ModularASMTransformer.java | 19 +- .../java/codechicken/lib/asm/ObfMapping.java | 72 +++-- .../java/codechicken/lib/colour/Colour.java | 21 +- .../codechicken/lib/colour/ColourARGB.java | 1 + .../codechicken/lib/colour/ColourRGBA.java | 1 + .../lib/colour/CustomGradient.java | 7 +- .../codechicken/lib/config/ConfigFile.java | 3 +- .../codechicken/lib/config/ConfigTag.java | 14 +- .../lib/config/ConfigTagParent.java | 10 +- .../lib/config/DefaultingConfigFile.java | 1 + .../lib/config/SimpleProperties.java | 5 +- .../codechicken/lib/data/MCDataInput.java | 4 +- .../lib/data/MCDataInputStream.java | 1 + .../codechicken/lib/data/MCDataOutput.java | 4 +- .../lib/data/MCDataOutputStream.java | 1 + .../lib/data/MCDataOutputWrapper.java | 32 +- .../java/codechicken/lib/gui/Canvas9Seg.java | 10 +- .../java/codechicken/lib/gui/GuiDraw.java | 13 +- .../lib/inventory/ContainerExtended.java | 44 +-- .../lib/inventory/ContainerSynchronised.java | 13 +- .../lib/inventory/IContainerSyncVar.java | 1 + .../lib/inventory/IntegerSync.java | 1 + .../lib/inventory/InventoryCopy.java | 1 + .../lib/inventory/InventoryNBT.java | 1 + .../lib/inventory/InventoryRange.java | 1 + .../lib/inventory/InventorySimple.java | 1 + .../lib/inventory/InventoryUtils.java | 39 ++- .../codechicken/lib/inventory/ItemKey.java | 10 +- .../codechicken/lib/inventory/SlotDummy.java | 1 + .../lib/inventory/SlotDummyOutput.java | 1 + .../lib/inventory/SlotHandleClicks.java | 1 + .../java/codechicken/lib/lighting/LC.java | 1 + .../codechicken/lib/lighting/LightMatrix.java | 76 ++--- .../codechicken/lib/lighting/LightModel.java | 8 +- .../lib/lighting/PlanarLightMatrix.java | 10 +- .../lib/lighting/PlanarLightModel.java | 1 + .../lib/lighting/SimpleBrightnessModel.java | 10 +- .../java/codechicken/lib/math/MathHelper.java | 31 +- .../lib/packet/ICustomPacketTile.java | 1 + .../codechicken/lib/packet/PacketCustom.java | 105 ++++--- .../lib/raytracer/ExtendedMOP.java | 1 + .../lib/raytracer/IndexedCuboid6.java | 1 + .../codechicken/lib/raytracer/RayTracer.java | 35 ++- .../codechicken/lib/render/BlockRenderer.java | 30 +- .../java/codechicken/lib/render/CCModel.java | 202 ++++++------ .../lib/render/CCModelLibrary.java | 17 +- .../lib/render/CCRenderPipeline.java | 11 +- .../codechicken/lib/render/CCRenderState.java | 68 +++-- .../lib/render/ColourMultiplier.java | 1 + .../lib/render/EntityDigIconFX.java | 63 ++-- .../codechicken/lib/render/FontUtils.java | 4 +- .../codechicken/lib/render/IFaceRenderer.java | 1 + .../lib/render/ManagedTextureFX.java | 1 + .../lib/render/PlaceholderTexture.java | 1 + .../codechicken/lib/render/QBImporter.java | 123 ++++---- .../codechicken/lib/render/RenderUtils.java | 54 ++-- .../codechicken/lib/render/ShaderProgram.java | 2 + .../lib/render/SpriteSheetManager.java | 15 +- .../lib/render/TextureDataHolder.java | 1 + .../codechicken/lib/render/TextureFX.java | 4 +- .../lib/render/TextureSpecial.java | 15 +- .../codechicken/lib/render/TextureUtils.java | 44 ++- .../java/codechicken/lib/render/Vertex5.java | 24 +- .../lib/render/uv/IconTransformation.java | 4 +- .../render/uv/MultiIconTransformation.java | 4 +- .../java/codechicken/lib/render/uv/UV.java | 4 +- .../codechicken/lib/render/uv/UVRotation.java | 4 +- .../codechicken/lib/render/uv/UVScale.java | 1 + .../lib/render/uv/UVTransformation.java | 5 +- .../lib/render/uv/UVTransformationList.java | 4 +- .../lib/render/uv/UVTranslation.java | 4 +- .../codechicken/lib/tool/LibDownloader.java | 17 +- .../lib/tool/MCStripTransformer.java | 6 +- src/main/java/codechicken/lib/tool/Main.java | 3 +- .../lib/tool/StripClassLoader.java | 1 + .../java/codechicken/lib/tool/ToolMain.java | 24 +- .../lib/tool/module/JOptModule.java | 4 +- .../lib/tool/module/ModuleQBConverter.java | 13 +- .../java/codechicken/lib/util/Copyable.java | 1 + .../java/codechicken/lib/util/LangProxy.java | 1 + .../java/codechicken/lib/vec/AxisCycle.java | 66 ++-- .../java/codechicken/lib/vec/BlockCoord.java | 16 +- .../java/codechicken/lib/vec/Cuboid6.java | 23 +- .../java/codechicken/lib/vec/CuboidCoord.java | 14 +- .../codechicken/lib/vec/ITransformation.java | 14 +- .../IrreversibleTransformationException.java | 1 + src/main/java/codechicken/lib/vec/Line3.java | 9 +- .../java/codechicken/lib/vec/Matrix4.java | 93 +++--- src/main/java/codechicken/lib/vec/Quat.java | 16 +- .../java/codechicken/lib/vec/Rectangle4i.java | 1 + .../lib/vec/RedundantTransformation.java | 1 + .../java/codechicken/lib/vec/Rotation.java | 287 +++++++++--------- src/main/java/codechicken/lib/vec/Scale.java | 15 +- src/main/java/codechicken/lib/vec/SwapYZ.java | 1 + .../codechicken/lib/vec/Transformation.java | 3 + .../lib/vec/TransformationList.java | 24 +- .../java/codechicken/lib/vec/Translation.java | 15 +- .../lib/vec/VariableTransformation.java | 1 + .../java/codechicken/lib/vec/Vector3.java | 22 +- .../codechicken/lib/world/ChunkExtension.java | 2 + .../codechicken/lib/world/IChunkLoadTile.java | 10 +- .../lib/world/TileChunkLoadHook.java | 8 +- .../codechicken/lib/world/WorldExtension.java | 2 + .../lib/world/WorldExtensionInstantiator.java | 1 + .../lib/world/WorldExtensionManager.java | 29 +- 115 files changed, 1266 insertions(+), 1067 deletions(-) diff --git a/src/main/java/codechicken/lib/asm/ASMBlock.java b/src/main/java/codechicken/lib/asm/ASMBlock.java index 5ab61a9..eb71c9f 100644 --- a/src/main/java/codechicken/lib/asm/ASMBlock.java +++ b/src/main/java/codechicken/lib/asm/ASMBlock.java @@ -2,17 +2,20 @@ import static org.objectweb.asm.tree.AbstractInsnNode.*; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.ImmutableMap; import java.util.*; import java.util.Map.Entry; + import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableMap; + public class ASMBlock { + public InsnListSection list; private BiMap labels; @@ -44,22 +47,21 @@ public LabelNode get(String s) { } public void replaceLabels(Map labelMap, Set usedLabels) { - for (AbstractInsnNode insn : list) - switch (insn.getType()) { - case LABEL: - AbstractInsnNode insn2 = insn.clone(labelMap); - if (insn2 == insn) // identity mapping + for (AbstractInsnNode insn : list) switch (insn.getType()) { + case LABEL: + AbstractInsnNode insn2 = insn.clone(labelMap); + if (insn2 == insn) // identity mapping continue; - if (usedLabels.contains(insn2)) - throw new IllegalStateException("LabelNode cannot be a part of two InsnLists"); - list.replace(insn, insn2); - break; - case JUMP_INSN: - case FRAME: - case LOOKUPSWITCH_INSN: - case TABLESWITCH_INSN: - list.replace(insn, insn.clone(labelMap)); - } + if (usedLabels.contains(insn2)) + throw new IllegalStateException("LabelNode cannot be a part of two InsnLists"); + list.replace(insn, insn2); + break; + case JUMP_INSN: + case FRAME: + case LOOKUPSWITCH_INSN: + case TABLESWITCH_INSN: + list.replace(insn, insn.clone(labelMap)); + } for (Entry entry : labelMap.entrySet()) { String key = labels.inverse().get(entry.getKey()); @@ -78,6 +80,7 @@ public void replaceLabel(String s, LabelNode l) { /** * Pulls all common labels from other into this + * * @return this */ public ASMBlock mergeLabels(ASMBlock other) { @@ -99,6 +102,7 @@ public ASMBlock mergeLabels(ASMBlock other) { /** * Like mergeLabels but pulls insns from other list into this so LabelNodes can be transferred + * * @return this */ public ASMBlock pullLabels(ASMBlock other) { @@ -125,7 +129,7 @@ public ASMBlock applyLabels(InsnListSection list2) { HashMap labelMap = new HashMap(); - for (int i = 0, k = 0; i < list.size() && k < list2.size(); ) { + for (int i = 0, k = 0; i < list.size() && k < list2.size();) { AbstractInsnNode insn1 = list.get(i); if (!InsnComparator.insnImportant(insn1, cFlowLabels1)) { i++; diff --git a/src/main/java/codechicken/lib/asm/ASMHelper.java b/src/main/java/codechicken/lib/asm/ASMHelper.java index ce68788..8d76a3f 100644 --- a/src/main/java/codechicken/lib/asm/ASMHelper.java +++ b/src/main/java/codechicken/lib/asm/ASMHelper.java @@ -1,7 +1,5 @@ package codechicken.lib.asm; -import codechicken.lib.config.ConfigFile; -import codechicken.lib.config.DefaultingConfigFile; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -9,6 +7,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; @@ -19,16 +18,18 @@ import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceClassVisitor; +import codechicken.lib.config.ConfigFile; +import codechicken.lib.config.DefaultingConfigFile; + public class ASMHelper { + public static ConfigFile config = loadConfig(); public static Logger logger = LogManager.getLogger("CCL ASM"); private static ConfigFile loadConfig() { try { // weak reference for environments without FML - File mcDir = (File) ((Object[]) Class.forName("cpw.mods.fml.relauncher.FMLInjectionData") - .getMethod("data") - .invoke(null)) - [6]; + File mcDir = (File) ((Object[]) Class.forName("cpw.mods.fml.relauncher.FMLInjectionData").getMethod("data") + .invoke(null))[6]; File file = new File(mcDir, "config/CodeChickenLib.cfg"); if (ObfMapping.obfuscated) return new DefaultingConfigFile(file); else return new ConfigFile(file).setComment("CodeChickenLib development configuration file."); @@ -38,6 +39,7 @@ private static ConfigFile loadConfig() { } public static interface Acceptor { + public void accept(ClassVisitor cv) throws IOException; } @@ -80,27 +82,30 @@ public static InsnList cloneInsnList(Map labelMap, InsnLis return new InsnListSection(list).copy(labelMap).list; } - public static List cloneTryCatchBlocks( - Map labelMap, List tcblocks) { + public static List cloneTryCatchBlocks(Map labelMap, + List tcblocks) { ArrayList clone = new ArrayList(); - for (TryCatchBlockNode node : tcblocks) - clone.add(new TryCatchBlockNode( - labelMap.get(node.start), labelMap.get(node.end), labelMap.get(node.handler), node.type)); + for (TryCatchBlockNode node : tcblocks) clone.add( + new TryCatchBlockNode( + labelMap.get(node.start), + labelMap.get(node.end), + labelMap.get(node.handler), + node.type)); return clone; } - public static List cloneLocals( - Map labelMap, List locals) { + public static List cloneLocals(Map labelMap, + List locals) { ArrayList clone = new ArrayList(locals.size()); - for (LocalVariableNode node : locals) - clone.add(new LocalVariableNode( - node.name, - node.desc, - node.signature, - labelMap.get(node.start), - labelMap.get(node.end), - node.index)); + for (LocalVariableNode node : locals) clone.add( + new LocalVariableNode( + node.name, + node.desc, + node.signature, + labelMap.get(node.start), + labelMap.get(node.end), + node.index)); return clone; } @@ -123,9 +128,8 @@ public static int getLocal(List list, String name) { int found = -1; for (LocalVariableNode node : list) { if (node.name.equals(name)) { - if (found >= 0) - throw new RuntimeException( - "Duplicate local variable: " + name + " not coded to handle this scenario."); + if (found >= 0) throw new RuntimeException( + "Duplicate local variable: " + name + " not coded to handle this scenario."); found = node.index; } @@ -140,8 +144,8 @@ public static void replaceMethod(MethodNode original, MethodNode replacement) { replacement.accept(original); } - public static void dump( - Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals, boolean textify) { + public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals, + boolean textify) { try { if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); if (!file.exists()) file.createNewFile(); @@ -158,50 +162,36 @@ public static void dump( } public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals) { - dump( - acceptor, - file, - filterImportant, - sortLocals, - config.getTag("textify").getBooleanValue(true)); + dump(acceptor, file, filterImportant, sortLocals, config.getTag("textify").getBooleanValue(true)); } public static void dump(final byte[] bytes, File file, boolean filterImportant, boolean sortLocals) { - dump( - new Acceptor() { - @Override - public void accept(ClassVisitor cv) { - new ClassReader(bytes).accept(cv, ClassReader.EXPAND_FRAMES); - } - }, - file, - filterImportant, - sortLocals); + dump(new Acceptor() { + + @Override + public void accept(ClassVisitor cv) { + new ClassReader(bytes).accept(cv, ClassReader.EXPAND_FRAMES); + } + }, file, filterImportant, sortLocals); } public static void dump(final InputStream is, File file, boolean filterImportant, boolean sortLocals) { - dump( - new Acceptor() { - @Override - public void accept(ClassVisitor cv) throws IOException { - new ClassReader(is).accept(cv, ClassReader.EXPAND_FRAMES); - } - }, - file, - filterImportant, - sortLocals); + dump(new Acceptor() { + + @Override + public void accept(ClassVisitor cv) throws IOException { + new ClassReader(is).accept(cv, ClassReader.EXPAND_FRAMES); + } + }, file, filterImportant, sortLocals); } public static void dump(final ClassNode cnode, File file, boolean filterImportant, boolean sortLocals) { - dump( - new Acceptor() { - @Override - public void accept(ClassVisitor cv) { - cnode.accept(cv); - } - }, - file, - filterImportant, - sortLocals); + dump(new Acceptor() { + + @Override + public void accept(ClassVisitor cv) { + cnode.accept(cv); + } + }, file, filterImportant, sortLocals); } } diff --git a/src/main/java/codechicken/lib/asm/ASMInit.java b/src/main/java/codechicken/lib/asm/ASMInit.java index a76db93..baa8a13 100644 --- a/src/main/java/codechicken/lib/asm/ASMInit.java +++ b/src/main/java/codechicken/lib/asm/ASMInit.java @@ -6,6 +6,7 @@ * Initialisation class for using this package. Call this on coremod load */ public class ASMInit { + private static boolean initialised = false; public static void init() { diff --git a/src/main/java/codechicken/lib/asm/ASMReader.java b/src/main/java/codechicken/lib/asm/ASMReader.java index f7e6343..dda47f2 100644 --- a/src/main/java/codechicken/lib/asm/ASMReader.java +++ b/src/main/java/codechicken/lib/asm/ASMReader.java @@ -8,9 +8,11 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.*; + import org.objectweb.asm.tree.*; public class ASMReader { + public static Map opCodes = new HashMap(); public static byte[] TYPE; @@ -235,9 +237,7 @@ public static Map loadResource(InputStream in, String res) { case METHOD_INSN: StringBuilder sb = new StringBuilder(); for (int i = 1; i < split.length; i++) sb.append(split[i]); - insn = ObfMapping.fromDesc(sb.toString()) - .toClassloading() - .toInsn(opcode); + insn = ObfMapping.fromDesc(sb.toString()).toClassloading().toInsn(opcode); break; case INVOKE_DYNAMIC_INSN: throw new Exception("Found INVOKEDYNAMIC while reading"); diff --git a/src/main/java/codechicken/lib/asm/CC_ClassWriter.java b/src/main/java/codechicken/lib/asm/CC_ClassWriter.java index 74c86d2..f3e0731 100644 --- a/src/main/java/codechicken/lib/asm/CC_ClassWriter.java +++ b/src/main/java/codechicken/lib/asm/CC_ClassWriter.java @@ -3,6 +3,7 @@ import org.objectweb.asm.ClassWriter; public class CC_ClassWriter extends ClassWriter { + private final boolean runtime; public CC_ClassWriter(int flags) { diff --git a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java index 837a65f..0566378 100644 --- a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java +++ b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java @@ -1,23 +1,29 @@ package codechicken.lib.asm; -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; + import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; + import org.objectweb.asm.tree.ClassNode; +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; + /** - * This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed evaluation up slightly by automatically caching superclasses when they are first loaded. + * This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed + * evaluation up slightly by automatically caching superclasses when they are first loaded. */ public class ClassHeirachyManager implements IClassTransformer { + static { ASMInit.init(); } public static class SuperCache { + String superclass; public HashSet parents = new HashSet(); private boolean flattened; @@ -51,9 +57,7 @@ public static String toKey(String name) { public static String unKey(String name) { if (ObfMapping.obfuscated) - name = FMLDeobfuscatingRemapper.INSTANCE - .unmap(name.replace('.', '/')) - .replace('/', '.'); + name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); return name; } @@ -70,7 +74,7 @@ public static boolean classExtends(String name, String superclass) { SuperCache cache = declareClass(name); if (cache == null) // just can't handle this - return false; + return false; cache.flatten(); return cache.parents.contains(superclass); @@ -85,15 +89,13 @@ private static SuperCache declareClass(String name) { try { byte[] bytes = cl.getClassBytes(unKey(name)); if (bytes != null) cache = declareASM(bytes); - } catch (Exception e) { - } + } catch (Exception e) {} if (cache != null) return cache; try { cache = declareReflection(name); - } catch (ClassNotFoundException e) { - } + } catch (ClassNotFoundException e) {} return cache; } diff --git a/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java b/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java index 9368bfc..c6b32ed 100644 --- a/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java +++ b/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java @@ -6,7 +6,9 @@ import org.objectweb.asm.tree.MethodNode; public class ImportantInsnVisitor extends ClassVisitor { + public class ImportantInsnMethodVisitor extends MethodVisitor { + MethodVisitor delegate; public ImportantInsnMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) { diff --git a/src/main/java/codechicken/lib/asm/InsnComparator.java b/src/main/java/codechicken/lib/asm/InsnComparator.java index 238651f..4a1c76d 100644 --- a/src/main/java/codechicken/lib/asm/InsnComparator.java +++ b/src/main/java/codechicken/lib/asm/InsnComparator.java @@ -2,12 +2,15 @@ import static org.objectweb.asm.tree.AbstractInsnNode.*; -import com.google.common.base.Function; -import com.google.common.collect.Maps; import java.util.*; + import org.objectweb.asm.tree.*; +import com.google.common.base.Function; +import com.google.common.collect.Maps; + public class InsnComparator { + public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2) { return insn1.var == -1 || insn2.var == -1 || insn1.var == insn2.var; } @@ -107,6 +110,7 @@ public static InsnListSection getImportantList(InsnListSection list) { Set controlFlowLabels = getControlFlowLabels(list); Map labelMap = Maps.asMap(controlFlowLabels, new Function() { + @Override public LabelNode apply(LabelNode input) { return input; @@ -138,8 +142,8 @@ public static List find(InsnList haystack, InsnListSection need return find(new InsnListSection(haystack), needle); } - public static InsnListSection matches( - InsnListSection haystack, InsnListSection needle, Set controlFlowLabels) { + public static InsnListSection matches(InsnListSection haystack, InsnListSection needle, + Set controlFlowLabels) { int h = 0, n = 0; for (; h < haystack.size() && n < needle.size(); h++) { AbstractInsnNode insn = haystack.get(h); @@ -155,9 +159,8 @@ public static InsnListSection matches( public static InsnListSection findOnce(InsnListSection haystack, InsnListSection needle) { List list = find(haystack, needle); - if (list.size() != 1) - throw new RuntimeException( - "Needle found " + list.size() + " times in Haystack:\n" + haystack + "\n\n" + needle); + if (list.size() != 1) throw new RuntimeException( + "Needle found " + list.size() + " times in Haystack:\n" + haystack + "\n\n" + needle); return list.get(0); } diff --git a/src/main/java/codechicken/lib/asm/InsnListSection.java b/src/main/java/codechicken/lib/asm/InsnListSection.java index 23a456c..c71a359 100644 --- a/src/main/java/codechicken/lib/asm/InsnListSection.java +++ b/src/main/java/codechicken/lib/asm/InsnListSection.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; + import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.tree.*; import org.objectweb.asm.util.Textifier; @@ -18,7 +19,9 @@ * A section of an InsnList, may become invalid if the insn list is modified */ public class InsnListSection implements Iterable { + private class InsnListSectionIterator implements Iterator { + int i = 0; @Override @@ -143,6 +146,7 @@ public InsnListSection slice(int start, int end) { /** * Removes leading and trailing labels and line number nodes that don't affect control flow + * * @return this */ public InsnListSection trim(Set controlFlowLabels) { @@ -167,34 +171,31 @@ public void println() { public HashMap identityLabelMap() { HashMap labelMap = new HashMap(); - for (AbstractInsnNode insn : this) - switch (insn.getType()) { - case LABEL: - labelMap.put((LabelNode) insn, (LabelNode) insn); - break; - case JUMP_INSN: - labelMap.put(((JumpInsnNode) insn).label, ((JumpInsnNode) insn).label); - break; - case LOOKUPSWITCH_INSN: - LookupSwitchInsnNode linsn = (LookupSwitchInsnNode) insn; - labelMap.put(linsn.dflt, linsn.dflt); - for (LabelNode label : linsn.labels) labelMap.put(label, label); - break; - case TABLESWITCH_INSN: - TableSwitchInsnNode tinsn = (TableSwitchInsnNode) insn; - labelMap.put(tinsn.dflt, tinsn.dflt); - for (LabelNode label : tinsn.labels) labelMap.put(label, label); - break; - case FRAME: - FrameNode fnode = (FrameNode) insn; - if (fnode.local != null) - for (Object o : fnode.local) - if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o); - if (fnode.stack != null) - for (Object o : fnode.stack) - if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o); - break; - } + for (AbstractInsnNode insn : this) switch (insn.getType()) { + case LABEL: + labelMap.put((LabelNode) insn, (LabelNode) insn); + break; + case JUMP_INSN: + labelMap.put(((JumpInsnNode) insn).label, ((JumpInsnNode) insn).label); + break; + case LOOKUPSWITCH_INSN: + LookupSwitchInsnNode linsn = (LookupSwitchInsnNode) insn; + labelMap.put(linsn.dflt, linsn.dflt); + for (LabelNode label : linsn.labels) labelMap.put(label, label); + break; + case TABLESWITCH_INSN: + TableSwitchInsnNode tinsn = (TableSwitchInsnNode) insn; + labelMap.put(tinsn.dflt, tinsn.dflt); + for (LabelNode label : tinsn.labels) labelMap.put(label, label); + break; + case FRAME: + FrameNode fnode = (FrameNode) insn; + if (fnode.local != null) + for (Object o : fnode.local) if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o); + if (fnode.stack != null) + for (Object o : fnode.stack) if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o); + break; + } return labelMap; } diff --git a/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java b/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java index dfd6ed9..0157384 100644 --- a/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java +++ b/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java @@ -1,12 +1,14 @@ package codechicken.lib.asm; import java.util.Set; + import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.LocalVariablesSorter; public class LocalVariablesSorterVisitor extends ClassVisitor { + public Set methods; public String owner; diff --git a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java index 7628f9e..c1998c3 100644 --- a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java +++ b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java @@ -4,13 +4,16 @@ import java.io.File; import java.util.*; + import org.objectweb.asm.*; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodNode; public class ModularASMTransformer { + public static class ClassNodeTransformerList { + List transformers = new LinkedList(); HashSet methodsToSort = new HashSet(); @@ -45,6 +48,7 @@ public byte[] transform(byte[] bytes) { } public abstract static class ClassNodeTransformer { + public int writeFlags; public ClassNodeTransformer(int writeFlags) { @@ -63,6 +67,7 @@ public void addMethodsToSort(Set set) {} } public abstract static class MethodTransformer extends ClassNodeTransformer { + public final ObfMapping method; public MethodTransformer(ObfMapping method) { @@ -90,6 +95,7 @@ public void transform(ClassNode cnode) { } public static class MethodWriter extends ClassNodeTransformer { + public final int access; public final ObfMapping method; public final String[] exceptions; @@ -148,6 +154,7 @@ public void write(MethodNode mv) { } public static class MethodInjector extends MethodTransformer { + public ASMBlock needle; public ASMBlock injection; public boolean before; @@ -184,8 +191,14 @@ public void transform(MethodNode mv) { else mv.instructions.add(injection.rawListCopy()); } else { for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) { - logger.debug("Injecting " + (before ? "before" : "after") + " method " + method + " @ " + key.start - + " - " + key.end); + logger.debug( + "Injecting " + (before ? "before" : "after") + + " method " + + method + + " @ " + + key.start + + " - " + + key.end); ASMBlock injectBlock = injection.copy().mergeLabels(needle.applyLabels(key)); if (before) key.insertBefore(injectBlock.list.list); @@ -196,6 +209,7 @@ public void transform(MethodNode mv) { } public static class MethodReplacer extends MethodTransformer { + public ASMBlock needle; public ASMBlock replacement; @@ -225,6 +239,7 @@ public void transform(MethodNode mv) { } public static class FieldWriter extends ClassNodeTransformer { + public final ObfMapping field; public final int access; public final Object value; diff --git a/src/main/java/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java index d7fea04..355ade8 100644 --- a/src/main/java/codechicken/lib/asm/ObfMapping.java +++ b/src/main/java/codechicken/lib/asm/ObfMapping.java @@ -1,29 +1,37 @@ package codechicken.lib.asm; -import codechicken.lib.config.ConfigTag; -import com.google.common.base.Charsets; -import com.google.common.base.Objects; -import com.google.common.io.LineProcessor; -import com.google.common.io.Resources; -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; -import cpw.mods.fml.relauncher.FMLInjectionData; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; + import javax.swing.*; + import net.minecraft.launchwrapper.Launch; import net.minecraftforge.common.ForgeVersion; + import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.*; +import codechicken.lib.config.ConfigTag; + +import com.google.common.base.Charsets; +import com.google.common.base.Objects; +import com.google.common.io.LineProcessor; +import com.google.common.io.Resources; + +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +import cpw.mods.fml.relauncher.FMLInjectionData; + public class ObfMapping { + public static class ObfRemapper extends Remapper { + private HashMap fields = new HashMap(); private HashMap funcs = new HashMap(); @@ -33,27 +41,20 @@ public ObfRemapper() { Field rawMethodMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawMethodMaps"); rawFieldMapsField.setAccessible(true); rawMethodMapsField.setAccessible(true); - Map> rawFieldMaps = - (Map>) rawFieldMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); - Map> rawMethodMaps = - (Map>) rawMethodMapsField.get(FMLDeobfuscatingRemapper.INSTANCE); + Map> rawFieldMaps = (Map>) rawFieldMapsField + .get(FMLDeobfuscatingRemapper.INSTANCE); + Map> rawMethodMaps = (Map>) rawMethodMapsField + .get(FMLDeobfuscatingRemapper.INSTANCE); - if (rawFieldMaps == null) - throw new IllegalStateException( - "codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); + if (rawFieldMaps == null) throw new IllegalStateException( + "codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage"); for (Map map : rawFieldMaps.values()) - for (Entry entry : map.entrySet()) - if (entry.getValue().startsWith("field")) - fields.put( - entry.getValue(), - entry.getKey().substring(0, entry.getKey().indexOf(':'))); + for (Entry entry : map.entrySet()) if (entry.getValue().startsWith("field")) + fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':'))); for (Map map : rawMethodMaps.values()) - for (Entry entry : map.entrySet()) - if (entry.getValue().startsWith("func")) - funcs.put( - entry.getValue(), - entry.getKey().substring(0, entry.getKey().indexOf('('))); + for (Entry entry : map.entrySet()) if (entry.getValue().startsWith("func")) + funcs.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf('('))); } catch (Exception e) { throw new RuntimeException(e); @@ -87,9 +88,9 @@ public boolean isObf(String typeName) { } public static class MCPRemapper extends Remapper implements LineProcessor { + public static File[] getConfFiles() { - ConfigTag tag = ASMHelper.config - .getTag("mappingDir") + ConfigTag tag = ASMHelper.config.getTag("mappingDir") .setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping"); for (int i = 0; i < DIR_GUESSES + DIR_ASKS; i++) { File dir = confDirectoryGuess(i, tag); @@ -125,13 +126,19 @@ public static File confDirectoryGuess(int i, ConfigTag tag) { case 3: return new File( System.getProperty("user.home"), - ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + "-" - + ForgeVersion.getVersion() + "/unpacked/conf"); + ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + + "-" + + ForgeVersion.getVersion() + + "/unpacked/conf"); case 4: return new File( System.getProperty("user.home"), - ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + "-" - + ForgeVersion.getVersion() + "-" + FMLInjectionData.data()[4] + "/unpacked/conf"); + ".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4] + + "-" + + ForgeVersion.getVersion() + + "-" + + FMLInjectionData.data()[4] + + "/unpacked/conf"); case 5: final String gradleCsvDir = System.getProperty("net.minecraftforge.gradle.GradleStart.csvDir"); return gradleCsvDir != null ? new File(gradleCsvDir) : null; @@ -160,7 +167,7 @@ public static File[] parseConfDir(File confDir) { File fields = new File(mapDir, "fields.csv"); if (!fields.exists()) throw new RuntimeException("Could not find fields.csv"); - return new File[] {srgs, methods, fields}; + return new File[] { srgs, methods, fields }; } private HashMap fields = new HashMap(); @@ -218,8 +225,7 @@ public static void loadMCPRemapper() { boolean obf = true; try { obf = Launch.classLoader.getClassBytes("net.minecraft.world.World") == null; - } catch (IOException ignored) { - } + } catch (IOException ignored) {} obfuscated = obf; if (!obf) loadMCPRemapper(); } diff --git a/src/main/java/codechicken/lib/colour/Colour.java b/src/main/java/codechicken/lib/colour/Colour.java index a50df3b..c73a5e8 100644 --- a/src/main/java/codechicken/lib/colour/Colour.java +++ b/src/main/java/codechicken/lib/colour/Colour.java @@ -1,16 +1,20 @@ package codechicken.lib.colour; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.lwjgl.opengl.GL11; + import codechicken.lib.config.ConfigTag.IConfigType; import codechicken.lib.math.MathHelper; import codechicken.lib.util.Copyable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.lwjgl.opengl.GL11; public abstract class Colour implements Copyable { + public static IConfigType configRGB = new IConfigType() { + @Override public String configValue(Colour entry) { String s = Long.toString(((long) entry.rgb()) << 32 >>> 32, 16); @@ -23,12 +27,11 @@ public String configValue(Colour entry) { @Override public Colour valueOf(String text) throws Exception { Matcher matcherRGB = patternRGB.matcher(text.replaceAll("\\s", "")); - if (matcherRGB.matches()) - return new ColourRGBA( - Integer.parseInt(matcherRGB.group(1)), - Integer.parseInt(matcherRGB.group(2)), - Integer.parseInt(matcherRGB.group(3)), - 0xFF); + if (matcherRGB.matches()) return new ColourRGBA( + Integer.parseInt(matcherRGB.group(1)), + Integer.parseInt(matcherRGB.group(2)), + Integer.parseInt(matcherRGB.group(3)), + 0xFF); int hex = (int) Long.parseLong(text.replace("0x", ""), 16); return new ColourRGBA(hex << 8 | 0xFF); diff --git a/src/main/java/codechicken/lib/colour/ColourARGB.java b/src/main/java/codechicken/lib/colour/ColourARGB.java index 765c31a..56483de 100644 --- a/src/main/java/codechicken/lib/colour/ColourARGB.java +++ b/src/main/java/codechicken/lib/colour/ColourARGB.java @@ -1,6 +1,7 @@ package codechicken.lib.colour; public class ColourARGB extends Colour { + public ColourARGB(int colour) { super((colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF, (colour >> 24) & 0xFF); } diff --git a/src/main/java/codechicken/lib/colour/ColourRGBA.java b/src/main/java/codechicken/lib/colour/ColourRGBA.java index 85aeb6c..a5ff30c 100644 --- a/src/main/java/codechicken/lib/colour/ColourRGBA.java +++ b/src/main/java/codechicken/lib/colour/ColourRGBA.java @@ -1,6 +1,7 @@ package codechicken.lib.colour; public class ColourRGBA extends Colour { + public ColourRGBA(int colour) { super((colour >> 24) & 0xFF, (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF); } diff --git a/src/main/java/codechicken/lib/colour/CustomGradient.java b/src/main/java/codechicken/lib/colour/CustomGradient.java index 1d5ac1c..4f228c7 100644 --- a/src/main/java/codechicken/lib/colour/CustomGradient.java +++ b/src/main/java/codechicken/lib/colour/CustomGradient.java @@ -1,11 +1,14 @@ package codechicken.lib.colour; -import codechicken.lib.math.MathHelper; -import codechicken.lib.render.TextureUtils; import java.awt.image.BufferedImage; + import net.minecraft.util.ResourceLocation; +import codechicken.lib.math.MathHelper; +import codechicken.lib.render.TextureUtils; + public class CustomGradient { + public int[] gradient; public CustomGradient(ResourceLocation textureFile) { diff --git a/src/main/java/codechicken/lib/config/ConfigFile.java b/src/main/java/codechicken/lib/config/ConfigFile.java index ebab9fb..8a1cff5 100644 --- a/src/main/java/codechicken/lib/config/ConfigFile.java +++ b/src/main/java/codechicken/lib/config/ConfigFile.java @@ -3,7 +3,8 @@ import java.io.*; public class ConfigFile extends ConfigTagParent { - public static final byte[] crlf = new byte[] {0xD, 0xA}; + + public static final byte[] crlf = new byte[] { 0xD, 0xA }; public File file; private boolean loading; diff --git a/src/main/java/codechicken/lib/config/ConfigTag.java b/src/main/java/codechicken/lib/config/ConfigTag.java index a565428..29e8eb3 100644 --- a/src/main/java/codechicken/lib/config/ConfigTag.java +++ b/src/main/java/codechicken/lib/config/ConfigTag.java @@ -3,7 +3,9 @@ import java.io.PrintWriter; public class ConfigTag extends ConfigTagParent { + public interface IConfigType { + public String configValue(T entry); public T valueOf(String text) throws Exception; @@ -80,8 +82,7 @@ public int getIntValue() { public int getIntValue(int defaultValue) { try { if (value != null) return getIntValue(); - } catch (NumberFormatException ignored) { - } + } catch (NumberFormatException ignored) {} setIntValue(defaultValue); return defaultValue; @@ -98,8 +99,7 @@ public boolean getBooleanValue() { public boolean getBooleanValue(boolean defaultValue) { try { if (value != null) return getBooleanValue(); - } catch (NumberFormatException ignored) { - } + } catch (NumberFormatException ignored) {} setBooleanValue(defaultValue); return defaultValue; @@ -112,8 +112,7 @@ public int getHexValue() { public int getHexValue(int defaultValue) { try { if (value != null) return getHexValue(); - } catch (NumberFormatException ignored) { - } + } catch (NumberFormatException ignored) {} setHexValue(defaultValue); return defaultValue; @@ -130,8 +129,7 @@ public T get(IConfigType type) { public T get(IConfigType type, T defaultValue) { try { if (value != null) return get(type); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} set(type, defaultValue); return defaultValue; diff --git a/src/main/java/codechicken/lib/config/ConfigTagParent.java b/src/main/java/codechicken/lib/config/ConfigTagParent.java index 96ccfc9..3ce68fb 100644 --- a/src/main/java/codechicken/lib/config/ConfigTagParent.java +++ b/src/main/java/codechicken/lib/config/ConfigTagParent.java @@ -7,7 +7,9 @@ import java.util.Map.Entry; public abstract class ConfigTagParent { + public static class TagOrderComparator implements Comparator { + int sortMode; public TagOrderComparator(int sortMode) { @@ -40,8 +42,8 @@ private int compareInt(int a, int b) { */ public int sortMode = 0; /** - * The mode for determining when child tags should leave a blank line between them and the one above - * 0 = never, 1 = when braced, 2 = always + * The mode for determining when child tags should leave a blank line between them and the one above 0 = never, 1 = + * when braced, 2 = always */ public int newlinemode = 1; @@ -147,9 +149,7 @@ public void loadChildren(BufferedReader reader) { else comment = comment + "\n" + line.substring(1); } else if (line.contains("=")) { String qualifiedname = line.substring(0, line.indexOf("=")); - getTag(qualifiedname) - .onLoaded() - .setComment(comment) + getTag(qualifiedname).onLoaded().setComment(comment) .setValue(line.substring(line.indexOf("=") + 1)); comment = ""; bracequalifier = qualifiedname; diff --git a/src/main/java/codechicken/lib/config/DefaultingConfigFile.java b/src/main/java/codechicken/lib/config/DefaultingConfigFile.java index a8e1374..237b7e5 100644 --- a/src/main/java/codechicken/lib/config/DefaultingConfigFile.java +++ b/src/main/java/codechicken/lib/config/DefaultingConfigFile.java @@ -3,6 +3,7 @@ import java.io.File; public class DefaultingConfigFile extends ConfigFile { + public DefaultingConfigFile(File file) { super(); if (file.exists()) load(file); diff --git a/src/main/java/codechicken/lib/config/SimpleProperties.java b/src/main/java/codechicken/lib/config/SimpleProperties.java index 8e4e26d..36609fb 100644 --- a/src/main/java/codechicken/lib/config/SimpleProperties.java +++ b/src/main/java/codechicken/lib/config/SimpleProperties.java @@ -6,6 +6,7 @@ import java.util.Map.Entry; public class SimpleProperties { + public HashMap propertyMap = new HashMap(); public File propertyFile; public boolean saveOnChange = false; @@ -32,8 +33,8 @@ public void load() { loading = true; try { - BufferedReader reader = - new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile), encoding)); + BufferedReader reader = new BufferedReader( + new InputStreamReader(new FileInputStream(propertyFile), encoding)); while (true) { String read = reader.readLine(); if (read == null) break; diff --git a/src/main/java/codechicken/lib/data/MCDataInput.java b/src/main/java/codechicken/lib/data/MCDataInput.java index 1d5eb12..df31842 100644 --- a/src/main/java/codechicken/lib/data/MCDataInput.java +++ b/src/main/java/codechicken/lib/data/MCDataInput.java @@ -1,11 +1,13 @@ package codechicken.lib.data; -import codechicken.lib.vec.BlockCoord; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.vec.BlockCoord; + public interface MCDataInput { + public long readLong(); public int readInt(); diff --git a/src/main/java/codechicken/lib/data/MCDataInputStream.java b/src/main/java/codechicken/lib/data/MCDataInputStream.java index 5c53cab..210a36c 100644 --- a/src/main/java/codechicken/lib/data/MCDataInputStream.java +++ b/src/main/java/codechicken/lib/data/MCDataInputStream.java @@ -3,6 +3,7 @@ import java.io.InputStream; public class MCDataInputStream extends InputStream { + private MCDataInput in; public MCDataInputStream(MCDataInput in) { diff --git a/src/main/java/codechicken/lib/data/MCDataOutput.java b/src/main/java/codechicken/lib/data/MCDataOutput.java index 34de499..63f8b17 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutput.java +++ b/src/main/java/codechicken/lib/data/MCDataOutput.java @@ -1,11 +1,13 @@ package codechicken.lib.data; -import codechicken.lib.vec.BlockCoord; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.vec.BlockCoord; + public interface MCDataOutput { + public MCDataOutput writeLong(long l); public MCDataOutput writeInt(int i); diff --git a/src/main/java/codechicken/lib/data/MCDataOutputStream.java b/src/main/java/codechicken/lib/data/MCDataOutputStream.java index 1f425c6..ec9cfd8 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutputStream.java +++ b/src/main/java/codechicken/lib/data/MCDataOutputStream.java @@ -3,6 +3,7 @@ import java.io.OutputStream; public class MCDataOutputStream extends OutputStream { + private MCDataOutput out; public MCDataOutputStream(MCDataOutput out) { diff --git a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java index 41ebbe3..1cd252f 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java +++ b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java @@ -1,24 +1,28 @@ package codechicken.lib.data; -import codechicken.lib.vec.BlockCoord; -import com.google.common.base.Charsets; -import cpw.mods.fml.common.network.ByteBufUtils; import java.io.DataOutput; import java.io.IOException; + import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; + import org.apache.commons.lang3.Validate; +import codechicken.lib.vec.BlockCoord; + +import com.google.common.base.Charsets; +import cpw.mods.fml.common.network.ByteBufUtils; + public class MCDataOutputWrapper implements MCDataOutput { + /** - * Mimics ByteBufUtils - * Write an integer using variable length encoding. + * Mimics ByteBufUtils Write an integer using variable length encoding. * * @param to The buffer to write to - * @param i The integer to write + * @param i The integer to write */ public static void writeVarInt(DataOutput to, int i) throws IOException { while ((i & 0x80) != 0) { @@ -30,11 +34,10 @@ public static void writeVarInt(DataOutput to, int i) throws IOException { } /** - * Mimics ByteBufUtils - * Write an extended short using a short and a byte if necessary + * Mimics ByteBufUtils Write an extended short using a short and a byte if necessary * * @param to The buffer to write to - * @param s The short to write, less than 0x7FFFFF + * @param s The short to write, less than 0x7FFFFF */ public static void writeVarShort(DataOutput to, int s) throws IOException { int low = s & 0x7FFF; @@ -45,16 +48,17 @@ public static void writeVarShort(DataOutput to, int s) throws IOException { } /** - * Mimics ByteBufUtils - * Write a String with UTF8 byte encoding to the buffer. - * It is encoded as [] - * @param to the data output to write to + * Mimics ByteBufUtils Write a String with UTF8 byte encoding to the buffer. It is encoded as [] + * + * @param to the data output to write to * @param string The string to write */ public static void writeUTF8String(DataOutput to, String string) throws IOException { byte[] utf8Bytes = string.getBytes(Charsets.UTF_8); Validate.isTrue( - ByteBufUtils.varIntByteCount(utf8Bytes.length) < 3, "The string is too long for this encoding."); + ByteBufUtils.varIntByteCount(utf8Bytes.length) < 3, + "The string is too long for this encoding."); writeVarInt(to, utf8Bytes.length); to.write(utf8Bytes); } diff --git a/src/main/java/codechicken/lib/gui/Canvas9Seg.java b/src/main/java/codechicken/lib/gui/Canvas9Seg.java index 4a35ad6..4c16368 100644 --- a/src/main/java/codechicken/lib/gui/Canvas9Seg.java +++ b/src/main/java/codechicken/lib/gui/Canvas9Seg.java @@ -1,12 +1,14 @@ package codechicken.lib.gui; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; + import codechicken.lib.render.CCRenderState; import codechicken.lib.render.TextureDataHolder; import codechicken.lib.render.TextureUtils; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.util.ResourceLocation; public class Canvas9Seg { + public final ResourceLocation tex; public float[] seg_u = new float[4]; public float[] seg_v = new float[4]; @@ -65,8 +67,8 @@ public void draw(int x, int y, int w, int h) { CCRenderState.reset(); CCRenderState.startDrawing(); - int[] sw = new int[] {x, x + seg_w[0], x + w - seg_w[2], x + w}; - int[] sh = new int[] {y, y + seg_h[0], y + h - seg_h[2], y + h}; + int[] sw = new int[] { x, x + seg_w[0], x + w - seg_w[2], x + w }; + int[] sh = new int[] { y, y + seg_h[0], y + h - seg_h[2], y + h }; for (int seg = 0; seg < 9; seg++) drawSeg(sw, sh, seg); diff --git a/src/main/java/codechicken/lib/gui/GuiDraw.java b/src/main/java/codechicken/lib/gui/GuiDraw.java index a878d4b..96ef7e0 100644 --- a/src/main/java/codechicken/lib/gui/GuiDraw.java +++ b/src/main/java/codechicken/lib/gui/GuiDraw.java @@ -1,11 +1,10 @@ package codechicken.lib.gui; -import codechicken.lib.math.MathHelper; -import codechicken.lib.render.CCRenderState; import java.awt.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; @@ -13,12 +12,18 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; + import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import codechicken.lib.math.MathHelper; +import codechicken.lib.render.CCRenderState; + public class GuiDraw { + public static class GuiHook extends Gui { + public void setZLevel(float f) { zLevel = f; } @@ -135,6 +140,7 @@ public static void drawTip(int x, int y, String text) { private static List tipLineHandlers = new ArrayList(); public static interface ITooltipLineHandler { + public Dimension getSize(); public void draw(int x, int y); @@ -166,8 +172,7 @@ public static void drawMultilineTip(FontRenderer font, int x, int y, List list, List playerCrafters) { + public void sendContainerAndContentsToPlayer(Container container, List list, + List playerCrafters) { LinkedList largeStacks = new LinkedList(); for (int i = 0; i < list.size(); i++) { ItemStack stack = list.get(i); @@ -159,8 +164,7 @@ public boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boo Slot slot = (Slot) inventorySlots.get(slotIndex); ItemStack slotStack = slot.getStack(); - if (slotStack != null - && slotStack.getItem() == stack.getItem() + if (slotStack != null && slotStack.getItem() == stack.getItem() && (!stack.getHasSubtypes() || stack.getItemDamage() == slotStack.getItemDamage()) && ItemStack.areItemStackTagsEqual(stack, slotStack)) { int totalStackSize = slotStack.stackSize + stack.stackSize; @@ -211,7 +215,8 @@ public boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boo } /** - * Called when slotIndex is shift clicked on. Recommended implementation is to call mergeItemStack based on slotIndex + * Called when slotIndex is shift clicked on. Recommended implementation is to call mergeItemStack based on + * slotIndex * * @param stack The stack in the clicked slot * @return True if one or more items were moved from this slots into other slots @@ -225,9 +230,8 @@ protected void bindPlayerInventory(InventoryPlayer inventoryPlayer) { } protected void bindPlayerInventory(InventoryPlayer inventoryPlayer, int x, int y) { - for (int row = 0; row < 3; row++) - for (int col = 0; col < 9; col++) - addSlotToContainer(new Slot(inventoryPlayer, col + row * 9 + 9, x + col * 18, y + row * 18)); + for (int row = 0; row < 3; row++) for (int col = 0; col < 9; col++) + addSlotToContainer(new Slot(inventoryPlayer, col + row * 9 + 9, x + col * 18, y + row * 18)); for (int slot = 0; slot < 9; slot++) addSlotToContainer(new Slot(inventoryPlayer, slot, x + slot * 18, y + 58)); } @@ -241,15 +245,15 @@ public void sendContainerPacket(PacketCustom packet) { } /** - * @param type An identifying number for the packet type between 2 and 0x79 inclusive. 1 is reserved for synchronising networkIDs + * @param type An identifying number for the packet type between 2 and 0x79 inclusive. 1 is reserved for + * synchronising networkIDs * @return A packet on the CCL inventory channel that will be recieved by this container on the other network side */ public PacketCustom getPacket(int type) { if (netID == 0) LogManager.getLogger("CodeChickenLib").error("Tried to get packet for container with 0 network ID"); - if (type == 1) - throw new IllegalArgumentException( - "Packet type 1 is reserved for network synchronisation in ContainerExtended"); + if (type == 1) throw new IllegalArgumentException( + "Packet type 1 is reserved for network synchronisation in ContainerExtended"); return new PacketCustom(netChannel, type).writeInt(netID); } diff --git a/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java b/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java index 5213416..8439a3b 100644 --- a/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java +++ b/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java @@ -1,19 +1,22 @@ package codechicken.lib.inventory; -import codechicken.lib.packet.PacketCustom; import java.util.ArrayList; import java.util.Collections; import java.util.List; + import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; +import codechicken.lib.packet.PacketCustom; + public abstract class ContainerSynchronised extends ContainerExtended { + private ArrayList syncVars = new ArrayList(); /** - * Create a packet to be used to send a synced variable update. - * Calls getPacket. Can be overriden to add extra identifying data or change the type (default 2) + * Create a packet to be used to send a synced variable update. Calls getPacket. Can be overriden to add extra + * identifying data or change the type (default 2) */ public PacketCustom createSyncPacket() { return getPacket(2); @@ -36,8 +39,8 @@ public final void detectAndSendChanges() { } @Override - public void sendContainerAndContentsToPlayer( - Container container, List list, List playerCrafters) { + public void sendContainerAndContentsToPlayer(Container container, List list, + List playerCrafters) { super.sendContainerAndContentsToPlayer(container, list, playerCrafters); for (int i = 0; i < syncVars.size(); i++) { IContainerSyncVar var = syncVars.get(i); diff --git a/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java b/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java index f1fd61d..07b3e25 100644 --- a/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java +++ b/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java @@ -3,6 +3,7 @@ import codechicken.lib.packet.PacketCustom; public interface IContainerSyncVar { + public boolean changed(); public void reset(); diff --git a/src/main/java/codechicken/lib/inventory/IntegerSync.java b/src/main/java/codechicken/lib/inventory/IntegerSync.java index 56d62fc..9cde12e 100644 --- a/src/main/java/codechicken/lib/inventory/IntegerSync.java +++ b/src/main/java/codechicken/lib/inventory/IntegerSync.java @@ -3,6 +3,7 @@ import codechicken.lib.packet.PacketCustom; public abstract class IntegerSync implements IContainerSyncVar { + public int c_value; @Override diff --git a/src/main/java/codechicken/lib/inventory/InventoryCopy.java b/src/main/java/codechicken/lib/inventory/InventoryCopy.java index 237e9db..06e7b71 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryCopy.java +++ b/src/main/java/codechicken/lib/inventory/InventoryCopy.java @@ -8,6 +8,7 @@ * Creates a copy of an IInventory for extended simulation */ public class InventoryCopy implements IInventory { + public boolean[] accessible; public ItemStack[] items; public IInventory inv; diff --git a/src/main/java/codechicken/lib/inventory/InventoryNBT.java b/src/main/java/codechicken/lib/inventory/InventoryNBT.java index 1df5f0c..b721741 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryNBT.java +++ b/src/main/java/codechicken/lib/inventory/InventoryNBT.java @@ -9,6 +9,7 @@ * IInventory implementation which saves and loads from an NBT tag */ public class InventoryNBT implements IInventory { + protected ItemStack[] items; protected NBTTagCompound tag; diff --git a/src/main/java/codechicken/lib/inventory/InventoryRange.java b/src/main/java/codechicken/lib/inventory/InventoryRange.java index d5c74b8..dacb4f5 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryRange.java +++ b/src/main/java/codechicken/lib/inventory/InventoryRange.java @@ -8,6 +8,7 @@ * Inventory wrapper for unified ISided/IInventory access */ public class InventoryRange { + public IInventory inv; public int side; public ISidedInventory sidedInv; diff --git a/src/main/java/codechicken/lib/inventory/InventorySimple.java b/src/main/java/codechicken/lib/inventory/InventorySimple.java index 487e393..ffbd604 100644 --- a/src/main/java/codechicken/lib/inventory/InventorySimple.java +++ b/src/main/java/codechicken/lib/inventory/InventorySimple.java @@ -8,6 +8,7 @@ * Simple IInventory implementation with an array of items, name and maximum stack size */ public class InventorySimple implements IInventory { + public ItemStack[] items; public int limit; public String name; diff --git a/src/main/java/codechicken/lib/inventory/InventoryUtils.java b/src/main/java/codechicken/lib/inventory/InventoryUtils.java index 17ac44f..c9729e5 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryUtils.java +++ b/src/main/java/codechicken/lib/inventory/InventoryUtils.java @@ -1,7 +1,5 @@ package codechicken.lib.inventory; -import codechicken.lib.vec.Vector3; -import com.google.common.base.Objects; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; @@ -17,7 +15,12 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import codechicken.lib.vec.Vector3; + +import com.google.common.base.Objects; + public class InventoryUtils { + /** * Constructor for ItemStack with tag */ @@ -167,8 +170,7 @@ public static int fitStackInSlot(InventoryRange inv, int slot, ItemStack stack) ItemStack base = inv.inv.getStackInSlot(slot); if (!canStack(base, stack) || !inv.canInsertItem(slot, stack)) return 0; - int fit = base != null - ? incrStackSize(base, inv.inv.getInventoryStackLimit() - base.stackSize) + int fit = base != null ? incrStackSize(base, inv.inv.getInventoryStackLimit() - base.stackSize) : inv.inv.getInventoryStackLimit(); return Math.min(fit, stack.stackSize); } @@ -227,8 +229,7 @@ public static ItemStack getExtractableStack(IInventory inv, int slot) { public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { if (stack1 == null || stack2 == null) return stack1 == stack2; - return stack1.getItem() == stack2.getItem() - && stack1.getItemDamage() == stack2.getItemDamage() + return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() && stack1.stackSize == stack2.stackSize && Objects.equal(stack1.getTagCompound(), stack2.getTagCompound()); } @@ -244,36 +245,30 @@ public static IInventory getInventory(World world, int x, int y, int z) { return (IInventory) tile; } - public static final ForgeDirection[] chestSides = - new ForgeDirection[] {ForgeDirection.WEST, ForgeDirection.EAST, ForgeDirection.NORTH, ForgeDirection.SOUTH}; + public static final ForgeDirection[] chestSides = new ForgeDirection[] { ForgeDirection.WEST, ForgeDirection.EAST, + ForgeDirection.NORTH, ForgeDirection.SOUTH }; public static IInventory getChest(TileEntityChest chest) { for (ForgeDirection fside : chestSides) { if (chest.getWorldObj() - .getBlock( - chest.xCoord + fside.offsetX, - chest.yCoord + fside.offsetY, - chest.zCoord + fside.offsetZ) + .getBlock(chest.xCoord + fside.offsetX, chest.yCoord + fside.offsetY, chest.zCoord + fside.offsetZ) == chest.getBlockType()) return new InventoryLargeChest( "container.chestDouble", - (TileEntityChest) chest.getWorldObj() - .getTileEntity( - chest.xCoord + fside.offsetX, - chest.yCoord + fside.offsetY, - chest.zCoord + fside.offsetZ), + (TileEntityChest) chest.getWorldObj().getTileEntity( + chest.xCoord + fside.offsetX, + chest.yCoord + fside.offsetY, + chest.zCoord + fside.offsetZ), chest); } return chest; } public static boolean canStack(ItemStack stack1, ItemStack stack2) { - return stack1 == null - || stack2 == null + return stack1 == null || stack2 == null || (stack1.getItem() == stack2.getItem() - && (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) - && ItemStack.areItemStackTagsEqual(stack2, stack1)) - && stack1.isStackable(); + && (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) + && ItemStack.areItemStackTagsEqual(stack2, stack1)) && stack1.isStackable(); } /** diff --git a/src/main/java/codechicken/lib/inventory/ItemKey.java b/src/main/java/codechicken/lib/inventory/ItemKey.java index d4b7d7e..dd0881a 100644 --- a/src/main/java/codechicken/lib/inventory/ItemKey.java +++ b/src/main/java/codechicken/lib/inventory/ItemKey.java @@ -2,16 +2,18 @@ import static codechicken.lib.inventory.InventoryUtils.actualDamage; -import com.google.common.base.Objects; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.oredict.OreDictionary; +import com.google.common.base.Objects; + /** * Comparable ItemStack with a hashCode implementation. */ public class ItemKey implements Comparable { + public ItemStack stack; private int hashcode = 0; @@ -37,15 +39,13 @@ public boolean equals(Object obj) { if (!(obj instanceof ItemKey)) return false; ItemKey k = (ItemKey) obj; - return stack.getItem() == k.stack.getItem() - && actualDamage(stack) == actualDamage(k.stack) + return stack.getItem() == k.stack.getItem() && actualDamage(stack) == actualDamage(k.stack) && Objects.equal(stack.stackTagCompound, k.stack.stackTagCompound); } @Override public int hashCode() { - return hashcode != 0 - ? hashcode + return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(stack.getItem(), actualDamage(stack), stack.stackTagCompound)); } diff --git a/src/main/java/codechicken/lib/inventory/SlotDummy.java b/src/main/java/codechicken/lib/inventory/SlotDummy.java index a695e29..43f298a 100644 --- a/src/main/java/codechicken/lib/inventory/SlotDummy.java +++ b/src/main/java/codechicken/lib/inventory/SlotDummy.java @@ -5,6 +5,7 @@ import net.minecraft.item.ItemStack; public class SlotDummy extends SlotHandleClicks { + public final int stackLimit; public SlotDummy(IInventory inv, int slot, int x, int y) { diff --git a/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java b/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java index 9b5d7e8..07c77fe 100644 --- a/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java +++ b/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java @@ -5,6 +5,7 @@ import net.minecraft.item.ItemStack; public class SlotDummyOutput extends SlotHandleClicks { + public SlotDummyOutput(IInventory inv, int slot, int x, int y) { super(inv, slot, x, y); } diff --git a/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java b/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java index 9a4b7f6..50e5a70 100644 --- a/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java +++ b/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java @@ -6,6 +6,7 @@ import net.minecraft.item.ItemStack; public abstract class SlotHandleClicks extends Slot { + public SlotHandleClicks(IInventory inv, int slot, int x, int y) { super(inv, slot, x, y); } diff --git a/src/main/java/codechicken/lib/lighting/LC.java b/src/main/java/codechicken/lib/lighting/LC.java index 187d518..d7b8d28 100644 --- a/src/main/java/codechicken/lib/lighting/LC.java +++ b/src/main/java/codechicken/lib/lighting/LC.java @@ -6,6 +6,7 @@ import codechicken.lib.vec.Vector3; public class LC implements Copyable { + public int side; public float fa; public float fb; diff --git a/src/main/java/codechicken/lib/lighting/LightMatrix.java b/src/main/java/codechicken/lib/lighting/LightMatrix.java index 30012cd..59f2e7a 100644 --- a/src/main/java/codechicken/lib/lighting/LightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/LightMatrix.java @@ -1,16 +1,19 @@ package codechicken.lib.lighting; -import codechicken.lib.colour.ColourRGBA; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.vec.BlockCoord; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.world.IBlockAccess; +import codechicken.lib.colour.ColourRGBA; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.BlockCoord; + /** - * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> (x+1, y+1, z+1) + * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> + * (x+1, y+1, z+1) */ public class LightMatrix implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); public int computed = 0; @@ -27,55 +30,26 @@ public class LightMatrix implements CCRenderState.IVertexOperation { /** * The 9 positions in the sample array for each side, sides >= 6 are centered on sample 13 (the block itself) */ - public static final int[][] ssamplem = new int[][] { - {0, 1, 2, 3, 4, 5, 6, 7, 8}, - {18, 19, 20, 21, 22, 23, 24, 25, 26}, - {0, 9, 18, 1, 10, 19, 2, 11, 20}, - {6, 15, 24, 7, 16, 25, 8, 17, 26}, - {0, 3, 6, 9, 12, 15, 18, 21, 24}, - {2, 5, 8, 11, 14, 17, 20, 23, 26}, - {9, 10, 11, 12, 13, 14, 15, 16, 17}, - {9, 10, 11, 12, 13, 14, 15, 16, 17}, - {3, 12, 21, 4, 13, 22, 5, 14, 23}, - {3, 12, 21, 4, 13, 22, 5, 14, 23}, - {1, 4, 7, 10, 13, 16, 19, 22, 25}, - {1, 4, 7, 10, 13, 16, 19, 22, 25}, - {13, 13, 13, 13, 13, 13, 13, 13, 13} - }; + public static final int[][] ssamplem = new int[][] { { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, + { 18, 19, 20, 21, 22, 23, 24, 25, 26 }, { 0, 9, 18, 1, 10, 19, 2, 11, 20 }, + { 6, 15, 24, 7, 16, 25, 8, 17, 26 }, { 0, 3, 6, 9, 12, 15, 18, 21, 24 }, + { 2, 5, 8, 11, 14, 17, 20, 23, 26 }, { 9, 10, 11, 12, 13, 14, 15, 16, 17 }, + { 9, 10, 11, 12, 13, 14, 15, 16, 17 }, { 3, 12, 21, 4, 13, 22, 5, 14, 23 }, + { 3, 12, 21, 4, 13, 22, 5, 14, 23 }, { 1, 4, 7, 10, 13, 16, 19, 22, 25 }, + { 1, 4, 7, 10, 13, 16, 19, 22, 25 }, { 13, 13, 13, 13, 13, 13, 13, 13, 13 } }; public static final int[][] qsamplem = new int[][] { // the positions in the side sample array for each corner - {0, 1, 3, 4}, - {5, 1, 2, 4}, - {6, 7, 3, 4}, - {5, 7, 8, 4} - }; - public static final float[] sideao = new float[] { - 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, - 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, - 1F - }; - - /*static - { - int[][] os = new int[][]{ - {0,-1,0}, - {0, 1,0}, - {0,0,-1}, - {0,0, 1}, - {-1,0,0}, - { 1,0,0}}; - - for(int s = 0; s < 12; s++) - { - int[] d0 = s < 6 ? new int[]{os[s][0]+1, os[s][1]+1, os[s][2]+1} : new int[]{1, 1, 1}; - int[] d1 = os[((s&0xE)+3)%6]; - int[] d2 = os[((s&0xE)+5)%6]; - for(int a = -1; a <= 1; a++) - for(int b = -1; b <= 1; b++) - ssamplem[s][(a+1)*3+b+1] = (d0[1]+d1[1]*a+d2[1]*b)*9+(d0[2]+d1[2]*a+d2[2]*b)*3+(d0[0]+d1[0]*a+d2[0]*b); - } - System.out.println(Arrays.deepToString(ssamplem)); - }*/ + { 0, 1, 3, 4 }, { 5, 1, 2, 4 }, { 6, 7, 3, 4 }, { 5, 7, 8, 4 } }; + public static final float[] sideao = new float[] { 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, 0.5F, 1F, 0.8F, 0.8F, 0.6F, + 0.6F, 1F }; + + /* + * static { int[][] os = new int[][]{ {0,-1,0}, {0, 1,0}, {0,0,-1}, {0,0, 1}, {-1,0,0}, { 1,0,0}}; for(int s = 0; s + * < 12; s++) { int[] d0 = s < 6 ? new int[]{os[s][0]+1, os[s][1]+1, os[s][2]+1} : new int[]{1, 1, 1}; int[] d1 = + * os[((s&0xE)+3)%6]; int[] d2 = os[((s&0xE)+5)%6]; for(int a = -1; a <= 1; a++) for(int b = -1; b <= 1; b++) + * ssamplem[s][(a+1)*3+b+1] = (d0[1]+d1[1]*a+d2[1]*b)*9+(d0[2]+d1[2]*a+d2[2]*b)*3+(d0[0]+d1[0]*a+d2[0]*b); } + * System.out.println(Arrays.deepToString(ssamplem)); } + */ public void locate(IBlockAccess a, int x, int y, int z) { access = a; diff --git a/src/main/java/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java index 7867ff8..6134fe1 100644 --- a/src/main/java/codechicken/lib/lighting/LightModel.java +++ b/src/main/java/codechicken/lib/lighting/LightModel.java @@ -5,9 +5,11 @@ import codechicken.lib.vec.Vector3; public class LightModel implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); public static class Light { + public Vector3 ambient = new Vector3(); public Vector3 diffuse = new Vector3(); public Vector3 position; @@ -30,8 +32,7 @@ public Light setAmbient(Vector3 vec) { public static LightModel standardLightModel; static { - standardLightModel = new LightModel() - .setAmbient(new Vector3(0.4, 0.4, 0.4)) + standardLightModel = new LightModel().setAmbient(new Vector3(0.4, 0.4, 0.4)) .addLight(new Light(new Vector3(0.2, 1, -0.7)).setDiffuse(new Vector3(0.6, 0.6, 0.6))) .addLight(new Light(new Vector3(-0.2, 1, 0.7)).setDiffuse(new Vector3(0.6, 0.6, 0.6))); } @@ -71,8 +72,7 @@ public int apply(int colour, Vector3 normal) { if (n_colour.z > 1) n_colour.z = 1; n_colour.multiply((colour >>> 24) / 255D, (colour >> 16 & 0xFF) / 255D, (colour >> 8 & 0xFF) / 255D); - return (int) (n_colour.x * 255) << 24 - | (int) (n_colour.y * 255) << 16 + return (int) (n_colour.x * 255) << 24 | (int) (n_colour.y * 255) << 16 | (int) (n_colour.z * 255) << 8 | colour & 0xFF; } diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java index cbaed30..cbbcb17 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java @@ -1,11 +1,13 @@ package codechicken.lib.lighting; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.vec.BlockCoord; import net.minecraft.block.Block; import net.minecraft.world.IBlockAccess; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.BlockCoord; + public class PlanarLightMatrix extends PlanarLightModel { + public static final int operationIndex = CCRenderState.registerOperation(); public static PlanarLightMatrix instance = new PlanarLightMatrix(); @@ -29,8 +31,8 @@ public PlanarLightMatrix locate(IBlockAccess a, int x, int y, int z) { public int brightness(int side) { if ((sampled & 1 << side) == 0) { Block b = access.getBlock(pos.x, pos.y, pos.z); - brightness[side] = access.getLightBrightnessForSkyBlocks( - pos.x, pos.y, pos.z, b.getLightValue(access, pos.x, pos.y, pos.z)); + brightness[side] = access + .getLightBrightnessForSkyBlocks(pos.x, pos.y, pos.z, b.getLightValue(access, pos.x, pos.y, pos.z)); sampled |= 1 << side; } return brightness[side]; diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java index 645eb45..f745373 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java @@ -7,6 +7,7 @@ * Faster precomputed version of LightModel that only works for axis planar sides */ public class PlanarLightModel implements CCRenderState.IVertexOperation { + public static PlanarLightModel standardLightModel = LightModel.standardLightModel.reducePlanar(); public int[] colours; diff --git a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java index 5fa6fed..7158594 100644 --- a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java +++ b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java @@ -1,14 +1,16 @@ package codechicken.lib.lighting; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.vec.BlockCoord; import net.minecraft.block.Block; import net.minecraft.world.IBlockAccess; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.BlockCoord; + /** * Faster precomputed version of LightModel that only works for axis planar sides */ public class SimpleBrightnessModel implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); public static SimpleBrightnessModel instance = new SimpleBrightnessModel(); @@ -29,8 +31,8 @@ public int sample(int side) { if ((sampled & 1 << side) == 0) { c.set(pos).offset(side); Block block = access.getBlock(c.x, c.y, c.z); - samples[side] = - access.getLightBrightnessForSkyBlocks(c.x, c.y, c.z, block.getLightValue(access, c.x, c.y, c.z)); + samples[side] = access + .getLightBrightnessForSkyBlocks(c.x, c.y, c.z, block.getLightValue(access, c.x, c.y, c.z)); sampled |= 1 << side; } return samples[side]; diff --git a/src/main/java/codechicken/lib/math/MathHelper.java b/src/main/java/codechicken/lib/math/MathHelper.java index 331398d..94220a0 100644 --- a/src/main/java/codechicken/lib/math/MathHelper.java +++ b/src/main/java/codechicken/lib/math/MathHelper.java @@ -1,6 +1,7 @@ package codechicken.lib.math; public class MathHelper { + public static final double phi = 1.618033988749894; public static final double pi = Math.PI; public static final double todeg = 57.29577951308232; @@ -27,8 +28,8 @@ public static double cos(double d) { } /** - * @param a The value - * @param b The value to approach + * @param a The value + * @param b The value to approach * @param max The maximum step * @return the closed value to b no less than max from a */ @@ -37,8 +38,8 @@ public static float approachLinear(float a, float b, float max) { } /** - * @param a The value - * @param b The value to approach + * @param a The value + * @param b The value to approach * @param max The maximum step * @return the closed value to b no less than max from a */ @@ -67,8 +68,8 @@ public static double interpolate(double a, double b, double d) { } /** - * @param a The value - * @param b The value to approach + * @param a The value + * @param b The value to approach * @param ratio The ratio to reduce the difference by * @return a+(b-a)*ratio */ @@ -77,10 +78,10 @@ public static double approachExp(double a, double b, double ratio) { } /** - * @param a The value - * @param b The value to approach + * @param a The value + * @param b The value to approach * @param ratio The ratio to reduce the difference by - * @param cap The maximum amount to advance by + * @param cap The maximum amount to advance by * @return a+(b-a)*ratio */ public static double approachExp(double a, double b, double ratio, double cap) { @@ -90,11 +91,11 @@ public static double approachExp(double a, double b, double ratio, double cap) { } /** - * @param a The value - * @param b The value to approach + * @param a The value + * @param b The value to approach * @param ratio The ratio to reduce the difference by - * @param c The value to retreat from - * @param kick The difference when a == c + * @param c The value to retreat from + * @param kick The difference when a == c * @return */ public static double retreatExp(double a, double b, double c, double ratio, double kick) { @@ -106,8 +107,8 @@ public static double retreatExp(double a, double b, double c, double ratio, doub /** * * @param value The value - * @param min The min value - * @param max The max value + * @param min The min value + * @param max The max value * @return The clipped value between min and max */ public static double clip(double value, double min, double max) { diff --git a/src/main/java/codechicken/lib/packet/ICustomPacketTile.java b/src/main/java/codechicken/lib/packet/ICustomPacketTile.java index 9bf9e03..0758be7 100644 --- a/src/main/java/codechicken/lib/packet/ICustomPacketTile.java +++ b/src/main/java/codechicken/lib/packet/ICustomPacketTile.java @@ -1,5 +1,6 @@ package codechicken.lib.packet; public interface ICustomPacketTile { + public void handleDescriptionPacket(PacketCustom packet); } diff --git a/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java index c87920e..468e2fd 100644 --- a/src/main/java/codechicken/lib/packet/PacketCustom.java +++ b/src/main/java/codechicken/lib/packet/PacketCustom.java @@ -1,27 +1,10 @@ package codechicken.lib.packet; -import codechicken.lib.data.MCDataInput; -import codechicken.lib.data.MCDataOutput; -import codechicken.lib.vec.BlockCoord; -import com.google.common.collect.Maps; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.ModContainer; -import cpw.mods.fml.common.network.*; -import cpw.mods.fml.common.network.handshake.NetworkDispatcher; -import cpw.mods.fml.common.network.internal.FMLProxyPacket; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.util.AttributeKey; import java.util.EnumMap; import java.util.List; import java.util.zip.Deflater; import java.util.zip.Inflater; + import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -41,14 +24,39 @@ import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; +import codechicken.lib.data.MCDataInput; +import codechicken.lib.data.MCDataOutput; +import codechicken.lib.vec.BlockCoord; + +import com.google.common.collect.Maps; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.network.*; +import cpw.mods.fml.common.network.handshake.NetworkDispatcher; +import cpw.mods.fml.common.network.internal.FMLProxyPacket; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.util.AttributeKey; + public final class PacketCustom implements MCDataInput, MCDataOutput { - public static interface ICustomPacketHandler {} + + public static interface ICustomPacketHandler { + } public interface IClientPacketHandler extends ICustomPacketHandler { + public void handlePacket(PacketCustom packetCustom, Minecraft mc, INetHandlerPlayClient handler); } public interface IServerPacketHandler extends ICustomPacketHandler { + public void handlePacket(PacketCustom packetCustom, EntityPlayerMP sender, INetHandlerPlayServer handler); } @@ -56,6 +64,7 @@ public interface IServerPacketHandler extends ICustomPacketHandler { @ChannelHandler.Sharable public static class CustomInboundHandler extends SimpleChannelInboundHandler { + public EnumMap handlers = Maps.newEnumMap(Side.class); @Override @@ -66,19 +75,20 @@ public void handlerAdded(ChannelHandlerContext ctx) throws Exception { @Override protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception { - handlers.get(ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get()) - .handle( - ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(), - ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get(), - new PacketCustom(msg.payload())); + handlers.get(ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get()).handle( + ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(), + ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get(), + new PacketCustom(msg.payload())); } } private static interface CustomHandler { + public void handle(INetHandler handler, String channel, PacketCustom packet) throws Exception; } public static class ClientInboundHandler implements CustomHandler { + private IClientPacketHandler handler; public ClientInboundHandler(ICustomPacketHandler handler) { @@ -94,6 +104,7 @@ public void handle(INetHandler netHandler, String channel, PacketCustom packet) } public static class ServerInboundHandler implements CustomHandler { + private IServerPacketHandler handler; public ServerInboundHandler(ICustomPacketHandler handler) { @@ -102,18 +113,21 @@ public ServerInboundHandler(ICustomPacketHandler handler) { @Override public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { - if (netHandler instanceof NetHandlerPlayServer) - handler.handlePacket( - packet, ((NetHandlerPlayServer) netHandler).playerEntity, (INetHandlerPlayServer) netHandler); + if (netHandler instanceof NetHandlerPlayServer) handler.handlePacket( + packet, + ((NetHandlerPlayServer) netHandler).playerEntity, + (INetHandlerPlayServer) netHandler); else System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } public static interface IHandshakeHandler { + public void handshakeRecieved(NetHandlerPlayServer netHandler); } public static class HandshakeInboundHandler extends ChannelInboundHandlerAdapter { + public IHandshakeHandler handler; public HandshakeInboundHandler(IHandshakeHandler handler) { @@ -124,9 +138,7 @@ public HandshakeInboundHandler(IHandshakeHandler handler) { public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof NetworkHandshakeEstablished) { INetHandler netHandler = ((NetworkDispatcher) ctx.channel() - .attr(FMLOutboundHandler.FML_MESSAGETARGETARGS) - .get()) - .getNetHandler(); + .attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).get()).getNetHandler(); if (netHandler instanceof NetHandlerPlayServer) handler.handshakeRecieved((NetHandlerPlayServer) netHandler); } else ctx.fireUserEventTriggered(evt); @@ -136,14 +148,12 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exc public static String channelName(Object channelKey) { if (channelKey instanceof String) return (String) channelKey; - ModContainer mc = channelKey instanceof ModContainer - ? (ModContainer) channelKey + ModContainer mc = channelKey instanceof ModContainer ? (ModContainer) channelKey : FMLCommonHandler.instance().findContainerFor(channelKey); if (mc != null) { String s = mc.getModId(); - if (s.length() > 20) - throw new IllegalArgumentException( - "Mod ID (" + s + ") too long for use as channel (20 chars). Use a string identifier"); + if (s.length() > 20) throw new IllegalArgumentException( + "Mod ID (" + s + ") too long for use as channel (20 chars). Use a string identifier"); return s; } @@ -160,9 +170,7 @@ public static void assignHandler(Object channelKey, ICustomPacketHandler handler String channelName = channelName(channelKey); Side side = handler instanceof IServerPacketHandler ? Side.SERVER : Side.CLIENT; FMLEmbeddedChannel channel = getOrCreateChannel(channelName, side); - channel.attr(cclHandler) - .get() - .handlers + channel.attr(cclHandler).get().handlers .put(side, side == Side.SERVER ? new ServerInboundHandler(handler) : new ClientInboundHandler(handler)); } @@ -225,7 +233,7 @@ private void do_compress() { ByteBuf out = Unpooled.buffer(len + 5); int clen = deflater.deflate(out.array(), 5, len); if (clen >= len - 5 || !deflater.finished()) // not worth compressing, gets larger - return; + return; out.setByte(0, type | 0x80); out.setInt(1, len); @@ -475,7 +483,7 @@ public void sendToPlayer(EntityPlayer player) { public static void sendToPlayer(Packet packet, EntityPlayer player) { if (player == null) sendToClients(packet); - else ((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet); + else((EntityPlayerMP) player).playerNetServerHandler.sendPacket(packet); } public void sendToClients() { @@ -508,14 +516,15 @@ public void sendToChunk(World world, int chunkX, int chunkZ) { public static void sendToChunk(Packet packet, World world, int chunkX, int chunkZ) { PlayerManager playerManager = ((WorldServer) world).getPlayerManager(); - for (EntityPlayerMP player : - (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + for (EntityPlayerMP player : (List) MinecraftServer.getServer() + .getConfigurationManager().playerEntityList) if (playerManager.isPlayerWatchingChunk(player, chunkX, chunkZ)) sendToPlayer(packet, player); - /* Commented until forge accepts access tranformer request - PlayerInstance p = ((WorldServer) world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); - if (p != null) - p.sendToAllPlayersWatchingChunk(packet);*/ + /* + * Commented until forge accepts access tranformer request PlayerInstance p = ((WorldServer) + * world).getPlayerManager().getOrCreateChunkWatcher(chunkX, chunkZ, false); if (p != null) + * p.sendToAllPlayersWatchingChunk(packet); + */ } public void sendToOps() { @@ -523,8 +532,8 @@ public void sendToOps() { } public static void sendToOps(Packet packet) { - for (EntityPlayerMP player : - (List) MinecraftServer.getServer().getConfigurationManager().playerEntityList) + for (EntityPlayerMP player : (List) MinecraftServer.getServer() + .getConfigurationManager().playerEntityList) if (MinecraftServer.getServer().getConfigurationManager().func_152596_g(player.getGameProfile())) sendToPlayer(packet, player); } diff --git a/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java b/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java index 8ef8cf4..4774d5a 100644 --- a/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java +++ b/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java @@ -5,6 +5,7 @@ import net.minecraft.util.Vec3; public class ExtendedMOP extends MovingObjectPosition implements Comparable { + public Object data; /** * The square distance from the start of the raytrace. diff --git a/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java b/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java index c38baf9..26651ff 100644 --- a/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java +++ b/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java @@ -3,6 +3,7 @@ import codechicken.lib.vec.Cuboid6; public class IndexedCuboid6 extends Cuboid6 { + public Object data; public IndexedCuboid6(Object data, Cuboid6 cuboid) { diff --git a/src/main/java/codechicken/lib/raytracer/RayTracer.java b/src/main/java/codechicken/lib/raytracer/RayTracer.java index 3eb9a8b..d06c0fb 100644 --- a/src/main/java/codechicken/lib/raytracer/RayTracer.java +++ b/src/main/java/codechicken/lib/raytracer/RayTracer.java @@ -1,12 +1,7 @@ package codechicken.lib.raytracer; -import codechicken.lib.math.MathHelper; -import codechicken.lib.vec.BlockCoord; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.Vector3; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.util.List; + import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; @@ -16,7 +11,15 @@ import net.minecraft.util.Vec3; import net.minecraft.world.World; +import codechicken.lib.math.MathHelper; +import codechicken.lib.vec.BlockCoord; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class RayTracer { + private Vector3 vec = new Vector3(); private Vector3 vec2 = new Vector3(); @@ -62,17 +65,20 @@ private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) { case 0: case 1: if (!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) - || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; + || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) + return; break; case 2: case 3: if (!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) - || !MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y)) return; + || !MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y)) + return; break; case 4: case 5: if (!MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y) - || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) return; + || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) + return; break; } @@ -114,8 +120,8 @@ public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids, BlockCoord pos, Block block) { + public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List cuboids, + BlockCoord pos, Block block) { MovingObjectPosition mop = rayTraceCuboids(start, end, cuboids); if (mop != null) { mop.typeOfHit = MovingObjectType.BLOCK; @@ -160,8 +166,8 @@ public static MovingObjectPosition reTrace(World world, EntityPlayer player, dou public static Vec3 getCorrectedHeadVec(EntityPlayer player) { Vec3 v = Vec3.createVectorHelper(player.posX, player.posY, player.posZ); if (player.worldObj.isRemote) { - v.yCoord += - player.getEyeHeight() - player.getDefaultEyeHeight(); // compatibility with eye height changing mods + v.yCoord += player.getEyeHeight() - player.getDefaultEyeHeight(); // compatibility with eye height changing + // mods } else { v.yCoord += player.getEyeHeight(); if (player instanceof EntityPlayerMP && player.isSneaking()) v.yCoord -= 0.08; @@ -174,8 +180,7 @@ public static Vec3 getStartVec(EntityPlayer player) { } public static double getBlockReachDistance(EntityPlayer player) { - return player.worldObj.isRemote - ? getBlockReachDistance_client() + return player.worldObj.isRemote ? getBlockReachDistance_client() : player instanceof EntityPlayerMP ? getBlockReachDistance_server((EntityPlayerMP) player) : 5D; } diff --git a/src/main/java/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java index d7563d6..3c2ef39 100644 --- a/src/main/java/codechicken/lib/render/BlockRenderer.java +++ b/src/main/java/codechicken/lib/render/BlockRenderer.java @@ -5,9 +5,11 @@ import codechicken.lib.vec.Cuboid6; public class BlockRenderer { + public static class BlockFace implements CCRenderState.IVertexSource { - public Vertex5[] verts = new Vertex5[] {new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5()}; - public LC[] lightCoords = new LC[] {new LC(), new LC(), new LC(), new LC()}; + + public Vertex5[] verts = new Vertex5[] { new Vertex5(), new Vertex5(), new Vertex5(), new Vertex5() }; + public LC[] lightCoords = new LC[] { new LC(), new LC(), new LC(), new LC() }; public boolean lcComputed = false; public int side; @@ -119,6 +121,7 @@ public BlockFace loadCuboidFace(Cuboid6 c, int side) { } public static class FullBlock implements CCRenderState.IVertexSource { + public Vertex5[] verts = CCModel.quadModel(24).generateBlock(0, Cuboid6.full).verts; public LC[] lightCoords = new LC[24]; @@ -156,31 +159,32 @@ public static void renderFullBlock(int sideMask) { /** * Renders faces of a block-like model based on a sideMask. Eg for side 2, verts 8-11 will be rendered + * * @param sideMask A mask of faces not to render */ public static void renderFaces(int sideMask) { if (sideMask == 0x3F) return; - for (int s = 0; s < 6; s++) - if ((sideMask & 1 << s) == 0) { - CCRenderState.setVertexRange(s * 4, (s + 1) * 4); - CCRenderState.render(); - } + for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) { + CCRenderState.setVertexRange(s * 4, (s + 1) * 4); + CCRenderState.render(); + } } private static BlockFace face = new BlockFace(); + /** * Renders faces of a cuboid with texture coordinates mapped to match a standard minecraft block - * @param bounds The bounding cuboid to render + * + * @param bounds The bounding cuboid to render * @param sideMask A mask of faces not to render */ public static void renderCuboid(Cuboid6 bounds, int sideMask) { if (sideMask == 0x3F) return; CCRenderState.setModel(face); - for (int s = 0; s < 6; s++) - if ((sideMask & 1 << s) == 0) { - face.loadCuboidFace(bounds, s); - CCRenderState.render(); - } + for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) { + face.loadCuboidFace(bounds, s); + CCRenderState.render(); + } } } diff --git a/src/main/java/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java index 29e7850..18b9164 100644 --- a/src/main/java/codechicken/lib/render/CCModel.java +++ b/src/main/java/codechicken/lib/render/CCModel.java @@ -2,6 +2,14 @@ import static codechicken.lib.vec.Rotation.sideRotations; +import java.io.*; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + import codechicken.lib.lighting.LC; import codechicken.lib.lighting.LightModel; import codechicken.lib.render.uv.UV; @@ -9,15 +17,11 @@ import codechicken.lib.render.uv.UVTranslation; import codechicken.lib.util.Copyable; import codechicken.lib.vec.*; -import java.io.*; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; public class CCModel implements CCRenderState.IVertexSource, Copyable { + private static class PositionNormalEntry { + public Vector3 pos; public LinkedList normals = new LinkedList(); @@ -83,33 +87,23 @@ public T getOrAllocate(CCRenderState.VertexAttribute attrib) { /** * Each pixel corresponds to one unit of position when generating the model - * @param i Vertex index to start generating at + * + * @param i Vertex index to start generating at * @param x1 The minX bound of the box * @param y1 The minY bound of the box * @param z1 The minZ bound of the box - * @param w The width of the box - * @param h The height of the box - * @param d The depth of the box + * @param w The width of the box + * @param h The height of the box + * @param d The depth of the box * @param tx The distance of the top left corner of the texture map from the left in pixels * @param ty The distance of the top left corner of the texture map from the top in pixels * @param tw The width of the texture in pixels * @param th The height of the texture in pixels - * @param f The scale of the model, pixels per block, normally 16 + * @param f The scale of the model, pixels per block, normally 16 * @return The generated model */ - public CCModel generateBox( - int i, - double x1, - double y1, - double z1, - double w, - double h, - double d, - double tx, - double ty, - double tw, - double th, - double f) { + public CCModel generateBox(int i, double x1, double y1, double z1, double w, double h, double d, double tx, + double ty, double tw, double th, double f) { double u1, v1, u2, v2; double x2 = x1 + w; double y2 = y1 + h; @@ -186,7 +180,8 @@ public CCModel generateBox( /** * Generates a box, uv mapped to be the same as a minecraft block with the same bounds - * @param i The vertex index to start generating at + * + * @param i The vertex index to start generating at * @param bounds The bounds of the block, 0 to 1 * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. */ @@ -196,7 +191,14 @@ public CCModel generateBlock(int i, Cuboid6 bounds) { public CCModel generateBlock(int i, Cuboid6 bounds, int mask) { return generateBlock( - i, bounds.min.x, bounds.min.y, bounds.min.z, bounds.max.x, bounds.max.y, bounds.max.z, mask); + i, + bounds.min.x, + bounds.min.y, + bounds.min.z, + bounds.max.x, + bounds.max.y, + bounds.max.z, + mask); } public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, double y2, double z2) { @@ -205,13 +207,14 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, /** * Generates a box, uv mapped to be the same as a minecraft block with the same bounds - * @param i The vertex index to start generating at - * @param x1 minX - * @param y1 minY - * @param z1 minZ - * @param x2 maxX - * @param y2 maxY - * @param z2 maxZ + * + * @param i The vertex index to start generating at + * @param x1 minX + * @param y1 minY + * @param z1 minZ + * @param x2 maxX + * @param y2 maxY + * @param z2 maxZ * @param mask A bitmask of sides NOT to generate. I high bit at index s means side s will not be generated * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. */ @@ -292,10 +295,11 @@ public CCModel computeNormals() { } /** - * Computes the normals of all faces in the model. - * Uses the cross product of the vectors along 2 sides of the face - * @param start The first vertex to generate normals for - * @param length The number of vertices to generate normals for. Note this must be a multiple of 3 for triangles or 4 for quads + * Computes the normals of all faces in the model. Uses the cross product of the vectors along 2 sides of the face + * + * @param start The first vertex to generate normals for + * @param length The number of vertices to generate normals for. Note this must be a multiple of 3 for triangles or + * 4 for quads * @return The model */ public CCModel computeNormals(int start, int length) { @@ -315,8 +319,9 @@ public CCModel computeNormals(int start, int length) { } /** - * Computes lighting using the normals add a light model - * If the model is rotated, the lighting will no longer be valid + * Computes lighting using the normals add a light model If the model is rotated, the lighting will no longer be + * valid + * * @return The model */ public CCModel computeLighting(LightModel light) { @@ -338,6 +343,7 @@ public CCModel setColour(int c) { /** * Computes the minecraft lighting coordinates for use with a LightMatrix + * * @return The model */ public CCModel computeLightCoords() { @@ -349,19 +355,18 @@ public CCModel computeLightCoords() { /** * Averages all normals at the same position to produce a smooth lighting effect. + * * @return The model */ public CCModel smoothNormals() { ArrayList map = new ArrayList(); Vector3[] normals = normals(); - nextvert: - for (int k = 0; k < verts.length; k++) { + nextvert: for (int k = 0; k < verts.length; k++) { Vector3 vec = verts[k].vec; - for (PositionNormalEntry e : map) - if (e.positionEqual(vec)) { - e.addNormal(normals[k]); - continue nextvert; - } + for (PositionNormalEntry e : map) if (e.positionEqual(vec)) { + e.addNormal(normals[k]); + continue nextvert; + } map.add(new PositionNormalEntry(vec).addNormal(normals[k])); } @@ -397,14 +402,12 @@ public CCModel apply(UVTransformation uvt) { public CCModel expand(int extraVerts) { int newLen = verts.length + extraVerts; verts = Arrays.copyOf(verts, newLen); - for (int i = 0; i < attributes.size(); i++) - if (attributes.get(i) != null) - attributes.set( - i, - CCRenderState.copyOf( - (CCRenderState.VertexAttribute) CCRenderState.getAttribute(i), - attributes.get(i), - newLen)); + for (int i = 0; i < attributes.size(); i++) if (attributes.get(i) != null) attributes.set( + i, + CCRenderState.copyOf( + (CCRenderState.VertexAttribute) CCRenderState.getAttribute(i), + attributes.get(i), + newLen)); return this; } @@ -427,9 +430,10 @@ public void render(CCRenderState.IVertexOperation... ops) { /** * Renders vertices start through start+length-1 of the model + * * @param start The first vertex index to render - * @param end The vertex index to render until - * @param ops Operations to apply + * @param end The vertex index to render until + * @param ops Operations to apply */ public void render(int start, int end, CCRenderState.IVertexOperation... ops) { CCRenderState.setPipeline(this, start, end, ops); @@ -481,8 +485,9 @@ public static void assertMatch(Matcher m, String s) { /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param input An input stream to a obj file - * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) + * + * @param input An input stream to a obj file + * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models * @throws IOException @@ -584,25 +589,25 @@ public static void quadulate(List polys, int[][] polyVerts) { /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file + * * @param res The resource for the obj file * @return A map of group names to models */ public static Map parseObjModels(ResourceLocation res) { return parseObjModels(res, 4, null); } + /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param res The resource for the obj file + * + * @param res The resource for the obj file * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models */ public static Map parseObjModels(ResourceLocation res, Transformation coordSystem) { try { return parseObjModels( - Minecraft.getMinecraft() - .getResourceManager() - .getResource(res) - .getInputStream(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), 4, coordSystem); } catch (IOException e) { @@ -612,19 +617,17 @@ public static Map parseObjModels(ResourceLocation res, Transfor /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * @param res The resource for the obj file - * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) + * + * @param res The resource for the obj file + * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models */ - public static Map parseObjModels( - ResourceLocation res, int vertexMode, Transformation coordSystem) { + public static Map parseObjModels(ResourceLocation res, int vertexMode, + Transformation coordSystem) { try { return parseObjModels( - Minecraft.getMinecraft() - .getResourceManager() - .getResource(res) - .getInputStream(), + Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream(), vertexMode, coordSystem); } catch (Exception e) { @@ -632,8 +635,8 @@ public static Map parseObjModels( } } - public static CCModel createModel( - List verts, List uvs, List normals, int vertexMode, List polys) { + public static CCModel createModel(List verts, List uvs, List normals, int vertexMode, + List polys) { int vp = vertexMode == 7 ? 4 : 3; if (polys.size() < vp || polys.size() % vp != 0) throw new IllegalArgumentException("Invalid number of vertices for model: " + polys.size()); @@ -725,8 +728,7 @@ public static void exportObj(Map models, PrintWriter p) { } /** - * Brings the UV coordinates of each face closer to the center UV by d. - * Useful for fixing texture seams + * Brings the UV coordinates of each face closer to the center UV by d. Useful for fixing texture seams */ public CCModel shrinkUVs(double d) { for (int k = 0; k < verts.length; k += vp) { @@ -760,21 +762,20 @@ public CCModel sidedCopy(int side1, int side2, Vector3 point) { public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int length) { for (int k = 0; k < length; k++) dst.verts[destpos + k] = src.verts[srcpos + k].copy(); - for (int i = 0; i < src.attributes.size(); i++) - if (src.attributes.get(i) != null) - CCRenderState.arrayCopy( - src.attributes.get(i), - srcpos, - dst.getOrAllocate(CCRenderState.getAttribute(i)), - destpos, - length); + for (int i = 0; i < src.attributes.size(); i++) if (src.attributes.get(i) != null) CCRenderState.arrayCopy( + src.attributes.get(i), + srcpos, + dst.getOrAllocate(CCRenderState.getAttribute(i)), + destpos, + length); } /** * Generate models rotated to the other 5 sides of the block + * * @param models An array of 6 models - * @param side The side of this model - * @param point The rotation point + * @param side The side of this model + * @param point The rotation point */ public static void generateSidedModels(CCModel[] models, int side, Vector3 point) { for (int s = 0; s < 6; s++) { @@ -786,9 +787,10 @@ public static void generateSidedModels(CCModel[] models, int side, Vector3 point /** * Generate models rotated to the other 3 horizontal of the block + * * @param models An array of 4 models - * @param side The side of this model - * @param point The rotation point + * @param side The side of this model + * @param point The rotation point */ public static void generateSidedModelsH(CCModel[] models, int side, Vector3 point) { for (int s = 2; s < 6; s++) { @@ -804,6 +806,7 @@ public CCModel backfacedCopy() { /** * Generates copies of faces with clockwise vertices + * * @return The model */ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int destpos, int length) { @@ -811,17 +814,15 @@ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int if (srcpos % vp != 0 || destpos % vp != 0 || length % vp != 0) throw new IllegalArgumentException("Vertices do not align with polygons"); - int[][] o = new int[][] {{0, 0}, {1, vp - 1}, {2, vp - 2}, {3, vp - 3}}; + int[][] o = new int[][] { { 0, 0 }, { 1, vp - 1 }, { 2, vp - 2 }, { 3, vp - 3 } }; for (int i = 0; i < length; i++) { int b = (i / vp) * vp; int d = i % vp; int di = destpos + b + o[d][1]; int si = srcpos + b + o[d][0]; dst.verts[di] = src.verts[si].copy(); - for (int a = 0; a < src.attributes.size(); a++) - if (src.attributes.get(a) != null) - CCRenderState.arrayCopy( - src.attributes.get(a), si, dst.getOrAllocate(CCRenderState.getAttribute(a)), di, 1); + for (int a = 0; a < src.attributes.size(); a++) if (src.attributes.get(a) != null) CCRenderState + .arrayCopy(src.attributes.get(a), si, dst.getOrAllocate(CCRenderState.getAttribute(a)), di, 1); if (dst.normals() != null && dst.normals()[di] != null) dst.normals()[di].negate(); } @@ -829,8 +830,8 @@ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int } /** - * Generates sided copies of vertices into this model. - * Assumes that your model has been generated at vertex side*(numVerts/6) + * Generates sided copies of vertices into this model. Assumes that your model has been generated at vertex + * side*(numVerts/6) */ public CCModel generateSidedParts(int side, Vector3 point) { if (verts.length % (6 * vp) != 0) @@ -847,8 +848,8 @@ public CCModel generateSidedParts(int side, Vector3 point) { } /** - * Generates sided copies of vertices into this model. - * Assumes that your model has been generated at vertex side*(numVerts/4) + * Generates sided copies of vertices into this model. Assumes that your model has been generated at vertex + * side*(numVerts/4) */ public CCModel generateSidedPartsH(int side, Vector3 point) { if (verts.length % (4 * vp) != 0) @@ -885,11 +886,10 @@ public CCModel apply(Transformation t, int srcpos, int destpos, int length) { } Vector3[] normals = normals(); - if (normals != null) - for (int k = 0; k < length; k++) { - normals[destpos + k] = normals[srcpos + k].copy(); - t.applyN(normals[destpos + k]); - } + if (normals != null) for (int k = 0; k < length; k++) { + normals[destpos + k] = normals[srcpos + k].copy(); + t.applyN(normals[destpos + k]); + } return this; } diff --git a/src/main/java/codechicken/lib/render/CCModelLibrary.java b/src/main/java/codechicken/lib/render/CCModelLibrary.java index 53f87a1..af3663f 100644 --- a/src/main/java/codechicken/lib/render/CCModelLibrary.java +++ b/src/main/java/codechicken/lib/render/CCModelLibrary.java @@ -5,6 +5,7 @@ import codechicken.lib.vec.*; public class CCModelLibrary { + public static CCModel icosahedron4; public static CCModel icosahedron7; @@ -68,20 +69,12 @@ private static void generateIcosahedron() { icosahedron7.computeNormals().smoothNormals(); } - private static void addIcosahedronTriangle( - Vector3 vec1, - double u1, - double v1, - Vector3 vec2, - double u2, - double v2, - Vector3 vec3, - double u3, - double v3) { + private static void addIcosahedronTriangle(Vector3 vec1, double u1, double v1, Vector3 vec2, double u2, double v2, + Vector3 vec3, double u3, double v3) { icosahedron4.verts[i * 3] = icosahedron7.verts[i * 4] = new Vertex5(vec1, u1, v1); icosahedron4.verts[i * 3 + 1] = icosahedron7.verts[i * 4 + 1] = new Vertex5(vec2, u2, v2); - icosahedron4.verts[i * 3 + 2] = - icosahedron7.verts[i * 4 + 2] = icosahedron7.verts[i * 4 + 3] = new Vertex5(vec3, u3, v3); + icosahedron4.verts[i * 3 + + 2] = icosahedron7.verts[i * 4 + 2] = icosahedron7.verts[i * 4 + 3] = new Vertex5(vec3, u3, v3); i++; } diff --git a/src/main/java/codechicken/lib/render/CCRenderPipeline.java b/src/main/java/codechicken/lib/render/CCRenderPipeline.java index 79d965e..5e7113d 100644 --- a/src/main/java/codechicken/lib/render/CCRenderPipeline.java +++ b/src/main/java/codechicken/lib/render/CCRenderPipeline.java @@ -1,11 +1,14 @@ package codechicken.lib.render; +import java.util.ArrayList; + import codechicken.lib.render.CCRenderState.IVertexOperation; import codechicken.lib.render.CCRenderState.VertexAttribute; -import java.util.ArrayList; public class CCRenderPipeline { + public class PipelineBuilder { + public PipelineBuilder add(IVertexOperation op) { ops.add(op); return this; @@ -27,6 +30,7 @@ public void render() { } private class PipelineNode { + public ArrayList deps = new ArrayList(); public IVertexOperation op; @@ -81,9 +85,8 @@ public void rebuild() { boolean loaded = op.load(); if (loaded) loading.op = op; - if (op instanceof VertexAttribute) - if (loaded) attribs.add((VertexAttribute) op); - else ((VertexAttribute) op).active = false; + if (op instanceof VertexAttribute) if (loaded) attribs.add((VertexAttribute) op); + else((VertexAttribute) op).active = false; } for (int i = 0; i < nodes.size(); i++) nodes.get(i).add(); diff --git a/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java index 51c92ec..9f110e3 100644 --- a/src/main/java/codechicken/lib/render/CCRenderState.java +++ b/src/main/java/codechicken/lib/render/CCRenderState.java @@ -1,5 +1,13 @@ package codechicken.lib.render; +import java.util.ArrayList; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.IBlockAccess; + import codechicken.lib.colour.ColourRGBA; import codechicken.lib.lighting.LC; import codechicken.lib.lighting.LightMatrix; @@ -7,18 +15,13 @@ import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; -import java.util.ArrayList; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.IBlockAccess; /** - * The core of the CodeChickenLib render system. - * Rendering operations are written to avoid object allocations by reusing static variables. + * The core of the CodeChickenLib render system. Rendering operations are written to avoid object allocations by reusing + * static variables. */ public class CCRenderState { + private static int nextOperationIndex; public static int registerOperation() { @@ -33,6 +36,7 @@ public static int operationCount() { * Represents an operation to be run for each vertex that operates on and modifies the current state */ public static interface IVertexOperation { + /** * Load any required references and add dependencies to the pipeline based on the current model (may be null) * Return false if this operation is redundant in the pipeline with the given model @@ -45,8 +49,9 @@ public static interface IVertexOperation { public void operate(); /** - * Get the unique id representing this type of operation. Duplicate operation IDs within the pipeline may have unexpected results. - * ID shoulld be obtained from CCRenderState.registerOperation() and stored in a static variable + * Get the unique id representing this type of operation. Duplicate operation IDs within the pipeline may have + * unexpected results. ID shoulld be obtained from CCRenderState.registerOperation() and stored in a static + * variable */ public int operationID(); } @@ -63,15 +68,18 @@ public static VertexAttribute getAttribute(int index) { } /** - * Management class for a vertex attrute such as colour, normal etc - * This class should handle the loading of the attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others + * Management class for a vertex attrute such as colour, normal etc This class should handle the loading of the + * attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others + * * @param The array type for this attrute eg. int[], Vector3[] */ public abstract static class VertexAttribute implements IVertexOperation { + public final int attributeIndex = registerVertexAttribute(this); private final int operationIndex = registerOperation(); /** - * Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when constructing the pipeline + * Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when + * constructing the pipeline */ public boolean active = false; @@ -102,18 +110,21 @@ public static T copyOf(VertexAttribute attr, T src, int length) { } public static interface IVertexSource { + public Vertex5[] getVertices(); /** * Gets an array of vertex attrutes + * * @param attr The vertex attrute to get - * @param The attrute array type + * @param The attrute array type * @return An array, or null if not computed */ public T getAttributes(VertexAttribute attr); /** - * @return True if the specified attrute is provided by this model, either by returning an array from getAttributes or by setting the state in prepareVertex + * @return True if the specified attrute is provided by this model, either by returning an array from + * getAttributes or by setting the state in prepareVertex */ public boolean hasAttribute(VertexAttribute attr); @@ -124,6 +135,7 @@ public static interface IVertexSource { } public static VertexAttribute normalAttrib = new VertexAttribute() { + private Vector3[] normalRef; @Override @@ -151,6 +163,7 @@ public void operate() { } }; public static VertexAttribute colourAttrib = new VertexAttribute() { + private int[] colourRef; @Override @@ -171,6 +184,7 @@ public void operate() { } }; public static VertexAttribute lightingAttrib = new VertexAttribute() { + private int[] colourRef; @Override @@ -196,6 +210,7 @@ public void operate() { } }; public static VertexAttribute sideAttrib = new VertexAttribute() { + private int[] sideRef; @Override @@ -222,6 +237,7 @@ public void operate() { * Uses the position of the lightmatrix to compute LC if not provided */ public static VertexAttribute lightCoordAttrib = new VertexAttribute() { + private LC[] lcRef; private Vector3 vec = new Vector3(); // for computation private Vector3 pos = new Vector3(); @@ -337,12 +353,11 @@ public static void runPipeline() { public static void writeVert() { if (hasNormal) Tessellator.instance.setNormal((float) normal.x, (float) normal.y, (float) normal.z); - if (hasColour) - Tessellator.instance.setColorRGBA( - colour >>> 24, - colour >> 16 & 0xFF, - colour >> 8 & 0xFF, - alphaOverride >= 0 ? alphaOverride : colour & 0xFF); + if (hasColour) Tessellator.instance.setColorRGBA( + colour >>> 24, + colour >> 16 & 0xFF, + colour >> 8 & 0xFF, + alphaOverride >= 0 ? alphaOverride : colour & 0xFF); if (hasBrightness) Tessellator.instance.setBrightness(brightness); Tessellator.instance.addVertexWithUV(vert.vec.x, vert.vec.y, vert.vec.z, vert.uv.u, vert.uv.v); } @@ -401,12 +416,11 @@ public static void startDrawing() { public static void startDrawing(int mode) { Tessellator.instance.startDrawing(mode); - if (hasColour) - Tessellator.instance.setColorRGBA( - colour >>> 24, - colour >> 16 & 0xFF, - colour >> 8 & 0xFF, - alphaOverride >= 0 ? alphaOverride : colour & 0xFF); + if (hasColour) Tessellator.instance.setColorRGBA( + colour >>> 24, + colour >> 16 & 0xFF, + colour >> 8 & 0xFF, + alphaOverride >= 0 ? alphaOverride : colour & 0xFF); if (hasBrightness) Tessellator.instance.setBrightness(brightness); } diff --git a/src/main/java/codechicken/lib/render/ColourMultiplier.java b/src/main/java/codechicken/lib/render/ColourMultiplier.java index cf3a0db..dd42364 100644 --- a/src/main/java/codechicken/lib/render/ColourMultiplier.java +++ b/src/main/java/codechicken/lib/render/ColourMultiplier.java @@ -3,6 +3,7 @@ import codechicken.lib.colour.ColourRGBA; public class ColourMultiplier implements CCRenderState.IVertexOperation { + private static ColourMultiplier instance = new ColourMultiplier(-1); public static ColourMultiplier instance(int colour) { diff --git a/src/main/java/codechicken/lib/render/EntityDigIconFX.java b/src/main/java/codechicken/lib/render/EntityDigIconFX.java index 1712859..fd2e631 100644 --- a/src/main/java/codechicken/lib/render/EntityDigIconFX.java +++ b/src/main/java/codechicken/lib/render/EntityDigIconFX.java @@ -1,14 +1,16 @@ package codechicken.lib.render; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.Vector3; import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.IIcon; import net.minecraft.world.World; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; + public class EntityDigIconFX extends EntityFX { + public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) { super(world, x, y, z, dx, dy, dz); particleIcon = icon; @@ -42,8 +44,8 @@ public int getMaxAge() { * copy pasted from EntityDiggingFX */ @Override - public void renderParticle( - Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7) { + public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, + float par7) { float f6 = (particleTextureIndexX + particleTextureJitterX / 4.0F) / 16.0F; float f7 = f6 + 0.015609375F; float f8 = (particleTextureIndexY + particleTextureJitterY / 4.0F) / 16.0F; @@ -63,17 +65,33 @@ public void renderParticle( float f14 = 1.0F; par1Tessellator.setColorOpaque_F(f14 * particleRed, f14 * particleGreen, f14 * particleBlue); par1Tessellator.addVertexWithUV( - f11 - par3 * f10 - par6 * f10, f12 - par4 * f10, f13 - par5 * f10 - par7 * f10, f6, f9); + f11 - par3 * f10 - par6 * f10, + f12 - par4 * f10, + f13 - par5 * f10 - par7 * f10, + f6, + f9); par1Tessellator.addVertexWithUV( - f11 - par3 * f10 + par6 * f10, f12 + par4 * f10, f13 - par5 * f10 + par7 * f10, f6, f8); + f11 - par3 * f10 + par6 * f10, + f12 + par4 * f10, + f13 - par5 * f10 + par7 * f10, + f6, + f8); par1Tessellator.addVertexWithUV( - f11 + par3 * f10 + par6 * f10, f12 + par4 * f10, f13 + par5 * f10 + par7 * f10, f7, f8); + f11 + par3 * f10 + par6 * f10, + f12 + par4 * f10, + f13 + par5 * f10 + par7 * f10, + f7, + f8); par1Tessellator.addVertexWithUV( - f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10, f7, f9); + f11 + par3 * f10 - par6 * f10, + f12 - par4 * f10, + f13 + par5 * f10 - par7 * f10, + f7, + f9); } - public static void addBlockHitEffects( - World world, Cuboid6 bounds, int side, IIcon icon, EffectRenderer effectRenderer) { + public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, + EffectRenderer effectRenderer) { float border = 0.1F; Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2 * border); diff.x *= world.rand.nextDouble(); @@ -88,13 +106,13 @@ public static void addBlockHitEffects( if (side == 4) diff.x = bounds.min.x - border; if (side == 5) diff.x = bounds.max.x + border; - effectRenderer.addEffect(new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon) - .multiplyVelocity(0.2F) - .multipleParticleScaleBy(0.6F)); + effectRenderer.addEffect( + new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon).multiplyVelocity(0.2F) + .multipleParticleScaleBy(0.6F)); } - public static void addBlockDestroyEffects( - World world, Cuboid6 bounds, IIcon[] icons, EffectRenderer effectRenderer) { + public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, + EffectRenderer effectRenderer) { Vector3 diff = bounds.max.copy().subtract(bounds.min); Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); Vector3 density = diff.copy().multiply(4); @@ -102,13 +120,12 @@ public static void addBlockDestroyEffects( density.y = Math.ceil(density.y); density.z = Math.ceil(density.z); - for (int i = 0; i < density.x; ++i) - for (int j = 0; j < density.y; ++j) - for (int k = 0; k < density.z; ++k) { - double x = bounds.min.x + (i + 0.5) * diff.x / density.x; - double y = bounds.min.y + (j + 0.5) * diff.y / density.y; - double z = bounds.min.z + (k + 0.5) * diff.z / density.z; - effectRenderer.addEffect(new EntityDigIconFX( + for (int i = 0; i < density.x; ++i) for (int j = 0; j < density.y; ++j) for (int k = 0; k < density.z; ++k) { + double x = bounds.min.x + (i + 0.5) * diff.x / density.x; + double y = bounds.min.y + (j + 0.5) * diff.y / density.y; + double z = bounds.min.z + (k + 0.5) * diff.z / density.z; + effectRenderer.addEffect( + new EntityDigIconFX( world, x, y, @@ -117,6 +134,6 @@ public static void addBlockDestroyEffects( y - center.y, z - center.z, icons[world.rand.nextInt(icons.length)])); - } + } } } diff --git a/src/main/java/codechicken/lib/render/FontUtils.java b/src/main/java/codechicken/lib/render/FontUtils.java index bada7cb..8397d8a 100644 --- a/src/main/java/codechicken/lib/render/FontUtils.java +++ b/src/main/java/codechicken/lib/render/FontUtils.java @@ -3,9 +3,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.item.ItemStack; + import org.lwjgl.opengl.GL11; public class FontUtils { + public static FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; public static void drawCenteredString(String s, int xCenter, int y, int colour) { @@ -16,7 +18,7 @@ public static void drawRightString(String s, int xRight, int y, int colour) { fontRenderer.drawString(s, xRight - fontRenderer.getStringWidth(s), y, colour); } - public static final String[] prefixes = new String[] {"K", "M", "G"}; + public static final String[] prefixes = new String[] { "K", "M", "G" }; public static void drawItemQuantity(int x, int y, ItemStack item, String quantity, int mode) { if (item == null || (quantity == null && item.stackSize <= 1)) return; diff --git a/src/main/java/codechicken/lib/render/IFaceRenderer.java b/src/main/java/codechicken/lib/render/IFaceRenderer.java index 891b8f9..2965346 100644 --- a/src/main/java/codechicken/lib/render/IFaceRenderer.java +++ b/src/main/java/codechicken/lib/render/IFaceRenderer.java @@ -1,5 +1,6 @@ package codechicken.lib.render; public interface IFaceRenderer { + public void renderFace(Vertex5[] face, int side); } diff --git a/src/main/java/codechicken/lib/render/ManagedTextureFX.java b/src/main/java/codechicken/lib/render/ManagedTextureFX.java index 602dbe0..80377ca 100644 --- a/src/main/java/codechicken/lib/render/ManagedTextureFX.java +++ b/src/main/java/codechicken/lib/render/ManagedTextureFX.java @@ -1,6 +1,7 @@ package codechicken.lib.render; public class ManagedTextureFX extends TextureFX { + public boolean changed; public ManagedTextureFX(int size, String name) { diff --git a/src/main/java/codechicken/lib/render/PlaceholderTexture.java b/src/main/java/codechicken/lib/render/PlaceholderTexture.java index 96aef9a..3f9b9e2 100644 --- a/src/main/java/codechicken/lib/render/PlaceholderTexture.java +++ b/src/main/java/codechicken/lib/render/PlaceholderTexture.java @@ -5,6 +5,7 @@ import net.minecraft.util.ResourceLocation; public class PlaceholderTexture extends TextureAtlasSprite { + protected PlaceholderTexture(String par1) { super(par1); } diff --git a/src/main/java/codechicken/lib/render/QBImporter.java b/src/main/java/codechicken/lib/render/QBImporter.java index 64efeac..25f60de 100644 --- a/src/main/java/codechicken/lib/render/QBImporter.java +++ b/src/main/java/codechicken/lib/render/QBImporter.java @@ -1,21 +1,27 @@ package codechicken.lib.render; -import codechicken.lib.render.uv.UV; -import codechicken.lib.render.uv.UVScale; -import codechicken.lib.vec.*; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; import java.awt.image.BufferedImage; import java.io.*; import java.util.*; + import javax.imageio.ImageIO; + import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVScale; +import codechicken.lib.vec.*; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + public class QBImporter { + private static class ImagePackNode { + Rectangle4i rect; ImagePackNode child1; ImagePackNode child2; @@ -83,11 +89,10 @@ public static ImagePackNode pack(List images, boolean square) { while (true) { boolean packed = true; - for (QBImage img : images) - if (!node.pack(img)) { - packed = false; - break; - } + for (QBImage img : images) if (!node.pack(img)) { + packed = false; + break; + } if (packed) return node; @@ -108,16 +113,16 @@ private void write(BufferedImage img) { child2.write(img); } else if (packed != null) { ImageTransform t = packed.packT; - for (int u = 0; u < rect.w; u++) - for (int v = 0; v < rect.h; v++) { - int rgba = t.access(packed, u, v); - img.setRGB(u + rect.x, v + rect.y, rgba >>> 8 | rgba << 24); - } + for (int u = 0; u < rect.w; u++) for (int v = 0; v < rect.h; v++) { + int rgba = t.access(packed, u, v); + img.setRGB(u + rect.x, v + rect.y, rgba >>> 8 | rgba << 24); + } } } } private static class ImageTransform { + int transform; public ImageTransform(int i) { @@ -166,6 +171,7 @@ public UV transform(UV uv) { } public static class QBImage implements Comparable { + int[][] data; ImageTransform packT; Rectangle4i packSlot; @@ -190,16 +196,14 @@ public int compareTo(QBImage o) { } public ImageTransform transformTo(QBImage img) { - if (width() == img.width() && height() == img.height()) - for (int i = 0; i < 4; i++) { - ImageTransform t = new ImageTransform(i); - if (equals(img, t)) return t; - } - if (width() == img.height() && height() == img.width()) - for (int i = 4; i < 8; i++) { - ImageTransform t = new ImageTransform(i); - if (equals(img, t)) return t; - } + if (width() == img.width() && height() == img.height()) for (int i = 0; i < 4; i++) { + ImageTransform t = new ImageTransform(i); + if (equals(img, t)) return t; + } + if (width() == img.height() && height() == img.width()) for (int i = 4; i < 8; i++) { + ImageTransform t = new ImageTransform(i); + if (equals(img, t)) return t; + } return null; } @@ -220,13 +224,10 @@ public void transform(UV uv) { } private static final int[][] vertOrder = new int[][] { // clockwise because MC is left handed - {3, 0}, - {1, 0}, - {1, 2}, - {3, 2} - }; + { 3, 0 }, { 1, 0 }, { 1, 2 }, { 3, 2 } }; public static class QBQuad { + public Vertex5[] verts = new Vertex5[4]; public QBImage image = new QBImage(); public ImageTransform t = new ImageTransform(); @@ -247,8 +248,7 @@ public static QBQuad restore(Rectangle4i flat, int side, double d, QBImage img) QBQuad quad = new QBQuad(side); quad.image = img; - Transformation t = new Scale(-1, 1, -1) - .with(Rotation.sideOrientation(side, 0)) + Transformation t = new Scale(-1, 1, -1).with(Rotation.sideOrientation(side, 0)) .with(new Translation(new Vector3().setSide(side, d))); quad.verts[0] = new Vertex5(flat.x, 0, flat.y, 0, 0); quad.verts[1] = new Vertex5(flat.x + flat.w, 0, flat.y, 1, 0); @@ -268,6 +268,7 @@ public Rectangle4i flatten() { } public static class QBCuboid { + public QBMatrix mat; public CuboidCoord c; public int sides; @@ -281,8 +282,7 @@ public QBCuboid(QBMatrix mat, CuboidCoord c) { public static boolean intersects(QBCuboid a, QBCuboid b) { CuboidCoord c = a.c; CuboidCoord d = b.c; - return c.min.x <= d.max.x - && d.min.x <= c.max.x + return c.min.x <= d.max.x && d.min.x <= c.max.x && c.min.y <= d.max.y && d.min.y <= c.max.y && c.min.z <= d.max.z @@ -301,8 +301,7 @@ public void clip(QBCuboid o) { for (int a = 0; a < 6; a += 2) { int a1 = (a + 2) % 6; int a2 = (a + 4) % 6; - if (c.getSide(a1 + 1) <= d.getSide(a1 + 1) - && c.getSide(a1) >= d.getSide(a1) + if (c.getSide(a1 + 1) <= d.getSide(a1 + 1) && c.getSide(a1) >= d.getSide(a1) && c.getSide(a2 + 1) <= d.getSide(a2 + 1) && c.getSide(a2) >= d.getSide(a2)) { @@ -350,16 +349,16 @@ private QBQuad extractQuad(int side, Cuboid6 box) { BlockCoord b = BlockCoord.fromAxes(ia); BlockCoord bU = BlockCoord.sideOffsets[sideU]; BlockCoord bV = BlockCoord.sideOffsets[sideV]; - for (int u = 0; u < image.width(); u++) - for (int v = 0; v < image.height(); v++) - image.data[u][v] = - mat.matrix[b.x + bU.x * u + bV.x * v][b.y + bU.y * u + bV.y * v][b.z + bU.z * u + bV.z * v]; + for (int u = 0; u < image.width(); u++) for (int v = 0; v < image.height(); v++) + image.data[u][v] = mat.matrix[b.x + bU.x * u + bV.x * v][b.y + bU.y * u + bV.y * v][b.z + bU.z * u + + bV.z * v]; return quad; } } public static class QBMatrix { + public String name; public BlockCoord pos; public BlockCoord size; @@ -395,12 +394,10 @@ public void readMatrix(DataInputStream din, boolean compressed) throws IOExcepti } public void convertBGRAtoRGBA() { - for (int z = 0; z < size.z; z++) - for (int y = 0; y < size.y; y++) - for (int x = 0; x < size.x; x++) { - int i = matrix[x][y][z]; - matrix[x][y][z] = Integer.reverseBytes(i >>> 8) | i & 0xFF; - } + for (int z = 0; z < size.z; z++) for (int y = 0; y < size.y; y++) for (int x = 0; x < size.x; x++) { + int i = matrix[x][y][z]; + matrix[x][y][z] = Integer.reverseBytes(i >>> 8) | i & 0xFF; + } } private boolean voxelFull(boolean[][][] solid, CuboidCoord c) { @@ -434,10 +431,8 @@ public List rectangulate() { for (int z = 0; z < size.z; z++) for (int y = 0; y < size.y; y++) for (int x = 0; x < size.x; x++) solid[x][y][z] = matrix[x][y][z] != 0; - for (int x = 0; x < size.x; x++) - for (int z = 0; z < size.z; z++) - for (int y = 0; y < size.y; y++) - if (solid[x][y][z]) list.add(expand(solid, new BlockCoord(x, y, z))); + for (int x = 0; x < size.x; x++) for (int z = 0; z < size.z; z++) + for (int y = 0; y < size.y; y++) if (solid[x][y][z]) list.add(expand(solid, new BlockCoord(x, y, z))); for (int i = 0; i < list.size(); i++) for (int j = i + 1; j < list.size(); j++) QBCuboid.clip(list.get(i), list.get(j)); @@ -468,9 +463,8 @@ private void optimisePlanes(List quads) { int side = key & 7; Rectangle4i rect = null; - for (QBQuad q : plane) - if (rect == null) rect = q.flatten(); - else rect.include(q.flatten()); + for (QBQuad q : plane) if (rect == null) rect = q.flatten(); + else rect.include(q.flatten()); QBImage img = new QBImage(); img.data = new int[rect.w][rect.h]; @@ -528,6 +522,7 @@ private static void addImages(List quads, List images) { public static final int SCALEMC = 8; public static class QBModel { + public QBMatrix[] matrices; public boolean rightHanded; @@ -551,8 +546,7 @@ public RasterisedModel toRasterisedModel(int flags) { } } - if (mergeTextures) - images.add(ImagePackNode.pack(qbImages, squareTextures).toImage()); + if (mergeTextures) images.add(ImagePackNode.pack(qbImages, squareTextures).toImage()); RasterisedModel m = new RasterisedModel(images); for (int i = 0; i < matrices.length; i++) { @@ -565,7 +559,9 @@ public RasterisedModel toRasterisedModel(int flags) { } public static class RasterisedModel { + private class Holder { + CCModel m; int img; @@ -594,9 +590,10 @@ public CCModel getModel(String key) { public IIcon getIcon(String key, IIconRegister r, String iconName) { int img = map.get(key).img; - if (icons[img] != null && !iconName.equals(icons[img])) - throw new IllegalArgumentException("Attempted to get a previously registered icon by a different name: " - + icons[img] + ", " + iconName); + if (icons[img] != null && !iconName.equals(icons[img])) throw new IllegalArgumentException( + "Attempted to get a previously registered icon by a different name: " + icons[img] + + ", " + + iconName); if (icons[img] != null) return r.registerIcon(iconName); icons[img] = iconName; @@ -622,9 +619,8 @@ public void export(File objFile, File imgDir) { if (images.size() < map.size()) exportImg(images.get(0), new File(imgDir, objFile.getName().replaceAll("(.+)\\..+", "$1.png"))); - else - for (Map.Entry e : map.entrySet()) - exportImg(images.get(e.getValue().img), new File(imgDir, e.getKey() + ".png")); + else for (Map.Entry e : map.entrySet()) + exportImg(images.get(e.getValue().img), new File(imgDir, e.getKey() + ".png")); } catch (IOException e) { throw new RuntimeException(e); @@ -674,10 +670,7 @@ public static QBModel loadQB(InputStream input) throws IOException { public static QBModel loadQB(ResourceLocation res) { try { - return loadQB(Minecraft.getMinecraft() - .getResourceManager() - .getResource(res) - .getInputStream()); + return loadQB(Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream()); } catch (Exception e) { throw new RuntimeException("failed to load model: " + res, e); } diff --git a/src/main/java/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java index b5327c3..aec0443 100644 --- a/src/main/java/codechicken/lib/render/RenderUtils.java +++ b/src/main/java/codechicken/lib/render/RenderUtils.java @@ -3,9 +3,6 @@ import static net.minecraftforge.client.IItemRenderer.ItemRenderType.ENTITY; import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3D; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.Rectangle4i; -import codechicken.lib.vec.Vector3; import net.minecraft.block.Block; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; @@ -20,11 +17,18 @@ import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; + import org.lwjgl.opengl.GL11; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Rectangle4i; +import codechicken.lib.vec.Vector3; + public class RenderUtils { + static Vector3[] vectors = new Vector3[8]; static RenderItem uniformRenderItem = new RenderItem() { + public boolean shouldBob() { return false; } @@ -40,8 +44,8 @@ public boolean shouldBob() { entityItem.hoverStart = 0; } - public static void renderFluidQuad( - Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, double res) { + public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, + double res) { renderFluidQuad( point2, vectors[0].set(point4).subtract(point1), @@ -52,10 +56,11 @@ public static void renderFluidQuad( /** * Draws a tessellated quadrilateral bottom to top, left to right + * * @param base The bottom left corner of the quad * @param wide The bottom of the quad * @param high The left side of the quad - * @param res Units per icon + * @param res Units per icon */ public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) { Tessellator t = Tessellator.instance; @@ -84,10 +89,18 @@ public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIc Vector3 dy2 = vectors[5].set(high).multiply((y + ry) / hlen); t.addVertexWithUV( - base.x + dx1.x + dy2.x, base.y + dx1.y + dy2.y, base.z + dx1.z + dy2.z, u1, v2 - ry / res * dv); + base.x + dx1.x + dy2.x, + base.y + dx1.y + dy2.y, + base.z + dx1.z + dy2.z, + u1, + v2 - ry / res * dv); t.addVertexWithUV(base.x + dx1.x + dy1.x, base.y + dx1.y + dy1.y, base.z + dx1.z + dy1.z, u1, v2); t.addVertexWithUV( - base.x + dx2.x + dy1.x, base.y + dx2.y + dy1.y, base.z + dx2.z + dy1.z, u1 + rx / res * du, v2); + base.x + dx2.x + dy1.x, + base.y + dx2.y + dy1.y, + base.z + dx2.z + dy1.z, + u1 + rx / res * du, + v2); t.addVertexWithUV( base.x + dx2.x + dy2.x, base.y + dx2.y + dy2.y, @@ -183,9 +196,9 @@ public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { res); } - public static void renderBlockOverlaySide( - int x, int y, int z, int side, double tx1, double tx2, double ty1, double ty2) { - double[] points = new double[] {x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009}; + public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1, + double ty2) { + double[] points = new double[] { x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009 }; Tessellator tessellator = Tessellator.instance; switch (side) { @@ -260,14 +273,15 @@ public static double fluidDensityToAlpha(double density) { } /** - * Renders a fluid within a bounding box. - * If the fluid is a liquid it will render as a normal tank with height equal to density/bound.height. - * If the fluid is a gas, it will render the full box with an alpha equal to density. + * Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal + * to density/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to density. * Warning, bound will be mutated if the fluid is a liquid - * @param stack The fluid to render. - * @param bound The box within which the fluid is contained. - * @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids this determines the height. - * @param res The resolution to render at. + * + * @param stack The fluid to render. + * @param bound The box within which the fluid is contained. + * @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids + * this determines the height. + * @param res The resolution to render at. */ public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { if (!shouldRenderFluid(stack)) return; @@ -315,6 +329,7 @@ public static void renderItemUniform(ItemStack item) { /** * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately + * * @param spin The spin angle of the item around the y axis in degrees */ public static void renderItemUniform(ItemStack item, double spin) { @@ -323,8 +338,7 @@ public static void renderItemUniform(ItemStack item, double spin) { boolean larger = false; if (item.getItem() instanceof ItemBlock - && RenderBlocks.renderItemIn3d( - Block.getBlockFromItem(item.getItem()).getRenderType())) { + && RenderBlocks.renderItemIn3d(Block.getBlockFromItem(item.getItem()).getRenderType())) { int renderType = Block.getBlockFromItem(item.getItem()).getRenderType(); larger = !(renderType == 1 || renderType == 19 || renderType == 12 || renderType == 2); } else if (is3D) { diff --git a/src/main/java/codechicken/lib/render/ShaderProgram.java b/src/main/java/codechicken/lib/render/ShaderProgram.java index efd1783..ccc145a 100644 --- a/src/main/java/codechicken/lib/render/ShaderProgram.java +++ b/src/main/java/codechicken/lib/render/ShaderProgram.java @@ -6,12 +6,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; + import org.lwjgl.opengl.ARBShaderObjects; import org.lwjgl.opengl.ARBVertexShader; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Matrix4f; public class ShaderProgram { + int programID; public ShaderProgram() { diff --git a/src/main/java/codechicken/lib/render/SpriteSheetManager.java b/src/main/java/codechicken/lib/render/SpriteSheetManager.java index e0ebcf9..2dedc86 100644 --- a/src/main/java/codechicken/lib/render/SpriteSheetManager.java +++ b/src/main/java/codechicken/lib/render/SpriteSheetManager.java @@ -1,18 +1,22 @@ package codechicken.lib.render; -import codechicken.lib.render.TextureUtils.IIconSelfRegister; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.util.ArrayList; import java.util.HashMap; + import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; +import codechicken.lib.render.TextureUtils.IIconSelfRegister; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class SpriteSheetManager { + @SideOnly(Side.CLIENT) public static class SpriteSheet implements IIconSelfRegister { + private int tilesX; private int tilesY; private ArrayList newSprites = new ArrayList(); @@ -65,9 +69,8 @@ private void reloadTexture() { public IIcon getSprite(int index) { IIcon i = sprites[index]; - if (i == null) - throw new IllegalArgumentException( - "Sprite at index: " + index + " from texture file " + resource + " was not preloaded."); + if (i == null) throw new IllegalArgumentException( + "Sprite at index: " + index + " from texture file " + resource + " was not preloaded."); return i; } diff --git a/src/main/java/codechicken/lib/render/TextureDataHolder.java b/src/main/java/codechicken/lib/render/TextureDataHolder.java index 3632787..fd5dccf 100644 --- a/src/main/java/codechicken/lib/render/TextureDataHolder.java +++ b/src/main/java/codechicken/lib/render/TextureDataHolder.java @@ -3,6 +3,7 @@ import java.awt.image.BufferedImage; public class TextureDataHolder { + public int width; public int height; public int[] data; diff --git a/src/main/java/codechicken/lib/render/TextureFX.java b/src/main/java/codechicken/lib/render/TextureFX.java index 364683f..d1cf852 100644 --- a/src/main/java/codechicken/lib/render/TextureFX.java +++ b/src/main/java/codechicken/lib/render/TextureFX.java @@ -1,12 +1,14 @@ package codechicken.lib.render; +import net.minecraft.client.Minecraft; + import codechicken.lib.render.SpriteSheetManager.SpriteSheet; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.Minecraft; @SideOnly(Side.CLIENT) public class TextureFX { + public int[] imageData; public int tileSizeBase = 16; public int tileSizeSquare = 256; diff --git a/src/main/java/codechicken/lib/render/TextureSpecial.java b/src/main/java/codechicken/lib/render/TextureSpecial.java index d69c398..ee797c7 100644 --- a/src/main/java/codechicken/lib/render/TextureSpecial.java +++ b/src/main/java/codechicken/lib/render/TextureSpecial.java @@ -1,11 +1,8 @@ package codechicken.lib.render; -import codechicken.lib.render.SpriteSheetManager.SpriteSheet; -import codechicken.lib.render.TextureUtils.IIconSelfRegister; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.awt.image.BufferedImage; import java.util.ArrayList; + import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -16,8 +13,14 @@ import net.minecraft.client.settings.GameSettings; import net.minecraft.util.ResourceLocation; +import codechicken.lib.render.SpriteSheetManager.SpriteSheet; +import codechicken.lib.render.TextureUtils.IIconSelfRegister; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + @SideOnly(Side.CLIENT) public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegister { + // sprite sheet fields private int spriteIndex; private SpriteSheet spriteSheet; @@ -99,8 +102,8 @@ public int[][] prepareAnisotropicFiltering(int[][] mipmaps) { } @Override - public void loadSprite( - BufferedImage[] images, AnimationMetadataSection animationMeta, boolean anisotropicFiltering) { + public void loadSprite(BufferedImage[] images, AnimationMetadataSection animationMeta, + boolean anisotropicFiltering) { rawWidth = images[0].getWidth(); rawHeight = images[0].getHeight(); super.loadSprite(images, animationMeta, anisotropicFiltering); diff --git a/src/main/java/codechicken/lib/render/TextureUtils.java b/src/main/java/codechicken/lib/render/TextureUtils.java index 6e90960..b7ab4bb 100644 --- a/src/main/java/codechicken/lib/render/TextureUtils.java +++ b/src/main/java/codechicken/lib/render/TextureUtils.java @@ -1,13 +1,12 @@ package codechicken.lib.render; -import codechicken.lib.colour.Colour; -import codechicken.lib.colour.ColourARGB; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; + import javax.imageio.ImageIO; + import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.client.renderer.texture.TextureManager; @@ -16,11 +15,18 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.MinecraftForge; + import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import codechicken.lib.colour.Colour; +import codechicken.lib.colour.ColourARGB; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; + public class TextureUtils { + public static interface IIconSelfRegister { + public void registerIcons(IIconRegister register); public int atlasIndex(); @@ -57,10 +63,7 @@ public static Colour[] loadTextureColours(ResourceLocation resource) { } public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException { - return Minecraft.getMinecraft() - .getResourceManager() - .getResource(textureFile) - .getInputStream(); + return Minecraft.getMinecraft().getResourceManager().getResource(textureFile).getInputStream(); } public static BufferedImage loadBufferedImage(ResourceLocation textureFile) { @@ -83,24 +86,14 @@ public static TextureManager engine() { return Minecraft.getMinecraft().renderEngine; } - public static void copySubImg( - int[] fromTex, - int fromWidth, - int fromX, - int fromY, - int width, - int height, - int[] toTex, - int toWidth, - int toX, - int toY) { - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++) { - int fp = (y + fromY) * fromWidth + x + fromX; - int tp = (y + toX) * toWidth + x + toX; + public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, + int[] toTex, int toWidth, int toX, int toY) { + for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { + int fp = (y + fromY) * fromWidth + x + fromX; + int tp = (y + toX) * toWidth + x + toX; - toTex[tp] = fromTex[fp]; - } + toTex[tp] = fromTex[fp]; + } } public static void bindAtlas(int atlasIndex) { @@ -148,7 +141,8 @@ public static TextureDataHolder loadTexture(ResourceLocation resource) { } /** - * Uses an empty placeholder texture to tell if the map has been reloaded since the last call to refresh texture and the texture with name needs to be reacquired to be valid + * Uses an empty placeholder texture to tell if the map has been reloaded since the last call to refresh texture and + * the texture with name needs to be reacquired to be valid */ public static boolean refreshTexture(TextureMap map, String name) { if (map.getTextureExtry(name) == null) { diff --git a/src/main/java/codechicken/lib/render/Vertex5.java b/src/main/java/codechicken/lib/render/Vertex5.java index 37e0827..6c5156b 100644 --- a/src/main/java/codechicken/lib/render/Vertex5.java +++ b/src/main/java/codechicken/lib/render/Vertex5.java @@ -1,15 +1,17 @@ package codechicken.lib.render; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + import codechicken.lib.render.uv.UV; import codechicken.lib.render.uv.UVTransformation; import codechicken.lib.util.Copyable; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; public class Vertex5 implements Copyable { + public Vector3 vec; public UV uv; @@ -62,9 +64,19 @@ public Vertex5 copy() { public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Vertex: (" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " - + new BigDecimal(vec.z, cont) + ") " + "(" + new BigDecimal(uv.u, cont) + ", " - + new BigDecimal(uv.v, cont) + ") (" + uv.tex + ")"; + return "Vertex: (" + new BigDecimal(vec.x, cont) + + ", " + + new BigDecimal(vec.y, cont) + + ", " + + new BigDecimal(vec.z, cont) + + ") " + + "(" + + new BigDecimal(uv.u, cont) + + ", " + + new BigDecimal(uv.v, cont) + + ") (" + + uv.tex + + ")"; } public Vertex5 apply(Transformation t) { diff --git a/src/main/java/codechicken/lib/render/uv/IconTransformation.java b/src/main/java/codechicken/lib/render/uv/IconTransformation.java index ff7b975..af19b26 100644 --- a/src/main/java/codechicken/lib/render/uv/IconTransformation.java +++ b/src/main/java/codechicken/lib/render/uv/IconTransformation.java @@ -1,9 +1,11 @@ package codechicken.lib.render.uv; -import codechicken.lib.vec.IrreversibleTransformationException; import net.minecraft.util.IIcon; +import codechicken.lib.vec.IrreversibleTransformationException; + public class IconTransformation extends UVTransformation { + public IIcon icon; public IconTransformation(IIcon icon) { diff --git a/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java b/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java index 7080f43..d0521a8 100644 --- a/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java +++ b/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java @@ -1,9 +1,11 @@ package codechicken.lib.render.uv; -import codechicken.lib.vec.IrreversibleTransformationException; import net.minecraft.util.IIcon; +import codechicken.lib.vec.IrreversibleTransformationException; + public class MultiIconTransformation extends UVTransformation { + public IIcon[] icons; public MultiIconTransformation(IIcon... icons) { diff --git a/src/main/java/codechicken/lib/render/uv/UV.java b/src/main/java/codechicken/lib/render/uv/UV.java index 1ca2956..e4828db 100644 --- a/src/main/java/codechicken/lib/render/uv/UV.java +++ b/src/main/java/codechicken/lib/render/uv/UV.java @@ -1,11 +1,13 @@ package codechicken.lib.render.uv; -import codechicken.lib.util.Copyable; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.util.Copyable; + public class UV implements Copyable { + public double u; public double v; public int tex; diff --git a/src/main/java/codechicken/lib/render/uv/UVRotation.java b/src/main/java/codechicken/lib/render/uv/UVRotation.java index 02cf97f..6935603 100644 --- a/src/main/java/codechicken/lib/render/uv/UVRotation.java +++ b/src/main/java/codechicken/lib/render/uv/UVRotation.java @@ -1,11 +1,13 @@ package codechicken.lib.render.uv; -import codechicken.lib.math.MathHelper; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.math.MathHelper; + public class UVRotation extends UVTransformation { + public double angle; /** diff --git a/src/main/java/codechicken/lib/render/uv/UVScale.java b/src/main/java/codechicken/lib/render/uv/UVScale.java index db229ec..a2de0ef 100644 --- a/src/main/java/codechicken/lib/render/uv/UVScale.java +++ b/src/main/java/codechicken/lib/render/uv/UVScale.java @@ -5,6 +5,7 @@ import java.math.RoundingMode; public class UVScale extends UVTransformation { + double su; double sv; diff --git a/src/main/java/codechicken/lib/render/uv/UVTransformation.java b/src/main/java/codechicken/lib/render/uv/UVTransformation.java index 066da2a..8e96173 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTransformation.java +++ b/src/main/java/codechicken/lib/render/uv/UVTransformation.java @@ -8,11 +8,14 @@ */ public abstract class UVTransformation extends ITransformation implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); public UVTransformation at(UV point) { return new UVTransformationList( - new UVTranslation(-point.u, -point.v), this, new UVTranslation(point.u, point.v)); + new UVTranslation(-point.u, -point.v), + this, + new UVTranslation(point.u, point.v)); } public UVTransformationList with(UVTransformation t) { diff --git a/src/main/java/codechicken/lib/render/uv/UVTransformationList.java b/src/main/java/codechicken/lib/render/uv/UVTransformationList.java index 149a943..745b22d 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTransformationList.java +++ b/src/main/java/codechicken/lib/render/uv/UVTransformationList.java @@ -4,6 +4,7 @@ import java.util.Iterator; public class UVTransformationList extends UVTransformation { + private ArrayList transformations = new ArrayList(); public UVTransformationList(UVTransformation... transforms) { @@ -69,8 +70,7 @@ public boolean isRedundant() { @Override public UVTransformation inverse() { UVTransformationList rev = new UVTransformationList(); - for (int i = transformations.size() - 1; i >= 0; i--) - rev.with(transformations.get(i).inverse()); + for (int i = transformations.size() - 1; i >= 0; i--) rev.with(transformations.get(i).inverse()); return rev; } diff --git a/src/main/java/codechicken/lib/render/uv/UVTranslation.java b/src/main/java/codechicken/lib/render/uv/UVTranslation.java index 69851eb..2daf58f 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTranslation.java +++ b/src/main/java/codechicken/lib/render/uv/UVTranslation.java @@ -1,11 +1,13 @@ package codechicken.lib.render.uv; -import codechicken.lib.math.MathHelper; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.math.MathHelper; + public class UVTranslation extends UVTransformation { + public double du; public double dv; diff --git a/src/main/java/codechicken/lib/tool/LibDownloader.java b/src/main/java/codechicken/lib/tool/LibDownloader.java index b09ca04..ca4a61f 100644 --- a/src/main/java/codechicken/lib/tool/LibDownloader.java +++ b/src/main/java/codechicken/lib/tool/LibDownloader.java @@ -12,13 +12,11 @@ import java.util.List; public class LibDownloader { - private static String[] libs = new String[] { - "org/ow2/asm/asm-debug-all/5.0.3/asm-debug-all-5.0.3.jar", - "com/google/guava/guava/14.0/guava-14.0.jar", - "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", - "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", - "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar" - }; + + private static String[] libs = new String[] { "org/ow2/asm/asm-debug-all/5.0.3/asm-debug-all-5.0.3.jar", + "com/google/guava/guava/14.0/guava-14.0.jar", "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", + "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", + "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar" }; private static File libDir = new File("lib"); private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); @@ -35,10 +33,9 @@ public static void load() { private static void addPaths(String[] libs) { try { URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); - Method m_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] {URL.class}); + Method m_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class }); m_addURL.setAccessible(true); - for (String lib : libs) - m_addURL.invoke(cl, new File(libDir, fileName(lib)).toURI().toURL()); + for (String lib : libs) m_addURL.invoke(cl, new File(libDir, fileName(lib)).toURI().toURL()); } catch (Exception e) { throw new RuntimeException("Failed to add libraries to classpath", e); } diff --git a/src/main/java/codechicken/lib/tool/MCStripTransformer.java b/src/main/java/codechicken/lib/tool/MCStripTransformer.java index 8114ae5..5c8e47b 100644 --- a/src/main/java/codechicken/lib/tool/MCStripTransformer.java +++ b/src/main/java/codechicken/lib/tool/MCStripTransformer.java @@ -1,7 +1,7 @@ package codechicken.lib.tool; -import codechicken.lib.asm.ASMHelper; import java.util.Iterator; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -10,8 +10,12 @@ import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; +import codechicken.lib.asm.ASMHelper; + public class MCStripTransformer { + public static class ReferenceDetector extends Remapper { + boolean found = false; @Override diff --git a/src/main/java/codechicken/lib/tool/Main.java b/src/main/java/codechicken/lib/tool/Main.java index 29dbac3..039121c 100644 --- a/src/main/java/codechicken/lib/tool/Main.java +++ b/src/main/java/codechicken/lib/tool/Main.java @@ -1,11 +1,12 @@ package codechicken.lib.tool; public class Main { + public static void main(String[] args) { LibDownloader.load(); try { Class c_toolMain = new StripClassLoader().loadClass("codechicken.lib.tool.ToolMain"); - c_toolMain.getDeclaredMethod("main", String[].class).invoke(null, new Object[] {args}); + c_toolMain.getDeclaredMethod("main", String[].class).invoke(null, new Object[] { args }); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/codechicken/lib/tool/StripClassLoader.java b/src/main/java/codechicken/lib/tool/StripClassLoader.java index f3de755..92e334b 100644 --- a/src/main/java/codechicken/lib/tool/StripClassLoader.java +++ b/src/main/java/codechicken/lib/tool/StripClassLoader.java @@ -7,6 +7,7 @@ import java.net.URLClassLoader; public class StripClassLoader extends URLClassLoader { + public StripClassLoader() { super(new URL[0], StripClassLoader.class.getClassLoader()); } diff --git a/src/main/java/codechicken/lib/tool/ToolMain.java b/src/main/java/codechicken/lib/tool/ToolMain.java index 3d49f88..ff51b7b 100644 --- a/src/main/java/codechicken/lib/tool/ToolMain.java +++ b/src/main/java/codechicken/lib/tool/ToolMain.java @@ -3,7 +3,9 @@ import codechicken.lib.tool.module.ModuleQBConverter; public class ToolMain { + public static interface Module { + public void main(String[] args); public String name(); @@ -11,7 +13,7 @@ public static interface Module { public void printHelp(); } - public static Module[] modules = new Module[] {new ModuleQBConverter()}; + public static Module[] modules = new Module[] { new ModuleQBConverter() }; private static void printHelp() { System.out.println("Usage: [module] [args]"); @@ -22,19 +24,17 @@ private static void printHelp() { public static void main(String[] args) { if (args.length > 0) { - for (Module m : modules) - if (args[0].equals(m.name())) { - String[] args2 = new String[args.length - 1]; - System.arraycopy(args, 1, args2, 0, args2.length); - m.main(args2); + for (Module m : modules) if (args[0].equals(m.name())) { + String[] args2 = new String[args.length - 1]; + System.arraycopy(args, 1, args2, 0, args2.length); + m.main(args2); + return; + } + if (args[0].equals("-h") && args.length >= 2) { + for (Module m : modules) if (args[1].equals(m.name())) { + m.printHelp(); return; } - if (args[0].equals("-h") && args.length >= 2) { - for (Module m : modules) - if (args[1].equals(m.name())) { - m.printHelp(); - return; - } } } printHelp(); diff --git a/src/main/java/codechicken/lib/tool/module/JOptModule.java b/src/main/java/codechicken/lib/tool/module/JOptModule.java index 9e72b81..206bcb0 100644 --- a/src/main/java/codechicken/lib/tool/module/JOptModule.java +++ b/src/main/java/codechicken/lib/tool/module/JOptModule.java @@ -1,12 +1,14 @@ package codechicken.lib.tool.module; -import codechicken.lib.tool.ToolMain; import java.io.IOException; + import joptsimple.OptionException; import joptsimple.OptionParser; import joptsimple.OptionSet; +import codechicken.lib.tool.ToolMain; public abstract class JOptModule implements ToolMain.Module { + OptionParser parser = new OptionParser(); @Override diff --git a/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java index 57bbfae..b9e3048 100644 --- a/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java +++ b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java @@ -2,22 +2,19 @@ import static java.util.Arrays.asList; -import codechicken.lib.render.QBImporter; import java.io.File; + import joptsimple.OptionParser; import joptsimple.OptionSet; +import codechicken.lib.render.QBImporter; public class ModuleQBConverter extends JOptModule { + public ModuleQBConverter() { parser.acceptsAll(asList("?", "h", "help"), "Show the help"); parser.acceptsAll(asList("i", "input"), "comma separated list of paths to models (.qb or directories)") - .withRequiredArg() - .ofType(File.class) - .withValuesSeparatedBy(',') - .required(); - parser.acceptsAll(asList("o", "out"), "Output Directory") - .withRequiredArg() - .ofType(File.class); + .withRequiredArg().ofType(File.class).withValuesSeparatedBy(',').required(); + parser.acceptsAll(asList("o", "out"), "Output Directory").withRequiredArg().ofType(File.class); parser.acceptsAll( asList("o2", "textureplanes"), "2nd level optimisation. Merges coplanar polygons. Increases texture size"); diff --git a/src/main/java/codechicken/lib/util/Copyable.java b/src/main/java/codechicken/lib/util/Copyable.java index 2f78c39..ae3de9a 100644 --- a/src/main/java/codechicken/lib/util/Copyable.java +++ b/src/main/java/codechicken/lib/util/Copyable.java @@ -1,5 +1,6 @@ package codechicken.lib.util; public interface Copyable { + public T copy(); } diff --git a/src/main/java/codechicken/lib/util/LangProxy.java b/src/main/java/codechicken/lib/util/LangProxy.java index a29cf8c..0fbebc8 100644 --- a/src/main/java/codechicken/lib/util/LangProxy.java +++ b/src/main/java/codechicken/lib/util/LangProxy.java @@ -3,6 +3,7 @@ import net.minecraft.util.StatCollector; public class LangProxy { + public final String namespace; public LangProxy(String namespace) { diff --git a/src/main/java/codechicken/lib/vec/AxisCycle.java b/src/main/java/codechicken/lib/vec/AxisCycle.java index 2de5767..eafcb70 100644 --- a/src/main/java/codechicken/lib/vec/AxisCycle.java +++ b/src/main/java/codechicken/lib/vec/AxisCycle.java @@ -1,39 +1,39 @@ package codechicken.lib.vec; public class AxisCycle { - public static Transformation[] cycles = new Transformation[] { - new RedundantTransformation(), - new VariableTransformation(new Matrix4(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d0 = vec.x; - double d1 = vec.y; - double d2 = vec.z; - vec.x = d2; - vec.y = d0; - vec.z = d1; - } - @Override - public Transformation inverse() { - return cycles[2]; - } - }, - new VariableTransformation(new Matrix4(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d0 = vec.x; - double d1 = vec.y; - double d2 = vec.z; - vec.x = d1; - vec.y = d2; - vec.z = d0; - } + public static Transformation[] cycles = new Transformation[] { new RedundantTransformation(), + new VariableTransformation(new Matrix4(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)) { - @Override - public Transformation inverse() { - return cycles[1]; - } - } - }; + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + double d2 = vec.z; + vec.x = d2; + vec.y = d0; + vec.z = d1; + } + + @Override + public Transformation inverse() { + return cycles[2]; + } + }, new VariableTransformation(new Matrix4(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + double d2 = vec.z; + vec.x = d1; + vec.y = d2; + vec.z = d0; + } + + @Override + public Transformation inverse() { + return cycles[1]; + } + } }; } diff --git a/src/main/java/codechicken/lib/vec/BlockCoord.java b/src/main/java/codechicken/lib/vec/BlockCoord.java index bc64997..adcecbc 100644 --- a/src/main/java/codechicken/lib/vec/BlockCoord.java +++ b/src/main/java/codechicken/lib/vec/BlockCoord.java @@ -1,10 +1,12 @@ package codechicken.lib.vec; +import net.minecraft.tileentity.TileEntity; + import codechicken.lib.math.MathHelper; import codechicken.lib.util.Copyable; -import net.minecraft.tileentity.TileEntity; public class BlockCoord implements Comparable, Copyable { + public int x; public int y; public int z; @@ -162,17 +164,11 @@ public BlockCoord setSide(int s, int v) { return this; } - public static final BlockCoord[] sideOffsets = new BlockCoord[] { - new BlockCoord(0, -1, 0), - new BlockCoord(0, 1, 0), - new BlockCoord(0, 0, -1), - new BlockCoord(0, 0, 1), - new BlockCoord(-1, 0, 0), - new BlockCoord(1, 0, 0) - }; + public static final BlockCoord[] sideOffsets = new BlockCoord[] { new BlockCoord(0, -1, 0), new BlockCoord(0, 1, 0), + new BlockCoord(0, 0, -1), new BlockCoord(0, 0, 1), new BlockCoord(-1, 0, 0), new BlockCoord(1, 0, 0) }; public int[] intArray() { - return new int[] {x, y, z}; + return new int[] { x, y, z }; } public BlockCoord copy() { diff --git a/src/main/java/codechicken/lib/vec/Cuboid6.java b/src/main/java/codechicken/lib/vec/Cuboid6.java index 66f0f28..2c0e572 100644 --- a/src/main/java/codechicken/lib/vec/Cuboid6.java +++ b/src/main/java/codechicken/lib/vec/Cuboid6.java @@ -1,13 +1,16 @@ package codechicken.lib.vec; -import codechicken.lib.util.Copyable; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; + import net.minecraft.block.Block; import net.minecraft.util.AxisAlignedBB; +import codechicken.lib.util.Copyable; + public class Cuboid6 implements Copyable { + public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); public Vector3 min; @@ -84,8 +87,7 @@ public void setBlockBounds(Block block) { } public boolean intersects(Cuboid6 b) { - return max.x - 1E-5 > b.min.x - && b.max.x - 1E-5 > min.x + return max.x - 1E-5 > b.min.x && b.max.x - 1E-5 > min.x && max.y - 1E-5 > b.min.y && b.max.y - 1E-5 > min.y && max.z - 1E-5 > b.min.z @@ -108,9 +110,18 @@ public static boolean intersects(Cuboid6 a, Cuboid6 b) { public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Cuboid: (" + new BigDecimal(min.x, cont) + ", " + new BigDecimal(min.y, cont) + ", " - + new BigDecimal(min.z, cont) + ") -> (" + new BigDecimal(max.x, cont) + ", " - + new BigDecimal(max.y, cont) + ", " + new BigDecimal(max.z, cont) + ")"; + return "Cuboid: (" + new BigDecimal(min.x, cont) + + ", " + + new BigDecimal(min.y, cont) + + ", " + + new BigDecimal(min.z, cont) + + ") -> (" + + new BigDecimal(max.x, cont) + + ", " + + new BigDecimal(max.y, cont) + + ", " + + new BigDecimal(max.z, cont) + + ")"; } public Cuboid6 enclose(Vector3 vec) { diff --git a/src/main/java/codechicken/lib/vec/CuboidCoord.java b/src/main/java/codechicken/lib/vec/CuboidCoord.java index 0348a29..29448fc 100644 --- a/src/main/java/codechicken/lib/vec/CuboidCoord.java +++ b/src/main/java/codechicken/lib/vec/CuboidCoord.java @@ -1,10 +1,13 @@ package codechicken.lib.vec; -import codechicken.lib.util.Copyable; import java.util.Iterator; + import net.minecraft.util.AxisAlignedBB; +import codechicken.lib.util.Copyable; + public class CuboidCoord implements Iterable, Copyable { + public BlockCoord min; public BlockCoord max; @@ -42,7 +45,7 @@ public CuboidCoord expand(int x, int y, int z) { public CuboidCoord expand(int side, int amount) { if (side % 2 == 0) // negative side - min = min.offset(side, amount); + min = min.offset(side, amount); else max = max.offset(side, amount); return this; } @@ -125,7 +128,9 @@ public int getVolume() { public Vector3 getCenterVec() { return new Vector3( - min.x + (max.x - min.x + 1) / 2D, min.y + (max.y - min.y + 1) / 2D, min.z + (max.z - min.z + 1) / 2D); + min.x + (max.x - min.x + 1) / 2D, + min.y + (max.y - min.y + 1) / 2D, + min.z + (max.z - min.z + 1) / 2D); } public BlockCoord getCenter(BlockCoord store) { @@ -142,7 +147,7 @@ public boolean contains(int x, int y, int z) { } public int[] intArray() { - return new int[] {min.x, min.y, min.z, max.x, max.y, max.z}; + return new int[] { min.x, min.y, min.z, max.x, max.y, max.z }; } public CuboidCoord copy() { @@ -197,6 +202,7 @@ public CuboidCoord include(int x, int y, int z) { public Iterator iterator() { return new Iterator() { + BlockCoord b = null; public boolean hasNext() { diff --git a/src/main/java/codechicken/lib/vec/ITransformation.java b/src/main/java/codechicken/lib/vec/ITransformation.java index 06f2819..8df95a9 100644 --- a/src/main/java/codechicken/lib/vec/ITransformation.java +++ b/src/main/java/codechicken/lib/vec/ITransformation.java @@ -2,10 +2,12 @@ /** * Abstract supertype for any VectorN transformation - * @param The vector type + * + * @param The vector type * @param The transformation type */ public abstract class ITransformation { + /** * Applies this transformation to vec */ @@ -18,20 +20,22 @@ public abstract class ITransformation= Math.min(line1.pt1.x, line1.pt2.x) - tol - && store.x >= Math.min(line2.pt1.x, line2.pt2.x) - tol + if (store.x >= Math.min(line1.pt1.x, line1.pt2.x) - tol && store.x >= Math.min(line2.pt1.x, line2.pt2.x) - tol && store.z >= Math.min(line1.pt1.z, line1.pt2.z) - tol && store.z >= Math.min(line2.pt1.z, line2.pt2.z) - tol && store.x <= Math.max(line1.pt1.x, line1.pt2.x) + tol && store.x <= Math.max(line2.pt1.x, line2.pt2.x) + tol && store.z <= Math.max(line1.pt1.z, line1.pt2.z) + tol - && store.z <= Math.max(line2.pt1.z, line2.pt2.z) + tol) return true; + && store.z <= Math.max(line2.pt1.z, line2.pt2.z) + tol) + return true; return false; } diff --git a/src/main/java/codechicken/lib/vec/Matrix4.java b/src/main/java/codechicken/lib/vec/Matrix4.java index fab8e52..0d51d52 100644 --- a/src/main/java/codechicken/lib/vec/Matrix4.java +++ b/src/main/java/codechicken/lib/vec/Matrix4.java @@ -1,19 +1,22 @@ package codechicken.lib.vec; -import codechicken.lib.util.Copyable; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.DoubleBuffer; + import org.lwjgl.opengl.GL11; +import codechicken.lib.util.Copyable; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class Matrix4 extends Transformation implements Copyable { - private static DoubleBuffer glBuf = - ByteBuffer.allocateDirect(16 * 8).order(ByteOrder.nativeOrder()).asDoubleBuffer(); + + private static DoubleBuffer glBuf = ByteBuffer.allocateDirect(16 * 8).order(ByteOrder.nativeOrder()) + .asDoubleBuffer(); // m public double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; @@ -22,23 +25,8 @@ public Matrix4() { m00 = m11 = m22 = m33 = 1; } - public Matrix4( - double d00, - double d01, - double d02, - double d03, - double d10, - double d11, - double d12, - double d13, - double d20, - double d21, - double d22, - double d23, - double d30, - double d31, - double d32, - double d33) { + public Matrix4(double d00, double d01, double d02, double d03, double d10, double d11, double d12, double d13, + double d20, double d21, double d22, double d23, double d30, double d31, double d32, double d33) { m00 = d00; m01 = d01; m02 = d02; @@ -315,14 +303,41 @@ public void applyN(Vector3 vec) { @Override public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "[" + new BigDecimal(m00, cont) + "," + new BigDecimal(m01, cont) + "," + new BigDecimal(m02, cont) + "," - + new BigDecimal(m03, cont) + "]\n" + "[" - + new BigDecimal(m10, cont) + "," + new BigDecimal(m11, cont) + "," + new BigDecimal(m12, cont) + "," - + new BigDecimal(m13, cont) + "]\n" + "[" - + new BigDecimal(m20, cont) + "," + new BigDecimal(m21, cont) + "," + new BigDecimal(m22, cont) + "," - + new BigDecimal(m23, cont) + "]\n" + "[" - + new BigDecimal(m30, cont) + "," + new BigDecimal(m31, cont) + "," + new BigDecimal(m32, cont) + "," - + new BigDecimal(m33, cont) + "]"; + return "[" + new BigDecimal(m00, cont) + + "," + + new BigDecimal(m01, cont) + + "," + + new BigDecimal(m02, cont) + + "," + + new BigDecimal(m03, cont) + + "]\n" + + "[" + + new BigDecimal(m10, cont) + + "," + + new BigDecimal(m11, cont) + + "," + + new BigDecimal(m12, cont) + + "," + + new BigDecimal(m13, cont) + + "]\n" + + "[" + + new BigDecimal(m20, cont) + + "," + + new BigDecimal(m21, cont) + + "," + + new BigDecimal(m22, cont) + + "," + + new BigDecimal(m23, cont) + + "]\n" + + "[" + + new BigDecimal(m30, cont) + + "," + + new BigDecimal(m31, cont) + + "," + + new BigDecimal(m32, cont) + + "," + + new BigDecimal(m33, cont) + + "]"; } public Matrix4 apply(Transformation t) { @@ -333,22 +348,8 @@ public Matrix4 apply(Transformation t) { @Override @SideOnly(Side.CLIENT) public void glApply() { - glBuf.put(m00) - .put(m10) - .put(m20) - .put(m30) - .put(m01) - .put(m11) - .put(m21) - .put(m31) - .put(m02) - .put(m12) - .put(m22) - .put(m32) - .put(m03) - .put(m13) - .put(m23) - .put(m33); + glBuf.put(m00).put(m10).put(m20).put(m30).put(m01).put(m11).put(m21).put(m31).put(m02).put(m12).put(m22) + .put(m32).put(m03).put(m13).put(m23).put(m33); glBuf.flip(); GL11.glMultMatrix(glBuf); } diff --git a/src/main/java/codechicken/lib/vec/Quat.java b/src/main/java/codechicken/lib/vec/Quat.java index 0bcf88e..da2ac5d 100644 --- a/src/main/java/codechicken/lib/vec/Quat.java +++ b/src/main/java/codechicken/lib/vec/Quat.java @@ -1,12 +1,14 @@ package codechicken.lib.vec; -import codechicken.lib.math.MathHelper; -import codechicken.lib.util.Copyable; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import codechicken.lib.math.MathHelper; +import codechicken.lib.util.Copyable; + public class Quat implements Copyable { + public double x; public double y; public double z; @@ -128,8 +130,14 @@ public void rotate(Vector3 vec) { public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Quat(" + new BigDecimal(s, cont) + ", " + new BigDecimal(x, cont) + ", " + new BigDecimal(y, cont) - + ", " + new BigDecimal(z, cont) + ")"; + return "Quat(" + new BigDecimal(s, cont) + + ", " + + new BigDecimal(x, cont) + + ", " + + new BigDecimal(y, cont) + + ", " + + new BigDecimal(z, cont) + + ")"; } public Rotation rotation() { diff --git a/src/main/java/codechicken/lib/vec/Rectangle4i.java b/src/main/java/codechicken/lib/vec/Rectangle4i.java index 9c9f942..9dd6e81 100644 --- a/src/main/java/codechicken/lib/vec/Rectangle4i.java +++ b/src/main/java/codechicken/lib/vec/Rectangle4i.java @@ -1,6 +1,7 @@ package codechicken.lib.vec; public class Rectangle4i { + public int x; public int y; public int w; diff --git a/src/main/java/codechicken/lib/vec/RedundantTransformation.java b/src/main/java/codechicken/lib/vec/RedundantTransformation.java index 664467c..d58da7f 100644 --- a/src/main/java/codechicken/lib/vec/RedundantTransformation.java +++ b/src/main/java/codechicken/lib/vec/RedundantTransformation.java @@ -4,6 +4,7 @@ import cpw.mods.fml.relauncher.SideOnly; public class RedundantTransformation extends Transformation { + @Override public void apply(Vector3 vec) {} diff --git a/src/main/java/codechicken/lib/vec/Rotation.java b/src/main/java/codechicken/lib/vec/Rotation.java index 5890fa5..15c50e2 100644 --- a/src/main/java/codechicken/lib/vec/Rotation.java +++ b/src/main/java/codechicken/lib/vec/Rotation.java @@ -1,162 +1,151 @@ package codechicken.lib.vec; -import codechicken.lib.math.MathHelper; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; + import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; + import org.lwjgl.opengl.GL11; +import codechicken.lib.math.MathHelper; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class Rotation extends Transformation { + /** * Clockwise pi/2 about y looking down */ - public static Transformation[] quarterRotations = new Transformation[] { - new RedundantTransformation(), - new VariableTransformation(new Matrix4(0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d1 = vec.x; - double d2 = vec.z; - vec.x = -d2; - vec.z = d1; - } - - @Override - public Transformation inverse() { - return quarterRotations[3]; - } - }, - new VariableTransformation(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - vec.x = -vec.x; - vec.z = -vec.z; - } - - @Override - public Transformation inverse() { - return this; - } - }, - new VariableTransformation(new Matrix4(0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d1 = vec.x; - double d2 = vec.z; - vec.x = d2; - vec.z = -d1; - } - - @Override - public Transformation inverse() { - return quarterRotations[1]; - } - } - }; - - public static Transformation[] sideRotations = new Transformation[] { - new RedundantTransformation(), - new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - vec.y = -vec.y; - vec.z = -vec.z; - } - - @Override - public Transformation inverse() { - return this; - } - }, - new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d1 = vec.y; - double d2 = vec.z; - vec.y = -d2; - vec.z = d1; - } - - @Override - public Transformation inverse() { - return sideRotations[3]; - } - }, - new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d1 = vec.y; - double d2 = vec.z; - vec.y = d2; - vec.z = -d1; - } - - @Override - public Transformation inverse() { - return sideRotations[2]; - } - }, - new VariableTransformation(new Matrix4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d0 = vec.x; - double d1 = vec.y; - vec.x = d1; - vec.y = -d0; - } - - @Override - public Transformation inverse() { - return sideRotations[5]; - } - }, - new VariableTransformation(new Matrix4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) { - @Override - public void apply(Vector3 vec) { - double d0 = vec.x; - double d1 = vec.y; - vec.x = -d1; - vec.y = d0; - } - - @Override - public Transformation inverse() { - return sideRotations[4]; - } - } - }; - - public static Vector3[] axes = new Vector3[] { - new Vector3(0, -1, 0), - new Vector3(0, 1, 0), - new Vector3(0, 0, -1), - new Vector3(0, 0, 1), - new Vector3(-1, 0, 0), - new Vector3(1, 0, 0) - }; - - public static int[] sideRotMap = new int[] { - 3, 4, 2, 5, - 3, 5, 2, 4, - 1, 5, 0, 4, - 1, 4, 0, 5, - 1, 2, 0, 3, - 1, 3, 0, 2 - }; - - public static int[] rotSideMap = new int[] { - -1, -1, 2, 0, 1, 3, -1, -1, 2, 0, 3, 1, 2, 0, -1, -1, 3, 1, 2, 0, -1, -1, 1, 3, 2, 0, 1, 3, -1, -1, 2, 0, 3, 1, - -1, -1 - }; + public static Transformation[] quarterRotations = new Transformation[] { new RedundantTransformation(), + new VariableTransformation(new Matrix4(0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d1 = vec.x; + double d2 = vec.z; + vec.x = -d2; + vec.z = d1; + } + + @Override + public Transformation inverse() { + return quarterRotations[3]; + } + }, new VariableTransformation(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + vec.x = -vec.x; + vec.z = -vec.z; + } + + @Override + public Transformation inverse() { + return this; + } + }, new VariableTransformation(new Matrix4(0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d1 = vec.x; + double d2 = vec.z; + vec.x = d2; + vec.z = -d1; + } + + @Override + public Transformation inverse() { + return quarterRotations[1]; + } + } }; + + public static Transformation[] sideRotations = new Transformation[] { new RedundantTransformation(), + new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + vec.y = -vec.y; + vec.z = -vec.z; + } + + @Override + public Transformation inverse() { + return this; + } + }, new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d1 = vec.y; + double d2 = vec.z; + vec.y = -d2; + vec.z = d1; + } + + @Override + public Transformation inverse() { + return sideRotations[3]; + } + }, new VariableTransformation(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d1 = vec.y; + double d2 = vec.z; + vec.y = d2; + vec.z = -d1; + } + + @Override + public Transformation inverse() { + return sideRotations[2]; + } + }, new VariableTransformation(new Matrix4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + vec.x = d1; + vec.y = -d0; + } + + @Override + public Transformation inverse() { + return sideRotations[5]; + } + }, new VariableTransformation(new Matrix4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) { + + @Override + public void apply(Vector3 vec) { + double d0 = vec.x; + double d1 = vec.y; + vec.x = -d1; + vec.y = d0; + } + + @Override + public Transformation inverse() { + return sideRotations[4]; + } + } }; + + public static Vector3[] axes = new Vector3[] { new Vector3(0, -1, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1), + new Vector3(0, 0, 1), new Vector3(-1, 0, 0), new Vector3(1, 0, 0) }; + + public static int[] sideRotMap = new int[] { 3, 4, 2, 5, 3, 5, 2, 4, 1, 5, 0, 4, 1, 4, 0, 5, 1, 2, 0, 3, 1, 3, 0, + 2 }; + + public static int[] rotSideMap = new int[] { -1, -1, 2, 0, 1, 3, -1, -1, 2, 0, 3, 1, 2, 0, -1, -1, 3, 1, 2, 0, -1, + -1, 1, 3, 2, 0, 1, 3, -1, -1, 2, 0, 3, 1, -1, -1 }; /** - * Rotate pi/2 * this offset for [side] about y axis before rotating to the side for the rotation indicies to line up + * Rotate pi/2 * this offset for [side] about y axis before rotating to the side for the rotation indicies to line + * up */ - public static int[] sideRotOffsets = new int[] {0, 2, 2, 0, 1, 3}; + public static int[] sideRotOffsets = new int[] { 0, 2, 2, 0, 1, 3 }; public static int rotateSide(int s, int r) { return sideRotMap[s << 2 | r]; @@ -172,7 +161,7 @@ public static int rotationTo(int s1, int s2) { /** * @param player The placing player, used for obtaining the look vector - * @param side The side of the block being placed on + * @param side The side of the block being placed on * @return The rotation for the face == side^1 */ public static int getSidedRotation(EntityPlayer player, int side) { @@ -294,7 +283,13 @@ public boolean isRedundant() { @Override public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Rotation(" + new BigDecimal(angle, cont) + ", " + new BigDecimal(axis.x, cont) + ", " - + new BigDecimal(axis.y, cont) + ", " + new BigDecimal(axis.z, cont) + ")"; + return "Rotation(" + new BigDecimal(angle, cont) + + ", " + + new BigDecimal(axis.x, cont) + + ", " + + new BigDecimal(axis.y, cont) + + ", " + + new BigDecimal(axis.z, cont) + + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/Scale.java b/src/main/java/codechicken/lib/vec/Scale.java index 8428d57..19b2e8c 100644 --- a/src/main/java/codechicken/lib/vec/Scale.java +++ b/src/main/java/codechicken/lib/vec/Scale.java @@ -1,13 +1,16 @@ package codechicken.lib.vec; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; + import org.lwjgl.opengl.GL11; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class Scale extends Transformation { + public Vector3 factor; public Scale(Vector3 factor) { @@ -61,7 +64,11 @@ public boolean isRedundant() { @Override public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Scale(" + new BigDecimal(factor.x, cont) + ", " + new BigDecimal(factor.y, cont) + ", " - + new BigDecimal(factor.z, cont) + ")"; + return "Scale(" + new BigDecimal(factor.x, cont) + + ", " + + new BigDecimal(factor.y, cont) + + ", " + + new BigDecimal(factor.z, cont) + + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/SwapYZ.java b/src/main/java/codechicken/lib/vec/SwapYZ.java index 0f965e6..ad256dd 100644 --- a/src/main/java/codechicken/lib/vec/SwapYZ.java +++ b/src/main/java/codechicken/lib/vec/SwapYZ.java @@ -1,6 +1,7 @@ package codechicken.lib.vec; public class SwapYZ extends VariableTransformation { + public SwapYZ() { super(new Matrix4(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1)); } diff --git a/src/main/java/codechicken/lib/vec/Transformation.java b/src/main/java/codechicken/lib/vec/Transformation.java index 9302109..7d9aa72 100644 --- a/src/main/java/codechicken/lib/vec/Transformation.java +++ b/src/main/java/codechicken/lib/vec/Transformation.java @@ -9,16 +9,19 @@ */ public abstract class Transformation extends ITransformation implements CCRenderState.IVertexOperation { + public static final int operationIndex = CCRenderState.registerOperation(); /** * Applies this transformation to a normal (doesn't translate) + * * @param normal The normal to transform */ public abstract void applyN(Vector3 normal); /** * Applies this transformation to a matrix as a multiplication on the right hand side. + * * @param mat The matrix to combine this transformation with */ public abstract void apply(Matrix4 mat); diff --git a/src/main/java/codechicken/lib/vec/TransformationList.java b/src/main/java/codechicken/lib/vec/TransformationList.java index 12f4f5c..0e5605e 100644 --- a/src/main/java/codechicken/lib/vec/TransformationList.java +++ b/src/main/java/codechicken/lib/vec/TransformationList.java @@ -1,11 +1,13 @@ package codechicken.lib.vec; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.util.ArrayList; import java.util.Iterator; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class TransformationList extends Transformation { + private ArrayList transformations = new ArrayList(); private Matrix4 mat; @@ -20,14 +22,14 @@ public TransformationList(Transformation... transforms) { public Matrix4 compile() { if (mat == null) { mat = new Matrix4(); - for (int i = transformations.size() - 1; i >= 0; i--) - transformations.get(i).apply(mat); + for (int i = transformations.size() - 1; i >= 0; i--) transformations.get(i).apply(mat); } return mat; } /** * Returns a global space matrix as opposed to an object space matrix (reverse application order) + * * @return */ public Matrix4 reverseCompile() { @@ -39,17 +41,13 @@ public Matrix4 reverseCompile() { @Override public void apply(Vector3 vec) { if (mat != null) mat.apply(vec); - else - for (int i = 0; i < transformations.size(); i++) - transformations.get(i).apply(vec); + else for (int i = 0; i < transformations.size(); i++) transformations.get(i).apply(vec); } @Override public void applyN(Vector3 normal) { if (mat != null) mat.applyN(normal); - else - for (int i = 0; i < transformations.size(); i++) - transformations.get(i).applyN(normal); + else for (int i = 0; i < transformations.size(); i++) transformations.get(i).applyN(normal); } @Override @@ -114,15 +112,13 @@ public boolean isRedundant() { @Override @SideOnly(Side.CLIENT) public void glApply() { - for (int i = transformations.size() - 1; i >= 0; i--) - transformations.get(i).glApply(); + for (int i = transformations.size() - 1; i >= 0; i--) transformations.get(i).glApply(); } @Override public Transformation inverse() { TransformationList rev = new TransformationList(); - for (int i = transformations.size() - 1; i >= 0; i--) - rev.with(transformations.get(i).inverse()); + for (int i = transformations.size() - 1; i >= 0; i--) rev.with(transformations.get(i).inverse()); return rev; } diff --git a/src/main/java/codechicken/lib/vec/Translation.java b/src/main/java/codechicken/lib/vec/Translation.java index 3e29216..f6f0a5e 100644 --- a/src/main/java/codechicken/lib/vec/Translation.java +++ b/src/main/java/codechicken/lib/vec/Translation.java @@ -1,13 +1,16 @@ package codechicken.lib.vec; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; + import org.lwjgl.opengl.GL11; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class Translation extends Transformation { + public Vector3 vec; public Translation(Vector3 vec) { @@ -62,7 +65,11 @@ public boolean isRedundant() { @Override public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Translation(" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " - + new BigDecimal(vec.z, cont) + ")"; + return "Translation(" + new BigDecimal(vec.x, cont) + + ", " + + new BigDecimal(vec.y, cont) + + ", " + + new BigDecimal(vec.z, cont) + + ")"; } } diff --git a/src/main/java/codechicken/lib/vec/VariableTransformation.java b/src/main/java/codechicken/lib/vec/VariableTransformation.java index bab385b..28669a2 100644 --- a/src/main/java/codechicken/lib/vec/VariableTransformation.java +++ b/src/main/java/codechicken/lib/vec/VariableTransformation.java @@ -4,6 +4,7 @@ import cpw.mods.fml.relauncher.SideOnly; public abstract class VariableTransformation extends Transformation { + public Matrix4 mat; public VariableTransformation(Matrix4 mat) { diff --git a/src/main/java/codechicken/lib/vec/Vector3.java b/src/main/java/codechicken/lib/vec/Vector3.java index e5cba67..5e907c0 100644 --- a/src/main/java/codechicken/lib/vec/Vector3.java +++ b/src/main/java/codechicken/lib/vec/Vector3.java @@ -1,20 +1,24 @@ package codechicken.lib.vec; -import codechicken.lib.math.MathHelper; -import codechicken.lib.util.Copyable; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; + import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Vec3; + import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; import org.lwjgl.util.vector.Vector4f; +import codechicken.lib.math.MathHelper; +import codechicken.lib.util.Copyable; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class Vector3 implements Copyable { + public static Vector3 zero = new Vector3(); public static Vector3 one = new Vector3(1, 1, 1); public static Vector3 center = new Vector3(0.5, 0.5, 0.5); @@ -223,7 +227,11 @@ public Vector3 normalize() { public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); - return "Vector3(" + new BigDecimal(x, cont) + ", " + new BigDecimal(y, cont) + ", " + new BigDecimal(z, cont) + return "Vector3(" + new BigDecimal(x, cont) + + ", " + + new BigDecimal(y, cont) + + ", " + + new BigDecimal(z, cont) + ")"; } @@ -390,11 +398,11 @@ public boolean equals(Object o) { /** * Equals method with tolerance + * * @return true if this is equal to v within +-1E-5 */ public boolean equalsT(Vector3 v) { - return MathHelper.between(x - 1E-5, v.x, x + 1E-5) - && MathHelper.between(y - 1E-5, v.y, y + 1E-5) + return MathHelper.between(x - 1E-5, v.x, x + 1E-5) && MathHelper.between(y - 1E-5, v.y, y + 1E-5) && MathHelper.between(z - 1E-5, v.z, z + 1E-5); } diff --git a/src/main/java/codechicken/lib/world/ChunkExtension.java b/src/main/java/codechicken/lib/world/ChunkExtension.java index 6b830d1..d376dd0 100644 --- a/src/main/java/codechicken/lib/world/ChunkExtension.java +++ b/src/main/java/codechicken/lib/world/ChunkExtension.java @@ -1,6 +1,7 @@ package codechicken.lib.world; import java.util.HashSet; + import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.Packet; @@ -8,6 +9,7 @@ import net.minecraft.world.chunk.Chunk; public abstract class ChunkExtension { + public final Chunk chunk; public final ChunkCoordIntPair coord; public final WorldExtension world; diff --git a/src/main/java/codechicken/lib/world/IChunkLoadTile.java b/src/main/java/codechicken/lib/world/IChunkLoadTile.java index 8e53c76..5e914df 100644 --- a/src/main/java/codechicken/lib/world/IChunkLoadTile.java +++ b/src/main/java/codechicken/lib/world/IChunkLoadTile.java @@ -1,11 +1,13 @@ package codechicken.lib.world; /** - * Provides a callback for tile entities when a chunk is loaded, as an alternative to validate when the chunk hasn't been added to the world. - * To hook all world join/seperate events. Use this, TileEntity.validate with a worldObj.blockExists check, TileEntity.onChunkUnload and TileEntity.invalidate - * Be sure to call TileChunkLoadHook.init() from your mod during initialisation - * You could easily implement this in your own mod, but providing it here reduces the number of times the chunkTileEntityMap needs to be iterated + * Provides a callback for tile entities when a chunk is loaded, as an alternative to validate when the chunk hasn't + * been added to the world. To hook all world join/seperate events. Use this, TileEntity.validate with a + * worldObj.blockExists check, TileEntity.onChunkUnload and TileEntity.invalidate Be sure to call + * TileChunkLoadHook.init() from your mod during initialisation You could easily implement this in your own mod, but + * providing it here reduces the number of times the chunkTileEntityMap needs to be iterated */ public interface IChunkLoadTile { + public void onChunkLoad(); } diff --git a/src/main/java/codechicken/lib/world/TileChunkLoadHook.java b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java index 7e75cbd..1ca6bba 100644 --- a/src/main/java/codechicken/lib/world/TileChunkLoadHook.java +++ b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java @@ -1,13 +1,16 @@ package codechicken.lib.world; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; import java.util.ArrayList; import java.util.List; + import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.ChunkEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; + public class TileChunkLoadHook { + private static boolean init; public static void init() { @@ -19,8 +22,7 @@ public static void init() { @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { - List list = - new ArrayList(event.getChunk().chunkTileEntityMap.values()); + List list = new ArrayList(event.getChunk().chunkTileEntityMap.values()); for (TileEntity t : list) if (t instanceof IChunkLoadTile) ((IChunkLoadTile) t).onChunkLoad(); } } diff --git a/src/main/java/codechicken/lib/world/WorldExtension.java b/src/main/java/codechicken/lib/world/WorldExtension.java index b074e46..7c3cd46 100644 --- a/src/main/java/codechicken/lib/world/WorldExtension.java +++ b/src/main/java/codechicken/lib/world/WorldExtension.java @@ -1,12 +1,14 @@ package codechicken.lib.world; import java.util.HashMap; + import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; public abstract class WorldExtension { + public final World world; public HashMap chunkMap = new HashMap(); diff --git a/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java index fbd93ea..38a4582 100644 --- a/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java +++ b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java @@ -4,6 +4,7 @@ import net.minecraft.world.chunk.Chunk; public abstract class WorldExtensionInstantiator { + public int instantiatorID; public abstract WorldExtension createWorldExtension(World world); diff --git a/src/main/java/codechicken/lib/world/WorldExtensionManager.java b/src/main/java/codechicken/lib/world/WorldExtensionManager.java index a121379..4831dc5 100644 --- a/src/main/java/codechicken/lib/world/WorldExtensionManager.java +++ b/src/main/java/codechicken/lib/world/WorldExtensionManager.java @@ -1,12 +1,8 @@ package codechicken.lib.world; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.TickEvent; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import java.util.ArrayList; import java.util.HashMap; + import net.minecraft.client.Minecraft; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -18,8 +14,16 @@ import net.minecraftforge.event.world.ChunkWatchEvent.Watch; import net.minecraftforge.event.world.WorldEvent; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class WorldExtensionManager { + public static class WorldExtensionEventHandler { + @SubscribeEvent public void onChunkDataLoad(ChunkDataEvent.Load event) { if (!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); @@ -70,7 +74,7 @@ public void onWorldLoad(WorldEvent.Load event) { @SubscribeEvent public void onWorldUnLoad(WorldEvent.Unload event) { if (worldMap.containsKey(event.world)) // because force closing unloads a world twice - for (WorldExtension extension : worldMap.remove(event.world)) extension.unload(); + for (WorldExtension extension : worldMap.remove(event.world)) extension.unload(); } @SubscribeEvent @@ -92,9 +96,8 @@ public void onChunkUnWatch(UnWatch event) { @SideOnly(Side.CLIENT) public void clientTick(TickEvent.ClientTickEvent event) { World world = Minecraft.getMinecraft().theWorld; - if (worldMap.containsKey(world)) - if (event.phase == TickEvent.Phase.START) preTick(world); - else postTick(world); + if (worldMap.containsKey(world)) if (event.phase == TickEvent.Phase.START) preTick(world); + else postTick(world); } @SubscribeEvent @@ -107,8 +110,7 @@ public void serverTick(TickEvent.WorldTickEvent event) { } private static boolean initialised; - private static ArrayList extensionIntialisers = - new ArrayList(); + private static ArrayList extensionIntialisers = new ArrayList(); public static void registerWorldExtension(WorldExtensionInstantiator init) { if (!initialised) init(); @@ -137,9 +139,8 @@ private static void onWorldLoad(World world) { private static void createChunkExtension(World world, Chunk chunk) { WorldExtension[] extensions = worldMap.get(world); - for (int i = 0; i < extensionIntialisers.size(); i++) - if (!extensions[i].containsChunk(chunk)) - extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); + for (int i = 0; i < extensionIntialisers.size(); i++) if (!extensions[i].containsChunk(chunk)) + extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); } private static void removeChunk(World world, Chunk chunk) { From d183e6d9a9f9e92686680b29b67e6bf1d3de681b Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 10:33:49 +0000 Subject: [PATCH 166/219] [ci skip] Add git-blame-ignore-revs for spotlessApply --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..3563c3d --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Ignore spotlessApply reformat +a4515fbef8382f0f961ade90ca82c85d924fc06d From 777235b7fb7db52c8e832cdd291bd1b512ba52aa Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:08:35 +0000 Subject: [PATCH 167/219] Release with RFG From de334d86f6b6550dc270c3e0190819c10fdd5d6f Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:13:42 +0000 Subject: [PATCH 168/219] [ci skip] Fix addon.gradle for RFG --- addon.gradle | 6 +++--- dependencies.gradle | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addon.gradle b/addon.gradle index 321d20b..8d81619 100644 --- a/addon.gradle +++ b/addon.gradle @@ -1,8 +1,8 @@ minecraft { if (replaceGradleTokenInFile) { - replaceIn "CodeChickenCorePlugin.java" + tagReplacementFiles.add "CodeChickenCorePlugin.java" if(gradleTokenVersion) { - replace gradleTokenVersion, versionDetails().lastTag + injectedTags.put gradleTokenVersion, versionDetails().lastTag } } -} \ No newline at end of file +} diff --git a/dependencies.gradle b/dependencies.gradle index 1ea2ad8..e1450c0 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ // Add your dependencies here dependencies { - compile('com.github.GTNewHorizons:CodeChickenLib:1.1.5.6:dev') + api('com.github.GTNewHorizons:CodeChickenLib:1.1.6:dev') } From b45ef7230d58b8e2eac01b208b5a5d8272e6a520 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:13:50 +0000 Subject: [PATCH 169/219] [ci skip] Update buildscript to RetroFuturaGradle --- .gitattributes | 75 +- build.gradle | 837 ++++++++++++++--------- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 272 +++++--- gradlew.bat | 38 +- settings.gradle | 24 +- 7 files changed, 739 insertions(+), 510 deletions(-) diff --git a/.gitattributes b/.gitattributes index 9917fc4..fd2792b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,35 +1,44 @@ * text eol=lf -*.jar binary - -*.png binary -*.jpg binary -*.jpeg binary -*.gif binary -*.tif binary -*.tiff binary -*.ico binary -*.svg text -*.eps binary - -*.kar binary -*.m4a binary -*.mid binary -*.midi binary -*.mp3 binary -*.ogg binary -*.ra binary - -*.7z binary -*.gz binary -*.tar binary -*.tgz binary -*.zip binary - -*.patch -text - -*.bat text eol=crlf -*.cmd text eol=crlf -*.ps1 text eol=crlf - -*autogenerated binary \ No newline at end of file +*.[jJ][aA][rR] binary + +*.[pP][nN][gG] binary +*.[jJ][pP][gG] binary +*.[jJ][pP][eE][gG] binary +*.[gG][iI][fF] binary +*.[tT][iI][fF] binary +*.[tT][iI][fF][fF] binary +*.[iI][cC][oO] binary +*.[sS][vV][gG] text +*.[eE][pP][sS] binary +*.[xX][cC][fF] binary + +*.[kK][aA][rR] binary +*.[mM]4[aA] binary +*.[mM][iI][dD] binary +*.[mM][iI][dD][iI] binary +*.[mM][pP]3 binary +*.[oO][gG][gG] binary +*.[rR][aA] binary + +*.7[zZ] binary +*.[gG][zZ] binary +*.[tT][aA][rR] binary +*.[tT][gG][zZ] binary +*.[zZ][iI][pP] binary + +*.[tT][cC][nN] binary +*.[sS][oO] binary +*.[dD][lL][lL] binary +*.[dD][yY][lL][iI][bB] binary +*.[pP][sS][dD] binary +*.[tT][tT][fF] binary +*.[oO][tT][fF] binary + +*.[pP][aA][tT][cC][hH] -text + +*.[bB][aA][tT] text eol=crlf +*.[cC][mM][dD] text eol=crlf +*.[pP][sS]1 text eol=crlf + +*[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary diff --git a/build.gradle b/build.gradle index fa88ae1..78caf98 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1671313514 +//version: 1675074449 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,24 +6,27 @@ */ +import com.diffplug.blowdryer.Blowdryer import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory +import org.jetbrains.gradle.ext.* import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit import java.util.zip.ZipEntry -import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream buildscript { repositories { + mavenLocal() mavenCentral() maven { @@ -31,9 +34,10 @@ buildscript { url 'https://maven.minecraftforge.net' } maven { - // GTNH ForgeGradle and ASM Fork - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + // GTNH RetroFuturaGradle and ASM Fork + name "GTNH Maven" + url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true } maven { name 'sonatype' @@ -44,76 +48,41 @@ buildscript { url 'https://repo1.maven.org/maven2/' } } - dependencies { - //Overwrite the current ASM version to fix shading newer than java 8 applicatations. - classpath 'org.ow2.asm:asm-debug-all-custom:5.0.3' - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.13' - } } plugins { id 'java-library' - id 'idea' + id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" id 'eclipse' id 'scala' id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false - id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false - id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false - id 'org.ajoberstar.grgit' version '4.1.1' - id 'com.github.johnrengelman.shadow' version '4.0.4' - id 'com.palantir.git-version' version '0.13.0' apply false - id 'de.undercouch.download' version '5.0.1' - id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false + id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false + id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false + id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false + id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '7.1.2' apply false + id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version + id 'de.undercouch.download' version '5.3.0' + id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle id 'com.diffplug.spotless' version '6.7.2' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false + id 'com.gtnewhorizons.retrofuturagradle' version '1.0.18' } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -dependencies { - implementation 'com.diffplug:blowdryer:1.6.0' -} - -apply plugin: 'com.diffplug.blowdryer' - if (project.file('.git/HEAD').isFile()) { apply plugin: 'com.palantir.git-version' } def out = services.get(StyledTextOutputFactory).create('an-output') -apply plugin: 'forge' - def projectJavaVersion = JavaLanguageVersion.of(8) -java { - toolchain { - languageVersion.set(projectJavaVersion) - } -} - -idea { - module { - inheritOutputDirs = true - downloadJavadoc = true - downloadSources = true - } -} - boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false -if (!disableSpotless) { - apply plugin: 'com.diffplug.spotless' - apply from: Blowdryer.file('spotless.gradle') -} - -if (JavaVersion.current() != JavaVersion.VERSION_1_8) { - throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) -} - checkPropertyExists("modName") checkPropertyExists("modId") checkPropertyExists("modGroup") @@ -121,10 +90,7 @@ checkPropertyExists("autoUpdateBuildScript") checkPropertyExists("minecraftVersion") checkPropertyExists("forgeVersion") checkPropertyExists("replaceGradleTokenInFile") -checkPropertyExists("gradleTokenModId") -checkPropertyExists("gradleTokenModName") checkPropertyExists("gradleTokenVersion") -checkPropertyExists("gradleTokenGroupName") checkPropertyExists("apiPackage") checkPropertyExists("accessTransformersFile") checkPropertyExists("usesMixins") @@ -135,6 +101,8 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") +propertyDefaultIfUnset("generateGradleTokenClass", "") +propertyDefaultIfUnset("includeWellKnownRepositories", true) propertyDefaultIfUnset("noPublishedSources", false) propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) @@ -144,14 +112,107 @@ propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") propertyDefaultIfUnset("curseForgeRelations", "") +propertyDefaultIfUnset("minimizeShadowedDependencies", true) +propertyDefaultIfUnset("relocateShadowedDependencies", true) +// Deprecated properties (kept for backwards compat) +propertyDefaultIfUnset("gradleTokenModId", "") +propertyDefaultIfUnset("gradleTokenModName", "") +propertyDefaultIfUnset("gradleTokenGroupName", "") + +propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only +propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only + +project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +if (!disableSpotless) { + apply plugin: 'com.diffplug.spotless' + apply from: Blowdryer.file('spotless.gradle') +} String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" +if (usesShadowedDependencies.toBoolean()) { + apply plugin: "com.github.johnrengelman.shadow" +} -final String modGroupPath = modGroup.toString().replaceAll("\\.", "/") -final String apiPackagePath = apiPackage.toString().replaceAll("\\.", "/") +java { + toolchain { + if (enableModernJavaSyntax.toBoolean()) { + languageVersion.set(JavaLanguageVersion.of(17)) + } else { + languageVersion.set(projectJavaVersion) + } + vendor.set(JvmVendorSpec.ADOPTIUM) + } + if (!noPublishedSources) { + withSourcesJar() + } +} + +pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { + // If Kotlin is enabled in the project + kotlin { + jvmToolchain(8) + } + // Kotlin hacks our source sets, so we hack Kotlin's tasks + def disabledKotlinTaskList = [ + "kaptGenerateStubsMcLauncherKotlin", + "kaptGenerateStubsPatchedMcKotlin", + "kaptGenerateStubsInjectedTagsKotlin", + "compileMcLauncherKotlin", + "compilePatchedMcKotlin", + "compileInjectedTagsKotlin", + "kaptMcLauncherKotlin", + "kaptPatchedMcKotlin", + "kaptInjectedTagsKotlin", + ] + tasks.configureEach { task -> + if (task.name in disabledKotlinTaskList) { + task.enabled = false + } + } +} + +configurations { + create("runtimeOnlyNonPublishable") { + description = "Runtime only dependencies that are not published alongside the jar" + canBeConsumed = false + canBeResolved = false + } +} + +if (enableModernJavaSyntax.toBoolean()) { + dependencies { + annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { + transitive = false // We only care about the 1 annotation class + } + } + + tasks.withType(JavaCompile).configureEach { + if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) { + return + } + sourceCompatibility = 17 // for the IDE support + options.release.set(8) + + javaCompiler.set(javaToolchains.compilerFor { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.ADOPTIUM) + }) + } +} + +eclipse { + classpath { + downloadSources = true + downloadJavadoc = true + } +} + +final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char) +final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char) String targetPackageJava = javaSourceDir + modGroupPath String targetPackageScala = scalaSourceDir + modGroupPath @@ -174,6 +235,27 @@ if (accessTransformersFile) { if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) +} else { + boolean atsFound = false + for (File at : sourceSets.getByName("main").resources.files) { + if (at.name.toLowerCase().endsWith("_at.cfg")) { + atsFound = true + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) + } + } + for (File at : sourceSets.getByName("api").resources.files) { + if (at.name.toLowerCase().endsWith("_at.cfg")) { + atsFound = true + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) + } + } + if (atsFound) { + logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name") + } } if (usesMixins.toBoolean()) { @@ -212,7 +294,7 @@ if (coreModClass) { } } -configurations.all { +configurations.configureEach { resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) // Make sure GregTech build won't time out @@ -243,7 +325,7 @@ catch (Exception ignored) { versionOverride = 'NO-GIT-TAG-SET' identifiedVersion = versionOverride } -version = minecraftVersion + '-' + identifiedVersion +version = identifiedVersion ext { modVersion = identifiedVersion } @@ -259,56 +341,72 @@ if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = modId } -def arguments = [] -def jvmArguments = [] - -if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - arguments += [ - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - if (usesMixinDebug.toBoolean()) { - jvmArguments += [ - "-Dmixin.debug.countInjections=true", - "-Dmixin.debug.verbose=true", - "-Dmixin.debug.export=true" - ] - } -} minecraft { - version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion - runDir = 'run' - if (replaceGradleTokenInFile) { for (f in replaceGradleTokenInFile.split(',')) { - replaceIn f + tagReplacementFiles.add f } - if (gradleTokenModId) { - replace gradleTokenModId, modId - } - if (gradleTokenModName) { - replace gradleTokenModName, modName - } - if (gradleTokenVersion) { - replace gradleTokenVersion, modVersion - } - if (gradleTokenGroupName) { - replace gradleTokenGroupName, modGroup + } + if (gradleTokenModId) { + injectedTags.put gradleTokenModId, modId + } + if (gradleTokenModName) { + injectedTags.put gradleTokenModName, modName + } + if (gradleTokenVersion) { + injectedTags.put gradleTokenVersion, modVersion + } + if (gradleTokenGroupName) { + injectedTags.put gradleTokenGroupName, modGroup + } + if (enableGenericInjection.toBoolean()) { + injectMissingGenerics.set(true) + } + + // Enable assertions in the current mod + extraRunJvmArguments.add("-ea:${modGroup}") + + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") + + if (usesMixinDebug.toBoolean()) { + extraRunJvmArguments.addAll([ + "-Dmixin.debug.countInjections=true", + "-Dmixin.debug.verbose=true", + "-Dmixin.debug.export=true" + ]) } } - clientIntellijRun { - args(arguments) - jvmArgs(jvmArguments) + // Blowdryer is present in some old mod builds, do not propagate it further as a dependency + // IC2 has no reobf jars in its Maven + groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"]) +} + +if (generateGradleTokenClass) { + tasks.injectTags.outputClassName.set(generateGradleTokenClass) +} - if (developmentEnvironmentUserName) { - args("--username", developmentEnvironmentUserName) +// Custom reobf auto-mappings +configurations.configureEach { + dependencies.configureEach { dep -> + if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) { + if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") { + // https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971 + project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971") + } } } +} - serverIntellijRun { - args(arguments) - jvmArgs(jvmArguments) +// Ensure tests have access to minecraft classes +sourceSets { + test { + java { + compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output + runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output + } } } @@ -316,24 +414,66 @@ if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// Allow unsafe repos but warn +repositories.configureEach { repo -> + if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { + if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) { + logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'") + repo.allowInsecureProtocol = true + } + } +} + apply from: 'repositories.gradle' configurations { - implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored - implementation.extendsFrom(shadowCompile) - implementation.extendsFrom(shadeCompile) + for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { + config.extendsFrom(runtimeOnlyNonPublishable) + if (usesShadowedDependencies.toBoolean()) { + config.extendsFrom(shadowImplementation) + // TODO: remove Compile after all uses are refactored to Implementation + config.extendsFrom(shadeCompile) + config.extendsFrom(shadowCompile) + } + } + // A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api" + create("compile") { + description = "Deprecated: use api or implementation instead, gets put in api" + canBeConsumed = false + canBeResolved = false + visible = false + } + create("testCompile") { + description = "Deprecated: use testImplementation instead" + canBeConsumed = false + canBeResolved = false + visible = false + } + api.extendsFrom(compile) + testImplementation.extendsFrom(testCompile) +} + +afterEvaluate { + if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) { + logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`") + logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle") + } } repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' + mavenContent { + excludeGroup("net.minecraftforge") // missing the `universal` artefact + } + } + maven { + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true } if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - } if (usesMixinDebug.toBoolean()) { maven { name = "Fabric Maven" @@ -341,6 +481,35 @@ repositories { } } } + if (includeWellKnownRepositories.toBoolean()) { + maven { + name "CurseMaven" + url "https://cursemaven.com" + content { + includeGroup "curse.maven" + } + } + maven { + name = "ic2" + url = "https://maven.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + name = "ic2-mirror" + url = "https://maven2.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + name "MMD Maven" + url "https://maven.mcmoddev.com/" + } + } } dependencies { @@ -348,30 +517,42 @@ dependencies { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') annotationProcessor('com.google.guava:guava:24.1.1-jre') annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.3:processor') + annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.10:processor') if (usesMixinDebug.toBoolean()) { - runtimeOnly('org.jetbrains:intellij-fernflower:1.2.1.16') + runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') } } if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - compile('com.gtnewhorizon:gtnhmixins:2.1.3') + implementation('com.gtnewhorizon:gtnhmixins:2.1.10') + } +} + +pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { + if (usesMixins.toBoolean()) { + dependencies { + kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + } } } apply from: 'dependencies.gradle' def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' -def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap -def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" - -task generateAssets { - if (usesMixins.toBoolean()) { +def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' +def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap +def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" + +tasks.register('generateAssets') { + group = "GTNH Buildscript" + description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" + onlyIf { usesMixins.toBoolean() } + doLast { def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") if (!mixinConfigFile.exists()) { def mixinPluginLine = "" - if(!mixinPlugin.isEmpty()) { + if (!mixinPlugin.isEmpty()) { // We might not have a mixin plugin if we're using early/late mixins - mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ + mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ } mixinConfigFile.text = """{ @@ -390,105 +571,58 @@ task generateAssets { } } -task relocateShadowJar(type: ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" -} - -shadowJar { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' - } +if (usesMixins.toBoolean()) { + tasks.named("reobfJar", ReobfuscatedJar).configure { + extraSrgFiles.from(mixinSrg) } - manifest { - attributes(getManifestAttributes()) + tasks.named("processResources").configure { + dependsOn("generateAssets") } - minimize() // This will only allow shading for actually used classes - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile - ] - dependsOn(relocateShadowJar) -} - -jar { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' + tasks.named("compileJava", JavaCompile).configure { + doFirst { + new File(mixinTmpDir).mkdirs() } + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" + ] } - manifest { - attributes(getManifestAttributes()) - } - - if (usesShadowedDependencies.toBoolean()) { - dependsOn(shadowJar) - enabled = false - } -} - -reobf { - if (usesMixins.toBoolean()) { - addExtraSrgFile mixinSrg - } -} - -afterEvaluate { - if (usesMixins.toBoolean()) { - tasks.compileJava { - options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobf.srg}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", - // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code - "-XDenableSunApiLintControl", - "-XDignore.symbol.file" - ] + pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { + kapt { + correctErrorTypes = true + javacOptions { + option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") + option("-AoutSrgFile=$mixinSrg") + option("-AoutRefMapFile=$refMap") + } + } + tasks.configureEach { task -> + if (task.name == "kaptKotlin") { + task.doFirst { + new File(mixinTmpDir).mkdirs() + } + } } - } -} - -runClient { - if (developmentEnvironmentUserName) { - arguments += [ - "--username", - developmentEnvironmentUserName - ] } - args(arguments) - jvmArgs(jvmArguments) } -runServer { - args(arguments) - jvmArgs(jvmArguments) -} - -tasks.withType(JavaExec).configureEach { - javaLauncher.set( - javaToolchains.launcherFor { - languageVersion = projectJavaVersion - } - ) -} - -processResources { +tasks.named("processResources", ProcessResources).configure { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version + inputs.property "mcversion", project.minecraft.mcVersion exclude("spotless.gradle") - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' - - // replace modVersion and minecraftVersion - expand "minecraftVersion": project.minecraft.version, + // replace stuff in mcmod.info, nothing else. replaces ${key} with value in text + filesMatching("mcmod.info") { + expand "minecraftVersion": project.minecraft.mcVersion, "modVersion": modVersion, "modId": modId, "modName": modName @@ -497,12 +631,6 @@ processResources { if (usesMixins.toBoolean()) { from refMap } - - // copy everything else that's not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - exclude 'spotless.gradle' - } } def getManifestAttributes() { @@ -529,65 +657,71 @@ def getManifestAttributes() { return manifestAttributes } -task sourcesJar(type: Jar) { - from(sourceSets.main.allSource) - from(file("$projectDir/LICENSE")) - getArchiveClassifier().set('sources') -} - -task shadowDevJar(type: ShadowJar) { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' - } - } - - from sourceSets.main.output - getArchiveClassifier().set("dev") - +tasks.named("jar", Jar).configure { manifest { attributes(getManifestAttributes()) } - - minimize() // This will only allow shading for actually used classes - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile - ] -} - -task relocateShadowDevJar(type: ConfigureShadowRelocation) { - target = tasks.shadowDevJar - prefix = modGroup + ".shadow" } -task circularResolverJar(type: Jar) { - dependsOn(relocateShadowDevJar) - dependsOn(shadowDevJar) - enabled = false -} +if (usesShadowedDependencies.toBoolean()) { + tasks.register('relocateShadowJar', ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" + enabled = minimizeShadowedDependencies.toBoolean() + } + tasks.named("shadowJar", ShadowJar).configure { + manifest { + attributes(getManifestAttributes()) + } -task devJar(type: Jar) { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' + if (minimizeShadowedDependencies.toBoolean()) { + minimize() // This will only allow shading for actually used classes + } + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile, + project.configurations.shadeCompile + ] + archiveClassifier.set('dev') + if (minimizeShadowedDependencies.toBoolean()) { + dependsOn(relocateShadowJar) } } - - from sourceSets.main.output - getArchiveClassifier().set("dev") - - manifest { - attributes(getManifestAttributes()) + configurations.runtimeElements.outgoing.artifacts.clear() + configurations.apiElements.outgoing.artifacts.clear() + configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) + configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) + tasks.named("jar", Jar) { + enabled = false + finalizedBy(tasks.shadowJar) + } + tasks.named("reobfJar", ReobfuscatedJar) { + inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) } + AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") + javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { + skip() + } + for (runTask in ["runClient", "runServer"]) { + tasks.named(runTask).configure { + dependsOn("shadowJar") + } + } +} +ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar +ext.publishableObfJar = tasks.reobfJar - if (usesShadowedDependencies.toBoolean()) { - dependsOn(circularResolverJar) - enabled = false +tasks.named('extractForgeUserdev', Copy).configure { efu -> + doLast { + // Fix CoFH-repackaged CCL not finding mappings + project.copy { + from(mcpTasks.userdevDir("conf")) + into(new File(project.buildDir, "unpacked/conf")) + } } } -task apiJar(type: Jar) { +tasks.register('apiJar', Jar) { from(sourceSets.main.allSource) { include modGroupPath + "/" + apiPackagePath + '/**' } @@ -605,18 +739,78 @@ task apiJar(type: Jar) { artifacts { if (!noPublishedSources) { - archives sourcesJar + archives tasks.named("sourcesJar") } - archives devJar if (apiPackage) { - archives apiJar + archives tasks.named("apiJar") } } -// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), -// and isn't strictly needed with the POM so just disable it. -tasks.withType(GenerateModuleMetadata) { - enabled = false +idea { + module { + downloadJavadoc = true + downloadSources = true + } + project { + settings { + runConfigurations { + "1. Run Client"(Gradle) { + taskNames = ["runClient"] + } + "2. Run Server"(Gradle) { + taskNames = ["runServer"] + } + "3. Run Obfuscated Client"(Gradle) { + taskNames = ["runObfClient"] + } + "4. Run Obfuscated Server"(Gradle) { + taskNames = ["runObfServer"] + } + if (!disableSpotless) { + "5. Apply spotless"(Gradle) { + taskNames = ["spotlessApply"] + } + } + def coreModArgs = "" + if (coreModClass) { + coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"' + } + "Run Client (IJ Native)"(Application) { + mainClass = "GradleStart" + moduleName = project.name + ".main" + afterEvaluate { + workingDirectory = tasks.runClient.workingDir.absolutePath + programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') + jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + + ' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + + coreModArgs + } + } + "Run Server (IJ Native)"(Application) { + mainClass = "GradleStartServer" + moduleName = project.name + ".main" + afterEvaluate { + workingDirectory = tasks.runServer.workingDir.absolutePath + programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') + jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + + ' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + + coreModArgs + } + } + } + compiler.javac { + afterEvaluate { + moduleJavacAdditionalOptions = [ + (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') + ] + } + } + } + } +} + +tasks.named("processIdeaSettings").configure { + dependsOn("injectTags") } // workaround variable hiding in pom processing @@ -624,51 +818,24 @@ def projectConfigs = project.configurations publishing { publications { - maven(MavenPublication) { + create("maven", MavenPublication) { from components.java - if (usesShadowedDependencies.toBoolean()) { - artifact source: shadowJar, classifier: "" - } - if (!noPublishedSources) { - artifact source: sourcesJar, classifier: "sources" - } - artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" + if (apiPackage) { - artifact source: apiJar, classifier: "api" + artifact apiJar } groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - - // remove extra garbage from minecraft and minecraftDeps configuration - pom.withXml { - def badArtifacts = [:].withDefault { [] as Set } - for (configuration in [ - projectConfigs.minecraft, - projectConfigs.minecraftDeps - ]) { - for (dependency in configuration.allDependencies) { - badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name - } - } - // example for specifying extra stuff to ignore - // badArtifacts["org.example.group"] += "artifactName" - - Node pomNode = asNode() - pomNode.dependencies.'*'.findAll() { - badArtifacts[it.groupId.text()].contains(it.artifactId.text()) - }.each() { - it.parent().remove(it) - } - } } } repositories { maven { url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" + allowInsecureProtocol = true credentials { username = System.getenv("MAVEN_USER") ?: "NONE" password = System.getenv("MAVEN_PASSWORD") ?: "NONE" @@ -688,7 +855,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { versionNumber = identifiedVersion versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" - uploadFile = jar + uploadFile = publishableObfJar additionalFiles = getSecondaryArtifacts() gameVersions = [minecraftVersion] loaders = ["forge"] @@ -729,7 +896,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" addGameVersion minecraftVersion addGameVersion "Forge" - mainArtifact jar + mainArtifact publishableObfJar for (artifact in getSecondaryArtifacts()) addArtifact artifact } @@ -757,7 +924,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null tasks.publish.dependsOn(tasks.curseforge) } -def addModrinthDep(scope, type, name) { +def addModrinthDep(String scope, String type, String name) { com.modrinth.minotaur.dependencies.Dependency dep; if (!(scope in ["required", "optional", "incompatible", "embedded"])) { throw new Exception("Invalid modrinth dependency scope: " + scope) @@ -775,7 +942,7 @@ def addModrinthDep(scope, type, name) { project.modrinth.dependencies.add(dep) } -def addCurseForgeRelation(type, name) { +def addCurseForgeRelation(String type, String name) { if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { throw new Exception("Invalid CurseForge relation type: " + type) } @@ -785,17 +952,20 @@ def addCurseForgeRelation(type, name) { } // Updating -task updateBuildScript { +tasks.register('updateBuildScript') { + group = 'GTNH Buildscript' + description = 'Updates the build script to the latest version' + doLast { - if (performBuildScriptUpdate(projectDir.toString())) return + if (performBuildScriptUpdate()) return print("Build script already up-to-date!") } } -if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) { +if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) { if (autoUpdateBuildScript.toBoolean()) { - performBuildScriptUpdate(projectDir.toString()) + performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") } @@ -838,10 +1008,11 @@ boolean verifySettingsGradle() { return false } -boolean performBuildScriptUpdate(String projectDir) { - if (isNewBuildScriptVersionAvailable(projectDir)) { +boolean performBuildScriptUpdate() { + if (isNewBuildScriptVersionAvailable()) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } + def out = services.get(StyledTextOutputFactory).create('buildscript-update-output') out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -852,7 +1023,7 @@ boolean performBuildScriptUpdate(String projectDir) { return false } -boolean isNewBuildScriptVersionAvailable(String projectDir) { +boolean isNewBuildScriptVersionAvailable() { Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] String currentBuildScript = getFile("build.gradle").getText() @@ -872,15 +1043,12 @@ static String getVersionHash(String buildScriptContent) { return "" } -configure(updateBuildScript) { - group = 'forgegradle' - description = 'Updates the build script to the latest version' -} - // Parameter Deobfuscation -task deobfParams { - doLast { +tasks.register('deobfParams') { + group = 'GTNH Buildscript' + description = 'Rename all obfuscated parameter names inherited from Minecraft classes' + doLast { // TODO String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" @@ -894,7 +1062,10 @@ task deobfParams { if (!file(paramsCSV).exists()) { println("Extracting MCP archive ...") - unzip(mcpZIP, mcpDir) + copy { + from(zipTree(mcpZIP)) + into(mcpDir) + } } println("Parsing params.csv ...") @@ -937,42 +1108,6 @@ static int replaceParams(File file, Map params) { return 0 } -// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681) -static unzip(String zipFileName, String outputDir) { - byte[] buffer = new byte[16384] - ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName)) - ZipEntry zipEntry = zis.getNextEntry() - while (zipEntry != null) { - File newFile = new File(outputDir + File.separator, zipEntry.name) - if (zipEntry.isDirectory()) { - if (!newFile.isDirectory() && !newFile.mkdirs()) { - throw new IOException("Failed to create directory $newFile") - } - } else { - // fix for Windows-created archives - File parent = newFile.parentFile - if (!parent.isDirectory() && !parent.mkdirs()) { - throw new IOException("Failed to create directory $parent") - } - // write file content - FileOutputStream fos = new FileOutputStream(newFile) - int len = 0 - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len) - } - fos.close() - } - zipEntry = zis.getNextEntry() - } - zis.closeEntry() - zis.close() -} - -configure(deobfParams) { - group = 'forgegradle' - description = 'Rename all obfuscated parameter names inherited from Minecraft classes' -} - // Dependency Deobfuscation def deobf(String sourceURL) { @@ -999,11 +1134,29 @@ def deobf(String sourceURL) { hostName = String.join(".", parts) return deobf(sourceURL, "$hostName/$fileName") - } catch (Exception e) { + } catch (Exception ignored) { return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } } +def deobfMaven(String repoURL, String mavenDep) { + if (!repoURL.endsWith("/")) { + repoURL += "/" + } + String[] parts = mavenDep.split(":") + parts[0] = parts[0].replace('.', '/') + def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" + return deobf(jarURL) +} + +def deobfCurse(String curseDep) { + try { + return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") + } catch (Exception ignored) { + out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") + } +} + // The method above is to be preferred. Use this method if the filename is not at the end of the URL. def deobf(String sourceURL, String rawFileName) { String bon2Version = "2.5.1" @@ -1109,7 +1262,7 @@ def getFile(String relativePath) { def getSecondaryArtifacts() { // Because noPublishedSources from the beginning of the script is somehow not visible here... boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - def secondaryArtifacts = [devJar] + def secondaryArtifacts = [publishableDevJar] if (!noPublishedSources) secondaryArtifacts += [sourcesJar] if (apiPackage) secondaryArtifacts += [apiJar] return secondaryArtifacts diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 42198 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%0Dx9&DJ+=*NrOLFNd~jpXIl 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 OOi;9)pb#jaQ2zt%fx@f+ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ab0b72..f398c33 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acf..79a61d4 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # 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"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +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 - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || 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 @@ -105,84 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +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=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=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -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" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +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 - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + 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 - i=$((i+1)) + # 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 - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +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 -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# 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. +# -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +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 index 9618d8d..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,14 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +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" @@ -37,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :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 %CMD_LINE_ARGS% +"%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%"=="0" goto mainEnd +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! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +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 diff --git a/settings.gradle b/settings.gradle index 93c852a..01ea5f1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,28 @@ + +pluginManagement { + repositories { + maven { + // RetroFuturaGradle + name "GTNH Maven" + url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true + mavenContent { + includeGroup("com.gtnewhorizons.retrofuturagradle") + } + } + gradlePluginPortal() + mavenCentral() + mavenLocal() + } +} + plugins { id 'com.diffplug.blowdryerSetup' version '1.6.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' // Provides java toolchains } -apply plugin: 'com.diffplug.blowdryerSetup' - blowdryerSetup { - github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.5') + repoSubfolder 'gtnhShared' + github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0') //devLocal '.' // Use this when testing config updates locally } From 955a875d42bd8f725d389ef8c4f571824f2ae0c8 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:13:51 +0000 Subject: [PATCH 170/219] [ci skip] spotlessApply with the new settings --- .../codechicken/core/CCUpdateChecker.java | 34 +++--- .../codechicken/core/ClassDiscoverer.java | 42 ++++--- .../java/codechicken/core/ClientUtils.java | 18 +-- .../java/codechicken/core/CommonUtils.java | 7 +- .../codechicken/core/GuiModListScroll.java | 32 ++--- .../codechicken/core/IGuiPacketSender.java | 1 + .../java/codechicken/core/IStringMatcher.java | 1 + .../java/codechicken/core/ProfileTimer.java | 1 + .../codechicken/core/ReflectionManager.java | 51 ++++---- .../java/codechicken/core/ServerUtils.java | 25 ++-- .../java/codechicken/core/TaskProfiler.java | 2 + .../asm/CodeChickenAccessTransformer.java | 18 +-- .../core/asm/CodeChickenCoreModContainer.java | 13 ++- .../asm/DefaultImplementationTransformer.java | 20 ++-- .../core/asm/DelegatedTransformer.java | 22 ++-- .../core/asm/DependancyLister.java | 3 + .../core/asm/InterfaceDependancies.java | 2 +- .../core/asm/MCPDeobfuscationTransformer.java | 50 ++++---- .../codechicken/core/asm/MethodASMifier.java | 6 +- .../core/asm/TweakTransformer.java | 77 ++++++------ .../core/commands/CoreCommand.java | 12 +- .../core/commands/PlayerCommand.java | 9 +- .../core/commands/ServerCommand.java | 1 + .../core/featurehack/EntityRenderHook.java | 2 + .../core/featurehack/EntityUpdateHook.java | 2 + .../core/featurehack/FeatureHack.java | 1 + .../core/featurehack/GameDataManipulator.java | 15 +-- .../core/featurehack/LiquidTextures.java | 25 ++-- .../featurehack/RenderEntityRenderHook.java | 2 + .../core/featurehack/RenderNull.java | 1 + .../featurehack/TweakTransformerHelper.java | 16 +-- .../core/featurehack/mc/TextureLavaFX.java | 20 ++-- .../featurehack/mc/TextureLavaFlowFX.java | 20 ++-- .../core/featurehack/mc/TextureWaterFX.java | 1 + .../featurehack/mc/TextureWaterFlowFX.java | 9 +- .../core/fluid/ExtendedFluidTank.java | 1 + .../codechicken/core/fluid/FluidUtils.java | 7 +- .../codechicken/core/fluid/TankAccess.java | 1 + .../codechicken/core/gui/ClickCounter.java | 5 +- .../codechicken/core/gui/GuiCCButton.java | 9 +- .../codechicken/core/gui/GuiCCTextField.java | 12 +- .../codechicken/core/gui/GuiScreenWidget.java | 6 +- .../codechicken/core/gui/GuiScrollPane.java | 26 ++--- .../codechicken/core/gui/GuiScrollSlot.java | 2 + .../java/codechicken/core/gui/GuiWidget.java | 1 + .../core/gui/IGuiActionListener.java | 1 + .../core/internal/CCCEventHandler.java | 4 +- .../core/inventory/GuiContainerWidget.java | 10 +- .../core/launch/CodeChickenCorePlugin.java | 106 ++++++++--------- .../codechicken/core/launch/DepLoader.java | 110 +++++++++++------- .../obfuscator/ConstantObfuscator.java | 5 +- .../obfuscator/DummyOutputStream.java | 1 + .../obfuscator/IHeirachyEvaluator.java | 4 +- .../codechicken/obfuscator/ILogStreams.java | 1 + .../codechicken/obfuscator/ObfDirection.java | 1 + .../codechicken/obfuscator/ObfRemapper.java | 4 +- .../obfuscator/ObfuscationMap.java | 25 ++-- .../obfuscator/ObfuscationRun.java | 53 +++++---- .../obfuscator/SystemLogStreams.java | 1 + 59 files changed, 540 insertions(+), 417 deletions(-) diff --git a/src/main/java/codechicken/core/CCUpdateChecker.java b/src/main/java/codechicken/core/CCUpdateChecker.java index 7f26b41..61a1bf3 100644 --- a/src/main/java/codechicken/core/CCUpdateChecker.java +++ b/src/main/java/codechicken/core/CCUpdateChecker.java @@ -1,10 +1,5 @@ package codechicken.core; -import codechicken.core.launch.CodeChickenCorePlugin; -import com.google.common.base.Function; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.versioning.ComparableVersion; -import cpw.mods.fml.relauncher.FMLInjectionData; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -14,14 +9,25 @@ import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; + import net.minecraft.client.Minecraft; import net.minecraft.util.ChatComponentText; import net.minecraft.util.StatCollector; +import codechicken.core.launch.CodeChickenCorePlugin; + +import com.google.common.base.Function; + +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.versioning.ComparableVersion; +import cpw.mods.fml.relauncher.FMLInjectionData; + public class CCUpdateChecker { + private static final ArrayList updates = new ArrayList(); private static class ThreadUpdateCheck extends Thread { + private final URL url; private final Function handler; @@ -44,9 +50,7 @@ public void run() { read.close(); if (ret == null) ret = ""; handler.apply(ret); - } catch (SocketTimeoutException ignored) { - } catch (UnknownHostException ignored) { - } catch (IOException iox) { + } catch (SocketTimeoutException ignored) {} catch (UnknownHostException ignored) {} catch (IOException iox) { iox.printStackTrace(); } } @@ -75,20 +79,22 @@ public static String mcVersion() { public static void updateCheck(final String mod, final String version) { updateCheck( "http://www.chickenbones.net/Files/notification/version.php?" + "version=" - + mcVersion() + "&" + "file=" + + mcVersion() + + "&" + + "file=" + mod, new Function() { + @Override public Void apply(String ret) { if (!ret.startsWith("Ret: ")) { - CodeChickenCorePlugin.logger.error( - "Failed to check update for " + mod + " returned: " + ret); + CodeChickenCorePlugin.logger + .error("Failed to check update for " + mod + " returned: " + ret); return null; } ComparableVersion newversion = new ComparableVersion(ret.substring(5)); - if (newversion.compareTo(new ComparableVersion(version)) > 0) - addUpdateMessage( - StatCollector.translateToLocalFormatted("codechickencore.update", newversion, mod)); + if (newversion.compareTo(new ComparableVersion(version)) > 0) addUpdateMessage( + StatCollector.translateToLocalFormatted("codechickencore.update", newversion, mod)); return null; } }); diff --git a/src/main/java/codechicken/core/ClassDiscoverer.java b/src/main/java/codechicken/core/ClassDiscoverer.java index 6ccbbc2..58056e9 100644 --- a/src/main/java/codechicken/core/ClassDiscoverer.java +++ b/src/main/java/codechicken/core/ClassDiscoverer.java @@ -1,12 +1,5 @@ package codechicken.core; -import codechicken.core.launch.CodeChickenCorePlugin; -import codechicken.lib.asm.ASMHelper; -import com.google.common.collect.ImmutableList; -import cpw.mods.fml.common.FMLLog; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.ModClassLoader; -import cpw.mods.fml.relauncher.CoreModManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -15,10 +8,23 @@ import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; + import net.minecraft.launchwrapper.Launch; + import org.objectweb.asm.tree.ClassNode; +import codechicken.core.launch.CodeChickenCorePlugin; +import codechicken.lib.asm.ASMHelper; + +import com.google.common.collect.ImmutableList; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModClassLoader; +import cpw.mods.fml.relauncher.CoreModManager; + public class ClassDiscoverer { + public IStringMatcher matcher; public String[] superclasses; public ArrayList> classes; @@ -35,13 +41,12 @@ public ClassDiscoverer(IStringMatcher matcher, Class... superclasses) { } public ClassDiscoverer(Class... superclasses) { - this( - new IStringMatcher() { - public boolean matches(String test) { - return true; - } - }, - superclasses); + this(new IStringMatcher() { + + public boolean matches(String test) { + return true; + } + }, superclasses); } public ArrayList> findClasses() { @@ -79,10 +84,8 @@ private void addClass(String classname) { } private void findClasspathMods() { - List knownLibraries = ImmutableList.builder() - .addAll(modClassLoader.getDefaultLibraries()) - .addAll(CoreModManager.getLoadedCoremods()) - .build(); + List knownLibraries = ImmutableList.builder().addAll(modClassLoader.getDefaultLibraries()) + .addAll(CoreModManager.getLoadedCoremods()).build(); File[] minecraftSources = modClassLoader.getParentSources(); HashSet searchedSources = new HashSet(); for (File minecraftSource : minecraftSources) { @@ -98,7 +101,8 @@ private void findClasspathMods() { readFromZipFile(minecraftSource); } catch (Exception e) { CodeChickenCorePlugin.logger.error( - "Failed to scan " + minecraftSource.getAbsolutePath() + ", the zip file is invalid", e); + "Failed to scan " + minecraftSource.getAbsolutePath() + ", the zip file is invalid", + e); } } } else if (minecraftSource.isDirectory()) { diff --git a/src/main/java/codechicken/core/ClientUtils.java b/src/main/java/codechicken/core/ClientUtils.java index 73adfe7..a02e5a5 100644 --- a/src/main/java/codechicken/core/ClientUtils.java +++ b/src/main/java/codechicken/core/ClientUtils.java @@ -1,10 +1,5 @@ package codechicken.core; -import codechicken.core.internal.CCCEventHandler; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.ModContainer; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.network.NetworkManager; @@ -12,7 +7,14 @@ import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.World; +import codechicken.core.internal.CCCEventHandler; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class ClientUtils extends CommonUtils { + private static Minecraft mc() { return Minecraft.getMinecraft(); } @@ -22,7 +24,7 @@ public static World getWorld() { } public static boolean inWorld() // TODO unused - { + { return mc().getNetHandler() != null; } @@ -59,8 +61,8 @@ public static String getWorldSaveName() { public static void enhanceSupportersList(Object mod) { ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod); - mc.getMetadata().description = - mc.getMetadata().description.replace("Supporters:", EnumChatFormatting.AQUA + "Supporters:"); + mc.getMetadata().description = mc.getMetadata().description + .replace("Supporters:", EnumChatFormatting.AQUA + "Supporters:"); GuiModListScroll.register(mod); } } diff --git a/src/main/java/codechicken/core/CommonUtils.java b/src/main/java/codechicken/core/CommonUtils.java index 11301b2..b482d19 100644 --- a/src/main/java/codechicken/core/CommonUtils.java +++ b/src/main/java/codechicken/core/CommonUtils.java @@ -1,14 +1,17 @@ package codechicken.core; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.FMLInjectionData; import java.io.File; + import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList; import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.FMLInjectionData; + public class CommonUtils { + public static boolean isClient() { return FMLCommonHandler.instance().getSide().isClient(); } diff --git a/src/main/java/codechicken/core/GuiModListScroll.java b/src/main/java/codechicken/core/GuiModListScroll.java index 299b04f..714a0bf 100644 --- a/src/main/java/codechicken/core/GuiModListScroll.java +++ b/src/main/java/codechicken/core/GuiModListScroll.java @@ -3,13 +3,6 @@ import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.glReadPixels; -import codechicken.core.launch.CodeChickenCorePlugin; -import codechicken.lib.gui.GuiDraw; -import codechicken.lib.vec.Rectangle4i; -import cpw.mods.fml.client.GuiModList; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.ModContainer; -import cpw.mods.fml.common.ModMetadata; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -17,14 +10,26 @@ import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; + import javax.imageio.ImageIO; + import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.MinecraftForgeClient; + import org.lwjgl.BufferUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; +import codechicken.core.launch.CodeChickenCorePlugin; +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; +import cpw.mods.fml.client.GuiModList; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.ModMetadata; + public class GuiModListScroll { + private static List scrollMods = new LinkedList(); public static void register(Object mod) { @@ -45,9 +50,8 @@ private static void screenshotStencil(int x) { glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glReadPixels(0, 0, d.width, d.height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf); - for (int i = 0; i < d.width; i++) - for (int j = 0; j < d.height; j++) - img.setRGB(i, d.height - j - 1, buf.get(j * d.width + i) == 0 ? 0 : 0xFFFFFF); + for (int i = 0; i < d.width; i++) for (int j = 0; j < d.height; j++) + img.setRGB(i, d.height - j - 1, buf.get(j * d.width + i) == 0 ? 0 : 0xFFFFFF); try { ImageIO.write(img, "png", new File("stencil" + x + ".png")); } catch (IOException e) { @@ -109,9 +113,7 @@ public static void draw(GuiModList gui, int mouseX, int mouseY) { glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); String description = selectedMod.getMetadata().description; - int height = GuiDraw.fontRenderer - .listFormattedStringToWidth(description, x2 - x1) - .size() + int height = GuiDraw.fontRenderer.listFormattedStringToWidth(description, x2 - x1).size() * GuiDraw.fontRenderer.FONT_HEIGHT; boolean needsScroll = height > y2 - y1draw; @@ -142,8 +144,8 @@ public static void draw(GuiModList gui, int mouseX, int mouseY) { } /** - * Does not add the last 10 px space before the description normally starts - * Ignores empty child mods expecting a background draw overwrite + * Does not add the last 10 px space before the description normally starts Ignores empty child mods expecting a + * background draw overwrite */ private static int calcDescY(GuiModList gui, ModContainer mod) { ModMetadata meta = mod.getMetadata(); diff --git a/src/main/java/codechicken/core/IGuiPacketSender.java b/src/main/java/codechicken/core/IGuiPacketSender.java index b8b0902..60bc354 100644 --- a/src/main/java/codechicken/core/IGuiPacketSender.java +++ b/src/main/java/codechicken/core/IGuiPacketSender.java @@ -3,5 +3,6 @@ import net.minecraft.entity.player.EntityPlayerMP; public interface IGuiPacketSender { + void sendPacket(EntityPlayerMP player, int windowId); } diff --git a/src/main/java/codechicken/core/IStringMatcher.java b/src/main/java/codechicken/core/IStringMatcher.java index 781b17a..cff5405 100644 --- a/src/main/java/codechicken/core/IStringMatcher.java +++ b/src/main/java/codechicken/core/IStringMatcher.java @@ -1,5 +1,6 @@ package codechicken.core; public interface IStringMatcher { + public boolean matches(String test); } diff --git a/src/main/java/codechicken/core/ProfileTimer.java b/src/main/java/codechicken/core/ProfileTimer.java index 3fb9fef..b6a2a8a 100644 --- a/src/main/java/codechicken/core/ProfileTimer.java +++ b/src/main/java/codechicken/core/ProfileTimer.java @@ -3,6 +3,7 @@ import codechicken.core.launch.CodeChickenCorePlugin; public class ProfileTimer { + public double decay; public long startTime; public long nanoTime; diff --git a/src/main/java/codechicken/core/ReflectionManager.java b/src/main/java/codechicken/core/ReflectionManager.java index 32fa16a..0948de6 100644 --- a/src/main/java/codechicken/core/ReflectionManager.java +++ b/src/main/java/codechicken/core/ReflectionManager.java @@ -1,13 +1,15 @@ package codechicken.core; -import codechicken.lib.asm.ObfMapping; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; +import codechicken.lib.asm.ObfMapping; + public class ReflectionManager { + public static HashMap, Class> primitiveWrappers = new HashMap, Class>(); static { @@ -27,12 +29,12 @@ public static boolean isInstance(Class class1, Object obj) { if (primitive == Long.class && Long.class.isInstance(obj)) return true; if ((primitive == Long.class || primitive == Integer.class) && Integer.class.isInstance(obj)) return true; if ((primitive == Long.class || primitive == Integer.class || primitive == Short.class) - && Short.class.isInstance(obj)) return true; - if ((primitive == Long.class - || primitive == Integer.class - || primitive == Short.class - || primitive == Byte.class) - && Integer.class.isInstance(obj)) return true; + && Short.class.isInstance(obj)) + return true; + if ((primitive == Long.class || primitive == Integer.class + || primitive == Short.class + || primitive == Byte.class) && Integer.class.isInstance(obj)) + return true; if (primitive == Double.class && Double.class.isInstance(obj)) return true; if ((primitive == Double.class || primitive == Float.class) && Float.class.isInstance(obj)) return true; @@ -64,7 +66,7 @@ public static Class findClass(String name, boolean init) { public static void setField(Class class1, Object instance, String name, Object value) throws IllegalArgumentException, IllegalAccessException { - setField(class1, instance, new String[] {name}, value); + setField(class1, instance, new String[] { name }, value); } public static void setField(Class class1, Object instance, String[] names, Object value) @@ -95,19 +97,15 @@ public static void setField(Class class1, Object instance, int fieldindex, Ob } /** - * Static function - * void return type - * single name + * Static function void return type single name */ public static void callMethod(Class class1, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - callMethod(class1, null, new String[] {name}, params); + callMethod(class1, null, new String[] { name }, params); } /** - * Static function - * void return type - * single name + * Static function void return type single name */ public static void callMethod(Class class1, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { @@ -115,12 +113,11 @@ public static void callMethod(Class class1, String[] names, Object... params) } /** - * void return type - * single name + * void return type single name */ public static void callMethod(Class class1, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - callMethod(class1, null, instance, new String[] {name}, params); + callMethod(class1, null, instance, new String[] { name }, params); } /** @@ -132,12 +129,11 @@ public static void callMethod(Class class1, Object instance, String[] names, } /** - * Static method - * single name + * Static method single name */ public static R callMethod(Class class1, Class returntype, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - return callMethod(class1, returntype, null, new String[] {name}, params); + return callMethod(class1, returntype, null, new String[] { name }, params); } /** @@ -153,14 +149,12 @@ public static R callMethod(Class class1, Class returntype, String[] na */ public static R callMethod(Class class1, Class returntype, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - return callMethod(class1, returntype, instance, new String[] {name}, params); + return callMethod(class1, returntype, instance, new String[] { name }, params); } - public static R callMethod( - Class class1, Class returntype, Object instance, String[] names, Object... params) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - nextMethod: - for (Method method : class1.getDeclaredMethods()) { + public static R callMethod(Class class1, Class returntype, Object instance, String[] names, + Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + nextMethod: for (Method method : class1.getDeclaredMethods()) { boolean match = false; for (String name : names) { if (method.getName().equals(name)) { @@ -204,8 +198,7 @@ public static T getField(Class class1, Class fieldType, Object instanc public static T newInstance(Class class1, Object... params) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { - nextMethod: - for (Constructor constructor : class1.getDeclaredConstructors()) { + nextMethod: for (Constructor constructor : class1.getDeclaredConstructors()) { Class[] paramtypes = constructor.getParameterTypes(); if (paramtypes.length != params.length) continue; diff --git a/src/main/java/codechicken/core/ServerUtils.java b/src/main/java/codechicken/core/ServerUtils.java index 42c93c4..2d2cf7f 100644 --- a/src/main/java/codechicken/core/ServerUtils.java +++ b/src/main/java/codechicken/core/ServerUtils.java @@ -1,20 +1,24 @@ package codechicken.core; -import codechicken.lib.asm.ObfMapping; -import com.mojang.authlib.GameProfile; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.server.MinecraftServer; import net.minecraft.util.IChatComponent; +import codechicken.lib.asm.ObfMapping; + +import com.mojang.authlib.GameProfile; + public class ServerUtils extends CommonUtils { + public static MinecraftServer mc() { return MinecraftServer.getServer(); } @@ -49,17 +53,18 @@ public static void openSMPContainer(EntityPlayerMP player, Container container, static { try { - field_152661_c = ReflectionManager.getField(new ObfMapping( - "net/minecraft/server/management/PlayerProfileCache", "field_152661_c", "[Ljava/util/Map;")); - c_ProfileEntry = ServerUtils.class - .getClassLoader() + field_152661_c = ReflectionManager.getField( + new ObfMapping( + "net/minecraft/server/management/PlayerProfileCache", + "field_152661_c", + "[Ljava/util/Map;")); + c_ProfileEntry = ServerUtils.class.getClassLoader() .loadClass("net.minecraft.server.management.PlayerProfileCache$ProfileEntry"); - func_152668_a = c_ProfileEntry.getDeclaredMethod(new ObfMapping( + func_152668_a = c_ProfileEntry.getDeclaredMethod( + new ObfMapping( "net/minecraft/server/management/PlayerProfileCache$ProfileEntry", "func_152668_a", - "()Lcom/mojang/authlib/GameProfile;") - .toRuntime() - .s_name); + "()Lcom/mojang/authlib/GameProfile;").toRuntime().s_name); func_152668_a.setAccessible(true); } catch (Exception e) { diff --git a/src/main/java/codechicken/core/TaskProfiler.java b/src/main/java/codechicken/core/TaskProfiler.java index 30f92bb..92a9769 100644 --- a/src/main/java/codechicken/core/TaskProfiler.java +++ b/src/main/java/codechicken/core/TaskProfiler.java @@ -6,7 +6,9 @@ import java.util.Map.Entry; public class TaskProfiler { + public static class ProfilerResult { + public final String name; public final long time; public final double fraction; diff --git a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java index d293700..6b35f15 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java @@ -1,13 +1,17 @@ package codechicken.core.asm; +import java.io.IOException; +import java.lang.reflect.Field; + import codechicken.lib.asm.ObfMapping; + import com.google.common.collect.ImmutableBiMap; + import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; -import java.io.IOException; -import java.lang.reflect.Field; public class CodeChickenAccessTransformer extends AccessTransformer { + private static boolean makeAllPublic; private static Field f_classNameBiMap; private static Object emptyMap = ImmutableBiMap.of(); @@ -20,12 +24,10 @@ public CodeChickenAccessTransformer() throws IOException { private void loadPublicConfig() { if (ObfMapping.obfuscated) return; - makeAllPublic = CodeChickenCoreModContainer.config - .getTag("dev.runtimePublic") - .setComment( - "Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader." - + "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers." - + "\nSuch mods are doing the wrong thing and should be fixed.") + makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic").setComment( + "Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader." + + "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers." + + "\nSuch mods are doing the wrong thing and should be fixed.") .getBooleanValue(false); if (!makeAllPublic) return; diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index da6e773..8728f66 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -1,25 +1,30 @@ package codechicken.core.asm; +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +import net.minecraftforge.common.MinecraftForge; + import codechicken.core.CCUpdateChecker; import codechicken.core.ClientUtils; import codechicken.core.featurehack.LiquidTextures; import codechicken.core.internal.CCCEventHandler; import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.lib.config.ConfigFile; + import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; + import cpw.mods.fml.common.*; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.versioning.ArtifactVersion; import cpw.mods.fml.common.versioning.VersionParser; import cpw.mods.fml.common.versioning.VersionRange; -import java.io.File; -import java.util.LinkedList; -import java.util.List; -import net.minecraftforge.common.MinecraftForge; public class CodeChickenCoreModContainer extends DummyModContainer { + public static ConfigFile config; public static void loadConfig() { diff --git a/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java index 57127df..8d92b9f 100644 --- a/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java +++ b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java @@ -1,19 +1,23 @@ package codechicken.core.asm; -import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.ClassHeirachyManager; -import codechicken.lib.asm.ObfMapping; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; + import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.LaunchClassLoader; + import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; +import codechicken.lib.asm.ASMHelper; +import codechicken.lib.asm.ClassHeirachyManager; +import codechicken.lib.asm.ObfMapping; + public class DefaultImplementationTransformer implements IClassTransformer { + private static LaunchClassLoader cl = (LaunchClassLoader) ClassHeirachyManager.class.getClassLoader(); private static ClassNode getClassNode(String name) { @@ -25,6 +29,7 @@ private static ClassNode getClassNode(String name) { } static class InterfaceImpl { + public final String iname; public ArrayList impls = new ArrayList(); @@ -35,11 +40,10 @@ public InterfaceImpl(String iname, String cname) { for (MethodNode method : inode.methods) names.add(method.name + method.desc); ClassNode cnode = getClassNode(cname); - for (MethodNode method : cnode.methods) - if (names.contains(method.name + method.desc)) { - impls.add(method); - method.desc = new ObfMapping(cnode.name, method.name, method.desc).toRuntime().s_desc; - } + for (MethodNode method : cnode.methods) if (names.contains(method.name + method.desc)) { + impls.add(method); + method.desc = new ObfMapping(cnode.name, method.name, method.desc).toRuntime().s_desc; + } } public boolean patch(ClassNode cnode) { diff --git a/src/main/java/codechicken/core/asm/DelegatedTransformer.java b/src/main/java/codechicken/core/asm/DelegatedTransformer.java index 6d5d820..eaf75dd 100644 --- a/src/main/java/codechicken/core/asm/DelegatedTransformer.java +++ b/src/main/java/codechicken/core/asm/DelegatedTransformer.java @@ -13,13 +13,16 @@ import java.util.Stack; import java.util.jar.JarFile; import java.util.zip.ZipEntry; + import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.Opcodes; public class DelegatedTransformer implements IClassTransformer { + private static ArrayList delegatedTransformers; private static Method m_defineClass; private static Field f_cachedClasses; @@ -27,8 +30,8 @@ public class DelegatedTransformer implements IClassTransformer { public DelegatedTransformer() { delegatedTransformers = new ArrayList(); try { - m_defineClass = ClassLoader.class.getDeclaredMethod( - "defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE); + m_defineClass = ClassLoader.class + .getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE); m_defineClass.setAccessible(true); f_cachedClasses = LaunchClassLoader.class.getDeclaredField("cachedClasses"); f_cachedClasses.setAccessible(true); @@ -53,9 +56,10 @@ public static void addTransformer(String transformer, JarFile jar, File jarFile) if (bytes == null) { String resourceName = transformer.replace('.', '/') + ".class"; ZipEntry entry = jar.getEntry(resourceName); - if (entry == null) - throw new Exception("Failed to add transformer: " + transformer + ". Entry not found in jar file " - + jarFile.getName()); + if (entry == null) throw new Exception( + "Failed to add transformer: " + transformer + + ". Entry not found in jar file " + + jarFile.getName()); bytes = readFully(jar.getInputStream(entry)); } @@ -63,14 +67,12 @@ public static void addTransformer(String transformer, JarFile jar, File jarFile) defineDependancies(bytes, jar, jarFile); Class clazz = defineClass(transformer, bytes); - if (!IClassTransformer.class.isAssignableFrom(clazz)) - throw new Exception( - "Failed to add transformer: " + transformer + " is not an instance of IClassTransformer"); + if (!IClassTransformer.class.isAssignableFrom(clazz)) throw new Exception( + "Failed to add transformer: " + transformer + " is not an instance of IClassTransformer"); IClassTransformer classTransformer; try { - classTransformer = (IClassTransformer) - clazz.getDeclaredConstructor(File.class).newInstance(jarFile); + classTransformer = (IClassTransformer) clazz.getDeclaredConstructor(File.class).newInstance(jarFile); } catch (NoSuchMethodException nsme) { classTransformer = (IClassTransformer) clazz.newInstance(); } diff --git a/src/main/java/codechicken/core/asm/DependancyLister.java b/src/main/java/codechicken/core/asm/DependancyLister.java index 92549a1..ddbc52c 100644 --- a/src/main/java/codechicken/core/asm/DependancyLister.java +++ b/src/main/java/codechicken/core/asm/DependancyLister.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; @@ -12,9 +13,11 @@ import org.objectweb.asm.Opcodes; public class DependancyLister extends ClassVisitor { + private static Pattern classdesc = Pattern.compile("L(.+?);"); private class DependancyMethodLister extends MethodVisitor { + public DependancyMethodLister(int api) { super(api); } diff --git a/src/main/java/codechicken/core/asm/InterfaceDependancies.java b/src/main/java/codechicken/core/asm/InterfaceDependancies.java index bf8e682..4d247a1 100644 --- a/src/main/java/codechicken/core/asm/InterfaceDependancies.java +++ b/src/main/java/codechicken/core/asm/InterfaceDependancies.java @@ -6,5 +6,5 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) +@Target({ ElementType.TYPE }) public @interface InterfaceDependancies {} diff --git a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java index 9af7f6f..6fa12ea 100644 --- a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java +++ b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java @@ -1,23 +1,14 @@ package codechicken.core.asm; -import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.ASMInit; -import codechicken.lib.asm.CC_ClassWriter; -import codechicken.lib.asm.ObfMapping; -import codechicken.obfuscator.IHeirachyEvaluator; -import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; -import codechicken.obfuscator.ObfuscationRun; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import cpw.mods.fml.common.asm.transformers.AccessTransformer; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; import java.util.Map.Entry; + import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.LaunchClassLoader; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; @@ -25,12 +16,28 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; +import codechicken.lib.asm.ASMHelper; +import codechicken.lib.asm.ASMInit; +import codechicken.lib.asm.CC_ClassWriter; +import codechicken.lib.asm.ObfMapping; +import codechicken.obfuscator.IHeirachyEvaluator; +import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; +import codechicken.obfuscator.ObfuscationRun; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +import cpw.mods.fml.common.asm.transformers.AccessTransformer; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; + public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator { + static { ASMInit.init(); } public static class LoadPlugin implements IFMLLoadingPlugin { + @Override public String[] getASMTransformerClass() { return new String[0]; @@ -72,8 +79,8 @@ public String getAccessTransformerClass() { try { f_transformers = LaunchClassLoader.class.getDeclaredField("transformers"); f_modifiers = AccessTransformer.class.getDeclaredField("modifiers"); - Class c_Modifier = - Class.forName(AccessTransformer.class.getName() + "$Modifier", false, Launch.classLoader); + Class c_Modifier = Class + .forName(AccessTransformer.class.getName() + "$Modifier", false, Launch.classLoader); f_Modifier_name = c_Modifier.getDeclaredField("name"); f_Modifier_desc = c_Modifier.getDeclaredField("desc"); @@ -110,8 +117,7 @@ private static List getTransformers() { public static void load() { CodeChickenCoreModContainer.loadConfig(); - if (CodeChickenCoreModContainer.config - .getTag("dev.deobfuscate") + if (CodeChickenCoreModContainer.config.getTag("dev.deobfuscate") .setComment("set to true to completely deobfuscate mcp names") .getBooleanValue(!ObfMapping.obfuscated)) { run = new ObfuscationRun( @@ -120,8 +126,7 @@ public static void load() { ObfuscationRun.fillDefaults(new HashMap())); run.obf.setHeirachyEvaluator(instance); run.setQuiet().parseMappings(); - Collections.addAll( - excludedPackages, run.config.get("excludedPackages").split(";")); + Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";")); if (ObfMapping.obfuscated) { ObfMapping.loadMCPRemapper(); @@ -151,8 +156,12 @@ public byte[] transform(String name, String transformedName, byte[] bytes) { private byte[] injectCallback(byte[] bytes) { ClassNode cnode = ASMHelper.createClassNode(bytes); MethodNode mnode = ASMHelper.findMethod(new ObfMapping(cnode.name, "", "()V"), cnode); - mnode.instructions.insert(new MethodInsnNode( - INVOKESTATIC, "codechicken/core/asm/MCPDeobfuscationTransformer", "loadCallback", "()V")); + mnode.instructions.insert( + new MethodInsnNode( + INVOKESTATIC, + "codechicken/core/asm/MCPDeobfuscationTransformer", + "loadCallback", + "()V")); return ASMHelper.createBytes(cnode, 0); } @@ -205,8 +214,7 @@ public List getParents(ObfuscationEntry desc) { try { byte[] bytes = Launch.classLoader.getClassBytes(name); if (bytes != null) return ObfuscationRun.getParents(ASMHelper.createClassNode(bytes)); - } catch (IOException ignored) { - } + } catch (IOException ignored) {} // clear the miss cache because the library containing it might be loaded later Launch.classLoader.clearNegativeEntries(Collections.singleton(name)); return null; diff --git a/src/main/java/codechicken/core/asm/MethodASMifier.java b/src/main/java/codechicken/core/asm/MethodASMifier.java index 55a1519..1585b56 100644 --- a/src/main/java/codechicken/core/asm/MethodASMifier.java +++ b/src/main/java/codechicken/core/asm/MethodASMifier.java @@ -2,17 +2,21 @@ import static org.objectweb.asm.Opcodes.*; -import codechicken.lib.asm.ObfMapping; import java.io.File; import java.io.PrintWriter; + import net.minecraft.launchwrapper.Launch; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.util.Printer; import org.objectweb.asm.util.TraceMethodVisitor; +import codechicken.lib.asm.ObfMapping; + public class MethodASMifier extends ClassVisitor { + PrintWriter printWriter; ObfMapping method; Printer asmifier; diff --git a/src/main/java/codechicken/core/asm/TweakTransformer.java b/src/main/java/codechicken/core/asm/TweakTransformer.java index 8ae895e..380ee4d 100644 --- a/src/main/java/codechicken/core/asm/TweakTransformer.java +++ b/src/main/java/codechicken/core/asm/TweakTransformer.java @@ -2,19 +2,23 @@ import static codechicken.lib.asm.InsnComparator.*; -import codechicken.lib.asm.*; -import codechicken.lib.asm.ModularASMTransformer.MethodReplacer; -import codechicken.lib.asm.ModularASMTransformer.MethodTransformer; -import codechicken.lib.asm.ModularASMTransformer.MethodWriter; -import codechicken.lib.config.ConfigTag; import java.util.Map; + import net.minecraft.launchwrapper.IClassTransformer; + import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; +import codechicken.lib.asm.*; +import codechicken.lib.asm.ModularASMTransformer.MethodReplacer; +import codechicken.lib.asm.ModularASMTransformer.MethodTransformer; +import codechicken.lib.asm.ModularASMTransformer.MethodWriter; +import codechicken.lib.config.ConfigTag; + public class TweakTransformer implements IClassTransformer, Opcodes { + static { ASMInit.init(); } @@ -25,43 +29,42 @@ public class TweakTransformer implements IClassTransformer, Opcodes { public static void load() { CodeChickenCoreModContainer.loadConfig(); - tweaks = CodeChickenCoreModContainer.config - .getTag("tweaks") - .setComment("Various tweaks that can be applied to game mechanics.") - .useBraces(); + tweaks = CodeChickenCoreModContainer.config.getTag("tweaks") + .setComment("Various tweaks that can be applied to game mechanics.").useBraces(); tweaks.removeTag("persistantLava"); - if (tweaks.getTag("environmentallyFriendlyCreepers") - .setComment( - "If set to true, creepers will not destroy landscape. (A version of mobGriefing setting just for creepers)") + if (tweaks.getTag("environmentallyFriendlyCreepers").setComment( + "If set to true, creepers will not destroy landscape. (A version of mobGriefing setting just for creepers)") .getBooleanValue(false)) { - transformer.add(new MethodReplacer( - new ObfMapping("net/minecraft/entity/monster/EntityCreeper", "func_146077_cc", "()V"), - blocks.get("d_environmentallyFriendlyCreepers"), - blocks.get("environmentallyFriendlyCreepers"))); + transformer.add( + new MethodReplacer( + new ObfMapping("net/minecraft/entity/monster/EntityCreeper", "func_146077_cc", "()V"), + blocks.get("d_environmentallyFriendlyCreepers"), + blocks.get("environmentallyFriendlyCreepers"))); } - if (!tweaks.getTag("softLeafReplace") - .setComment("If set to false, leaves will only replace air when growing") + if (!tweaks.getTag("softLeafReplace").setComment("If set to false, leaves will only replace air when growing") .getBooleanValue(false)) { - transformer.add(new MethodWriter( - ACC_PUBLIC, - new ObfMapping( - "net/minecraft/block/Block", - "canBeReplacedByLeaves", - "(Lnet/minecraft/world/IBlockAccess;III)Z"), - blocks.get("softLeafReplace"))); + transformer.add( + new MethodWriter( + ACC_PUBLIC, + new ObfMapping( + "net/minecraft/block/Block", + "canBeReplacedByLeaves", + "(Lnet/minecraft/world/IBlockAccess;III)Z"), + blocks.get("softLeafReplace"))); } - if (tweaks.getTag("doFireTickOut") - .setComment( - "If set to true and doFireTick is disabled in the game rules, fire will still dissipate if it's not over a fire source") + if (tweaks.getTag("doFireTickOut").setComment( + "If set to true and doFireTick is disabled in the game rules, fire will still dissipate if it's not over a fire source") .getBooleanValue(true)) { transformer.add( - new MethodTransformer(new ObfMapping( - "net/minecraft/block/BlockFire", - "func_149674_a", - "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) { + new MethodTransformer( + new ObfMapping( + "net/minecraft/block/BlockFire", + "func_149674_a", + "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) { + @Override public void transform(MethodNode mv) { ASMBlock needle = blocks.get("n_doFireTick"); @@ -79,10 +82,12 @@ public void transform(MethodNode mv) { .setComment("If set to true two adjacent water source blocks will not generate a third.") .getBooleanValue(false)) { transformer.add( - new MethodTransformer(new ObfMapping( - "net/minecraft/block/BlockDynamicLiquid", - "func_149674_a", - "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) { + new MethodTransformer( + new ObfMapping( + "net/minecraft/block/BlockDynamicLiquid", + "func_149674_a", + "(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) { + @Override public void transform(MethodNode mv) { ASMBlock needle = blocks.get("finiteWater"); diff --git a/src/main/java/codechicken/core/commands/CoreCommand.java b/src/main/java/codechicken/core/commands/CoreCommand.java index dffde45..606c230 100644 --- a/src/main/java/codechicken/core/commands/CoreCommand.java +++ b/src/main/java/codechicken/core/commands/CoreCommand.java @@ -1,7 +1,7 @@ package codechicken.core.commands; -import codechicken.core.ServerUtils; import java.util.List; + import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; @@ -15,8 +15,12 @@ import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; +import codechicken.core.ServerUtils; + public abstract class CoreCommand implements ICommand { + public class WCommandSender implements ICommandSender { + public ICommandSender wrapped; public WCommandSender(ICommandSender sender) { @@ -125,10 +129,8 @@ public boolean isUsernameIndex(String[] astring, int i) { @Override public boolean canCommandSenderUseCommand(ICommandSender var1) { if (OPOnly()) { - if (var1 instanceof EntityPlayer) - return MinecraftServer.getServer() - .getConfigurationManager() - .func_152596_g(((EntityPlayer) var1).getGameProfile()); + if (var1 instanceof EntityPlayer) return MinecraftServer.getServer().getConfigurationManager() + .func_152596_g(((EntityPlayer) var1).getGameProfile()); else if (var1 instanceof MinecraftServer) return true; else return false; } diff --git a/src/main/java/codechicken/core/commands/PlayerCommand.java b/src/main/java/codechicken/core/commands/PlayerCommand.java index 694f03d..4426344 100644 --- a/src/main/java/codechicken/core/commands/PlayerCommand.java +++ b/src/main/java/codechicken/core/commands/PlayerCommand.java @@ -11,6 +11,7 @@ import net.minecraft.world.WorldServer; public abstract class PlayerCommand extends CoreCommand { + @Override public boolean canCommandSenderUseCommand(ICommandSender var1) { if (!super.canCommandSenderUseCommand(var1)) return false; @@ -26,8 +27,8 @@ public void handleCommand(String command, String playername, String[] args, WCom public abstract void handleCommand(WorldServer world, EntityPlayerMP player, String[] args); public ChunkPosition getPlayerLookingAtBlock(EntityPlayerMP player, float reach) { - Vec3 vec3d = - Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); + Vec3 vec3d = Vec3 + .createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); Vec3 vec3d1 = player.getLook(1.0F); Vec3 vec3d2 = vec3d.addVector(vec3d1.xCoord * reach, vec3d1.yCoord * reach, vec3d1.zCoord * reach); MovingObjectPosition hit = player.worldObj.rayTraceBlocks(vec3d, vec3d2); @@ -39,8 +40,8 @@ public ChunkPosition getPlayerLookingAtBlock(EntityPlayerMP player, float reach) } public Entity getPlayerLookingAtEntity(EntityPlayerMP player, float reach) { - Vec3 vec3d = - Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); + Vec3 vec3d = Vec3 + .createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ); Vec3 vec3d1 = player.getLook(1.0F); Vec3 vec3d2 = vec3d.addVector(vec3d1.xCoord * reach, vec3d1.yCoord * reach, vec3d1.zCoord * reach); MovingObjectPosition hit = player.worldObj.rayTraceBlocks(vec3d, vec3d2); diff --git a/src/main/java/codechicken/core/commands/ServerCommand.java b/src/main/java/codechicken/core/commands/ServerCommand.java index 86cdc6a..164485f 100644 --- a/src/main/java/codechicken/core/commands/ServerCommand.java +++ b/src/main/java/codechicken/core/commands/ServerCommand.java @@ -4,6 +4,7 @@ import net.minecraft.server.MinecraftServer; public abstract class ServerCommand extends CoreCommand { + @Override public void processCommand(ICommandSender var1, String[] var2) { handleCommand(var2, (MinecraftServer) var1); diff --git a/src/main/java/codechicken/core/featurehack/EntityRenderHook.java b/src/main/java/codechicken/core/featurehack/EntityRenderHook.java index 9d51fef..452def2 100644 --- a/src/main/java/codechicken/core/featurehack/EntityRenderHook.java +++ b/src/main/java/codechicken/core/featurehack/EntityRenderHook.java @@ -5,7 +5,9 @@ import net.minecraft.world.World; public class EntityRenderHook extends Entity { + public static interface IRenderCallback { + public void render(float frame, int pass); public boolean shouldRenderInPass(int pass); diff --git a/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java b/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java index 36eff20..c34a5c4 100644 --- a/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java +++ b/src/main/java/codechicken/core/featurehack/EntityUpdateHook.java @@ -5,7 +5,9 @@ import net.minecraft.world.World; public class EntityUpdateHook extends Entity { + public static interface IUpdateCallback { + public void onUpdate(); public boolean isValid(); diff --git a/src/main/java/codechicken/core/featurehack/FeatureHack.java b/src/main/java/codechicken/core/featurehack/FeatureHack.java index 911a97b..d840541 100644 --- a/src/main/java/codechicken/core/featurehack/FeatureHack.java +++ b/src/main/java/codechicken/core/featurehack/FeatureHack.java @@ -6,6 +6,7 @@ import cpw.mods.fml.relauncher.SideOnly; public class FeatureHack { + private static boolean updateHookEnabled = false; private static boolean renderHookEnabled = false; diff --git a/src/main/java/codechicken/core/featurehack/GameDataManipulator.java b/src/main/java/codechicken/core/featurehack/GameDataManipulator.java index 2a1f0e3..920fcb4 100644 --- a/src/main/java/codechicken/core/featurehack/GameDataManipulator.java +++ b/src/main/java/codechicken/core/featurehack/GameDataManipulator.java @@ -1,14 +1,17 @@ package codechicken.core.featurehack; -import codechicken.lib.asm.ObfMapping; import java.lang.reflect.Field; import java.util.Map; + import net.minecraft.item.Item; import net.minecraft.util.ObjectIntIdentityMap; import net.minecraft.util.RegistryNamespaced; import net.minecraft.util.RegistrySimple; +import codechicken.lib.asm.ObfMapping; + public class GameDataManipulator { + public static Field f_registryObjects; public static Field f_underlyingIntegerMap; @@ -16,15 +19,13 @@ public class GameDataManipulator { try { f_registryObjects = RegistrySimple.class.getDeclaredField( new ObfMapping("net/minecraft/util/RegistrySimple", "field_82596_a", "Ljava/util/Map;") - .toRuntime() - .s_name); + .toRuntime().s_name); f_registryObjects.setAccessible(true); - f_underlyingIntegerMap = RegistryNamespaced.class.getDeclaredField(new ObfMapping( + f_underlyingIntegerMap = RegistryNamespaced.class.getDeclaredField( + new ObfMapping( "net/minecraft/util/RegistryNamespaced", "field_148759_a", - "Lnet/minecraft/util/ObjectIntIdentityMap;") - .toRuntime() - .s_name); + "Lnet/minecraft/util/ObjectIntIdentityMap;").toRuntime().s_name); f_underlyingIntegerMap.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); diff --git a/src/main/java/codechicken/core/featurehack/LiquidTextures.java b/src/main/java/codechicken/core/featurehack/LiquidTextures.java index 9c00606..7c531bd 100644 --- a/src/main/java/codechicken/core/featurehack/LiquidTextures.java +++ b/src/main/java/codechicken/core/featurehack/LiquidTextures.java @@ -1,5 +1,12 @@ package codechicken.core.featurehack; +import java.lang.reflect.Field; + +import net.minecraft.init.Blocks; +import net.minecraft.util.IIcon; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.common.MinecraftForge; + import codechicken.core.ReflectionManager; import codechicken.core.asm.TweakTransformer; import codechicken.core.featurehack.mc.TextureLavaFX; @@ -8,13 +15,9 @@ import codechicken.core.featurehack.mc.TextureWaterFlowFX; import codechicken.lib.asm.ObfMapping; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import java.lang.reflect.Field; -import net.minecraft.init.Blocks; -import net.minecraft.util.IIcon; -import net.minecraftforge.client.event.TextureStitchEvent; -import net.minecraftforge.common.MinecraftForge; public class LiquidTextures { + public static IIcon[] newTextures = new IIcon[4]; public static boolean replaceLava; @@ -23,14 +26,10 @@ public class LiquidTextures { private static Field field_tex; public static void init() { - replaceWater = TweakTransformer.tweaks - .getTag("replaceWaterFX") - .setComment("Set this to true to use the pre1.5 water textures") - .getBooleanValue(false); - replaceLava = TweakTransformer.tweaks - .getTag("replaceLavaFX") - .setComment("Set this to true to use the pre1.5 lava textures") - .getBooleanValue(false); + replaceWater = TweakTransformer.tweaks.getTag("replaceWaterFX") + .setComment("Set this to true to use the pre1.5 water textures").getBooleanValue(false); + replaceLava = TweakTransformer.tweaks.getTag("replaceLavaFX") + .setComment("Set this to true to use the pre1.5 lava textures").getBooleanValue(false); if (replaceWater) { newTextures[0] = new TextureWaterFX().texture; newTextures[1] = new TextureWaterFlowFX().texture; diff --git a/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java b/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java index 53ba9aa..d32f8cd 100644 --- a/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java +++ b/src/main/java/codechicken/core/featurehack/RenderEntityRenderHook.java @@ -4,9 +4,11 @@ import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.MinecraftForgeClient; + import org.lwjgl.opengl.GL11; public class RenderEntityRenderHook extends Render { + @Override public void doRender(Entity entity, double x, double y, double z, float f, float frame) { EntityRenderHook hook = (EntityRenderHook) entity; diff --git a/src/main/java/codechicken/core/featurehack/RenderNull.java b/src/main/java/codechicken/core/featurehack/RenderNull.java index 9d6d099..a15240d 100644 --- a/src/main/java/codechicken/core/featurehack/RenderNull.java +++ b/src/main/java/codechicken/core/featurehack/RenderNull.java @@ -5,6 +5,7 @@ import net.minecraft.util.ResourceLocation; public class RenderNull extends Render { + @Override public void doRender(Entity var1, double var2, double var4, double var6, float var8, float var9) {} diff --git a/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java b/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java index c03af77..873aaeb 100644 --- a/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java +++ b/src/main/java/codechicken/core/featurehack/TweakTransformerHelper.java @@ -3,23 +3,23 @@ import static net.minecraftforge.common.util.ForgeDirection.UP; import java.util.Random; + import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.world.World; public class TweakTransformerHelper { + public static void quenchFireTick(World world, int x, int y, int z, Random rand) { Block base = world.getBlock(x, y - 1, z); boolean supported = (base != null && base.isFireSource(world, x, y - 1, z, UP)); - if (!Blocks.fire.canPlaceBlockAt(world, x, y, z) - || !supported - && world.isRaining() - && (world.canLightningStrikeAt(x, y, z) - || world.canLightningStrikeAt(x - 1, y, z) - || world.canLightningStrikeAt(x + 1, y, z) - || world.canLightningStrikeAt(x, y, z - 1) - || world.canLightningStrikeAt(x, y, z + 1))) world.setBlockToAir(x, y, z); + if (!Blocks.fire.canPlaceBlockAt(world, x, y, z) || !supported && world.isRaining() + && (world.canLightningStrikeAt(x, y, z) || world.canLightningStrikeAt(x - 1, y, z) + || world.canLightningStrikeAt(x + 1, y, z) + || world.canLightningStrikeAt(x, y, z - 1) + || world.canLightningStrikeAt(x, y, z + 1))) + world.setBlockToAir(x, y, z); else { int meta = world.getBlockMetadata(x, y, z); if (meta < 15) world.setBlockMetadataWithNotify(x, y, z, meta + rand.nextInt(3) / 2, 0); diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java index 0ebfd58..18f1217 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFX.java @@ -1,13 +1,15 @@ package codechicken.core.featurehack.mc; +import net.minecraft.util.MathHelper; + import codechicken.lib.colour.ColourRGBA; import codechicken.lib.render.TextureFX; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.util.MathHelper; @SideOnly(Side.CLIENT) public class TextureLavaFX extends TextureFX { + protected float[] field_76876_g = new float[256]; protected float[] field_76878_h = new float[256]; protected float[] field_76879_i = new float[256]; @@ -52,16 +54,16 @@ public void onTick() { this.field_76878_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + (this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] - + this.field_76879_i[ - (var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] - + this.field_76879_i[ - (var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] - + this.field_76879_i[ - (var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) + + this.field_76879_i[(var1 + 1 & tileSizeMask) + + (var2 + 0 & tileSizeMask) * tileSizeBase] + + this.field_76879_i[(var1 + 1 & tileSizeMask) + + (var2 + 1 & tileSizeMask) * tileSizeBase] + + this.field_76879_i[(var1 + 0 & tileSizeMask) + + (var2 + 1 & tileSizeMask) * tileSizeBase]) / 4.0F * 0.8F; - this.field_76879_i[var1 + var2 * tileSizeBase] += - this.field_76877_j[var1 + var2 * tileSizeBase] * 0.01F; + this.field_76879_i[var1 + var2 * tileSizeBase] += this.field_76877_j[var1 + var2 * tileSizeBase] + * 0.01F; if (this.field_76879_i[var1 + var2 * tileSizeBase] < 0.0F) { this.field_76879_i[var1 + var2 * tileSizeBase] = 0.0F; diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java index 849c102..37d58eb 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureLavaFlowFX.java @@ -1,13 +1,15 @@ package codechicken.core.featurehack.mc; +import net.minecraft.util.MathHelper; + import codechicken.lib.colour.ColourRGBA; import codechicken.lib.render.TextureFX; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.util.MathHelper; @SideOnly(Side.CLIENT) public class TextureLavaFlowFX extends TextureFX { + protected float[] field_76871_g = new float[256]; protected float[] field_76874_h = new float[256]; protected float[] field_76875_i = new float[256]; @@ -60,16 +62,16 @@ public void onTick() { this.field_76874_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + (this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] - + this.field_76875_i[ - (var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] - + this.field_76875_i[ - (var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] - + this.field_76875_i[ - (var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) + + this.field_76875_i[(var1 + 1 & tileSizeMask) + + (var2 + 0 & tileSizeMask) * tileSizeBase] + + this.field_76875_i[(var1 + 1 & tileSizeMask) + + (var2 + 1 & tileSizeMask) * tileSizeBase] + + this.field_76875_i[(var1 + 0 & tileSizeMask) + + (var2 + 1 & tileSizeMask) * tileSizeBase]) / 4.0F * 0.8F; - this.field_76875_i[var1 + var2 * tileSizeBase] += - this.field_76872_j[var1 + var2 * tileSizeBase] * 0.01F; + this.field_76875_i[var1 + var2 * tileSizeBase] += this.field_76872_j[var1 + var2 * tileSizeBase] + * 0.01F; if (this.field_76875_i[var1 + var2 * tileSizeBase] < 0.0F) { this.field_76875_i[var1 + var2 * tileSizeBase] = 0.0F; diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java index bb3c0ec..bed6518 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFX.java @@ -7,6 +7,7 @@ @SideOnly(Side.CLIENT) public class TextureWaterFX extends TextureFX { + /** red RGB value for water texture */ protected float[] red = new float[256]; diff --git a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java index 7632a16..fb03e0d 100644 --- a/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java +++ b/src/main/java/codechicken/core/featurehack/mc/TextureWaterFlowFX.java @@ -7,6 +7,7 @@ @SideOnly(Side.CLIENT) public class TextureWaterFlowFX extends TextureFX { + protected float[] field_76880_g = new float[256]; protected float[] field_76883_h = new float[256]; protected float[] field_76884_i = new float[256]; @@ -51,15 +52,15 @@ public void onTick() { var3 += this.field_76880_g[var5 + var6 * tileSizeBase]; } - this.field_76883_h[var1 + var2 * tileSizeBase] = - var3 / 3.2F + this.field_76884_i[var1 + var2 * tileSizeBase] * 0.8F; + this.field_76883_h[var1 + var2 * tileSizeBase] = var3 / 3.2F + + this.field_76884_i[var1 + var2 * tileSizeBase] * 0.8F; } } for (var1 = 0; var1 < tileSizeBase; ++var1) { for (var2 = 0; var2 < tileSizeBase; ++var2) { - this.field_76884_i[var1 + var2 * tileSizeBase] += - this.field_76881_j[var1 + var2 * tileSizeBase] * 0.05F; + this.field_76884_i[var1 + var2 * tileSizeBase] += this.field_76881_j[var1 + var2 * tileSizeBase] + * 0.05F; if (this.field_76884_i[var1 + var2 * tileSizeBase] < 0.0F) { this.field_76884_i[var1 + var2 * tileSizeBase] = 0.0F; diff --git a/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java b/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java index 06cc648..b40642a 100644 --- a/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java +++ b/src/main/java/codechicken/core/fluid/ExtendedFluidTank.java @@ -6,6 +6,7 @@ import net.minecraftforge.fluids.IFluidTank; public class ExtendedFluidTank implements IFluidTank { + private FluidStack fluid; private boolean changeType; private int capacity; diff --git a/src/main/java/codechicken/core/fluid/FluidUtils.java b/src/main/java/codechicken/core/fluid/FluidUtils.java index 689b1c3..81e5ca3 100644 --- a/src/main/java/codechicken/core/fluid/FluidUtils.java +++ b/src/main/java/codechicken/core/fluid/FluidUtils.java @@ -1,6 +1,5 @@ package codechicken.core.fluid; -import codechicken.lib.inventory.InventoryUtils; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -11,7 +10,10 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidHandler; +import codechicken.lib.inventory.InventoryUtils; + public class FluidUtils { + public static int B = FluidContainerRegistry.BUCKET_VOLUME; public static FluidStack water = new FluidStack(FluidRegistry.WATER, 1000); public static FluidStack lava = new FluidStack(FluidRegistry.LAVA, 1000); @@ -68,8 +70,7 @@ public static FluidStack read(NBTTagCompound tag) { } public static NBTTagCompound write(FluidStack fluid, NBTTagCompound tag) { - return fluid == null || fluid.getFluid() == null - ? new NBTTagCompound() + return fluid == null || fluid.getFluid() == null ? new NBTTagCompound() : fluid.writeToNBT(new NBTTagCompound()); } diff --git a/src/main/java/codechicken/core/fluid/TankAccess.java b/src/main/java/codechicken/core/fluid/TankAccess.java index e3f6575..f1d2f52 100644 --- a/src/main/java/codechicken/core/fluid/TankAccess.java +++ b/src/main/java/codechicken/core/fluid/TankAccess.java @@ -5,6 +5,7 @@ import net.minecraftforge.fluids.IFluidHandler; public class TankAccess { + public IFluidHandler tank; public ForgeDirection side; diff --git a/src/main/java/codechicken/core/gui/ClickCounter.java b/src/main/java/codechicken/core/gui/ClickCounter.java index 7faeea6..74f85cf 100644 --- a/src/main/java/codechicken/core/gui/ClickCounter.java +++ b/src/main/java/codechicken/core/gui/ClickCounter.java @@ -1,11 +1,14 @@ package codechicken.core.gui; -import com.google.common.base.Objects; import java.util.Map; import java.util.TreeMap; +import com.google.common.base.Objects; + public class ClickCounter { + public class ClickCount { + public T clicked; public long time; public int count; diff --git a/src/main/java/codechicken/core/gui/GuiCCButton.java b/src/main/java/codechicken/core/gui/GuiCCButton.java index 4a1ea29..8c81242 100644 --- a/src/main/java/codechicken/core/gui/GuiCCButton.java +++ b/src/main/java/codechicken/core/gui/GuiCCButton.java @@ -3,9 +3,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.util.ResourceLocation; + import org.lwjgl.opengl.GL11; public class GuiCCButton extends GuiWidget { + public String text; public String actionCommand; private boolean isEnabled = true; @@ -32,8 +34,7 @@ public void setEnabled(boolean b) { public void mouseClicked(int x, int y, int button) { if (isEnabled && pointInside(x, y) && actionCommand != null) { sendAction(actionCommand, button); - Minecraft.getMinecraft() - .getSoundHandler() + Minecraft.getMinecraft().getSoundHandler() .playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); } } @@ -52,8 +53,8 @@ public void drawButtonTex(int mousex, int mousey) { int state = getButtonTex(mousex, mousey); drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2); // top left drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2); // top right - drawTexturedModalRect( - x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2); // bottom left + drawTexturedModalRect(x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2); // bottom + // left drawTexturedModalRect( x + width / 2, y + height / 2, diff --git a/src/main/java/codechicken/core/gui/GuiCCTextField.java b/src/main/java/codechicken/core/gui/GuiCCTextField.java index 944853b..015070f 100644 --- a/src/main/java/codechicken/core/gui/GuiCCTextField.java +++ b/src/main/java/codechicken/core/gui/GuiCCTextField.java @@ -2,9 +2,11 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ChatAllowedCharacters; + import org.lwjgl.input.Keyboard; public class GuiCCTextField extends GuiWidget { + private String text; private boolean isFocused; private boolean isEnabled; @@ -63,10 +65,9 @@ public void update() { public void keyTyped(char c, int keycode) { if (!isEnabled || !isFocused) return; - /*if(c == '\t')//tab - { - parentGuiScreen.selectNextField(); - }*/ + /* + * if(c == '\t')//tab { parentGuiScreen.selectNextField(); } + */ if (c == '\026') // paste { String s = GuiScreen.getClipboardString(); @@ -90,8 +91,7 @@ public void keyTyped(char c, int keycode) { } public boolean canAddChar(char c) { - return allowedCharacters == null - ? ChatAllowedCharacters.isAllowedCharacter(c) + return allowedCharacters == null ? ChatAllowedCharacters.isAllowedCharacter(c) : allowedCharacters.indexOf(c) >= 0; } diff --git a/src/main/java/codechicken/core/gui/GuiScreenWidget.java b/src/main/java/codechicken/core/gui/GuiScreenWidget.java index 5136ffa..132692a 100644 --- a/src/main/java/codechicken/core/gui/GuiScreenWidget.java +++ b/src/main/java/codechicken/core/gui/GuiScreenWidget.java @@ -1,14 +1,18 @@ package codechicken.core.gui; -import codechicken.lib.gui.GuiDraw; import java.awt.Point; import java.util.ArrayList; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; + import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; +import codechicken.lib.gui.GuiDraw; + public class GuiScreenWidget extends GuiScreen implements IGuiActionListener { + public ArrayList widgets = new ArrayList(); public int xSize, ySize, guiTop, guiLeft; diff --git a/src/main/java/codechicken/core/gui/GuiScrollPane.java b/src/main/java/codechicken/core/gui/GuiScrollPane.java index aa91bc9..ba5f35a 100644 --- a/src/main/java/codechicken/core/gui/GuiScrollPane.java +++ b/src/main/java/codechicken/core/gui/GuiScrollPane.java @@ -1,10 +1,12 @@ package codechicken.core.gui; +import java.awt.*; + import codechicken.lib.math.MathHelper; import codechicken.lib.vec.Rectangle4i; -import java.awt.*; public abstract class GuiScrollPane extends GuiWidget { + protected int scrollclicky = -1; protected float scrollpercent; protected int scrollmousey; @@ -28,7 +30,10 @@ public void setMargins(int left, int top, int right, int bottom) { public Rectangle windowBounds() { return new Rectangle( - x + marginleft, y + margintop, width - marginleft - marginright, height - margintop - marginbottom); + x + marginleft, + y + margintop, + width - marginleft - marginright, + height - margintop - marginbottom); } public abstract int contentHeight(); @@ -103,13 +108,8 @@ public void mouseClicked(int mx, int my, int button) { Rectangle w = windowBounds(); int barempty = height - sbar.height; - if (button == 0 - && sbar.height < height - && // the scroll bar can move (not full length) - mx >= sbar.x - && mx <= sbar.x + sbar.width - && my >= y - && my <= y + height) // in the scroll pane + if (button == 0 && sbar.height < height && // the scroll bar can move (not full length) + mx >= sbar.x && mx <= sbar.x + sbar.width && my >= y && my <= y + height) // in the scroll pane { if (my < sbar.y) { percentscrolled = (my - y) / (float) barempty; @@ -126,14 +126,12 @@ public void mouseClicked(int mx, int my, int button) { } /** - * Mouse down on slot area - * Coordinates relative to slot content area + * Mouse down on slot area Coordinates relative to slot content area */ public void slotDown(int mx, int my, int button) {} /** - * Mouse up on slot area - * Coordinates relative to slot content area + * Mouse up on slot area Coordinates relative to slot content area */ public void slotUp(int mx, int my, int button) {} @@ -141,7 +139,7 @@ public void slotUp(int mx, int my, int button) {} public void mouseMovedOrUp(int mx, int my, int button) { Rectangle w = windowBounds(); if (isScrolling() && button == 0) // we were scrolling and we released mouse - scrollclicky = -1; + scrollclicky = -1; else if (w.contains(mx, my)) slotUp(mx - w.x, my - w.y + scrolledPixels(), button); } diff --git a/src/main/java/codechicken/core/gui/GuiScrollSlot.java b/src/main/java/codechicken/core/gui/GuiScrollSlot.java index 442a4b1..67c2d9a 100644 --- a/src/main/java/codechicken/core/gui/GuiScrollSlot.java +++ b/src/main/java/codechicken/core/gui/GuiScrollSlot.java @@ -1,9 +1,11 @@ package codechicken.core.gui; import java.awt.*; + import org.lwjgl.input.Keyboard; public abstract class GuiScrollSlot extends GuiScrollPane { + protected String actionCommand; public boolean focused; protected ClickCounter click = new ClickCounter(); diff --git a/src/main/java/codechicken/core/gui/GuiWidget.java b/src/main/java/codechicken/core/gui/GuiWidget.java index a4a0cbe..e3a7bd9 100644 --- a/src/main/java/codechicken/core/gui/GuiWidget.java +++ b/src/main/java/codechicken/core/gui/GuiWidget.java @@ -8,6 +8,7 @@ import net.minecraft.util.ResourceLocation; public class GuiWidget extends Gui { + protected static final ResourceLocation guiTex = new ResourceLocation("textures/gui/widgets.png"); public GuiScreen parentScreen; diff --git a/src/main/java/codechicken/core/gui/IGuiActionListener.java b/src/main/java/codechicken/core/gui/IGuiActionListener.java index c32c02a..4dfeb9e 100644 --- a/src/main/java/codechicken/core/gui/IGuiActionListener.java +++ b/src/main/java/codechicken/core/gui/IGuiActionListener.java @@ -1,5 +1,6 @@ package codechicken.core.gui; public interface IGuiActionListener { + public void actionPerformed(String actionCommand, Object... params); } diff --git a/src/main/java/codechicken/core/internal/CCCEventHandler.java b/src/main/java/codechicken/core/internal/CCCEventHandler.java index 59d5263..62515e4 100644 --- a/src/main/java/codechicken/core/internal/CCCEventHandler.java +++ b/src/main/java/codechicken/core/internal/CCCEventHandler.java @@ -1,5 +1,7 @@ package codechicken.core.internal; +import net.minecraftforge.client.event.GuiScreenEvent; + import codechicken.core.CCUpdateChecker; import codechicken.core.GuiModListScroll; import cpw.mods.fml.client.GuiModList; @@ -8,9 +10,9 @@ import cpw.mods.fml.common.gameevent.TickEvent.Phase; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraftforge.client.event.GuiScreenEvent; public class CCCEventHandler { + public static int renderTime; public static float renderFrame; diff --git a/src/main/java/codechicken/core/inventory/GuiContainerWidget.java b/src/main/java/codechicken/core/inventory/GuiContainerWidget.java index c14d900..9255b28 100644 --- a/src/main/java/codechicken/core/inventory/GuiContainerWidget.java +++ b/src/main/java/codechicken/core/inventory/GuiContainerWidget.java @@ -1,17 +1,21 @@ package codechicken.core.inventory; -import codechicken.core.gui.GuiWidget; -import codechicken.core.gui.IGuiActionListener; -import codechicken.lib.gui.GuiDraw; import java.awt.Point; import java.util.ArrayList; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.inventory.Container; + import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; +import codechicken.core.gui.GuiWidget; +import codechicken.core.gui.IGuiActionListener; +import codechicken.lib.gui.GuiDraw; + public class GuiContainerWidget extends GuiContainer implements IGuiActionListener { + public ArrayList widgets = new ArrayList(); public GuiContainerWidget(Container inventorySlots) { diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index a1e3b69..8a2f427 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -1,16 +1,5 @@ package codechicken.core.launch; -import codechicken.core.asm.*; -import codechicken.lib.config.ConfigTag; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.common.versioning.DefaultArtifactVersion; -import cpw.mods.fml.common.versioning.VersionParser; -import cpw.mods.fml.relauncher.CoreModManager; -import cpw.mods.fml.relauncher.FMLInjectionData; -import cpw.mods.fml.relauncher.IFMLCallHook; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; import java.awt.*; import java.io.File; import java.lang.reflect.Constructor; @@ -22,16 +11,31 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; + import javax.swing.JEditorPane; import javax.swing.JOptionPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -@TransformerExclusions(value = {"codechicken.core.asm", "codechicken.obfuscator"}) +import codechicken.core.asm.*; +import codechicken.lib.config.ConfigTag; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.versioning.DefaultArtifactVersion; +import cpw.mods.fml.common.versioning.VersionParser; +import cpw.mods.fml.relauncher.CoreModManager; +import cpw.mods.fml.relauncher.FMLInjectionData; +import cpw.mods.fml.relauncher.IFMLCallHook; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; + +@TransformerExclusions(value = { "codechicken.core.asm", "codechicken.obfuscator" }) @MCVersion("1.7.10") public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { + public static final String mcVersion = "[1.7.10]"; @Deprecated @@ -54,20 +58,19 @@ public CodeChickenCorePlugin() { private void injectDeobfPlugin() { try { Class wrapperClass = Class.forName("cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper"); - Constructor wrapperConstructor = wrapperClass.getConstructor( - String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class); + Constructor wrapperConstructor = wrapperClass + .getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class); Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins"); wrapperConstructor.setAccessible(true); f_loadPlugins.setAccessible(true); - ((List) f_loadPlugins.get(null)) - .add( - 2, - wrapperConstructor.newInstance( - "CCCDeobfPlugin", - new MCPDeobfuscationTransformer.LoadPlugin(), - null, - 0, - new String[0])); + ((List) f_loadPlugins.get(null)).add( + 2, + wrapperConstructor.newInstance( + "CCCDeobfPlugin", + new MCPDeobfuscationTransformer.LoadPlugin(), + null, + 0, + new String[0])); } catch (Exception e) { logger.error("Failed to inject MCPDeobfuscation Transformer", e); } @@ -88,13 +91,13 @@ public static void versionCheck(String reqVersion, String mod) { ep.setEditable(false); ep.setOpaque(false); ep.addHyperlinkListener(new HyperlinkListener() { + @Override public void hyperlinkUpdate(HyperlinkEvent event) { try { if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } }); @@ -134,45 +137,43 @@ public static String humanReadableByteCountBin(long bytes) { } public static void systemCheck(ConfigTag checkRAM) { - long minBytes = parseSize(checkRAM.getTag("minRAM") - .setComment("Amount of RAM minimum this modpack needs to load") - .getValue("3GB")); + long minBytes = parseSize( + checkRAM.getTag("minRAM").setComment("Amount of RAM minimum this modpack needs to load") + .getValue("3GB")); if (Runtime.getRuntime().maxMemory() < minBytes) { String err = "You should have at least " + humanReadableByteCountBin(minBytes) + " of RAM but you have only allocated " - + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + "."; + + humanReadableByteCountBin(Runtime.getRuntime().maxMemory()) + + "."; logger.error(err); JEditorPane ep = new JEditorPane( "text/html", - "" + err + "
" - + checkRAM.getTag("modPack") - .setComment("Name of the modpack") + "" + err + + "
" + + checkRAM.getTag("modPack").setComment("Name of the modpack") .getValue("Unidentified ModPack") + " seriously won't run without enough RAM. " - + checkRAM.getTag("wiki") - .setComment("Webpage describing RAM settings") - .getValue( - "See DownloadMoreRam.com for details.") + + checkRAM.getTag("wiki").setComment("Webpage describing RAM settings").getValue( + "See DownloadMoreRam.com for details.") + "
Recommended values are between " - + checkRAM.getTag("recRAM") - .setComment("Lower bound of recommended RAM") - .getValue("4GB") + " and " - + checkRAM.getTag("recRAMUpper") - .setComment("Upper bound of recommended RAM") + + checkRAM.getTag("recRAM").setComment("Lower bound of recommended RAM").getValue("4GB") + + " and " + + checkRAM.getTag("recRAMUpper").setComment("Upper bound of recommended RAM") .getValue("6GB") - + ". Check your launcher's JVM arguments." + ""); + + ". Check your launcher's JVM arguments." + + ""); ep.setEditable(false); ep.setOpaque(false); ep.addHyperlinkListener(new HyperlinkListener() { + @Override public void hyperlinkUpdate(HyperlinkEvent event) { try { if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } }); @@ -185,12 +186,8 @@ public void hyperlinkUpdate(HyperlinkEvent event) { @Override public String[] getASMTransformerClass() { versionCheck(mcVersion, "CodeChickenCore"); - return new String[] { - "codechicken.lib.asm.ClassHeirachyManager", - "codechicken.core.asm.TweakTransformer", - "codechicken.core.asm.DelegatedTransformer", - "codechicken.core.asm.DefaultImplementationTransformer" - }; + return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.core.asm.TweakTransformer", + "codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer" }; } @Override @@ -215,13 +212,12 @@ public void injectData(Map data) {} public Void call() { CodeChickenCoreModContainer.loadConfig(); ConfigTag checkRAM; - checkRAM = CodeChickenCoreModContainer.config - .getTag("checks") - .setComment("Configuration options for checking various requirements for a modpack.") - .useBraces(); + checkRAM = CodeChickenCoreModContainer.config.getTag("checks") + .setComment("Configuration options for checking various requirements for a modpack.").useBraces(); if (checkRAM.getTag("checkRAM") .setComment("If set to true, check RAM available for Minecraft before continuing to load") - .getBooleanValue(false)) systemCheck(checkRAM); + .getBooleanValue(false)) + systemCheck(checkRAM); TweakTransformer.load(); scanCodeChickenMods(); diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index 630e0c9..afae28c 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -1,14 +1,5 @@ package codechicken.core.launch; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import cpw.mods.fml.common.versioning.ComparableVersion; -import cpw.mods.fml.relauncher.FMLInjectionData; -import cpw.mods.fml.relauncher.FMLLaunchHandler; -import cpw.mods.fml.relauncher.IFMLCallHook; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import java.awt.*; import java.awt.Dialog.ModalityType; import java.awt.event.WindowAdapter; @@ -29,24 +20,39 @@ import java.util.regex.PatternSyntaxException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; + import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; + import net.minecraft.launchwrapper.LaunchClassLoader; + import sun.misc.URLClassPath; import sun.net.util.URLUtil; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import cpw.mods.fml.common.versioning.ComparableVersion; +import cpw.mods.fml.relauncher.FMLInjectionData; +import cpw.mods.fml.relauncher.FMLLaunchHandler; +import cpw.mods.fml.relauncher.IFMLCallHook; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; + /** - * For autodownloading stuff. - * This is really unoriginal, mostly ripped off FML, credits to cpw. + * For autodownloading stuff. This is really unoriginal, mostly ripped off FML, credits to cpw. */ @MCVersion("1.7.10") public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { + private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); private static final String owner = "CB's DepLoader"; private static DepLoadInst inst; public interface IDownloadDisplay { + void resetProgress(int sizeGuess); void setPokeThread(Thread currentThread); @@ -64,6 +70,7 @@ public interface IDownloadDisplay { @SuppressWarnings("serial") public static class Downloader extends JOptionPane implements IDownloadDisplay { + private JDialog container; private JLabel currentActivity; private JProgressBar progress; @@ -73,12 +80,13 @@ public static class Downloader extends JOptionPane implements IDownloadDisplay { private Box makeProgressPanel() { Box box = Box.createVerticalBox(); box.add(Box.createRigidArea(new Dimension(0, 10))); - JLabel welcomeLabel = new JLabel("" + owner - + " is setting up your minecraft environment"); + JLabel welcomeLabel = new JLabel( + "" + owner + + " is setting up your minecraft environment"); box.add(welcomeLabel); welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); - welcomeLabel = - new JLabel("Please wait, " + owner + " has some tasks to do before you can play"); + welcomeLabel = new JLabel( + "Please wait, " + owner + " has some tasks to do before you can play"); welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); box.add(welcomeLabel); box.add(Box.createRigidArea(new Dimension(0, 10))); @@ -98,8 +106,9 @@ public JDialog makeDialog() { setMessageType(JOptionPane.INFORMATION_MESSAGE); setMessage(makeProgressPanel()); - setOptions(new Object[] {"Stop"}); + setOptions(new Object[] { "Stop" }); addPropertyChangeListener(new PropertyChangeListener() { + @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() == Downloader.this && evt.getPropertyName() == VALUE_PROPERTY) { @@ -117,6 +126,7 @@ public void propertyChange(PropertyChangeEvent evt) { container.setVisible(true); container.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); container.addWindowListener(new WindowAdapter() { + @Override public void windowClosing(WindowEvent e) { requestClose( @@ -170,21 +180,26 @@ public void showErrorDialog(String name, String url) { JEditorPane ep = new JEditorPane( "text/html", "" + owner - + " was unable to download required library " + name + + " was unable to download required library " + + name + "
Check your internet connection and try restarting or download it manually from" + "
" + url + " and put it in your mods folder" + ""); + + url + + "\">" + + url + + " and put it in your mods folder" + + ""); ep.setEditable(false); ep.setOpaque(false); ep.addHyperlinkListener(new HyperlinkListener() { + @Override public void hyperlinkUpdate(HyperlinkEvent event) { try { if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception e) { - } + } catch (Exception e) {} } }); @@ -193,6 +208,7 @@ public void hyperlinkUpdate(HyperlinkEvent event) { } public static class DummyDownloader implements IDownloadDisplay { + @Override public void resetProgress(int sizeGuess) {} @@ -220,6 +236,7 @@ public void showErrorDialog(String name, String url) {} } public static class VersionedFile { + public final Pattern pattern; public final String filename; public final ComparableVersion version; @@ -244,6 +261,7 @@ public boolean matches() { } public static class Dependency { + public String url; public VersionedFile file; @@ -261,6 +279,7 @@ public Dependency(String url, VersionedFile file, boolean coreLib) { } public static class DepLoadInst { + private File modsDir; private File v_modsDir; private IDownloadDisplay downloadMonitor; @@ -312,7 +331,8 @@ private void deleteMod(File mod) { if (!mod.delete()) { mod.deleteOnExit(); - String msg = owner + " was unable to delete file " + mod.getPath() + String msg = owner + " was unable to delete file " + + mod.getPath() + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; CodeChickenCorePlugin.logger.error(msg); if (!GraphicsEnvironment.isHeadless()) @@ -342,8 +362,8 @@ private void download(Dependency dep) { } catch (Exception e) { libFile.delete(); if (downloadMonitor.shouldStopIt()) { - CodeChickenCorePlugin.logger.error( - "You have stopped the downloading operation before it could complete"); + CodeChickenCorePlugin.logger + .error("You have stopped the downloading operation before it could complete"); System.exit(1); return; } @@ -353,10 +373,10 @@ private void download(Dependency dep) { } private void download(InputStream is, int sizeGuess, File target) throws Exception { - if (sizeGuess > downloadBuffer.capacity()) - throw new Exception(String.format( - "The file %s is too large to be downloaded by " + owner + " - the download is invalid", - target.getName())); + if (sizeGuess > downloadBuffer.capacity()) throw new Exception( + String.format( + "The file %s is too large to be downloaded by " + owner + " - the download is invalid", + target.getName())); downloadBuffer.clear(); @@ -387,20 +407,20 @@ private void download(InputStream is, int sizeGuess, File target) throws Excepti } try { - /*String cksum = generateChecksum(downloadBuffer); - if (cksum.equals(validationHash)) - {*/ + /* + * String cksum = generateChecksum(downloadBuffer); if (cksum.equals(validationHash)) { + */ if (!target.exists()) target.createNewFile(); downloadBuffer.position(0); FileOutputStream fos = new FileOutputStream(target); fos.getChannel().write(downloadBuffer); fos.close(); - /*} - else - { - throw new RuntimeException(String.format("The downloaded file %s has an invalid checksum %s (expecting %s). The download did not succeed correctly and the file has been deleted. Please try launching again.", target.getName(), cksum, validationHash)); - }*/ + /* + * } else { throw new RuntimeException(String. + * format("The downloaded file %s has an invalid checksum %s (expecting %s). The download did not succeed correctly and the file has been deleted. Please try launching again." + * , target.getName(), cksum, validationHash)); } + */ } catch (Exception e) { throw e; } @@ -427,8 +447,12 @@ private String checkExisting(Dependency dep) { return null; } if (cmp > 0) { - CodeChickenCorePlugin.logger.warn("Warning: version of " + dep.file.name + ", " + vfile.version - + " is newer than request " + dep.file.version); + CodeChickenCorePlugin.logger.warn( + "Warning: version of " + dep.file.name + + ", " + + vfile.version + + " is newer than request " + + dep.file.version); return f.getName(); } return f.getName(); // found dependency @@ -497,8 +521,8 @@ private void scanDepInfo(File file) { if (e != null) loadJSon(zip.getInputStream(e)); zip.close(); } catch (Exception e) { - CodeChickenCorePlugin.logger.error( - "Failed to load dependencies.info from " + file.getName() + " as JSON"); + CodeChickenCorePlugin.logger + .error("Failed to load dependencies.info from " + file.getName() + " as JSON"); e.printStackTrace(); } } @@ -516,9 +540,8 @@ private void loadJSonArr(JsonElement root) throws IOException { } private void loadJson(JsonObject node) throws IOException { - boolean obfuscated = - ((LaunchClassLoader) DepLoader.class.getClassLoader()).getClassBytes("net.minecraft.world.World") - == null; + boolean obfuscated = ((LaunchClassLoader) DepLoader.class.getClassLoader()) + .getClassBytes("net.minecraft.world.World") == null; String testClass = node.get("class").getAsString(); if (DepLoader.class.getResource("/" + testClass.replace('.', '/') + ".class") != null) return; @@ -531,8 +554,7 @@ private void loadJson(JsonObject node) throws IOException { Pattern pattern = null; try { - if (node.has("pattern")) - pattern = Pattern.compile(node.get("pattern").getAsString()); + if (node.has("pattern")) pattern = Pattern.compile(node.get("pattern").getAsString()); } catch (PatternSyntaxException e) { CodeChickenCorePlugin.logger.error("Invalid filename pattern: " + node.get("pattern")); e.printStackTrace(); diff --git a/src/main/java/codechicken/obfuscator/ConstantObfuscator.java b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java index 0af3660..3279184 100644 --- a/src/main/java/codechicken/obfuscator/ConstantObfuscator.java +++ b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java @@ -2,9 +2,9 @@ import static org.objectweb.asm.tree.AbstractInsnNode.*; -import codechicken.lib.asm.ObfMapping; import java.util.LinkedList; import java.util.List; + import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; @@ -12,7 +12,10 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; +import codechicken.lib.asm.ObfMapping; + public class ConstantObfuscator implements Opcodes { + public ObfRemapper obf; public List descCalls = new LinkedList(); public List classCalls = new LinkedList(); diff --git a/src/main/java/codechicken/obfuscator/DummyOutputStream.java b/src/main/java/codechicken/obfuscator/DummyOutputStream.java index 475526c..b5b4e8c 100644 --- a/src/main/java/codechicken/obfuscator/DummyOutputStream.java +++ b/src/main/java/codechicken/obfuscator/DummyOutputStream.java @@ -3,6 +3,7 @@ import java.io.OutputStream; public class DummyOutputStream extends OutputStream { + public static DummyOutputStream instance = new DummyOutputStream(); @Override diff --git a/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java b/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java index bca8fa0..906ed92 100644 --- a/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java +++ b/src/main/java/codechicken/obfuscator/IHeirachyEvaluator.java @@ -1,9 +1,11 @@ package codechicken.obfuscator; -import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; import java.util.List; +import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; + public interface IHeirachyEvaluator { + /** * @param desc The mapping descriptor of the class to evaluate heirachy for * @return A list of parents (srg or obf names) diff --git a/src/main/java/codechicken/obfuscator/ILogStreams.java b/src/main/java/codechicken/obfuscator/ILogStreams.java index 3beeedf..31c7e95 100644 --- a/src/main/java/codechicken/obfuscator/ILogStreams.java +++ b/src/main/java/codechicken/obfuscator/ILogStreams.java @@ -3,6 +3,7 @@ import java.io.PrintStream; public interface ILogStreams { + public PrintStream err(); public PrintStream out(); diff --git a/src/main/java/codechicken/obfuscator/ObfDirection.java b/src/main/java/codechicken/obfuscator/ObfDirection.java index a1bb715..8c2732e 100644 --- a/src/main/java/codechicken/obfuscator/ObfDirection.java +++ b/src/main/java/codechicken/obfuscator/ObfDirection.java @@ -4,6 +4,7 @@ import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; public class ObfDirection { + public boolean obfuscate; public boolean srg; public boolean srg_cst; diff --git a/src/main/java/codechicken/obfuscator/ObfRemapper.java b/src/main/java/codechicken/obfuscator/ObfRemapper.java index b4668b5..8d46a7d 100644 --- a/src/main/java/codechicken/obfuscator/ObfRemapper.java +++ b/src/main/java/codechicken/obfuscator/ObfRemapper.java @@ -1,9 +1,11 @@ package codechicken.obfuscator; -import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; import org.objectweb.asm.commons.Remapper; +import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; + public class ObfRemapper extends Remapper { + public final ObfuscationMap obf; public ObfDirection dir; diff --git a/src/main/java/codechicken/obfuscator/ObfuscationMap.java b/src/main/java/codechicken/obfuscator/ObfuscationMap.java index 0183ff7..8d79f61 100644 --- a/src/main/java/codechicken/obfuscator/ObfuscationMap.java +++ b/src/main/java/codechicken/obfuscator/ObfuscationMap.java @@ -1,8 +1,5 @@ package codechicken.obfuscator; -import codechicken.lib.asm.ObfMapping; -import com.google.common.base.Function; -import com.google.common.collect.ArrayListMultimap; import java.io.File; import java.util.HashMap; import java.util.HashSet; @@ -10,8 +7,15 @@ import java.util.Map; import java.util.Map.Entry; +import codechicken.lib.asm.ObfMapping; + +import com.google.common.base.Function; +import com.google.common.collect.ArrayListMultimap; + public class ObfuscationMap { + public class ObfuscationEntry { + public final ObfMapping obf; public final ObfMapping srg; public final ObfMapping mcp; @@ -24,6 +28,7 @@ public ObfuscationEntry(ObfMapping obf, ObfMapping srg, ObfMapping mcp) { } private class ClassEntry extends ObfuscationEntry { + public Map mcpMap = new HashMap(); public Map srgMap = new HashMap(); public Map obfMap = new HashMap(); @@ -81,8 +86,8 @@ public ObfuscationEntry addField(String obf_owner, String obf_name, String srg_o return addEntry(new ObfMapping(obf_owner, obf_name, ""), new ObfMapping(srg_owner, srg_name, "")); } - public ObfuscationEntry addMethod( - String obf_owner, String obf_name, String obf_desc, String srg_owner, String srg_name, String srg_desc) { + public ObfuscationEntry addMethod(String obf_owner, String obf_name, String obf_desc, String srg_owner, + String srg_name, String srg_desc) { return addEntry(new ObfMapping(obf_owner, obf_name, obf_desc), new ObfMapping(srg_owner, srg_name, srg_desc)); } @@ -161,10 +166,8 @@ private boolean isMapped(ObfuscationEntry desc) { private ObfuscationEntry getOrCreateClassEntry(String name) { ObfuscationEntry e = lookupObfClass(name); if (e == null) e = lookupMcpClass(name); - if (e == null) - e = addClass( - name, - name); // if the class isn't in obf or srg maps, it must be a custom mod class with no name change. + if (e == null) e = addClass(name, name); // if the class isn't in obf or srg maps, it must be a custom mod class + // with no name change. return e; } @@ -207,7 +210,7 @@ public void parseMappings(File[] mappings) { public static String[] splitLast(String s, char c) { int i = s.lastIndexOf(c); - return new String[] {s.substring(0, i), s.substring(i + 1)}; + return new String[] { s.substring(0, i), s.substring(i + 1) }; } public static String[] split4(String s, char c) { @@ -230,6 +233,7 @@ private void parseSRGS(File srgs) { log.out().println("Parsing " + srgs.getName()); Function function = new Function() { + @Override public Void apply(String line) { int hpos = line.indexOf('#'); @@ -261,6 +265,7 @@ private void parseCSV(File csv) { log.out().println("Parsing " + csv.getName()); Function function = new Function() { + @Override public Void apply(String line) { if (line.startsWith("func_") || line.startsWith("field_")) { diff --git a/src/main/java/codechicken/obfuscator/ObfuscationRun.java b/src/main/java/codechicken/obfuscator/ObfuscationRun.java index 9831ab1..6ae3854 100644 --- a/src/main/java/codechicken/obfuscator/ObfuscationRun.java +++ b/src/main/java/codechicken/obfuscator/ObfuscationRun.java @@ -1,6 +1,5 @@ package codechicken.obfuscator; -import com.google.common.base.Function; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -9,11 +8,15 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; + import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.commons.RemappingClassAdapter; import org.objectweb.asm.tree.ClassNode; +import com.google.common.base.Function; + public class ObfuscationRun implements ILogStreams { + public final ObfDirection obfDir; public final ObfuscationMap obf; public final ObfRemapper obfMapper; @@ -98,27 +101,24 @@ public void start() { } public static Map fillDefaults(Map config) { - if (!config.containsKey("excludedPackages")) - config.put( - "excludedPackages", - "java/;sun/;javax/;scala/;" + "argo/;org/lwjgl/;org/objectweb/;org/bouncycastle/;com/google/"); + if (!config.containsKey("excludedPackages")) config.put( + "excludedPackages", + "java/;sun/;javax/;scala/;" + "argo/;org/lwjgl/;org/objectweb/;org/bouncycastle/;com/google/"); if (!config.containsKey("ignore")) config.put("ignore", "."); - if (!config.containsKey("classConstantCalls")) - config.put( - "classConstantCalls", - "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;)V," - + "codechicken/lib/asm/ObfMapping.subclass(Ljava/lang/String;)Lcodechicken/lib/asm/ObfMapping;," - + "codechicken/lib/asm/ObfMapping.(Lcodechicken/lib/asm/ObfMapping;Ljava/lang/String;)V"); - if (!config.containsKey("descConstantCalls")) - config.put( - "descConstantCalls", - "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," - + "org/objectweb/asm/MethodVisitor.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," - + "org/objectweb/asm/tree/MethodNode.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," - + "org/objectweb/asm/MethodVisitor.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," - + "org/objectweb/asm/tree/MethodNode.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," - + "org/objectweb/asm/tree/MethodInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," - + "org/objectweb/asm/tree/FieldInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (!config.containsKey("classConstantCalls")) config.put( + "classConstantCalls", + "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;)V," + + "codechicken/lib/asm/ObfMapping.subclass(Ljava/lang/String;)Lcodechicken/lib/asm/ObfMapping;," + + "codechicken/lib/asm/ObfMapping.(Lcodechicken/lib/asm/ObfMapping;Ljava/lang/String;)V"); + if (!config.containsKey("descConstantCalls")) config.put( + "descConstantCalls", + "codechicken/lib/asm/ObfMapping.(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/MethodVisitor.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/MethodNode.visitFieldInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/MethodVisitor.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/MethodNode.visitMethodInsn(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/MethodInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V," + + "org/objectweb/asm/tree/FieldInsnNode.(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); return config; } @@ -135,9 +135,8 @@ public static void processLines(File file, Function function) { } public static void processFiles(File dir, Function function, boolean recursive) { - for (File file : dir.listFiles()) - if (file.isDirectory() && recursive) processFiles(file, function, recursive); - else function.apply(file); + for (File file : dir.listFiles()) if (file.isDirectory() && recursive) processFiles(file, function, recursive); + else function.apply(file); } public static void deleteDir(File directory, boolean remove) { @@ -173,7 +172,7 @@ public static File[] parseConfDir(File confDir) { File fields = new File(mapDir, "fields.csv"); if (!fields.exists()) throw new RuntimeException("Could not find fields.csv"); - return new File[] {srgs, methods, fields}; + return new File[] { srgs, methods, fields }; } public long startTime() { @@ -196,8 +195,8 @@ public static List getParents(ClassNode cnode) { public void finish(boolean errored) { long millis = System.currentTimeMillis() - startTime; - out().println((errored ? "Errored after" : "Done in ") + new DecimalFormat("0.00").format(millis / 1000D) - + "s"); + out().println( + (errored ? "Errored after" : "Done in ") + new DecimalFormat("0.00").format(millis / 1000D) + "s"); finished = true; } diff --git a/src/main/java/codechicken/obfuscator/SystemLogStreams.java b/src/main/java/codechicken/obfuscator/SystemLogStreams.java index aaddd2a..bdf7a8b 100644 --- a/src/main/java/codechicken/obfuscator/SystemLogStreams.java +++ b/src/main/java/codechicken/obfuscator/SystemLogStreams.java @@ -3,6 +3,7 @@ import java.io.PrintStream; public class SystemLogStreams implements ILogStreams { + public static SystemLogStreams inst = new SystemLogStreams(); @Override From 331a5fcd3f54ed772fa0714548f2731c39314ed2 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:13:51 +0000 Subject: [PATCH 171/219] [ci skip] Add git-blame-ignore-revs for spotlessApply --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..7749bd3 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Ignore spotlessApply reformat +955a875d42bd8f725d389ef8c4f571824f2ae0c8 From b52d844ed62afe468f43c672ed985849e5491fa7 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:14:43 +0000 Subject: [PATCH 172/219] Release with RFG From 6273a1e71a3965c7d5f7f54d118db75a5b33a963 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:39:47 +0000 Subject: [PATCH 173/219] Use version substitution in CCC mod container --- .../java/codechicken/core/launch/CodeChickenCorePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 8a2f427..d26b188 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -39,7 +39,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; @Deprecated - public static final String version = "1.1.3-unused"; + public static final String version = "GRADLETOKEN_VERSION"; public static File minecraftDir; public static String currentMcVersion; From 2cf72263063b3d5ee03f4dcc6209d5fae210b7a5 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 30 Jan 2023 11:50:18 +0000 Subject: [PATCH 174/219] Actually fix the broken version/modid this time --- gradle.properties | 15 +++++++++------ .../core/asm/CodeChickenCoreModContainer.java | 6 +++--- .../core/launch/CodeChickenCorePlugin.java | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5e76708..553bbba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,16 +21,19 @@ forgeVersion = 10.13.4.1614 # Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty developmentEnvironmentUserName = Developer -# Define a source file of your project with: +# Generate a class with String fields for the mod id, name, version and group name named with the fields below +generateGradleTokenClass = codechicken.core.asm.Tags +gradleTokenModId = MODID +gradleTokenModName = MODNAME +gradleTokenVersion = VERSION +gradleTokenGroupName = GROUPNAME +# [DEPRECATED] +# Multiple source files can be defined here by providing a comma-seperated list: Class1.java,Class2.java,Class3.java # public static final String VERSION = "GRADLETOKEN_VERSION"; # The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's # version in @Mod([...], version = VERSION, [...]) # Leave these properties empty to skip individual token replacements -replaceGradleTokenInFile = CodeChickenCoreModContainer.java -gradleTokenModId = GRADLETOKEN_MODID -gradleTokenModName = GRADLETOKEN_MODNAME -gradleTokenVersion = GRADLETOKEN_VERSION -gradleTokenGroupName = +replaceGradleTokenInFile = # In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can # leave this property empty. diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index 8728f66..ee640f5 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -39,9 +39,9 @@ public CodeChickenCoreModContainer() { private static ModMetadata getModMetadata() { final ModMetadata modMetadata = new ModMetadata(); - modMetadata.name = "GRADLETOKEN_MODNAME"; - modMetadata.modId = "GRADLETOKEN_MODID"; - modMetadata.version = "GRADLETOKEN_VERSION"; + modMetadata.name = "CodeChicken Core"; + modMetadata.modId = "CodeChickenCore"; + modMetadata.version = Tags.VERSION; return modMetadata; } diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index d26b188..3247450 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -39,7 +39,7 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { public static final String mcVersion = "[1.7.10]"; @Deprecated - public static final String version = "GRADLETOKEN_VERSION"; + public static final String version = Tags.VERSION; public static File minecraftDir; public static String currentMcVersion; From 83f5eac8d8e216b666b217cef4e9c5dcb52e4bdf Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Tue, 31 Jan 2023 09:51:52 +0000 Subject: [PATCH 175/219] [ci skip] upgraded build system --- build.gradle | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 78caf98..fe8a2e7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675074449 +//version: 1675110695 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -66,7 +66,7 @@ plugins { id 'com.diffplug.spotless' version '6.7.2' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.0.18' + id 'com.gtnewhorizons.retrofuturagradle' version '1.1.2' } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -166,6 +166,9 @@ pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { "kaptMcLauncherKotlin", "kaptPatchedMcKotlin", "kaptInjectedTagsKotlin", + "kspMcLauncherKotlin", + "kspPatchedMcKotlin", + "kspInjectedTagsKotlin", ] tasks.configureEach { task -> if (task.name in disabledKotlinTaskList) { @@ -334,7 +337,7 @@ if (identifiedVersion == versionOverride) { out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } -group = modGroup +group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName } else { @@ -711,16 +714,6 @@ if (usesShadowedDependencies.toBoolean()) { ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar ext.publishableObfJar = tasks.reobfJar -tasks.named('extractForgeUserdev', Copy).configure { efu -> - doLast { - // Fix CoFH-repackaged CCL not finding mappings - project.copy { - from(mcpTasks.userdevDir("conf")) - into(new File(project.buildDir, "unpacked/conf")) - } - } -} - tasks.register('apiJar', Jar) { from(sourceSets.main.allSource) { include modGroupPath + "/" + apiPackagePath + '/**' @@ -825,7 +818,7 @@ publishing { artifact apiJar } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion From f1034f699e94e1f90428e918184e4f7f9c1b4d59 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Tue, 31 Jan 2023 09:51:54 +0000 Subject: [PATCH 176/219] [ci skip] upgraded build system --- build.gradle | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 78caf98..fe8a2e7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675074449 +//version: 1675110695 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -66,7 +66,7 @@ plugins { id 'com.diffplug.spotless' version '6.7.2' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.0.18' + id 'com.gtnewhorizons.retrofuturagradle' version '1.1.2' } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -166,6 +166,9 @@ pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { "kaptMcLauncherKotlin", "kaptPatchedMcKotlin", "kaptInjectedTagsKotlin", + "kspMcLauncherKotlin", + "kspPatchedMcKotlin", + "kspInjectedTagsKotlin", ] tasks.configureEach { task -> if (task.name in disabledKotlinTaskList) { @@ -334,7 +337,7 @@ if (identifiedVersion == versionOverride) { out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } -group = modGroup +group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName } else { @@ -711,16 +714,6 @@ if (usesShadowedDependencies.toBoolean()) { ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar ext.publishableObfJar = tasks.reobfJar -tasks.named('extractForgeUserdev', Copy).configure { efu -> - doLast { - // Fix CoFH-repackaged CCL not finding mappings - project.copy { - from(mcpTasks.userdevDir("conf")) - into(new File(project.buildDir, "unpacked/conf")) - } - } -} - tasks.register('apiJar', Jar) { from(sourceSets.main.allSource) { include modGroupPath + "/" + apiPackagePath + '/**' @@ -825,7 +818,7 @@ publishing { artifact apiJar } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group artifactId = System.getenv("ARTIFACT_ID") ?: project.name // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion From 16883088a6a461c6a48484cfdde70dc33c96316e Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Thu, 2 Feb 2023 19:20:03 -0800 Subject: [PATCH 177/219] Publish to CF & MN --- gradle.properties | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/gradle.properties b/gradle.properties index 59d5c49..1c509df 100644 --- a/gradle.properties +++ b/gradle.properties @@ -58,3 +58,33 @@ containsMixinsAndOrCoreModOnly = # If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your # responsibility check the licence and request permission for distribution, if required. usesShadowedDependencies = false + + +# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. + +# The project's numeric ID on CurseForge. You can find this in the About Project box. +# Leave this empty if you don't want to publish on CurseForge. +curseForgeProjectId = 746280 + +# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. +# Syntax: type1:name1;type2:name2;... +# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], +# and the name is the CurseForge project id of the other mod. +# curseForgeRelations = + + +# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token. + +# The project's ID on Modrinth. Can be either the slug or the ID. +# Leave this empty if you don't want to publish on Modrinth. + +modrinthProjectId = codechickenlib-unofficial + +# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. +# Syntax: scope1-type1:name1;scope2-type2:name2;... +# Where scope can be one of [required, optional, incompatible, embedded], +# type can be one of [project, version], +# and the name is the Modrinth project or version slug/id of the other mod. + +# modrinthRelations = + From cc15e4cec60399378f5a15cb6fffade13641b04a Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Thu, 2 Feb 2023 22:07:24 -0800 Subject: [PATCH 178/219] Add Curse/Modrinth projects (#10) --- gradle.properties | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/gradle.properties b/gradle.properties index 553bbba..bc5ab4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -61,3 +61,32 @@ containsMixinsAndOrCoreModOnly = true # If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your # responsibility check the licence and request permission for distribution, if required. usesShadowedDependencies = false + +# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. + +# The project's numeric ID on CurseForge. You can find this in the About Project box. +# Leave this empty if you don't want to publish on CurseForge. +curseForgeProjectId = 746279 + +# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. +# Syntax: type1:name1;type2:name2;... +# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], +# and the name is the CurseForge project id of the other mod. +# curseForgeRelations = + + +# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token. + +# The project's ID on Modrinth. Can be either the slug or the ID. +# Leave this empty if you don't want to publish on Modrinth. + +modrinthProjectId = codechickencore-unofficial + +# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. +# Syntax: scope1-type1:name1;scope2-type2:name2;... +# Where scope can be one of [required, optional, incompatible, embedded], +# type can be one of [project, version], +# and the name is the Modrinth project or version slug/id of the other mod. + +# modrinthRelations = + From 3145cccd70afb8bff79ef27a6eae4f0749266a63 Mon Sep 17 00:00:00 2001 From: unix-supremacist <100294596+unix-supremacist@users.noreply.github.com> Date: Wed, 8 Feb 2023 15:07:50 -0600 Subject: [PATCH 179/219] null check chunk extensions to not cause errors with chunk pregenerator (#11) --- src/main/java/codechicken/lib/world/WorldExtension.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/codechicken/lib/world/WorldExtension.java b/src/main/java/codechicken/lib/world/WorldExtension.java index 7c3cd46..e6ff496 100644 --- a/src/main/java/codechicken/lib/world/WorldExtension.java +++ b/src/main/java/codechicken/lib/world/WorldExtension.java @@ -43,7 +43,8 @@ protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) { } protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) { - chunkMap.get(chunk).saveData(tag); + final ChunkExtension extension = chunkMap.get(chunk); + if (extension != null) extension.saveData(tag); } protected final void remChunk(Chunk chunk) { From c841d484eea3701b76ff21e819d4b46aec15723c Mon Sep 17 00:00:00 2001 From: miozune Date: Thu, 30 Nov 2023 00:36:25 +0900 Subject: [PATCH 180/219] updateBuildScript --- .gitignore | 12 +- build.gradle | 735 +++++++++++++++++------ gradle/wrapper/gradle-wrapper.jar | Bin 61608 -> 61574 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 +- repositories.gradle | 5 - 6 files changed, 562 insertions(+), 196 deletions(-) diff --git a/.gitignore b/.gitignore index 558ad12..5e80e0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .gradle .settings /.idea/ +/.vscode/ /run/ /build/ /eclipse/ @@ -25,4 +26,13 @@ whitelist.json *.iml *.ipr *.iws -src/main/resources/mixins.*.json +src/main/resources/mixins.*([!.]).json +*.bat +*.DS_Store +!gradlew.bat +.factorypath +addon.local.gradle +addon.local.gradle.kts +addon.late.local.gradle +addon.late.local.gradle.kts +layout.json diff --git a/build.gradle b/build.gradle index fe8a2e7..4e31dc8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675110695 +//version: 1700844281 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,27 +6,28 @@ */ -import com.diffplug.blowdryer.Blowdryer -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask +import com.gtnewhorizons.retrofuturagradle.util.Distribution import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.jetbrains.gradle.ext.* +import org.gradle.internal.xml.XmlTransformer +import org.jetbrains.gradle.ext.Application +import org.jetbrains.gradle.ext.Gradle +import javax.inject.Inject import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream buildscript { repositories { - mavenLocal() mavenCentral() maven { @@ -47,6 +48,8 @@ buildscript { name 'Scala CI dependencies' url 'https://repo1.maven.org/maven2/' } + + mavenLocal() } } plugins { @@ -58,22 +61,26 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version - id 'de.undercouch.download' version '5.3.0' + id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false + id 'com.palantir.git-version' version '3.0.0' apply false + id 'de.undercouch.download' version '5.4.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.7.2' apply false + id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.1.2' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' } + +print("You might want to check out './gradlew :faq' if your build fails.\n") + boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -if (project.file('.git/HEAD').isFile()) { +// In submodules, .git is a file pointing to the real git dir +if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { apply plugin: 'com.palantir.git-version' } @@ -82,6 +89,23 @@ def out = services.get(StyledTextOutputFactory).create('an-output') def projectJavaVersion = JavaLanguageVersion.of(8) boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false +boolean disableCheckstyle = project.hasProperty("disableCheckstyle") ? project.disableCheckstyle.toBoolean() : false + +final String CHECKSTYLE_CONFIG = """ + + + + + + + + + + + +""" checkPropertyExists("modName") checkPropertyExists("modId") @@ -108,6 +132,8 @@ propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("usesMavenPublishing", true) +propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -122,12 +148,26 @@ propertyDefaultIfUnset("gradleTokenGroupName", "") propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only -project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +// this is meant to be set using the user wide property file. by default we do nothing. +propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" + +project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts if (!disableSpotless) { apply plugin: 'com.diffplug.spotless' apply from: Blowdryer.file('spotless.gradle') } +if (!disableCheckstyle) { + apply plugin: 'checkstyle' + tasks.named("checkstylePatchedMc") { enabled = false } + tasks.named("checkstyleMcLauncher") { enabled = false } + tasks.named("checkstyleIdeVirtualMain") { enabled = false } + tasks.named("checkstyleInjectedTags") { enabled = false } + checkstyle { + config = resources.text.fromString(CHECKSTYLE_CONFIG) + } +} + String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" @@ -143,13 +183,21 @@ java { } else { languageVersion.set(projectJavaVersion) } - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) } if (!noPublishedSources) { withSourcesJar() } } +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} + +tasks.withType(ScalaCompile).configureEach { + options.encoding = "UTF-8" +} + pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { // If Kotlin is enabled in the project kotlin { @@ -183,14 +231,34 @@ configurations { canBeConsumed = false canBeResolved = false } + + create("devOnlyNonPublishable") { + description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" + canBeConsumed = false + canBeResolved = false + } + compileOnly.extendsFrom(devOnlyNonPublishable) + runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) } if (enableModernJavaSyntax.toBoolean()) { + repositories { + mavenCentral { + mavenContent { + includeGroup("me.eigenraven.java8unsupported") + } + } + } + dependencies { annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + // workaround for https://github.com/bsideup/jabel/issues/174 + annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { transitive = false // We only care about the 1 annotation class } + // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. + patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') } tasks.withType(JavaCompile).configureEach { @@ -202,7 +270,7 @@ if (enableModernJavaSyntax.toBoolean()) { javaCompiler.set(javaToolchains.compilerFor { languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) }) } } @@ -234,12 +302,14 @@ if (apiPackage) { } if (accessTransformersFile) { - String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if (!getFile(targetFile).exists()) { - throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + for (atFile in accessTransformersFile.split(" ")) { + String targetFile = "src/main/resources/META-INF/" + atFile.trim() + if (!getFile(targetFile).exists()) { + throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } else { boolean atsFound = false for (File at : sourceSets.getByName("main").resources.files) { @@ -317,7 +387,27 @@ catch (Exception ignored) { String identifiedVersion String versionOverride = System.getenv("VERSION") ?: null try { - identifiedVersion = versionOverride == null ? gitVersion() : versionOverride + // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty + if (versionOverride == null) { + def gitDetails = versionDetails() + def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning + String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') + if (branchName.startsWith('origin/')) { + branchName = branchName.minus('origin/') + } + branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver + identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' + if (gitDetails.commitDistance > 0) { + identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" + if (isDirty) { + identifiedVersion += "-dirty" + } + } else if (isDirty) { + identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" + } + } else { + identifiedVersion = versionOverride + } } catch (Exception ignored) { out.style(Style.Failure).text( @@ -339,9 +429,13 @@ if (identifiedVersion == versionOverride) { group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - archivesBaseName = customArchiveBaseName + base { + archivesName = customArchiveBaseName + } } else { - archivesBaseName = modId + base { + archivesName = modId + } } @@ -367,12 +461,14 @@ minecraft { injectMissingGenerics.set(true) } + username = developmentEnvironmentUserName.toString() + + lwjgl3Version = "3.3.2" + // Enable assertions in the current mod extraRunJvmArguments.add("-ea:${modGroup}") if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") - if (usesMixinDebug.toBoolean()) { extraRunJvmArguments.addAll([ "-Dmixin.debug.countInjections=true", @@ -401,6 +497,16 @@ configurations.configureEach { } } } + def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) + if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server + if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { + details.useVersion '2388750' + details.because 'Pick obfuscated jar' + } + } + } } // Ensure tests have access to minecraft classes @@ -413,10 +519,19 @@ sourceSets { } } -if (file('addon.gradle').exists()) { +if (file('addon.gradle.kts').exists()) { + apply from: 'addon.gradle.kts' +} else if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// File for local tweaks not commited to Git +if (file('addon.local.gradle.kts').exists()) { + apply from: 'addon.local.gradle.kts' +} else if (file('addon.local.gradle').exists()) { + apply from: 'addon.local.gradle' +} + // Allow unsafe repos but warn repositories.configureEach { repo -> if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { @@ -427,11 +542,19 @@ repositories.configureEach { repo -> } } -apply from: 'repositories.gradle' +if (file('repositories.gradle.kts').exists()) { + apply from: 'repositories.gradle.kts' +} else if (file('repositories.gradle').exists()) { + apply from: 'repositories.gradle' +} else { + logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing repositories.gradle[.kts]") +} configurations { + runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) + testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - config.extendsFrom(runtimeOnlyNonPublishable) if (usesShadowedDependencies.toBoolean()) { config.extendsFrom(shadowImplementation) // TODO: remove Compile after all uses are refactored to Implementation @@ -467,42 +590,48 @@ repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' - mavenContent { - excludeGroup("net.minecraftforge") // missing the `universal` artefact - } } maven { name = "GTNH Maven" url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - maven { - name = "Fabric Maven" - url = "https://maven.fabricmc.net/" - } + maven { + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' + content { + includeGroup "org.lwjgl" } } if (includeWellKnownRepositories.toBoolean()) { - maven { - name "CurseMaven" - url "https://cursemaven.com" - content { + exclusiveContent { + forRepository { + maven { + name "CurseMaven" + url "https://cursemaven.com" + } + } + filter { includeGroup "curse.maven" } } - maven { - name = "ic2" - url = "https://maven.ic2.player.to/" - metadataSources { - mavenPom() - artifact() + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" } } maven { - name = "ic2-mirror" - url = "https://maven2.ic2.player.to/" + name = "ic2" + url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + content { + includeGroup "net.industrial-craft" + } metadataSources { mavenPom() artifact() @@ -515,35 +644,78 @@ repositories { } } +def mixinProviderGroup = "io.github.legacymoddingmc" +def mixinProviderModule = "unimixins" +def mixinProviderVersion = "0.1.13" +def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" +def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" +ext.mixinProviderSpec = mixinProviderSpec + +def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' + dependencies { if (usesMixins.toBoolean()) { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') annotationProcessor('com.google.guava:guava:24.1.1-jre') annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + annotationProcessor(mixinProviderSpec) if (usesMixinDebug.toBoolean()) { runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') } } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - implementation('com.gtnewhorizon:gtnhmixins:2.1.10') + if (usesMixins.toBoolean()) { + implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) + } else if (forceEnableMixins.toBoolean()) { + runtimeOnlyNonPublishable(mixinProviderSpec) } } pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { if (usesMixins.toBoolean()) { dependencies { - kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + kapt(mixinProviderSpec) } } } -apply from: 'dependencies.gradle' +// Replace old mixin mods with unimixins +// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier +configurations.all { + resolutionStrategy.dependencySubstitution { + substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + } +} -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' -def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' -def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap -def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" +dependencies { + constraints { + def minGtnhLibVersion = "0.0.13" + implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + } +} + +if (file('dependencies.gradle.kts').exists()) { + apply from: 'dependencies.gradle.kts' +} else if (file('dependencies.gradle').exists()) { + apply from: 'dependencies.gradle' +} else { + logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing dependencies.gradle[.kts]") +} tasks.register('generateAssets') { group = "GTNH Buildscript" @@ -575,46 +747,17 @@ tasks.register('generateAssets') { } if (usesMixins.toBoolean()) { - tasks.named("reobfJar", ReobfuscatedJar).configure { - extraSrgFiles.from(mixinSrg) - } - tasks.named("processResources").configure { dependsOn("generateAssets") } tasks.named("compileJava", JavaCompile).configure { - doFirst { - new File(mixinTmpDir).mkdirs() - } options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code "-XDenableSunApiLintControl", "-XDignore.symbol.file" ] } - - pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - kapt { - correctErrorTypes = true - javacOptions { - option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") - option("-AoutSrgFile=$mixinSrg") - option("-AoutRefMapFile=$refMap") - } - } - tasks.configureEach { task -> - if (task.name == "kaptKotlin") { - task.doFirst { - new File(mixinTmpDir).mkdirs() - } - } - } - } - } tasks.named("processResources", ProcessResources).configure { @@ -632,10 +775,149 @@ tasks.named("processResources", ProcessResources).configure { } if (usesMixins.toBoolean()) { - from refMap + dependsOn("compileJava", "compileScala") } } +ext.java17Toolchain = (JavaToolchainSpec spec) -> { + spec.languageVersion.set(JavaLanguageVersion.of(17)) + spec.vendor.set(JvmVendorSpec.matching("jetbrains")) +} + +ext.java17DependenciesCfg = configurations.create("java17Dependencies") { + extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution + canBeConsumed = false +} +ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { + canBeConsumed = false +} + +dependencies { + def lwjgl3ifyVersion = '1.5.1' + if (modId != 'lwjgl3ify') { + java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") + } + if (modId != 'hodgepodge') { + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.17') + } + + java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} +} + +ext.java17JvmArgs = [ + // Java 9+ support + "--illegal-access=warn", + "-Djava.security.manager=allow", + "-Dfile.encoding=UTF-8", + "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", + "--add-opens", "java.base/java.net=ALL-UNNAMED", + "--add-opens", "java.base/java.nio=ALL-UNNAMED", + "--add-opens", "java.base/java.io=ALL-UNNAMED", + "--add-opens", "java.base/java.lang=ALL-UNNAMED", + "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens", "java.base/java.text=ALL-UNNAMED", + "--add-opens", "java.base/java.util=ALL-UNNAMED", + "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", + "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", + "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", + "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", + "--add-modules", "jdk.dynalink", + "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", + "--add-modules", "java.sql.rowset", + "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" +] + +ext.hotswapJvmArgs = [ + // DCEVM advanced hot reload + "-XX:+AllowEnhancedClassRedefinition", + "-XX:HotswapAgent=fatjar" +] + +ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { + group = "GTNH Buildscript" + description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" + def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' + def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} + def targetFilename = "hotswap-agent.jar" + onlyIf { + !targetFolderProvider.get().file(targetFilename).asFile.exists() + } + doLast { + def targetFolder = targetFolderProvider.get() + targetFolder.asFile.mkdirs() + download.run { + src hsaUrl + dest targetFolder.file(targetFilename).asFile + overwrite false + tempAndMove true + } + } +} + +public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { + // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable + private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); + + @Input + public boolean getEnableHotswap() { return enableHotswap } + @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") + public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } + + @Inject + public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { + super(side, gradle) + + this.lwjglVersion = 3 + this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) + this.extraJvmArgs.addAll(project.java17JvmArgs) + this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) + + this.classpath(project.java17PatchDependenciesCfg) + if (side == Distribution.CLIENT) { + this.classpath(project.minecraftTasks.lwjgl3Configuration) + } + // Use a raw provider instead of map to not create a dependency on the task + this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) + this.classpath.filter { file -> + !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 + } + this.classpath(project.java17DependenciesCfg) + } + + public void setup(Project project) { + super.setup(project) + if (project.usesMixins.toBoolean()) { + this.extraJvmArgs.addAll(project.provider(() -> { + def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) + mixinCfg.canBeConsumed = false + mixinCfg.transitive = false + enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] + })) + } + } +} + +def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") +runClient17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStart" + username = minecraft.username + userUUID = minecraft.userUUID +} + +def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") +runServer17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStartServer" + extraArgs.add("nogui") +} + def getManifestAttributes() { def manifestAttributes = [:] if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { @@ -667,11 +949,6 @@ tasks.named("jar", Jar).configure { } if (usesShadowedDependencies.toBoolean()) { - tasks.register('relocateShadowJar', ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" - enabled = minimizeShadowedDependencies.toBoolean() - } tasks.named("shadowJar", ShadowJar).configure { manifest { attributes(getManifestAttributes()) @@ -686,8 +963,9 @@ if (usesShadowedDependencies.toBoolean()) { project.configurations.shadeCompile ] archiveClassifier.set('dev') - if (minimizeShadowedDependencies.toBoolean()) { - dependsOn(relocateShadowJar) + if (relocateShadowedDependencies.toBoolean()) { + relocationPrefix = modGroup + ".shadow" + enableRelocation = true } } configurations.runtimeElements.outgoing.artifacts.clear() @@ -705,7 +983,7 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer"]) { + for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { tasks.named(runTask).configure { dependsOn("shadowJar") } @@ -743,16 +1021,47 @@ idea { module { downloadJavadoc = true downloadSources = true + inheritOutputDirs = true } project { settings { + if (ideaOverrideBuildType != "") { + delegateActions { + if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = true + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE + } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = false + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM + } else { + throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') + } + } + } runConfigurations { + "0. Build and Test"(Gradle) { + taskNames = ["build"] + } "1. Run Client"(Gradle) { taskNames = ["runClient"] } "2. Run Server"(Gradle) { taskNames = ["runServer"] } + "1a. Run Client (Java 17)"(Gradle) { + taskNames = ["runClient17"] + } + "2a. Run Server (Java 17)"(Gradle) { + taskNames = ["runServer17"] + } + "1b. Run Client (Java 17, Hotswap)"(Gradle) { + taskNames = ["runClient17"] + envs = ["HOTSWAP": "true"] + } + "2b. Run Server (Java 17, Hotswap)"(Gradle) { + taskNames = ["runServer17"] + envs = ["HOTSWAP": "true"] + } "3. Run Obfuscated Client"(Gradle) { taskNames = ["runObfClient"] } @@ -770,7 +1079,7 @@ idea { } "Run Client (IJ Native)"(Application) { mainClass = "GradleStart" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runClient.workingDir.absolutePath programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -781,7 +1090,7 @@ idea { } "Run Server (IJ Native)"(Application) { mainClass = "GradleStartServer" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runServer.workingDir.absolutePath programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -793,11 +1102,57 @@ idea { } compiler.javac { afterEvaluate { + javacAdditionalOptions = "-encoding utf8" moduleJavacAdditionalOptions = [ (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') ] } } + withIDEADir { File ideaDir -> + if (!ideaDir.path.contains(".idea")) { + // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory + ideaDir = new File(ideaDir, ".idea") + } + if (ideaDir.isDirectory()) { + def miscFile = new File(ideaDir, "misc.xml") + if (miscFile.isFile()) { + boolean dirty = false + def miscTransformer = new XmlTransformer() + miscTransformer.addAction { root -> + Node rootNode = root.asNode() + def rootManager = rootNode + .component.find { it.@name == 'ProjectRootManager' } + if (!rootManager) { + rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) + dirty = true + } + def output = rootManager.output + if (!output) { + output = rootManager.appendNode('output') + dirty = true + } + if (!output.@url) { + // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. + // This is a sensible default for most setups + output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' + dirty = true + } + } + def result = miscTransformer.transform(miscFile.text) + if (dirty) { + miscFile.write(result) + } + } else { + miscFile.text = """ + + + + + +""" + } + } + } } } } @@ -806,6 +1161,14 @@ tasks.named("processIdeaSettings").configure { dependsOn("injectTags") } +tasks.named("ideVirtualMainClasses").configure { + // Make IntelliJ "Build project" build the mod jars + dependsOn("jar", "reobfJar") + if (!disableSpotless) { + dependsOn("spotlessCheck") + } +} + // workaround variable hiding in pom processing def projectConfigs = project.configurations @@ -824,14 +1187,15 @@ publishing { version = System.getenv("RELEASE_VERSION") ?: identifiedVersion } } - repositories { - maven { - url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" - allowInsecureProtocol = true - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { + maven { + url = mavenPublishUrl + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + } } } } @@ -867,7 +1231,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { } } if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "gtnhmixins") + addModrinthDep("required", "project", "unimixins") } tasks.modrinth.dependsOn(build) tasks.publish.dependsOn(tasks.modrinth) @@ -911,7 +1275,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null } } if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "gtnhmixins") + addCurseForgeRelation("requiredDependency", "unimixins") } tasks.curseforge.dependsOn(build) tasks.publish.dependsOn(tasks.curseforge) @@ -945,10 +1309,21 @@ def addCurseForgeRelation(String type, String name) { } // Updating + +def buildscriptGradleVersion = "8.2.1" + +tasks.named('wrapper', Wrapper).configure { + gradleVersion = buildscriptGradleVersion +} + tasks.register('updateBuildScript') { group = 'GTNH Buildscript' description = 'Updates the build script to the latest version' + if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { + dependsOn('wrapper') + } + doLast { if (performBuildScriptUpdate()) return @@ -961,6 +1336,26 @@ if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISA performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") + if (gradle.gradleVersion != buildscriptGradleVersion) { + out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") + } + } +} + +// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large +tasks.register('faq') { + group = 'GTNH Buildscript' + description = 'Prints frequently asked questions about building a project' + + doLast { + print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + + "Or you can manually check if the versions are still on the distributing sites - " + + "the links can be found in repositories.gradle and build.gradle:repositories, " + + "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + + "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + + "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + + "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + + "Java 9 or later.") } } @@ -1021,8 +1416,14 @@ boolean isNewBuildScriptVersionAvailable() { String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - String availableBuildScriptHash = getVersionHash(availableBuildScript) + String availableBuildScriptHash + try { + String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() + availableBuildScriptHash = getVersionHash(availableBuildScript) + } catch (IOException e) { + logger.warn("Could not check for buildscript update availability: {}", e.message) + return false + } boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash return !isUpToDate @@ -1101,7 +1502,7 @@ static int replaceParams(File file, Map params) { return 0 } -// Dependency Deobfuscation +// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) def deobf(String sourceURL) { try { @@ -1143,11 +1544,7 @@ def deobfMaven(String repoURL, String mavenDep) { } def deobfCurse(String curseDep) { - try { - return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") - } catch (Exception ignored) { - out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") - } + return dependencies.rfg.deobf("curse.maven:$curseDep") } // The method above is to be preferred. Use this method if the filename is not at the end of the URL. @@ -1155,34 +1552,7 @@ def deobf(String sourceURL, String rawFileName) { String bon2Version = "2.5.1" String fileName = URLDecoder.decode(rawFileName, "UTF-8") String cacheDir = "$project.gradle.gradleUserHomeDir/caches" - String bon2Dir = "$cacheDir/forge_gradle/deobf" - String bon2File = "$bon2Dir/BON2-${bon2Version}.jar" String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" - String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar" - - if (file(deobfFile).exists()) { - return files(deobfFile) - } - - String mappingsVer - String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' - if (remoteMappings) { - String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" - String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" - - zipMappings(mappingsZIP, remoteMappings, bon2Dir) - - mappingsVer = "snapshot_$id" - } else { - mappingsVer = "${channel}_$mappingsVersion" - } - - download.run { - src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar" - dest bon2File - quiet true - overwrite false - } download.run { src sourceURL @@ -1190,50 +1560,8 @@ def deobf(String sourceURL, String rawFileName) { quiet true overwrite false } - - exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' - workingDir bon2Dir - standardOutput = new FileOutputStream("${deobfFile}.log") - } - - return files(deobfFile) -} - -def zipMappings(String zipPath, String url, String bon2Dir) { - File zipFile = new File(zipPath) - if (zipFile.exists()) { - return - } - - String fieldsCache = "$bon2Dir/data/fields.csv" - String methodsCache = "$bon2Dir/data/methods.csv" - - download.run { - src "${url}fields.csv" - dest fieldsCache - quiet true - } - download.run { - src "${url}methods.csv" - dest methodsCache - quiet true - } - - zipFile.getParentFile().mkdirs() - ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)) - - zos.putNextEntry(new ZipEntry("fields.csv")) - Files.copy(Paths.get(fieldsCache), zos) - zos.closeEntry() - - zos.putNextEntry(new ZipEntry("methods.csv")) - Files.copy(Paths.get(methodsCache), zos) - zos.closeEntry() - - zos.close() + return dependencies.rfg.deobf(files(obfFile)) } - // Helper methods def checkPropertyExists(String propertyName) { @@ -1260,3 +1588,36 @@ def getSecondaryArtifacts() { if (apiPackage) secondaryArtifacts += [apiJar] return secondaryArtifacts } + +def getURL(String main, String fallback) { + return pingURL(main, 10000) ? main : fallback +} + +// credit: https://stackoverflow.com/a/3584332 +def pingURL(String url, int timeout) { + url = url.replaceFirst("^https", "http") // Otherwise an exception may be thrown on invalid SSL certificates. + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection() + connection.setConnectTimeout(timeout) + connection.setReadTimeout(timeout) + connection.setRequestMethod("HEAD") + int responseCode = connection.getResponseCode() + return 200 <= responseCode && responseCode <= 399 + } catch (IOException ignored) { + return false + } +} + +// For easier scripting of things that require variables defined earlier in the buildscript +if (file('addon.late.gradle.kts').exists()) { + apply from: 'addon.late.gradle.kts' +} else if (file('addon.late.gradle').exists()) { + apply from: 'addon.late.gradle' +} + +// File for local tweaks not commited to Git +if (file('addon.late.local.gradle.kts').exists()) { + apply from: 'addon.late.local.gradle.kts' +} else if (file('addon.late.local.gradle').exists()) { + apply from: 'addon.late.local.gradle' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba7710deaf9f98673a68957ea02138b60d0a..943f0cbfa754578e88a3dae77fce6e3dea56edbf 100644 GIT binary patch delta 5107 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 I6Xdi10eY*&F8}}l delta 5094 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f398c33..17a8ddc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 79a61d4..65dcd68 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ 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=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/repositories.gradle b/repositories.gradle index 871afc7..45729e1 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,9 +1,4 @@ // Add any additional repositiroes for your dependencies here repositories { - maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - } - } From 52d522f311379a2f9badf491a6eb67bc0679e97d Mon Sep 17 00:00:00 2001 From: miozune Date: Thu, 30 Nov 2023 00:37:22 +0900 Subject: [PATCH 181/219] Fix wildcard import & spotlessApply --- .../java/codechicken/lib/asm/ASMBlock.java | 14 +- .../java/codechicken/lib/asm/ASMHelper.java | 8 +- .../java/codechicken/lib/asm/ASMReader.java | 187 +++++++++++++++++- .../codechicken/lib/asm/InsnComparator.java | 38 +++- .../codechicken/lib/asm/InsnListSection.java | 14 +- .../lib/asm/ModularASMTransformer.java | 18 +- .../java/codechicken/lib/asm/ObfMapping.java | 12 +- .../codechicken/lib/config/ConfigFile.java | 7 +- .../lib/config/ConfigTagParent.java | 6 +- .../lib/config/SimpleProperties.java | 6 +- .../lib/data/MCDataOutputWrapper.java | 4 +- .../java/codechicken/lib/gui/GuiDraw.java | 3 +- .../lib/inventory/InventoryUtils.java | 4 +- .../codechicken/lib/packet/PacketCustom.java | 11 +- .../java/codechicken/lib/render/CCModel.java | 20 +- .../lib/render/CCModelLibrary.java | 6 +- .../codechicken/lib/render/QBImporter.java | 31 ++- .../codechicken/lib/render/ShaderProgram.java | 16 +- .../lib/tool/module/JOptModule.java | 2 +- .../lib/tool/module/ModuleQBConverter.java | 2 +- 20 files changed, 361 insertions(+), 48 deletions(-) diff --git a/src/main/java/codechicken/lib/asm/ASMBlock.java b/src/main/java/codechicken/lib/asm/ASMBlock.java index eb71c9f..1f85ae7 100644 --- a/src/main/java/codechicken/lib/asm/ASMBlock.java +++ b/src/main/java/codechicken/lib/asm/ASMBlock.java @@ -1,9 +1,17 @@ package codechicken.lib.asm; -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -import java.util.*; +import static org.objectweb.asm.tree.AbstractInsnNode.FRAME; +import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.LABEL; +import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; diff --git a/src/main/java/codechicken/lib/asm/ASMHelper.java b/src/main/java/codechicken/lib/asm/ASMHelper.java index 8d76a3f..e90b99f 100644 --- a/src/main/java/codechicken/lib/asm/ASMHelper.java +++ b/src/main/java/codechicken/lib/asm/ASMHelper.java @@ -13,7 +13,13 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.*; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LocalVariableNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.util.ASMifier; import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceClassVisitor; diff --git a/src/main/java/codechicken/lib/asm/ASMReader.java b/src/main/java/codechicken/lib/asm/ASMReader.java index dda47f2..b348649 100644 --- a/src/main/java/codechicken/lib/asm/ASMReader.java +++ b/src/main/java/codechicken/lib/asm/ASMReader.java @@ -1,15 +1,194 @@ package codechicken.lib.asm; -import static org.objectweb.asm.Opcodes.*; -import static org.objectweb.asm.tree.AbstractInsnNode.*; +import static org.objectweb.asm.Opcodes.AALOAD; +import static org.objectweb.asm.Opcodes.AASTORE; +import static org.objectweb.asm.Opcodes.ACONST_NULL; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ANEWARRAY; +import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.ARRAYLENGTH; +import static org.objectweb.asm.Opcodes.ASTORE; +import static org.objectweb.asm.Opcodes.ATHROW; +import static org.objectweb.asm.Opcodes.BALOAD; +import static org.objectweb.asm.Opcodes.BASTORE; +import static org.objectweb.asm.Opcodes.BIPUSH; +import static org.objectweb.asm.Opcodes.CALOAD; +import static org.objectweb.asm.Opcodes.CASTORE; +import static org.objectweb.asm.Opcodes.CHECKCAST; +import static org.objectweb.asm.Opcodes.D2F; +import static org.objectweb.asm.Opcodes.D2I; +import static org.objectweb.asm.Opcodes.D2L; +import static org.objectweb.asm.Opcodes.DADD; +import static org.objectweb.asm.Opcodes.DALOAD; +import static org.objectweb.asm.Opcodes.DASTORE; +import static org.objectweb.asm.Opcodes.DCMPG; +import static org.objectweb.asm.Opcodes.DCMPL; +import static org.objectweb.asm.Opcodes.DCONST_0; +import static org.objectweb.asm.Opcodes.DCONST_1; +import static org.objectweb.asm.Opcodes.DDIV; +import static org.objectweb.asm.Opcodes.DLOAD; +import static org.objectweb.asm.Opcodes.DMUL; +import static org.objectweb.asm.Opcodes.DNEG; +import static org.objectweb.asm.Opcodes.DREM; +import static org.objectweb.asm.Opcodes.DRETURN; +import static org.objectweb.asm.Opcodes.DSTORE; +import static org.objectweb.asm.Opcodes.DSUB; +import static org.objectweb.asm.Opcodes.DUP; +import static org.objectweb.asm.Opcodes.DUP2; +import static org.objectweb.asm.Opcodes.DUP2_X1; +import static org.objectweb.asm.Opcodes.DUP2_X2; +import static org.objectweb.asm.Opcodes.DUP_X1; +import static org.objectweb.asm.Opcodes.DUP_X2; +import static org.objectweb.asm.Opcodes.F2D; +import static org.objectweb.asm.Opcodes.F2I; +import static org.objectweb.asm.Opcodes.F2L; +import static org.objectweb.asm.Opcodes.FADD; +import static org.objectweb.asm.Opcodes.FALOAD; +import static org.objectweb.asm.Opcodes.FASTORE; +import static org.objectweb.asm.Opcodes.FCMPG; +import static org.objectweb.asm.Opcodes.FCMPL; +import static org.objectweb.asm.Opcodes.FCONST_0; +import static org.objectweb.asm.Opcodes.FCONST_1; +import static org.objectweb.asm.Opcodes.FCONST_2; +import static org.objectweb.asm.Opcodes.FDIV; +import static org.objectweb.asm.Opcodes.FLOAD; +import static org.objectweb.asm.Opcodes.FMUL; +import static org.objectweb.asm.Opcodes.FNEG; +import static org.objectweb.asm.Opcodes.FREM; +import static org.objectweb.asm.Opcodes.FRETURN; +import static org.objectweb.asm.Opcodes.FSTORE; +import static org.objectweb.asm.Opcodes.FSUB; +import static org.objectweb.asm.Opcodes.GETFIELD; +import static org.objectweb.asm.Opcodes.GETSTATIC; +import static org.objectweb.asm.Opcodes.GOTO; +import static org.objectweb.asm.Opcodes.I2B; +import static org.objectweb.asm.Opcodes.I2C; +import static org.objectweb.asm.Opcodes.I2D; +import static org.objectweb.asm.Opcodes.I2F; +import static org.objectweb.asm.Opcodes.I2L; +import static org.objectweb.asm.Opcodes.I2S; +import static org.objectweb.asm.Opcodes.IADD; +import static org.objectweb.asm.Opcodes.IALOAD; +import static org.objectweb.asm.Opcodes.IAND; +import static org.objectweb.asm.Opcodes.IASTORE; +import static org.objectweb.asm.Opcodes.ICONST_0; +import static org.objectweb.asm.Opcodes.ICONST_1; +import static org.objectweb.asm.Opcodes.ICONST_2; +import static org.objectweb.asm.Opcodes.ICONST_3; +import static org.objectweb.asm.Opcodes.ICONST_4; +import static org.objectweb.asm.Opcodes.ICONST_5; +import static org.objectweb.asm.Opcodes.ICONST_M1; +import static org.objectweb.asm.Opcodes.IDIV; +import static org.objectweb.asm.Opcodes.IFEQ; +import static org.objectweb.asm.Opcodes.IFGE; +import static org.objectweb.asm.Opcodes.IFGT; +import static org.objectweb.asm.Opcodes.IFLE; +import static org.objectweb.asm.Opcodes.IFLT; +import static org.objectweb.asm.Opcodes.IFNE; +import static org.objectweb.asm.Opcodes.IFNONNULL; +import static org.objectweb.asm.Opcodes.IFNULL; +import static org.objectweb.asm.Opcodes.IF_ACMPEQ; +import static org.objectweb.asm.Opcodes.IF_ACMPNE; +import static org.objectweb.asm.Opcodes.IF_ICMPEQ; +import static org.objectweb.asm.Opcodes.IF_ICMPGE; +import static org.objectweb.asm.Opcodes.IF_ICMPGT; +import static org.objectweb.asm.Opcodes.IF_ICMPLE; +import static org.objectweb.asm.Opcodes.IF_ICMPLT; +import static org.objectweb.asm.Opcodes.IF_ICMPNE; +import static org.objectweb.asm.Opcodes.IINC; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.IMUL; +import static org.objectweb.asm.Opcodes.INEG; +import static org.objectweb.asm.Opcodes.INSTANCEOF; +import static org.objectweb.asm.Opcodes.INVOKEDYNAMIC; +import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; +import static org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; +import static org.objectweb.asm.Opcodes.IOR; +import static org.objectweb.asm.Opcodes.IREM; +import static org.objectweb.asm.Opcodes.IRETURN; +import static org.objectweb.asm.Opcodes.ISHL; +import static org.objectweb.asm.Opcodes.ISHR; +import static org.objectweb.asm.Opcodes.ISTORE; +import static org.objectweb.asm.Opcodes.ISUB; +import static org.objectweb.asm.Opcodes.IUSHR; +import static org.objectweb.asm.Opcodes.IXOR; +import static org.objectweb.asm.Opcodes.JSR; +import static org.objectweb.asm.Opcodes.L2D; +import static org.objectweb.asm.Opcodes.L2F; +import static org.objectweb.asm.Opcodes.L2I; +import static org.objectweb.asm.Opcodes.LADD; +import static org.objectweb.asm.Opcodes.LALOAD; +import static org.objectweb.asm.Opcodes.LAND; +import static org.objectweb.asm.Opcodes.LASTORE; +import static org.objectweb.asm.Opcodes.LCMP; +import static org.objectweb.asm.Opcodes.LCONST_0; +import static org.objectweb.asm.Opcodes.LCONST_1; +import static org.objectweb.asm.Opcodes.LDC; +import static org.objectweb.asm.Opcodes.LDIV; +import static org.objectweb.asm.Opcodes.LLOAD; +import static org.objectweb.asm.Opcodes.LMUL; +import static org.objectweb.asm.Opcodes.LNEG; +import static org.objectweb.asm.Opcodes.LOOKUPSWITCH; +import static org.objectweb.asm.Opcodes.LOR; +import static org.objectweb.asm.Opcodes.LREM; +import static org.objectweb.asm.Opcodes.LRETURN; +import static org.objectweb.asm.Opcodes.LSHL; +import static org.objectweb.asm.Opcodes.LSHR; +import static org.objectweb.asm.Opcodes.LSTORE; +import static org.objectweb.asm.Opcodes.LSUB; +import static org.objectweb.asm.Opcodes.LUSHR; +import static org.objectweb.asm.Opcodes.LXOR; +import static org.objectweb.asm.Opcodes.MONITORENTER; +import static org.objectweb.asm.Opcodes.MONITOREXIT; +import static org.objectweb.asm.Opcodes.MULTIANEWARRAY; +import static org.objectweb.asm.Opcodes.NEW; +import static org.objectweb.asm.Opcodes.NEWARRAY; +import static org.objectweb.asm.Opcodes.NOP; +import static org.objectweb.asm.Opcodes.POP; +import static org.objectweb.asm.Opcodes.POP2; +import static org.objectweb.asm.Opcodes.PUTFIELD; +import static org.objectweb.asm.Opcodes.PUTSTATIC; +import static org.objectweb.asm.Opcodes.RET; +import static org.objectweb.asm.Opcodes.RETURN; +import static org.objectweb.asm.Opcodes.SALOAD; +import static org.objectweb.asm.Opcodes.SASTORE; +import static org.objectweb.asm.Opcodes.SIPUSH; +import static org.objectweb.asm.Opcodes.SWAP; +import static org.objectweb.asm.Opcodes.TABLESWITCH; +import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.FRAME; +import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.INVOKE_DYNAMIC_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.LABEL; +import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.MULTIANEWARRAY_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.*; +import java.util.HashMap; +import java.util.Map; -import org.objectweb.asm.tree.*; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.VarInsnNode; public class ASMReader { diff --git a/src/main/java/codechicken/lib/asm/InsnComparator.java b/src/main/java/codechicken/lib/asm/InsnComparator.java index 4a1c76d..f88da92 100644 --- a/src/main/java/codechicken/lib/asm/InsnComparator.java +++ b/src/main/java/codechicken/lib/asm/InsnComparator.java @@ -1,10 +1,38 @@ package codechicken.lib.asm; -import static org.objectweb.asm.tree.AbstractInsnNode.*; - -import java.util.*; - -import org.objectweb.asm.tree.*; +import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.FRAME; +import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.LABEL; +import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.LINE; +import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.VarInsnNode; import com.google.common.base.Function; import com.google.common.collect.Maps; diff --git a/src/main/java/codechicken/lib/asm/InsnListSection.java b/src/main/java/codechicken/lib/asm/InsnListSection.java index c71a359..dbe204a 100644 --- a/src/main/java/codechicken/lib/asm/InsnListSection.java +++ b/src/main/java/codechicken/lib/asm/InsnListSection.java @@ -1,6 +1,10 @@ package codechicken.lib.asm; -import static org.objectweb.asm.tree.AbstractInsnNode.*; +import static org.objectweb.asm.tree.AbstractInsnNode.FRAME; +import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.LABEL; +import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN; import java.io.PrintWriter; import java.io.StringWriter; @@ -11,7 +15,13 @@ import java.util.Set; import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.tree.*; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FrameNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceMethodVisitor; diff --git a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java index c1998c3..baa4eb6 100644 --- a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java +++ b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java @@ -1,11 +1,21 @@ package codechicken.lib.asm; -import static codechicken.lib.asm.ASMHelper.*; +import static codechicken.lib.asm.ASMHelper.config; +import static codechicken.lib.asm.ASMHelper.createBytes; +import static codechicken.lib.asm.ASMHelper.dump; +import static codechicken.lib.asm.ASMHelper.findMethod; +import static codechicken.lib.asm.ASMHelper.logger; import java.io.File; -import java.util.*; - -import org.objectweb.asm.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodNode; diff --git a/src/main/java/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java index 355ade8..f8ccb92 100644 --- a/src/main/java/codechicken/lib/asm/ObfMapping.java +++ b/src/main/java/codechicken/lib/asm/ObfMapping.java @@ -7,7 +7,7 @@ import java.util.Map; import java.util.Map.Entry; -import javax.swing.*; +import javax.swing.JFileChooser; import net.minecraft.launchwrapper.Launch; import net.minecraftforge.common.ForgeVersion; @@ -16,15 +16,19 @@ import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.commons.Remapper; -import org.objectweb.asm.tree.*; - -import codechicken.lib.config.ConfigTag; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TypeInsnNode; import com.google.common.base.Charsets; import com.google.common.base.Objects; import com.google.common.io.LineProcessor; import com.google.common.io.Resources; +import codechicken.lib.config.ConfigTag; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.relauncher.FMLInjectionData; diff --git a/src/main/java/codechicken/lib/config/ConfigFile.java b/src/main/java/codechicken/lib/config/ConfigFile.java index 8a1cff5..31a18de 100644 --- a/src/main/java/codechicken/lib/config/ConfigFile.java +++ b/src/main/java/codechicken/lib/config/ConfigFile.java @@ -1,6 +1,11 @@ package codechicken.lib.config; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; public class ConfigFile extends ConfigTagParent { diff --git a/src/main/java/codechicken/lib/config/ConfigTagParent.java b/src/main/java/codechicken/lib/config/ConfigTagParent.java index 3ce68fb..79514b9 100644 --- a/src/main/java/codechicken/lib/config/ConfigTagParent.java +++ b/src/main/java/codechicken/lib/config/ConfigTagParent.java @@ -3,8 +3,12 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; import java.util.Map.Entry; +import java.util.TreeMap; public abstract class ConfigTagParent { diff --git a/src/main/java/codechicken/lib/config/SimpleProperties.java b/src/main/java/codechicken/lib/config/SimpleProperties.java index 36609fb..4ec65e0 100644 --- a/src/main/java/codechicken/lib/config/SimpleProperties.java +++ b/src/main/java/codechicken/lib/config/SimpleProperties.java @@ -1,6 +1,10 @@ package codechicken.lib.config; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map.Entry; diff --git a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java index 1cd252f..84aee32 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java +++ b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java @@ -11,9 +11,9 @@ import org.apache.commons.lang3.Validate; -import codechicken.lib.vec.BlockCoord; - import com.google.common.base.Charsets; + +import codechicken.lib.vec.BlockCoord; import cpw.mods.fml.common.network.ByteBufUtils; public class MCDataOutputWrapper implements MCDataOutput { diff --git a/src/main/java/codechicken/lib/gui/GuiDraw.java b/src/main/java/codechicken/lib/gui/GuiDraw.java index 96ef7e0..d68e043 100644 --- a/src/main/java/codechicken/lib/gui/GuiDraw.java +++ b/src/main/java/codechicken/lib/gui/GuiDraw.java @@ -1,6 +1,7 @@ package codechicken.lib.gui; -import java.awt.*; +import java.awt.Dimension; +import java.awt.Point; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/codechicken/lib/inventory/InventoryUtils.java b/src/main/java/codechicken/lib/inventory/InventoryUtils.java index c9729e5..fa78174 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryUtils.java +++ b/src/main/java/codechicken/lib/inventory/InventoryUtils.java @@ -15,10 +15,10 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; -import codechicken.lib.vec.Vector3; - import com.google.common.base.Objects; +import codechicken.lib.vec.Vector3; + public class InventoryUtils { /** diff --git a/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java index 468e2fd..37cd108 100644 --- a/src/main/java/codechicken/lib/packet/PacketCustom.java +++ b/src/main/java/codechicken/lib/packet/PacketCustom.java @@ -24,15 +24,18 @@ import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; +import com.google.common.collect.Maps; + import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.vec.BlockCoord; - -import com.google.common.collect.Maps; - import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.ModContainer; -import cpw.mods.fml.common.network.*; +import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.network.FMLEmbeddedChannel; +import cpw.mods.fml.common.network.FMLOutboundHandler; +import cpw.mods.fml.common.network.NetworkHandshakeEstablished; +import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.handshake.NetworkDispatcher; import cpw.mods.fml.common.network.internal.FMLProxyPacket; import cpw.mods.fml.relauncher.Side; diff --git a/src/main/java/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java index 18b9164..649045c 100644 --- a/src/main/java/codechicken/lib/render/CCModel.java +++ b/src/main/java/codechicken/lib/render/CCModel.java @@ -2,8 +2,18 @@ import static codechicken.lib.vec.Rotation.sideRotations; -import java.io.*; -import java.util.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,7 +26,11 @@ import codechicken.lib.render.uv.UVTransformation; import codechicken.lib.render.uv.UVTranslation; import codechicken.lib.util.Copyable; -import codechicken.lib.vec.*; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.RedundantTransformation; +import codechicken.lib.vec.Transformation; +import codechicken.lib.vec.TransformationList; +import codechicken.lib.vec.Vector3; public class CCModel implements CCRenderState.IVertexSource, Copyable { diff --git a/src/main/java/codechicken/lib/render/CCModelLibrary.java b/src/main/java/codechicken/lib/render/CCModelLibrary.java index af3663f..7806fa7 100644 --- a/src/main/java/codechicken/lib/render/CCModelLibrary.java +++ b/src/main/java/codechicken/lib/render/CCModelLibrary.java @@ -2,7 +2,11 @@ import static codechicken.lib.math.MathHelper.phi; -import codechicken.lib.vec.*; +import codechicken.lib.vec.Matrix4; +import codechicken.lib.vec.Quat; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Scale; +import codechicken.lib.vec.Vector3; public class CCModelLibrary { diff --git a/src/main/java/codechicken/lib/render/QBImporter.java b/src/main/java/codechicken/lib/render/QBImporter.java index 25f60de..5b5d457 100644 --- a/src/main/java/codechicken/lib/render/QBImporter.java +++ b/src/main/java/codechicken/lib/render/QBImporter.java @@ -1,8 +1,19 @@ package codechicken.lib.render; import java.awt.image.BufferedImage; -import java.io.*; -import java.util.*; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import javax.imageio.ImageIO; @@ -11,13 +22,21 @@ import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; -import codechicken.lib.render.uv.UV; -import codechicken.lib.render.uv.UVScale; -import codechicken.lib.vec.*; - import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import codechicken.lib.render.uv.UV; +import codechicken.lib.render.uv.UVScale; +import codechicken.lib.vec.BlockCoord; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.CuboidCoord; +import codechicken.lib.vec.Rectangle4i; +import codechicken.lib.vec.Rotation; +import codechicken.lib.vec.Scale; +import codechicken.lib.vec.Transformation; +import codechicken.lib.vec.Translation; +import codechicken.lib.vec.Vector3; + public class QBImporter { private static class ImagePackNode { diff --git a/src/main/java/codechicken/lib/render/ShaderProgram.java b/src/main/java/codechicken/lib/render/ShaderProgram.java index ccc145a..60a3d69 100644 --- a/src/main/java/codechicken/lib/render/ShaderProgram.java +++ b/src/main/java/codechicken/lib/render/ShaderProgram.java @@ -1,6 +1,20 @@ package codechicken.lib.render; -import static org.lwjgl.opengl.ARBShaderObjects.*; +import static org.lwjgl.opengl.ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB; +import static org.lwjgl.opengl.ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB; +import static org.lwjgl.opengl.ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB; +import static org.lwjgl.opengl.ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB; +import static org.lwjgl.opengl.ARBShaderObjects.glAttachObjectARB; +import static org.lwjgl.opengl.ARBShaderObjects.glCompileShaderARB; +import static org.lwjgl.opengl.ARBShaderObjects.glCreateProgramObjectARB; +import static org.lwjgl.opengl.ARBShaderObjects.glCreateShaderObjectARB; +import static org.lwjgl.opengl.ARBShaderObjects.glDeleteObjectARB; +import static org.lwjgl.opengl.ARBShaderObjects.glGetInfoLogARB; +import static org.lwjgl.opengl.ARBShaderObjects.glGetObjectParameteriARB; +import static org.lwjgl.opengl.ARBShaderObjects.glLinkProgramARB; +import static org.lwjgl.opengl.ARBShaderObjects.glShaderSourceARB; +import static org.lwjgl.opengl.ARBShaderObjects.glUseProgramObjectARB; +import static org.lwjgl.opengl.ARBShaderObjects.glValidateProgramARB; import java.io.BufferedReader; import java.io.IOException; diff --git a/src/main/java/codechicken/lib/tool/module/JOptModule.java b/src/main/java/codechicken/lib/tool/module/JOptModule.java index 206bcb0..2c9adee 100644 --- a/src/main/java/codechicken/lib/tool/module/JOptModule.java +++ b/src/main/java/codechicken/lib/tool/module/JOptModule.java @@ -2,10 +2,10 @@ import java.io.IOException; +import codechicken.lib.tool.ToolMain; import joptsimple.OptionException; import joptsimple.OptionParser; import joptsimple.OptionSet; -import codechicken.lib.tool.ToolMain; public abstract class JOptModule implements ToolMain.Module { diff --git a/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java index b9e3048..f9d9bda 100644 --- a/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java +++ b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java @@ -4,9 +4,9 @@ import java.io.File; +import codechicken.lib.render.QBImporter; import joptsimple.OptionParser; import joptsimple.OptionSet; -import codechicken.lib.render.QBImporter; public class ModuleQBConverter extends JOptModule { From d6e2b946b14d0fe19f376e5ca4baa817745a415e Mon Sep 17 00:00:00 2001 From: miozune Date: Thu, 30 Nov 2023 00:38:54 +0900 Subject: [PATCH 182/219] Fix ItemStack packet id limited by short --- src/main/java/codechicken/lib/packet/PacketCustom.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java index 37cd108..67753d4 100644 --- a/src/main/java/codechicken/lib/packet/PacketCustom.java +++ b/src/main/java/codechicken/lib/packet/PacketCustom.java @@ -351,9 +351,9 @@ public PacketCustom writeItemStack(ItemStack stack) { public PacketCustom writeItemStack(ItemStack stack, boolean large) { if (stack == null) { - writeShort(-1); + writeInt(-1); } else { - writeShort(Item.getIdFromItem(stack.getItem())); + writeInt(Item.getIdFromItem(stack.getItem())); if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); writeShort(stack.getItemDamage()); @@ -448,7 +448,7 @@ public ItemStack readItemStack() { public ItemStack readItemStack(boolean large) { ItemStack item = null; - short itemID = readShort(); + int itemID = readInt(); if (itemID >= 0) { int stackSize = large ? readInt() : readByte(); From 20b1e280745169618b9ff0f96f217e9abbf563be Mon Sep 17 00:00:00 2001 From: bombcar Date: Wed, 29 Nov 2023 15:14:41 -0600 Subject: [PATCH 183/219] update BS and spotlessApply (#11) --- build.gradle | 735 +++++++++++++----- dependencies.gradle | 2 +- repositories.gradle | 8 - .../codechicken/core/CCUpdateChecker.java | 3 +- .../codechicken/core/ClassDiscoverer.java | 5 +- .../codechicken/core/GuiModListScroll.java | 19 +- .../java/codechicken/core/ServerUtils.java | 4 +- .../asm/CodeChickenAccessTransformer.java | 3 +- .../core/asm/CodeChickenCoreModContainer.java | 12 +- .../core/asm/MCPDeobfuscationTransformer.java | 13 +- .../codechicken/core/asm/MethodASMifier.java | 2 +- .../core/asm/TweakTransformer.java | 8 +- .../codechicken/core/gui/GuiScrollPane.java | 3 +- .../codechicken/core/gui/GuiScrollSlot.java | 2 +- .../core/launch/CodeChickenCorePlugin.java | 9 +- .../codechicken/core/launch/DepLoader.java | 32 +- .../obfuscator/ConstantObfuscator.java | 3 +- .../obfuscator/ObfuscationMap.java | 4 +- 18 files changed, 633 insertions(+), 234 deletions(-) diff --git a/build.gradle b/build.gradle index fe8a2e7..4e31dc8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675110695 +//version: 1700844281 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,27 +6,28 @@ */ -import com.diffplug.blowdryer.Blowdryer -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask +import com.gtnewhorizons.retrofuturagradle.util.Distribution import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.jetbrains.gradle.ext.* +import org.gradle.internal.xml.XmlTransformer +import org.jetbrains.gradle.ext.Application +import org.jetbrains.gradle.ext.Gradle +import javax.inject.Inject import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream buildscript { repositories { - mavenLocal() mavenCentral() maven { @@ -47,6 +48,8 @@ buildscript { name 'Scala CI dependencies' url 'https://repo1.maven.org/maven2/' } + + mavenLocal() } } plugins { @@ -58,22 +61,26 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version - id 'de.undercouch.download' version '5.3.0' + id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false + id 'com.palantir.git-version' version '3.0.0' apply false + id 'de.undercouch.download' version '5.4.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.7.2' apply false + id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.1.2' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' } + +print("You might want to check out './gradlew :faq' if your build fails.\n") + boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -if (project.file('.git/HEAD').isFile()) { +// In submodules, .git is a file pointing to the real git dir +if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { apply plugin: 'com.palantir.git-version' } @@ -82,6 +89,23 @@ def out = services.get(StyledTextOutputFactory).create('an-output') def projectJavaVersion = JavaLanguageVersion.of(8) boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false +boolean disableCheckstyle = project.hasProperty("disableCheckstyle") ? project.disableCheckstyle.toBoolean() : false + +final String CHECKSTYLE_CONFIG = """ + + + + + + + + + + + +""" checkPropertyExists("modName") checkPropertyExists("modId") @@ -108,6 +132,8 @@ propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("usesMavenPublishing", true) +propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -122,12 +148,26 @@ propertyDefaultIfUnset("gradleTokenGroupName", "") propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only -project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +// this is meant to be set using the user wide property file. by default we do nothing. +propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" + +project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts if (!disableSpotless) { apply plugin: 'com.diffplug.spotless' apply from: Blowdryer.file('spotless.gradle') } +if (!disableCheckstyle) { + apply plugin: 'checkstyle' + tasks.named("checkstylePatchedMc") { enabled = false } + tasks.named("checkstyleMcLauncher") { enabled = false } + tasks.named("checkstyleIdeVirtualMain") { enabled = false } + tasks.named("checkstyleInjectedTags") { enabled = false } + checkstyle { + config = resources.text.fromString(CHECKSTYLE_CONFIG) + } +} + String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" @@ -143,13 +183,21 @@ java { } else { languageVersion.set(projectJavaVersion) } - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) } if (!noPublishedSources) { withSourcesJar() } } +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} + +tasks.withType(ScalaCompile).configureEach { + options.encoding = "UTF-8" +} + pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { // If Kotlin is enabled in the project kotlin { @@ -183,14 +231,34 @@ configurations { canBeConsumed = false canBeResolved = false } + + create("devOnlyNonPublishable") { + description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" + canBeConsumed = false + canBeResolved = false + } + compileOnly.extendsFrom(devOnlyNonPublishable) + runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) } if (enableModernJavaSyntax.toBoolean()) { + repositories { + mavenCentral { + mavenContent { + includeGroup("me.eigenraven.java8unsupported") + } + } + } + dependencies { annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + // workaround for https://github.com/bsideup/jabel/issues/174 + annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { transitive = false // We only care about the 1 annotation class } + // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. + patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') } tasks.withType(JavaCompile).configureEach { @@ -202,7 +270,7 @@ if (enableModernJavaSyntax.toBoolean()) { javaCompiler.set(javaToolchains.compilerFor { languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) }) } } @@ -234,12 +302,14 @@ if (apiPackage) { } if (accessTransformersFile) { - String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if (!getFile(targetFile).exists()) { - throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + for (atFile in accessTransformersFile.split(" ")) { + String targetFile = "src/main/resources/META-INF/" + atFile.trim() + if (!getFile(targetFile).exists()) { + throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } else { boolean atsFound = false for (File at : sourceSets.getByName("main").resources.files) { @@ -317,7 +387,27 @@ catch (Exception ignored) { String identifiedVersion String versionOverride = System.getenv("VERSION") ?: null try { - identifiedVersion = versionOverride == null ? gitVersion() : versionOverride + // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty + if (versionOverride == null) { + def gitDetails = versionDetails() + def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning + String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') + if (branchName.startsWith('origin/')) { + branchName = branchName.minus('origin/') + } + branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver + identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' + if (gitDetails.commitDistance > 0) { + identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" + if (isDirty) { + identifiedVersion += "-dirty" + } + } else if (isDirty) { + identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" + } + } else { + identifiedVersion = versionOverride + } } catch (Exception ignored) { out.style(Style.Failure).text( @@ -339,9 +429,13 @@ if (identifiedVersion == versionOverride) { group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - archivesBaseName = customArchiveBaseName + base { + archivesName = customArchiveBaseName + } } else { - archivesBaseName = modId + base { + archivesName = modId + } } @@ -367,12 +461,14 @@ minecraft { injectMissingGenerics.set(true) } + username = developmentEnvironmentUserName.toString() + + lwjgl3Version = "3.3.2" + // Enable assertions in the current mod extraRunJvmArguments.add("-ea:${modGroup}") if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") - if (usesMixinDebug.toBoolean()) { extraRunJvmArguments.addAll([ "-Dmixin.debug.countInjections=true", @@ -401,6 +497,16 @@ configurations.configureEach { } } } + def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) + if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server + if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { + details.useVersion '2388750' + details.because 'Pick obfuscated jar' + } + } + } } // Ensure tests have access to minecraft classes @@ -413,10 +519,19 @@ sourceSets { } } -if (file('addon.gradle').exists()) { +if (file('addon.gradle.kts').exists()) { + apply from: 'addon.gradle.kts' +} else if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// File for local tweaks not commited to Git +if (file('addon.local.gradle.kts').exists()) { + apply from: 'addon.local.gradle.kts' +} else if (file('addon.local.gradle').exists()) { + apply from: 'addon.local.gradle' +} + // Allow unsafe repos but warn repositories.configureEach { repo -> if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { @@ -427,11 +542,19 @@ repositories.configureEach { repo -> } } -apply from: 'repositories.gradle' +if (file('repositories.gradle.kts').exists()) { + apply from: 'repositories.gradle.kts' +} else if (file('repositories.gradle').exists()) { + apply from: 'repositories.gradle' +} else { + logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing repositories.gradle[.kts]") +} configurations { + runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) + testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - config.extendsFrom(runtimeOnlyNonPublishable) if (usesShadowedDependencies.toBoolean()) { config.extendsFrom(shadowImplementation) // TODO: remove Compile after all uses are refactored to Implementation @@ -467,42 +590,48 @@ repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' - mavenContent { - excludeGroup("net.minecraftforge") // missing the `universal` artefact - } } maven { name = "GTNH Maven" url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - maven { - name = "Fabric Maven" - url = "https://maven.fabricmc.net/" - } + maven { + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' + content { + includeGroup "org.lwjgl" } } if (includeWellKnownRepositories.toBoolean()) { - maven { - name "CurseMaven" - url "https://cursemaven.com" - content { + exclusiveContent { + forRepository { + maven { + name "CurseMaven" + url "https://cursemaven.com" + } + } + filter { includeGroup "curse.maven" } } - maven { - name = "ic2" - url = "https://maven.ic2.player.to/" - metadataSources { - mavenPom() - artifact() + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" } } maven { - name = "ic2-mirror" - url = "https://maven2.ic2.player.to/" + name = "ic2" + url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + content { + includeGroup "net.industrial-craft" + } metadataSources { mavenPom() artifact() @@ -515,35 +644,78 @@ repositories { } } +def mixinProviderGroup = "io.github.legacymoddingmc" +def mixinProviderModule = "unimixins" +def mixinProviderVersion = "0.1.13" +def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" +def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" +ext.mixinProviderSpec = mixinProviderSpec + +def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' + dependencies { if (usesMixins.toBoolean()) { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') annotationProcessor('com.google.guava:guava:24.1.1-jre') annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + annotationProcessor(mixinProviderSpec) if (usesMixinDebug.toBoolean()) { runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') } } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - implementation('com.gtnewhorizon:gtnhmixins:2.1.10') + if (usesMixins.toBoolean()) { + implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) + } else if (forceEnableMixins.toBoolean()) { + runtimeOnlyNonPublishable(mixinProviderSpec) } } pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { if (usesMixins.toBoolean()) { dependencies { - kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + kapt(mixinProviderSpec) } } } -apply from: 'dependencies.gradle' +// Replace old mixin mods with unimixins +// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier +configurations.all { + resolutionStrategy.dependencySubstitution { + substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + } +} -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' -def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' -def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap -def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" +dependencies { + constraints { + def minGtnhLibVersion = "0.0.13" + implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + } +} + +if (file('dependencies.gradle.kts').exists()) { + apply from: 'dependencies.gradle.kts' +} else if (file('dependencies.gradle').exists()) { + apply from: 'dependencies.gradle' +} else { + logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing dependencies.gradle[.kts]") +} tasks.register('generateAssets') { group = "GTNH Buildscript" @@ -575,46 +747,17 @@ tasks.register('generateAssets') { } if (usesMixins.toBoolean()) { - tasks.named("reobfJar", ReobfuscatedJar).configure { - extraSrgFiles.from(mixinSrg) - } - tasks.named("processResources").configure { dependsOn("generateAssets") } tasks.named("compileJava", JavaCompile).configure { - doFirst { - new File(mixinTmpDir).mkdirs() - } options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code "-XDenableSunApiLintControl", "-XDignore.symbol.file" ] } - - pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - kapt { - correctErrorTypes = true - javacOptions { - option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") - option("-AoutSrgFile=$mixinSrg") - option("-AoutRefMapFile=$refMap") - } - } - tasks.configureEach { task -> - if (task.name == "kaptKotlin") { - task.doFirst { - new File(mixinTmpDir).mkdirs() - } - } - } - } - } tasks.named("processResources", ProcessResources).configure { @@ -632,10 +775,149 @@ tasks.named("processResources", ProcessResources).configure { } if (usesMixins.toBoolean()) { - from refMap + dependsOn("compileJava", "compileScala") } } +ext.java17Toolchain = (JavaToolchainSpec spec) -> { + spec.languageVersion.set(JavaLanguageVersion.of(17)) + spec.vendor.set(JvmVendorSpec.matching("jetbrains")) +} + +ext.java17DependenciesCfg = configurations.create("java17Dependencies") { + extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution + canBeConsumed = false +} +ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { + canBeConsumed = false +} + +dependencies { + def lwjgl3ifyVersion = '1.5.1' + if (modId != 'lwjgl3ify') { + java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") + } + if (modId != 'hodgepodge') { + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.17') + } + + java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} +} + +ext.java17JvmArgs = [ + // Java 9+ support + "--illegal-access=warn", + "-Djava.security.manager=allow", + "-Dfile.encoding=UTF-8", + "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", + "--add-opens", "java.base/java.net=ALL-UNNAMED", + "--add-opens", "java.base/java.nio=ALL-UNNAMED", + "--add-opens", "java.base/java.io=ALL-UNNAMED", + "--add-opens", "java.base/java.lang=ALL-UNNAMED", + "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens", "java.base/java.text=ALL-UNNAMED", + "--add-opens", "java.base/java.util=ALL-UNNAMED", + "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", + "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", + "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", + "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", + "--add-modules", "jdk.dynalink", + "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", + "--add-modules", "java.sql.rowset", + "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" +] + +ext.hotswapJvmArgs = [ + // DCEVM advanced hot reload + "-XX:+AllowEnhancedClassRedefinition", + "-XX:HotswapAgent=fatjar" +] + +ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { + group = "GTNH Buildscript" + description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" + def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' + def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} + def targetFilename = "hotswap-agent.jar" + onlyIf { + !targetFolderProvider.get().file(targetFilename).asFile.exists() + } + doLast { + def targetFolder = targetFolderProvider.get() + targetFolder.asFile.mkdirs() + download.run { + src hsaUrl + dest targetFolder.file(targetFilename).asFile + overwrite false + tempAndMove true + } + } +} + +public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { + // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable + private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); + + @Input + public boolean getEnableHotswap() { return enableHotswap } + @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") + public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } + + @Inject + public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { + super(side, gradle) + + this.lwjglVersion = 3 + this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) + this.extraJvmArgs.addAll(project.java17JvmArgs) + this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) + + this.classpath(project.java17PatchDependenciesCfg) + if (side == Distribution.CLIENT) { + this.classpath(project.minecraftTasks.lwjgl3Configuration) + } + // Use a raw provider instead of map to not create a dependency on the task + this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) + this.classpath.filter { file -> + !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 + } + this.classpath(project.java17DependenciesCfg) + } + + public void setup(Project project) { + super.setup(project) + if (project.usesMixins.toBoolean()) { + this.extraJvmArgs.addAll(project.provider(() -> { + def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) + mixinCfg.canBeConsumed = false + mixinCfg.transitive = false + enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] + })) + } + } +} + +def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") +runClient17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStart" + username = minecraft.username + userUUID = minecraft.userUUID +} + +def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") +runServer17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStartServer" + extraArgs.add("nogui") +} + def getManifestAttributes() { def manifestAttributes = [:] if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { @@ -667,11 +949,6 @@ tasks.named("jar", Jar).configure { } if (usesShadowedDependencies.toBoolean()) { - tasks.register('relocateShadowJar', ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" - enabled = minimizeShadowedDependencies.toBoolean() - } tasks.named("shadowJar", ShadowJar).configure { manifest { attributes(getManifestAttributes()) @@ -686,8 +963,9 @@ if (usesShadowedDependencies.toBoolean()) { project.configurations.shadeCompile ] archiveClassifier.set('dev') - if (minimizeShadowedDependencies.toBoolean()) { - dependsOn(relocateShadowJar) + if (relocateShadowedDependencies.toBoolean()) { + relocationPrefix = modGroup + ".shadow" + enableRelocation = true } } configurations.runtimeElements.outgoing.artifacts.clear() @@ -705,7 +983,7 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer"]) { + for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { tasks.named(runTask).configure { dependsOn("shadowJar") } @@ -743,16 +1021,47 @@ idea { module { downloadJavadoc = true downloadSources = true + inheritOutputDirs = true } project { settings { + if (ideaOverrideBuildType != "") { + delegateActions { + if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = true + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE + } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = false + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM + } else { + throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') + } + } + } runConfigurations { + "0. Build and Test"(Gradle) { + taskNames = ["build"] + } "1. Run Client"(Gradle) { taskNames = ["runClient"] } "2. Run Server"(Gradle) { taskNames = ["runServer"] } + "1a. Run Client (Java 17)"(Gradle) { + taskNames = ["runClient17"] + } + "2a. Run Server (Java 17)"(Gradle) { + taskNames = ["runServer17"] + } + "1b. Run Client (Java 17, Hotswap)"(Gradle) { + taskNames = ["runClient17"] + envs = ["HOTSWAP": "true"] + } + "2b. Run Server (Java 17, Hotswap)"(Gradle) { + taskNames = ["runServer17"] + envs = ["HOTSWAP": "true"] + } "3. Run Obfuscated Client"(Gradle) { taskNames = ["runObfClient"] } @@ -770,7 +1079,7 @@ idea { } "Run Client (IJ Native)"(Application) { mainClass = "GradleStart" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runClient.workingDir.absolutePath programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -781,7 +1090,7 @@ idea { } "Run Server (IJ Native)"(Application) { mainClass = "GradleStartServer" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runServer.workingDir.absolutePath programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -793,11 +1102,57 @@ idea { } compiler.javac { afterEvaluate { + javacAdditionalOptions = "-encoding utf8" moduleJavacAdditionalOptions = [ (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') ] } } + withIDEADir { File ideaDir -> + if (!ideaDir.path.contains(".idea")) { + // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory + ideaDir = new File(ideaDir, ".idea") + } + if (ideaDir.isDirectory()) { + def miscFile = new File(ideaDir, "misc.xml") + if (miscFile.isFile()) { + boolean dirty = false + def miscTransformer = new XmlTransformer() + miscTransformer.addAction { root -> + Node rootNode = root.asNode() + def rootManager = rootNode + .component.find { it.@name == 'ProjectRootManager' } + if (!rootManager) { + rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) + dirty = true + } + def output = rootManager.output + if (!output) { + output = rootManager.appendNode('output') + dirty = true + } + if (!output.@url) { + // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. + // This is a sensible default for most setups + output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' + dirty = true + } + } + def result = miscTransformer.transform(miscFile.text) + if (dirty) { + miscFile.write(result) + } + } else { + miscFile.text = """ + + + + + +""" + } + } + } } } } @@ -806,6 +1161,14 @@ tasks.named("processIdeaSettings").configure { dependsOn("injectTags") } +tasks.named("ideVirtualMainClasses").configure { + // Make IntelliJ "Build project" build the mod jars + dependsOn("jar", "reobfJar") + if (!disableSpotless) { + dependsOn("spotlessCheck") + } +} + // workaround variable hiding in pom processing def projectConfigs = project.configurations @@ -824,14 +1187,15 @@ publishing { version = System.getenv("RELEASE_VERSION") ?: identifiedVersion } } - repositories { - maven { - url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" - allowInsecureProtocol = true - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { + maven { + url = mavenPublishUrl + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + } } } } @@ -867,7 +1231,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { } } if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "gtnhmixins") + addModrinthDep("required", "project", "unimixins") } tasks.modrinth.dependsOn(build) tasks.publish.dependsOn(tasks.modrinth) @@ -911,7 +1275,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null } } if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "gtnhmixins") + addCurseForgeRelation("requiredDependency", "unimixins") } tasks.curseforge.dependsOn(build) tasks.publish.dependsOn(tasks.curseforge) @@ -945,10 +1309,21 @@ def addCurseForgeRelation(String type, String name) { } // Updating + +def buildscriptGradleVersion = "8.2.1" + +tasks.named('wrapper', Wrapper).configure { + gradleVersion = buildscriptGradleVersion +} + tasks.register('updateBuildScript') { group = 'GTNH Buildscript' description = 'Updates the build script to the latest version' + if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { + dependsOn('wrapper') + } + doLast { if (performBuildScriptUpdate()) return @@ -961,6 +1336,26 @@ if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISA performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") + if (gradle.gradleVersion != buildscriptGradleVersion) { + out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") + } + } +} + +// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large +tasks.register('faq') { + group = 'GTNH Buildscript' + description = 'Prints frequently asked questions about building a project' + + doLast { + print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + + "Or you can manually check if the versions are still on the distributing sites - " + + "the links can be found in repositories.gradle and build.gradle:repositories, " + + "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + + "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + + "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + + "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + + "Java 9 or later.") } } @@ -1021,8 +1416,14 @@ boolean isNewBuildScriptVersionAvailable() { String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - String availableBuildScriptHash = getVersionHash(availableBuildScript) + String availableBuildScriptHash + try { + String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() + availableBuildScriptHash = getVersionHash(availableBuildScript) + } catch (IOException e) { + logger.warn("Could not check for buildscript update availability: {}", e.message) + return false + } boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash return !isUpToDate @@ -1101,7 +1502,7 @@ static int replaceParams(File file, Map params) { return 0 } -// Dependency Deobfuscation +// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) def deobf(String sourceURL) { try { @@ -1143,11 +1544,7 @@ def deobfMaven(String repoURL, String mavenDep) { } def deobfCurse(String curseDep) { - try { - return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") - } catch (Exception ignored) { - out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") - } + return dependencies.rfg.deobf("curse.maven:$curseDep") } // The method above is to be preferred. Use this method if the filename is not at the end of the URL. @@ -1155,34 +1552,7 @@ def deobf(String sourceURL, String rawFileName) { String bon2Version = "2.5.1" String fileName = URLDecoder.decode(rawFileName, "UTF-8") String cacheDir = "$project.gradle.gradleUserHomeDir/caches" - String bon2Dir = "$cacheDir/forge_gradle/deobf" - String bon2File = "$bon2Dir/BON2-${bon2Version}.jar" String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" - String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar" - - if (file(deobfFile).exists()) { - return files(deobfFile) - } - - String mappingsVer - String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' - if (remoteMappings) { - String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" - String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" - - zipMappings(mappingsZIP, remoteMappings, bon2Dir) - - mappingsVer = "snapshot_$id" - } else { - mappingsVer = "${channel}_$mappingsVersion" - } - - download.run { - src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar" - dest bon2File - quiet true - overwrite false - } download.run { src sourceURL @@ -1190,50 +1560,8 @@ def deobf(String sourceURL, String rawFileName) { quiet true overwrite false } - - exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' - workingDir bon2Dir - standardOutput = new FileOutputStream("${deobfFile}.log") - } - - return files(deobfFile) -} - -def zipMappings(String zipPath, String url, String bon2Dir) { - File zipFile = new File(zipPath) - if (zipFile.exists()) { - return - } - - String fieldsCache = "$bon2Dir/data/fields.csv" - String methodsCache = "$bon2Dir/data/methods.csv" - - download.run { - src "${url}fields.csv" - dest fieldsCache - quiet true - } - download.run { - src "${url}methods.csv" - dest methodsCache - quiet true - } - - zipFile.getParentFile().mkdirs() - ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)) - - zos.putNextEntry(new ZipEntry("fields.csv")) - Files.copy(Paths.get(fieldsCache), zos) - zos.closeEntry() - - zos.putNextEntry(new ZipEntry("methods.csv")) - Files.copy(Paths.get(methodsCache), zos) - zos.closeEntry() - - zos.close() + return dependencies.rfg.deobf(files(obfFile)) } - // Helper methods def checkPropertyExists(String propertyName) { @@ -1260,3 +1588,36 @@ def getSecondaryArtifacts() { if (apiPackage) secondaryArtifacts += [apiJar] return secondaryArtifacts } + +def getURL(String main, String fallback) { + return pingURL(main, 10000) ? main : fallback +} + +// credit: https://stackoverflow.com/a/3584332 +def pingURL(String url, int timeout) { + url = url.replaceFirst("^https", "http") // Otherwise an exception may be thrown on invalid SSL certificates. + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection() + connection.setConnectTimeout(timeout) + connection.setReadTimeout(timeout) + connection.setRequestMethod("HEAD") + int responseCode = connection.getResponseCode() + return 200 <= responseCode && responseCode <= 399 + } catch (IOException ignored) { + return false + } +} + +// For easier scripting of things that require variables defined earlier in the buildscript +if (file('addon.late.gradle.kts').exists()) { + apply from: 'addon.late.gradle.kts' +} else if (file('addon.late.gradle').exists()) { + apply from: 'addon.late.gradle' +} + +// File for local tweaks not commited to Git +if (file('addon.late.local.gradle.kts').exists()) { + apply from: 'addon.late.local.gradle.kts' +} else if (file('addon.late.local.gradle').exists()) { + apply from: 'addon.late.local.gradle' +} diff --git a/dependencies.gradle b/dependencies.gradle index e1450c0..3d93d59 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ // Add your dependencies here dependencies { - api('com.github.GTNewHorizons:CodeChickenLib:1.1.6:dev') + api('com.github.GTNewHorizons:CodeChickenLib:1.1.9:dev') } diff --git a/repositories.gradle b/repositories.gradle index c0d848e..45729e1 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,12 +1,4 @@ // Add any additional repositiroes for your dependencies here repositories { - maven { - name 'GTNH Maven' - url 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/' - allowInsecureProtocol - } - maven { - url 'https://jitpack.io' - } } diff --git a/src/main/java/codechicken/core/CCUpdateChecker.java b/src/main/java/codechicken/core/CCUpdateChecker.java index 61a1bf3..25b67d0 100644 --- a/src/main/java/codechicken/core/CCUpdateChecker.java +++ b/src/main/java/codechicken/core/CCUpdateChecker.java @@ -14,10 +14,9 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.StatCollector; -import codechicken.core.launch.CodeChickenCorePlugin; - import com.google.common.base.Function; +import codechicken.core.launch.CodeChickenCorePlugin; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.versioning.ComparableVersion; import cpw.mods.fml.relauncher.FMLInjectionData; diff --git a/src/main/java/codechicken/core/ClassDiscoverer.java b/src/main/java/codechicken/core/ClassDiscoverer.java index 58056e9..1857997 100644 --- a/src/main/java/codechicken/core/ClassDiscoverer.java +++ b/src/main/java/codechicken/core/ClassDiscoverer.java @@ -13,11 +13,10 @@ import org.objectweb.asm.tree.ClassNode; -import codechicken.core.launch.CodeChickenCorePlugin; -import codechicken.lib.asm.ASMHelper; - import com.google.common.collect.ImmutableList; +import codechicken.core.launch.CodeChickenCorePlugin; +import codechicken.lib.asm.ASMHelper; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.ModClassLoader; diff --git a/src/main/java/codechicken/core/GuiModListScroll.java b/src/main/java/codechicken/core/GuiModListScroll.java index 714a0bf..3c01b4e 100644 --- a/src/main/java/codechicken/core/GuiModListScroll.java +++ b/src/main/java/codechicken/core/GuiModListScroll.java @@ -1,9 +1,24 @@ package codechicken.core; -import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.GL_ALWAYS; +import static org.lwjgl.opengl.GL11.GL_EQUAL; +import static org.lwjgl.opengl.GL11.GL_KEEP; +import static org.lwjgl.opengl.GL11.GL_PACK_ALIGNMENT; +import static org.lwjgl.opengl.GL11.GL_REPLACE; +import static org.lwjgl.opengl.GL11.GL_STENCIL_INDEX; +import static org.lwjgl.opengl.GL11.GL_STENCIL_TEST; +import static org.lwjgl.opengl.GL11.GL_UNPACK_ALIGNMENT; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.GL_ZERO; +import static org.lwjgl.opengl.GL11.glColorMask; +import static org.lwjgl.opengl.GL11.glDisable; +import static org.lwjgl.opengl.GL11.glEnable; +import static org.lwjgl.opengl.GL11.glPixelStorei; import static org.lwjgl.opengl.GL11.glReadPixels; +import static org.lwjgl.opengl.GL11.glStencilFunc; +import static org.lwjgl.opengl.GL11.glStencilOp; -import java.awt.*; +import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; diff --git a/src/main/java/codechicken/core/ServerUtils.java b/src/main/java/codechicken/core/ServerUtils.java index 2d2cf7f..8daf323 100644 --- a/src/main/java/codechicken/core/ServerUtils.java +++ b/src/main/java/codechicken/core/ServerUtils.java @@ -13,10 +13,10 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.IChatComponent; -import codechicken.lib.asm.ObfMapping; - import com.mojang.authlib.GameProfile; +import codechicken.lib.asm.ObfMapping; + public class ServerUtils extends CommonUtils { public static MinecraftServer mc() { diff --git a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java index 6b35f15..8b26c6c 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java @@ -3,10 +3,9 @@ import java.io.IOException; import java.lang.reflect.Field; -import codechicken.lib.asm.ObfMapping; - import com.google.common.collect.ImmutableBiMap; +import codechicken.lib.asm.ObfMapping; import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index ee640f5..2907b25 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -6,17 +6,19 @@ import net.minecraftforge.common.MinecraftForge; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + import codechicken.core.CCUpdateChecker; import codechicken.core.ClientUtils; import codechicken.core.featurehack.LiquidTextures; import codechicken.core.internal.CCCEventHandler; import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.lib.config.ConfigFile; - -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; - -import cpw.mods.fml.common.*; +import cpw.mods.fml.common.DummyModContainer; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.LoadController; +import cpw.mods.fml.common.ModMetadata; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.versioning.ArtifactVersion; diff --git a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java index 6fa12ea..9983017 100644 --- a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java +++ b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java @@ -2,7 +2,11 @@ import java.io.IOException; import java.lang.reflect.Field; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; import net.minecraft.launchwrapper.IClassTransformer; @@ -16,6 +20,9 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + import codechicken.lib.asm.ASMHelper; import codechicken.lib.asm.ASMInit; import codechicken.lib.asm.CC_ClassWriter; @@ -23,10 +30,6 @@ import codechicken.obfuscator.IHeirachyEvaluator; import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry; import codechicken.obfuscator.ObfuscationRun; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; diff --git a/src/main/java/codechicken/core/asm/MethodASMifier.java b/src/main/java/codechicken/core/asm/MethodASMifier.java index 1585b56..6880a18 100644 --- a/src/main/java/codechicken/core/asm/MethodASMifier.java +++ b/src/main/java/codechicken/core/asm/MethodASMifier.java @@ -1,6 +1,6 @@ package codechicken.core.asm; -import static org.objectweb.asm.Opcodes.*; +import static org.objectweb.asm.Opcodes.ASM4; import java.io.File; import java.io.PrintWriter; diff --git a/src/main/java/codechicken/core/asm/TweakTransformer.java b/src/main/java/codechicken/core/asm/TweakTransformer.java index 380ee4d..faa4c3e 100644 --- a/src/main/java/codechicken/core/asm/TweakTransformer.java +++ b/src/main/java/codechicken/core/asm/TweakTransformer.java @@ -1,6 +1,6 @@ package codechicken.core.asm; -import static codechicken.lib.asm.InsnComparator.*; +import static codechicken.lib.asm.InsnComparator.findOnce; import java.util.Map; @@ -11,10 +11,14 @@ import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; -import codechicken.lib.asm.*; +import codechicken.lib.asm.ASMBlock; +import codechicken.lib.asm.ASMInit; +import codechicken.lib.asm.ASMReader; +import codechicken.lib.asm.ModularASMTransformer; import codechicken.lib.asm.ModularASMTransformer.MethodReplacer; import codechicken.lib.asm.ModularASMTransformer.MethodTransformer; import codechicken.lib.asm.ModularASMTransformer.MethodWriter; +import codechicken.lib.asm.ObfMapping; import codechicken.lib.config.ConfigTag; public class TweakTransformer implements IClassTransformer, Opcodes { diff --git a/src/main/java/codechicken/core/gui/GuiScrollPane.java b/src/main/java/codechicken/core/gui/GuiScrollPane.java index ba5f35a..7b77c68 100644 --- a/src/main/java/codechicken/core/gui/GuiScrollPane.java +++ b/src/main/java/codechicken/core/gui/GuiScrollPane.java @@ -1,6 +1,7 @@ package codechicken.core.gui; -import java.awt.*; +import java.awt.Dimension; +import java.awt.Rectangle; import codechicken.lib.math.MathHelper; import codechicken.lib.vec.Rectangle4i; diff --git a/src/main/java/codechicken/core/gui/GuiScrollSlot.java b/src/main/java/codechicken/core/gui/GuiScrollSlot.java index 67c2d9a..8e31626 100644 --- a/src/main/java/codechicken/core/gui/GuiScrollSlot.java +++ b/src/main/java/codechicken/core/gui/GuiScrollSlot.java @@ -1,6 +1,6 @@ package codechicken.core.gui; -import java.awt.*; +import java.awt.Rectangle; import org.lwjgl.input.Keyboard; diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 3247450..2bf2827 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -1,6 +1,7 @@ package codechicken.core.launch; -import java.awt.*; +import java.awt.Desktop; +import java.awt.GraphicsEnvironment; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -20,7 +21,11 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import codechicken.core.asm.*; +import codechicken.core.asm.CodeChickenCoreModContainer; +import codechicken.core.asm.DelegatedTransformer; +import codechicken.core.asm.MCPDeobfuscationTransformer; +import codechicken.core.asm.Tags; +import codechicken.core.asm.TweakTransformer; import codechicken.lib.config.ConfigTag; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.versioning.DefaultArtifactVersion; diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index afae28c..8a728e4 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -1,35 +1,51 @@ package codechicken.core.launch; -import java.awt.*; +import java.awt.Desktop; import java.awt.Dialog.ModalityType; +import java.awt.Dimension; +import java.awt.GraphicsEnvironment; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.io.*; +import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.ByteBuffer; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import javax.swing.*; +import javax.swing.Box; +import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JProgressBar; +import javax.swing.WindowConstants; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import net.minecraft.launchwrapper.LaunchClassLoader; -import sun.misc.URLClassPath; -import sun.net.util.URLUtil; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -40,6 +56,8 @@ import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; +import sun.misc.URLClassPath; +import sun.net.util.URLUtil; /** * For autodownloading stuff. This is really unoriginal, mostly ripped off FML, credits to cpw. diff --git a/src/main/java/codechicken/obfuscator/ConstantObfuscator.java b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java index 3279184..ec44e11 100644 --- a/src/main/java/codechicken/obfuscator/ConstantObfuscator.java +++ b/src/main/java/codechicken/obfuscator/ConstantObfuscator.java @@ -1,6 +1,7 @@ package codechicken.obfuscator; -import static org.objectweb.asm.tree.AbstractInsnNode.*; +import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN; +import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN; import java.util.LinkedList; import java.util.List; diff --git a/src/main/java/codechicken/obfuscator/ObfuscationMap.java b/src/main/java/codechicken/obfuscator/ObfuscationMap.java index 8d79f61..474b911 100644 --- a/src/main/java/codechicken/obfuscator/ObfuscationMap.java +++ b/src/main/java/codechicken/obfuscator/ObfuscationMap.java @@ -7,11 +7,11 @@ import java.util.Map; import java.util.Map.Entry; -import codechicken.lib.asm.ObfMapping; - import com.google.common.base.Function; import com.google.common.collect.ArrayListMultimap; +import codechicken.lib.asm.ObfMapping; + public class ObfuscationMap { public class ObfuscationEntry { From e8dab5710171baa9c9d99d0be1eb96fd0e191c02 Mon Sep 17 00:00:00 2001 From: miozune Date: Fri, 1 Dec 2023 17:56:58 +0900 Subject: [PATCH 184/219] Fix incomplete patch for item id packet (#13) --- src/main/java/codechicken/lib/data/MCDataOutputWrapper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java index 84aee32..baea780 100644 --- a/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java +++ b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java @@ -201,9 +201,9 @@ public MCDataOutputWrapper writeItemStack(ItemStack stack) { public MCDataOutputWrapper writeItemStack(ItemStack stack, boolean large) { if (stack == null) { - writeShort(-1); + writeInt(-1); } else { - writeShort(Item.getIdFromItem(stack.getItem())); + writeInt(Item.getIdFromItem(stack.getItem())); if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); writeShort(stack.getItemDamage()); From 14983449e86dbc38346e73a531d71148da3312fd Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sun, 24 Dec 2023 10:07:13 -0800 Subject: [PATCH 185/219] Angelica Support - Static -> Instanced (#14) Static -> Instanced * Now significantly more thread safe --- build.gradle | 30 +- gradle.properties | 10 +- .../lib/asm/ClassConstantPoolParser.java | 109 ++++++ .../java/codechicken/lib/asm/ObfMapping.java | 8 +- .../lib/asm/RedirectorTransformer.java | 207 +++++++++++ .../java/codechicken/lib/gui/Canvas9Seg.java | 12 +- .../codechicken/lib/lighting/LightMatrix.java | 16 +- .../codechicken/lib/lighting/LightModel.java | 12 +- .../lib/lighting/PlanarLightMatrix.java | 10 +- .../lib/lighting/PlanarLightModel.java | 12 +- .../lib/lighting/SimpleBrightnessModel.java | 12 +- .../codechicken/lib/render/BlockRenderer.java | 40 ++- .../java/codechicken/lib/render/CCModel.java | 35 +- .../lib/render/CCRenderPipeline.java | 53 ++- .../codechicken/lib/render/CCRenderState.java | 322 ++++++++++++------ .../lib/render/ColourMultiplier.java | 14 +- .../codechicken/lib/render/RenderUtils.java | 42 ++- .../lib/render/uv/UVTransformation.java | 6 +- .../java/codechicken/lib/vec/BlockCoord.java | 18 +- .../codechicken/lib/vec/Transformation.java | 10 +- 20 files changed, 742 insertions(+), 236 deletions(-) create mode 100644 src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java create mode 100644 src/main/java/codechicken/lib/asm/RedirectorTransformer.java diff --git a/build.gradle b/build.gradle index 4e31dc8..bdbaeb9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1700844281 +//version: 1702141377 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -28,27 +28,12 @@ import java.util.concurrent.TimeUnit buildscript { repositories { - mavenCentral() - - maven { - name 'forge' - url 'https://maven.minecraftforge.net' - } maven { // GTNH RetroFuturaGradle and ASM Fork name "GTNH Maven" url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - maven { - name 'sonatype' - url 'https://oss.sonatype.org/content/repositories/snapshots/' - } - maven { - name 'Scala CI dependencies' - url 'https://repo1.maven.org/maven2/' - } - mavenLocal() } } @@ -69,7 +54,7 @@ plugins { id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.26' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -628,7 +613,7 @@ repositories { } maven { name = "ic2" - url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + url = getURL("https://maven2.ic2.player.to/", "https://maven.ic2.player.to/") content { includeGroup "net.industrial-craft" } @@ -687,6 +672,8 @@ configurations.all { substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + + substitute module('org.scala-lang:scala-library:2.11.1') using module('org.scala-lang:scala-library:2.11.5') because('To allow mixing with Java 8 targets') } } @@ -793,12 +780,12 @@ ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies" } dependencies { - def lwjgl3ifyVersion = '1.5.1' + def lwjgl3ifyVersion = '1.5.7' if (modId != 'lwjgl3ify') { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.17') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35') } java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} @@ -1310,7 +1297,7 @@ def addCurseForgeRelation(String type, String name) { // Updating -def buildscriptGradleVersion = "8.2.1" +def buildscriptGradleVersion = "8.5" tasks.named('wrapper', Wrapper).configure { gradleVersion = buildscriptGradleVersion @@ -1621,3 +1608,4 @@ if (file('addon.late.local.gradle.kts').exists()) { } else if (file('addon.late.local.gradle').exists()) { apply from: 'addon.late.local.gradle' } + diff --git a/gradle.properties b/gradle.properties index 1c509df..24279a2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,15 @@ forgeVersion = 10.13.4.1614 # Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty developmentEnvironmentUserName = Developer +# Enables using modern java syntax (up to version 17) via Jabel, while still targetting JVM 8. +# See https://github.com/bsideup/jabel for details on how this works. +enableModernJavaSyntax = true + +# Enables injecting missing generics into the decompiled source code for a better coding experience +# Turns most publically visible List, Map, etc. into proper List, Map types +enableGenericInjection = true + + # Define a source file of your project with: # public static final String VERSION = "GRADLETOKEN_VERSION"; # The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's @@ -87,4 +96,3 @@ modrinthProjectId = codechickenlib-unofficial # and the name is the Modrinth project or version slug/id of the other mod. # modrinthRelations = - diff --git a/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java b/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java new file mode 100644 index 0000000..299e185 --- /dev/null +++ b/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java @@ -0,0 +1,109 @@ +package codechicken.lib.asm; + +/*** + * This Class is derived from the ASM ClassReader + *

+ * ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA, France Telecom All + * rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or other materials provided with the + * distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.charset.StandardCharsets; + +import org.objectweb.asm.Opcodes; + +/** + * Using this class to search for a (single) String reference is > 40 times faster than parsing a class with a + * ClassReader + ClassNode while using way less RAM + */ +public class ClassConstantPoolParser { + + private static final int UTF8 = 1; + private static final int INT = 3; + private static final int FLOAT = 4; + private static final int LONG = 5; + private static final int DOUBLE = 6; + private static final int FIELD = 9; + private static final int METH = 10; + private static final int IMETH = 11; + private static final int NAME_TYPE = 12; + private static final int HANDLE = 15; + private static final int INDY = 18; + + private final byte[][] BYTES_TO_SEARCH; + + public ClassConstantPoolParser(String... strings) { + BYTES_TO_SEARCH = new byte[strings.length][]; + for (int i = 0; i < BYTES_TO_SEARCH.length; i++) { + BYTES_TO_SEARCH[i] = strings[i].getBytes(StandardCharsets.UTF_8); + } + } + + /** + * Returns true if the constant pool of the class represented by this byte array contains one of the Strings we are + * looking for + */ + public boolean find(byte[] basicClass) { + if (basicClass == null || basicClass.length == 0) { + return false; + } + // checks the class version + if (readShort(6, basicClass) > Opcodes.V1_8) { + return false; + } + // parses the constant pool + int n = readUnsignedShort(8, basicClass); + int index = 10; + for (int i = 1; i < n; ++i) { + int size; + switch (basicClass[index]) { + case FIELD, METH, IMETH, INT, FLOAT, NAME_TYPE, INDY -> size = 5; + case LONG, DOUBLE -> { + size = 9; + ++i; + } + case UTF8 -> { + final int strLen = readUnsignedShort(index + 1, basicClass); + size = 3 + strLen; + label: for (byte[] bytes : BYTES_TO_SEARCH) { + if (strLen == bytes.length) { + for (int j = index + 3; j < index + 3 + strLen; j++) { + if (basicClass[j] != bytes[j - (index + 3)]) { + break label; + } + } + return true; + } + } + } + case HANDLE -> size = 4; + default -> size = 3; + } + index += size; + } + return false; + } + + private static short readShort(final int index, byte[] basicClass) { + return (short) (((basicClass[index] & 0xFF) << 8) | (basicClass[index + 1] & 0xFF)); + } + + private static int readUnsignedShort(final int index, byte[] basicClass) { + return ((basicClass[index] & 0xFF) << 8) | (basicClass[index + 1] & 0xFF); + } + +} diff --git a/src/main/java/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java index f8ccb92..27ca913 100644 --- a/src/main/java/codechicken/lib/asm/ObfMapping.java +++ b/src/main/java/codechicken/lib/asm/ObfMapping.java @@ -36,8 +36,8 @@ public class ObfMapping { public static class ObfRemapper extends Remapper { - private HashMap fields = new HashMap(); - private HashMap funcs = new HashMap(); + private final HashMap fields = new HashMap<>(); + private final HashMap funcs = new HashMap<>(); public ObfRemapper() { try { @@ -174,8 +174,8 @@ public static File[] parseConfDir(File confDir) { return new File[] { srgs, methods, fields }; } - private HashMap fields = new HashMap(); - private HashMap funcs = new HashMap(); + private final HashMap fields = new HashMap<>(); + private final HashMap funcs = new HashMap<>(); public MCPRemapper() { File[] mappings = getConfFiles(); diff --git a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java new file mode 100644 index 0000000..0d9d107 --- /dev/null +++ b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java @@ -0,0 +1,207 @@ +package codechicken.lib.asm; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.launchwrapper.Launch; + +import org.apache.commons.io.FileUtils; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.util.ASMifier; +import org.objectweb.asm.util.Textifier; +import org.objectweb.asm.util.TraceClassVisitor; + +public class RedirectorTransformer implements IClassTransformer { + + private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("ccl.dumpClass", "false")); + private static final String RenderStateClass = "codechicken/lib/render/CCRenderState"; + private static final Set redirectedFields = new HashSet<>(); + private static final Set redirectedSimpleMethods = new HashSet<>(); + private static final Set redirectedMethods = new HashSet<>(); + private static final ClassConstantPoolParser cstPoolParser; + + static { + Collections.addAll( + redirectedFields, + "pipeline", + "model", + "firstVertexIndex", + "lastVertexIndex", + "vertexIndex", + "baseColour", + "alphaOverride", + "useNormals", + "computeLighting", + "useColour", + "lightMatrix", + "vert", + "hasNormal", + "normal", + "hasColour", + "colour", + "hasBrightness", + "brightness", + "side", + "lc" + + ); + Collections.addAll(redirectedSimpleMethods, "reset", "pullLightmap", "pushLightmap", "setDynamic", "draw"); + Collections.addAll( + redirectedMethods, + "setPipeline", + "bindModel", + "setModel", + "setVertexRange", + "render", + "runPipeline", + "writeVert", + "setNormal", + "setColour", + "setBrightness", + "startDrawing"); + + cstPoolParser = new ClassConstantPoolParser(RenderStateClass); + } + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (!cstPoolParser.find(basicClass)) { + return basicClass; + } + + final ClassReader cr = new ClassReader(basicClass); + final ClassNode cn = new ClassNode(); + cr.accept(cn, 0); + boolean changed = false; + + for (MethodNode mn : cn.methods) { + for (AbstractInsnNode node : mn.instructions.toArray()) { + if (node instanceof FieldInsnNode fNode) { + if (node.getOpcode() == Opcodes.GETSTATIC && redirectedFields.contains(fNode.name) + && fNode.owner.equals(RenderStateClass)) { + mn.instructions.insertBefore( + fNode, + new MethodInsnNode( + Opcodes.INVOKESTATIC, + fNode.owner, + "instance", + "()Lcodechicken/lib/render/CCRenderState;")); + fNode.setOpcode(Opcodes.GETFIELD); + changed = true; + } else if (node.getOpcode() == Opcodes.PUTSTATIC + && (redirectedFields.contains(fNode.name) && fNode.owner.equals(RenderStateClass))) { + InsnList beforePut = new InsnList(); + beforePut.add( + new MethodInsnNode( + Opcodes.INVOKESTATIC, + fNode.owner, + "instance", + "()Lcodechicken/lib/render/CCRenderState;")); + beforePut.add(new InsnNode(Opcodes.SWAP)); + mn.instructions.insertBefore(fNode, beforePut); + fNode.setOpcode(Opcodes.PUTFIELD); + changed = true; + + } + } else if (node.getOpcode() == Opcodes.INVOKESTATIC && node instanceof MethodInsnNode mNode) { + if (redirectedMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) { + mNode.name = mNode.name + "Static"; + changed = true; + } else if (redirectedSimpleMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) { + mn.instructions.insertBefore( + mNode, + new MethodInsnNode( + Opcodes.INVOKESTATIC, + mNode.owner, + "instance", + "()Lcodechicken/lib/render/CCRenderState;")); + mNode.setOpcode(Opcodes.INVOKEVIRTUAL); + changed = true; + } + } + } + } + + if (changed) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cn.accept(cw); + final byte[] bytes = cw.toByteArray(); + if (DUMP_CLASSES) { + saveTransformedClass(bytes, transformedName); + saveTransformedClass(basicClass, transformedName + "_original"); + } + return bytes; + } + return basicClass; + } + + private File outputDir = null; + + private void saveTransformedClass(final byte[] data, final String transformedName) { + if (!DUMP_CLASSES) { + return; + } + + if (outputDir == null) { + outputDir = new File(Launch.minecraftHome, "ASM_REDIRECTOR"); + try { + FileUtils.deleteDirectory(outputDir); + } catch (IOException ignored) {} + if (!outputDir.exists()) { + // noinspection ResultOfMethodCallIgnored + outputDir.mkdirs(); + } + } + + final String fileName = transformedName.replace('.', File.separatorChar); + final File classFile = new File(outputDir, fileName + ".class"); + final File bytecodeFile = new File(outputDir, fileName + "_BYTE.txt"); + final File asmifiedFile = new File(outputDir, fileName + "_ASM.txt"); + final File outDir = classFile.getParentFile(); + if (!outDir.exists()) { + outDir.mkdirs(); + } + if (classFile.exists()) { + classFile.delete(); + } + try (final OutputStream output = Files.newOutputStream(classFile.toPath())) { + output.write(data); + } catch (IOException e) { + e.printStackTrace(); + } + if (bytecodeFile.exists()) { + bytecodeFile.delete(); + } + try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) { + final ClassReader classReader = new ClassReader(data); + classReader.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(output)), 0); + } catch (IOException e) { + e.printStackTrace(); + } + if (asmifiedFile.exists()) { + asmifiedFile.delete(); + } + try (final OutputStream output = Files.newOutputStream(asmifiedFile.toPath())) { + final ClassReader classReader = new ClassReader(data); + classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(output)), 0); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/codechicken/lib/gui/Canvas9Seg.java b/src/main/java/codechicken/lib/gui/Canvas9Seg.java index 4c16368..15b3f22 100644 --- a/src/main/java/codechicken/lib/gui/Canvas9Seg.java +++ b/src/main/java/codechicken/lib/gui/Canvas9Seg.java @@ -62,16 +62,20 @@ private void drawSeg(int[] sw, int[] sh, int seg) { t.addVertexWithUV(sw[u + 1], sh[v], 0, seg_u[u + 1], seg_v[v]); } - public void draw(int x, int y, int w, int h) { + public void draw(CCRenderState state, int x, int y, int w, int h) { CCRenderState.changeTexture(tex); - CCRenderState.reset(); - CCRenderState.startDrawing(); + state.reset(); + state.startDrawing(); int[] sw = new int[] { x, x + seg_w[0], x + w - seg_w[2], x + w }; int[] sh = new int[] { y, y + seg_h[0], y + h - seg_h[2], y + h }; for (int seg = 0; seg < 9; seg++) drawSeg(sw, sh, seg); - CCRenderState.draw(); + state.draw(); + } + + public void draw(int x, int y, int w, int h) { + draw(CCRenderState.instance(), x, y, w, h); } } diff --git a/src/main/java/codechicken/lib/lighting/LightMatrix.java b/src/main/java/codechicken/lib/lighting/LightMatrix.java index 59f2e7a..d6fe986 100644 --- a/src/main/java/codechicken/lib/lighting/LightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/LightMatrix.java @@ -114,22 +114,22 @@ public static int interpBrightness(int a, int b, int c, int d) { } @Override - public boolean load() { - if (!CCRenderState.computeLighting) return false; + public boolean load(CCRenderState state) { + if (!state.computeLighting) return false; - CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); - CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); + state.pipeline.addDependency(state.colourAttrib); + state.pipeline.addDependency(state.lightCoordAttrib); return true; } @Override - public void operate() { - LC lc = CCRenderState.lc; + public void operate(CCRenderState state) { + LC lc = state.lc; float[] a = ao(lc.side); float f = (a[0] * lc.fa + a[1] * lc.fb + a[2] * lc.fc + a[3] * lc.fd); int[] b = brightness(lc.side); - CCRenderState.setColour(ColourRGBA.multiplyC(CCRenderState.colour, f)); - CCRenderState.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); + state.setColour(ColourRGBA.multiplyC(state.colour, f)); + state.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); } @Override diff --git a/src/main/java/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java index 6134fe1..8766737 100644 --- a/src/main/java/codechicken/lib/lighting/LightModel.java +++ b/src/main/java/codechicken/lib/lighting/LightModel.java @@ -78,17 +78,17 @@ public int apply(int colour, Vector3 normal) { } @Override - public boolean load() { - if (!CCRenderState.computeLighting) return false; + public boolean load(CCRenderState state) { + if (!state.computeLighting) return false; - CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); - CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + state.pipeline.addDependency(CCRenderState.normalAttrib); + state.pipeline.addDependency(CCRenderState.colourAttrib); return true; } @Override - public void operate() { - CCRenderState.setColour(apply(CCRenderState.colour, CCRenderState.normal)); + public void operate(CCRenderState state) { + state.setColour(apply(state.colour, state.normal)); } @Override diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java index cbbcb17..798d382 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java @@ -39,15 +39,15 @@ public int brightness(int side) { } @Override - public boolean load() { - CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + public boolean load(CCRenderState state) { + state.pipeline.addDependency(CCRenderState.sideAttrib); return true; } @Override - public void operate() { - super.operate(); - CCRenderState.setBrightness(brightness(CCRenderState.side)); + public void operate(CCRenderState state) { + super.operate(state); + state.setBrightness(brightness(state.side)); } @Override diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java index f745373..280d962 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java @@ -17,17 +17,17 @@ public PlanarLightModel(int[] colours) { } @Override - public boolean load() { - if (!CCRenderState.computeLighting) return false; + public boolean load(CCRenderState state) { + if (!state.computeLighting) return false; - CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); - CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + state.pipeline.addDependency(CCRenderState.sideAttrib); + state.pipeline.addDependency(CCRenderState.colourAttrib); return true; } @Override - public void operate() { - CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colours[CCRenderState.side])); + public void operate(CCRenderState state) { + state.setColour(ColourRGBA.multiply(state.colour, colours[state.side])); } @Override diff --git a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java index 7158594..c557993 100644 --- a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java +++ b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java @@ -18,8 +18,8 @@ public class SimpleBrightnessModel implements CCRenderState.IVertexOperation { public BlockCoord pos = new BlockCoord(); private int sampled = 0; - private int[] samples = new int[6]; - private BlockCoord c = new BlockCoord(); + private final int[] samples = new int[6]; + private final BlockCoord c = new BlockCoord(); public void locate(IBlockAccess a, int x, int y, int z) { access = a; @@ -39,14 +39,14 @@ public int sample(int side) { } @Override - public boolean load() { - CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + public boolean load(CCRenderState state) { + state.pipeline.addDependency(CCRenderState.sideAttrib); return true; } @Override - public void operate() { - CCRenderState.setBrightness(sample(CCRenderState.side)); + public void operate(CCRenderState state) { + state.setBrightness(sample(state.side)); } @Override diff --git a/src/main/java/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java index 3c2ef39..09f7a8b 100644 --- a/src/main/java/codechicken/lib/render/BlockRenderer.java +++ b/src/main/java/codechicken/lib/render/BlockRenderer.java @@ -29,8 +29,8 @@ public boolean hasAttribute(CCRenderState.VertexAttribute attr) { } @Override - public void prepareVertex() { - CCRenderState.side = side; + public void prepareVertex(CCRenderState state) { + state.side = side; } public BlockFace computeLightCoords() { @@ -145,16 +145,21 @@ public boolean hasAttribute(VertexAttribute attr) { } @Override - public void prepareVertex() { - CCRenderState.side = CCRenderState.vertexIndex >> 2; + public void prepareVertex(CCRenderState state) { + state.side = state.vertexIndex >> 2; } } public static FullBlock fullBlock = new FullBlock(); + // public static void renderFullBlock(int sideMask) { + public static void renderFullBlock(CCRenderState state, int sideMask) { + state.setModel(fullBlock); + renderFaces(state, sideMask); + } + public static void renderFullBlock(int sideMask) { - CCRenderState.setModel(fullBlock); - renderFaces(sideMask); + renderFullBlock(CCRenderState.instance(), sideMask); } /** @@ -162,15 +167,20 @@ public static void renderFullBlock(int sideMask) { * * @param sideMask A mask of faces not to render */ - public static void renderFaces(int sideMask) { + // public static void renderFaces(int sideMask) { + public static void renderFaces(CCRenderState state, int sideMask) { if (sideMask == 0x3F) return; for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) { - CCRenderState.setVertexRange(s * 4, (s + 1) * 4); - CCRenderState.render(); + state.setVertexRange(s * 4, (s + 1) * 4); + state.render(); } } - private static BlockFace face = new BlockFace(); + public static void renderFaces(int sideMask) { + renderFaces(CCRenderState.instance(), sideMask); + } + + private static final BlockFace face = new BlockFace(); /** * Renders faces of a cuboid with texture coordinates mapped to match a standard minecraft block @@ -178,13 +188,17 @@ public static void renderFaces(int sideMask) { * @param bounds The bounding cuboid to render * @param sideMask A mask of faces not to render */ - public static void renderCuboid(Cuboid6 bounds, int sideMask) { + public static void renderCuboid(CCRenderState state, Cuboid6 bounds, int sideMask) { if (sideMask == 0x3F) return; - CCRenderState.setModel(face); + state.setModel(face); for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) { face.loadCuboidFace(bounds, s); - CCRenderState.render(); + state.render(); } } + + public static void renderCuboid(Cuboid6 bounds, int sideMask) { + renderCuboid(CCRenderState.instance(), bounds, sideMask); + } } diff --git a/src/main/java/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java index 649045c..b9a5e4b 100644 --- a/src/main/java/codechicken/lib/render/CCModel.java +++ b/src/main/java/codechicken/lib/render/CCModel.java @@ -32,6 +32,7 @@ import codechicken.lib.vec.TransformationList; import codechicken.lib.vec.Vector3; +@SuppressWarnings("ForLoopReplaceableByForEach") public class CCModel implements CCRenderState.IVertexSource, Copyable { private static class PositionNormalEntry { @@ -88,7 +89,7 @@ public boolean hasAttribute(CCRenderState.VertexAttribute attrib) { } @Override - public void prepareVertex() {} + public void prepareVertex(CCRenderState state) {} public T getOrAllocate(CCRenderState.VertexAttribute attrib) { T array = getAttributes(attrib); @@ -426,20 +427,36 @@ public CCModel expand(int extraVerts) { return this; } + public void render(CCRenderState state, double x, double y, double z, double u, double v) { + render(state, new Vector3(x, y, z).translation(), new UVTranslation(u, v)); + } + public void render(double x, double y, double z, double u, double v) { - render(new Vector3(x, y, z).translation(), new UVTranslation(u, v)); + render(CCRenderState.instance(), new Vector3(x, y, z).translation(), new UVTranslation(u, v)); + } + + public void render(CCRenderState state, double x, double y, double z, UVTransformation u) { + render(state, new Vector3(x, y, z).translation(), u); } public void render(double x, double y, double z, UVTransformation u) { - render(new Vector3(x, y, z).translation(), u); + render(CCRenderState.instance(), new Vector3(x, y, z).translation(), u); + } + + public void render(CCRenderState state, Transformation t, double u, double v) { + render(state, t, new UVTranslation(u, v)); } public void render(Transformation t, double u, double v) { - render(t, new UVTranslation(u, v)); + render(CCRenderState.instance(), t, new UVTranslation(u, v)); + } + + public void render(CCRenderState state, CCRenderState.IVertexOperation... ops) { + render(state, 0, verts.length, ops); } public void render(CCRenderState.IVertexOperation... ops) { - render(0, verts.length, ops); + render(CCRenderState.instance(), 0, verts.length, ops); } /** @@ -449,9 +466,13 @@ public void render(CCRenderState.IVertexOperation... ops) { * @param end The vertex index to render until * @param ops Operations to apply */ + public void render(CCRenderState state, int start, int end, CCRenderState.IVertexOperation... ops) { + state.setPipeline(this, start, end, ops); + state.render(); + } + public void render(int start, int end, CCRenderState.IVertexOperation... ops) { - CCRenderState.setPipeline(this, start, end, ops); - CCRenderState.render(); + render(CCRenderState.instance(), start, end, ops); } public static CCModel quadModel(int numVerts) { diff --git a/src/main/java/codechicken/lib/render/CCRenderPipeline.java b/src/main/java/codechicken/lib/render/CCRenderPipeline.java index 5e7113d..9d9d521 100644 --- a/src/main/java/codechicken/lib/render/CCRenderPipeline.java +++ b/src/main/java/codechicken/lib/render/CCRenderPipeline.java @@ -1,21 +1,45 @@ package codechicken.lib.render; import java.util.ArrayList; +import java.util.Collections; import codechicken.lib.render.CCRenderState.IVertexOperation; import codechicken.lib.render.CCRenderState.VertexAttribute; +@SuppressWarnings("ForLoopReplaceableByForEach") public class CCRenderPipeline { + private final CCRenderState renderState; + private final PipelineBuilder builder; + + public CCRenderPipeline(CCRenderState renderState) { + this.renderState = renderState; + builder = new PipelineBuilder(renderState); + } + + public CCRenderPipeline() { + this(CCRenderState.instance()); + } + public class PipelineBuilder { + private final CCRenderState renderState; + + public PipelineBuilder(CCRenderState renderState) { + this.renderState = renderState; + } + + public PipelineBuilder() { + this(CCRenderState.instance()); + } + public PipelineBuilder add(IVertexOperation op) { ops.add(op); return this; } public PipelineBuilder add(IVertexOperation... ops) { - for (int i = 0; i < ops.length; i++) CCRenderPipeline.this.ops.add(ops[i]); + Collections.addAll(CCRenderPipeline.this.ops, ops); return this; } @@ -25,13 +49,13 @@ public void build() { public void render() { rebuild(); - CCRenderState.render(); + renderState.render(); } } private class PipelineNode { - public ArrayList deps = new ArrayList(); + public ArrayList deps = new ArrayList<>(); public IVertexOperation op; public void add() { @@ -44,12 +68,11 @@ public void add() { } } - private ArrayList attribs = new ArrayList(); - private ArrayList ops = new ArrayList(); - private ArrayList nodes = new ArrayList(); - private ArrayList sorted = new ArrayList(); + private final ArrayList attribs = new ArrayList<>(); + private final ArrayList ops = new ArrayList<>(); + private final ArrayList nodes = new ArrayList<>(); + private final ArrayList sorted = new ArrayList<>(); private PipelineNode loading; - private PipelineBuilder builder = new PipelineBuilder(); public void setPipeline(IVertexOperation... ops) { this.ops.clear(); @@ -69,20 +92,20 @@ private void unbuild() { } public void rebuild() { - if (ops.isEmpty() || CCRenderState.model == null) return; + if (ops.isEmpty() || this.renderState.model == null) return; // ensure enough nodes for all ops - while (nodes.size() < CCRenderState.operationCount()) nodes.add(new PipelineNode()); + while (nodes.size() < this.renderState.operationCount()) nodes.add(new PipelineNode()); unbuild(); - if (CCRenderState.useNormals) addAttribute(CCRenderState.normalAttrib); - if (CCRenderState.useColour) addAttribute(CCRenderState.colourAttrib); - if (CCRenderState.computeLighting) addAttribute(CCRenderState.lightingAttrib); + if (this.renderState.useNormals) addAttribute(this.renderState.normalAttrib); + if (this.renderState.useColour) addAttribute(this.renderState.colourAttrib); + if (this.renderState.computeLighting) addAttribute(this.renderState.lightingAttrib); for (int i = 0; i < ops.size(); i++) { IVertexOperation op = ops.get(i); loading = nodes.get(op.operationID()); - boolean loaded = op.load(); + boolean loaded = op.load(renderState); if (loaded) loading.op = op; if (op instanceof VertexAttribute) if (loaded) attribs.add((VertexAttribute) op); @@ -109,7 +132,7 @@ public void addAttribute(VertexAttribute attrib) { } public void operate() { - for (int i = 0; i < sorted.size(); i++) sorted.get(i).operate(); + for (int i = 0; i < sorted.size(); i++) sorted.get(i).operate(renderState); } public PipelineBuilder builder() { diff --git a/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java index 9f110e3..39655f0 100644 --- a/src/main/java/codechicken/lib/render/CCRenderState.java +++ b/src/main/java/codechicken/lib/render/CCRenderState.java @@ -17,11 +17,27 @@ import codechicken.lib.vec.Vector3; /** - * The core of the CodeChickenLib render system. Rendering operations are written to avoid object allocations by reusing - * static variables. + * The core of the CodeChickenLib render system. Where possible assign a local var of CCRenderState to avoid millions of + * calls to instance(); Uses a ThreadLocal system to assign each thread their own CCRenderState so we can use it in + * Multithreaded chunk batching. + *

+ * Backported from CCL - 1.16.x */ + public class CCRenderState { + public final CCRenderPipeline pipeline; + + private static final ThreadLocal instances = ThreadLocal.withInitial(CCRenderState::new); + + private CCRenderState() { + pipeline = new CCRenderPipeline(this); + } + + public static CCRenderState instance() { + return instances.get(); + } + private static int nextOperationIndex; public static int registerOperation() { @@ -35,28 +51,43 @@ public static int operationCount() { /** * Represents an operation to be run for each vertex that operates on and modifies the current state */ - public static interface IVertexOperation { + public interface IVertexOperation { /** * Load any required references and add dependencies to the pipeline based on the current model (may be null) * Return false if this operation is redundant in the pipeline with the given model */ - public boolean load(); + default boolean load() { + // Existing code will will override this method so it shouldn't infinite loop + // Default it only for new state aware code + return load(CCRenderState.instance()); + } + + default boolean load(CCRenderState state) { + // New code will override this and not inplement load() so we shouldn't infinite loop + return load(); + } /** * Perform the operation on the current render state */ - public void operate(); + default void operate() { + operate(CCRenderState.instance()); + } + + default void operate(CCRenderState state) { + operate(); + } /** * Get the unique id representing this type of operation. Duplicate operation IDs within the pipeline may have * unexpected results. ID shoulld be obtained from CCRenderState.registerOperation() and stored in a static * variable */ - public int operationID(); + int operationID(); } - private static ArrayList> vertexAttributes = new ArrayList>(); + private static ArrayList> vertexAttributes = new ArrayList<>(); private static int registerVertexAttribute(VertexAttribute attr) { vertexAttributes.add(attr); @@ -109,9 +140,9 @@ public static T copyOf(VertexAttribute attr, T src, int length) { return dst; } - public static interface IVertexSource { + public interface IVertexSource { - public Vertex5[] getVertices(); + Vertex5[] getVertices(); /** * Gets an array of vertex attrutes @@ -120,21 +151,25 @@ public static interface IVertexSource { * @param The attrute array type * @return An array, or null if not computed */ - public T getAttributes(VertexAttribute attr); + T getAttributes(VertexAttribute attr); /** * @return True if the specified attrute is provided by this model, either by returning an array from * getAttributes or by setting the state in prepareVertex */ - public boolean hasAttribute(VertexAttribute attr); + boolean hasAttribute(VertexAttribute attr); /** * Callback to set CCRenderState for a vertex before the pipeline runs */ - public void prepareVertex(); + void prepareVertex(CCRenderState state); + + default void prepareVertex() { + prepareVertex(CCRenderState.instance()); + } } - public static VertexAttribute normalAttrib = new VertexAttribute() { + public static VertexAttribute normalAttrib = new VertexAttribute<>() { private Vector3[] normalRef; @@ -144,12 +179,12 @@ public Vector3[] newArray(int length) { } @Override - public boolean load() { - normalRef = model.getAttributes(this); - if (model.hasAttribute(this)) return normalRef != null; + public boolean load(CCRenderState state) { + normalRef = state.model.getAttributes(this); + if (state.model.hasAttribute(this)) return normalRef != null; - if (model.hasAttribute(sideAttrib)) { - pipeline.addDependency(sideAttrib); + if (state.model.hasAttribute(sideAttrib)) { + state.pipeline.addDependency(sideAttrib); return true; } throw new IllegalStateException( @@ -157,12 +192,12 @@ public boolean load() { } @Override - public void operate() { - if (normalRef != null) setNormal(normalRef[vertexIndex]); - else setNormal(Rotation.axes[side]); + public void operate(CCRenderState state) { + if (normalRef != null) state.setNormal(normalRef[state.vertexIndex]); + else state.setNormal(Rotation.axes[state.side]); } }; - public static VertexAttribute colourAttrib = new VertexAttribute() { + public static VertexAttribute colourAttrib = new VertexAttribute<>() { private int[] colourRef; @@ -172,18 +207,18 @@ public int[] newArray(int length) { } @Override - public boolean load() { - colourRef = model.getAttributes(this); - return colourRef != null || !model.hasAttribute(this); + public boolean load(CCRenderState state) { + colourRef = state.model.getAttributes(this); + return colourRef != null || !state.model.hasAttribute(this); } @Override - public void operate() { - if (colourRef != null) setColour(ColourRGBA.multiply(baseColour, colourRef[vertexIndex])); - else setColour(baseColour); + public void operate(CCRenderState state) { + if (colourRef != null) state.setColour(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex])); + else state.setColour(state.baseColour); } }; - public static VertexAttribute lightingAttrib = new VertexAttribute() { + public static VertexAttribute lightingAttrib = new VertexAttribute<>() { private int[] colourRef; @@ -193,23 +228,23 @@ public int[] newArray(int length) { } @Override - public boolean load() { - if (!computeLighting || !useColour || !model.hasAttribute(this)) return false; + public boolean load(CCRenderState state) { + if (!state.computeLighting || !state.useColour || !state.model.hasAttribute(this)) return false; - colourRef = model.getAttributes(this); + colourRef = state.model.getAttributes(this); if (colourRef != null) { - pipeline.addDependency(colourAttrib); + state.pipeline.addDependency(colourAttrib); return true; } return false; } @Override - public void operate() { - setColour(ColourRGBA.multiply(colour, colourRef[vertexIndex])); + public void operate(CCRenderState state) { + state.setColour(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex])); } }; - public static VertexAttribute sideAttrib = new VertexAttribute() { + public static VertexAttribute sideAttrib = new VertexAttribute<>() { private int[] sideRef; @@ -219,28 +254,28 @@ public int[] newArray(int length) { } @Override - public boolean load() { - sideRef = model.getAttributes(this); - if (model.hasAttribute(this)) return sideRef != null; + public boolean load(CCRenderState state) { + sideRef = state.model.getAttributes(this); + if (state.model.hasAttribute(this)) return sideRef != null; - pipeline.addDependency(normalAttrib); + state.pipeline.addDependency(normalAttrib); return true; } @Override - public void operate() { - if (sideRef != null) side = sideRef[vertexIndex]; - else side = CCModel.findSide(normal); + public void operate(CCRenderState state) { + if (sideRef != null) state.side = sideRef[state.vertexIndex]; + else state.side = CCModel.findSide(state.normal); } }; /** * Uses the position of the lightmatrix to compute LC if not provided */ - public static VertexAttribute lightCoordAttrib = new VertexAttribute() { + public static VertexAttribute lightCoordAttrib = new VertexAttribute<>() { private LC[] lcRef; - private Vector3 vec = new Vector3(); // for computation - private Vector3 pos = new Vector3(); + private final Vector3 vec = new Vector3(); // for computation + private final Vector3 pos = new Vector3(); @Override public LC[] newArray(int length) { @@ -248,52 +283,54 @@ public LC[] newArray(int length) { } @Override - public boolean load() { - lcRef = model.getAttributes(this); - if (model.hasAttribute(this)) return lcRef != null; + public boolean load(CCRenderState state) { + lcRef = state.model.getAttributes(this); + if (state.model.hasAttribute(this)) return lcRef != null; - pos.set(lightMatrix.pos.x, lightMatrix.pos.y, lightMatrix.pos.z); - pipeline.addDependency(sideAttrib); - pipeline.addRequirement(Transformation.operationIndex); + pos.set(state.lightMatrix.pos.x, state.lightMatrix.pos.y, state.lightMatrix.pos.z); + state.pipeline.addDependency(sideAttrib); + state.pipeline.addRequirement(Transformation.operationIndex); return true; } @Override - public void operate() { - if (lcRef != null) lc.set(lcRef[vertexIndex]); - else lc.compute(vec.set(vert.vec).sub(pos), side); + public void operate(CCRenderState state) { + if (lcRef != null) state.lc.set(lcRef[state.vertexIndex]); + else state.lc.compute(vec.set(state.vert.vec).sub(pos), state.side); } }; // pipeline state - public static IVertexSource model; - public static int firstVertexIndex; - public static int lastVertexIndex; - public static int vertexIndex; - public static CCRenderPipeline pipeline = new CCRenderPipeline(); + public IVertexSource model; + + public int firstVertexIndex; + public int lastVertexIndex; + public int vertexIndex; // context - public static int baseColour; - public static int alphaOverride; - public static boolean useNormals; - public static boolean computeLighting; - public static boolean useColour; - public static LightMatrix lightMatrix = new LightMatrix(); + public int baseColour; + public int alphaOverride; + public boolean useNormals; + public boolean computeLighting; + public boolean useColour; + public LightMatrix lightMatrix = new LightMatrix(); // vertex outputs - public static Vertex5 vert = new Vertex5(); - public static boolean hasNormal; - public static Vector3 normal = new Vector3(); - public static boolean hasColour; - public static int colour; - public static boolean hasBrightness; - public static int brightness; + public Vertex5 vert = new Vertex5(); + public boolean hasNormal; + public Vector3 normal = new Vector3(); + + public boolean hasColour; + public int colour; + + public boolean hasBrightness; + public int brightness; // attrute storage - public static int side; - public static LC lc = new LC(); + public int side; + public LC lc = new LC(); - public static void reset() { + public void reset() { model = null; pipeline.reset(); useNormals = hasNormal = hasBrightness = hasColour = false; @@ -301,57 +338,102 @@ public static void reset() { baseColour = alphaOverride = -1; } - public static void setPipeline(IVertexOperation... ops) { + public void setPipeline(IVertexOperation... ops) { pipeline.setPipeline(ops); } - public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) { + @Deprecated + public static void setPipelineStatic(IVertexOperation... ops) { + instance().setPipeline(ops); + } + + public void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) { pipeline.reset(); setModel(model, start, end); pipeline.setPipeline(ops); } - public static void bindModel(IVertexSource model) { - if (CCRenderState.model != model) { - CCRenderState.model = model; + @Deprecated + public static void setPipelineStatic(IVertexSource model, int start, int end, IVertexOperation... ops) { + instance().setPipeline(model, start, end, ops); + } + + public void bindModel(IVertexSource model) { + if (this.model != model) { + this.model = model; pipeline.rebuild(); } } - public static void setModel(IVertexSource source) { + @Deprecated + public static void bindModelStatic(IVertexSource model) { + instance().bindModel(model); + } + + public void setModel(IVertexSource source) { setModel(source, 0, source.getVertices().length); } - public static void setModel(IVertexSource source, int start, int end) { + @Deprecated + public static void setModelStatic(IVertexSource source) { + instance().setModel(source); + } + + public void setModel(IVertexSource source, int start, int end) { bindModel(source); setVertexRange(start, end); } - public static void setVertexRange(int start, int end) { + @Deprecated + public static void setModelStatic(IVertexSource source, int start, int end) { + instance().setModel(source, start, end); + } + + public void setVertexRange(int start, int end) { firstVertexIndex = start; lastVertexIndex = end; } - public static void render(IVertexOperation... ops) { + @Deprecated + public static void setVertexRangeStatic(int start, int end) { + instance().setVertexRange(start, end); + } + + public void render(IVertexOperation... ops) { setPipeline(ops); render(); } - public static void render() { + @Deprecated + public static void renderStatic(IVertexOperation... ops) { + instance().render(ops); + } + + public void render() { Vertex5[] verts = model.getVertices(); for (vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) { - model.prepareVertex(); + model.prepareVertex(this); vert.set(verts[vertexIndex]); runPipeline(); writeVert(); } } - public static void runPipeline() { + @Deprecated + public static void renderStatic() { + instance().render(); + } + + public void runPipeline() { pipeline.operate(); } - public static void writeVert() { + @Deprecated + public static void runPipelineStatic() { + instance().runPipeline(); + } + + public void writeVert() { if (hasNormal) Tessellator.instance.setNormal((float) normal.x, (float) normal.y, (float) normal.z); if (hasColour) Tessellator.instance.setColorRGBA( colour >>> 24, @@ -362,42 +444,72 @@ public static void writeVert() { Tessellator.instance.addVertexWithUV(vert.vec.x, vert.vec.y, vert.vec.z, vert.uv.u, vert.uv.v); } - public static void setNormal(double x, double y, double z) { + @Deprecated + public static void writeVertStatic() { + instance().writeVert(); + } + + public void setNormal(double x, double y, double z) { hasNormal = true; normal.set(x, y, z); } - public static void setNormal(Vector3 n) { + @Deprecated + public static void setNormalStatic(double x, double y, double z) { + instance().setNormal(x, y, z); + } + + public void setNormal(Vector3 n) { hasNormal = true; normal.set(n); } - public static void setColour(int c) { + @Deprecated + public static void setNormalStatic(Vector3 n) { + instance().setNormal(n); + } + + public void setColour(int c) { hasColour = true; colour = c; } - public static void setBrightness(int b) { + @Deprecated + public static void setColourStatic(int c) { + instance().setColour(c); + } + + public void setBrightness(int b) { hasBrightness = true; brightness = b; } - public static void setBrightness(IBlockAccess world, int x, int y, int z) { + @Deprecated + public static void setBrightnessStatic(int b) { + instance().setBrightness(b); + } + + public void setBrightness(IBlockAccess world, int x, int y, int z) { setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z)); } - public static void pullLightmap() { + @Deprecated + public static void setBrightnessStatic(IBlockAccess world, int x, int y, int z) { + instance().setBrightness(world, x, y, z); + } + + public void pullLightmap() { setBrightness((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX); } - public static void pushLightmap() { + public void pushLightmap() { OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness & 0xFFFF, brightness >>> 16); } /** * Compact helper for setting dynamic rendering context. Uses normals and doesn't compute lighting */ - public static void setDynamic() { + public void setDynamic() { useNormals = true; computeLighting = false; } @@ -410,11 +522,16 @@ public static void changeTexture(ResourceLocation texture) { Minecraft.getMinecraft().renderEngine.bindTexture(texture); } - public static void startDrawing() { + public void startDrawing() { startDrawing(7); } - public static void startDrawing(int mode) { + @Deprecated + public static void startDrawingStatic() { + instance().startDrawing(); + } + + public void startDrawing(int mode) { Tessellator.instance.startDrawing(mode); if (hasColour) Tessellator.instance.setColorRGBA( colour >>> 24, @@ -424,7 +541,12 @@ public static void startDrawing(int mode) { if (hasBrightness) Tessellator.instance.setBrightness(brightness); } - public static void draw() { + @Deprecated + public static void startDrawingStatic(int mode) { + instance().startDrawing(mode); + } + + public void draw() { Tessellator.instance.draw(); } } diff --git a/src/main/java/codechicken/lib/render/ColourMultiplier.java b/src/main/java/codechicken/lib/render/ColourMultiplier.java index dd42364..292048c 100644 --- a/src/main/java/codechicken/lib/render/ColourMultiplier.java +++ b/src/main/java/codechicken/lib/render/ColourMultiplier.java @@ -4,9 +4,11 @@ public class ColourMultiplier implements CCRenderState.IVertexOperation { - private static ColourMultiplier instance = new ColourMultiplier(-1); + private static final ThreadLocal instances = ThreadLocal + .withInitial(() -> new ColourMultiplier(-1)); public static ColourMultiplier instance(int colour) { + ColourMultiplier instance = instances.get(); instance.colour = colour; return instance; } @@ -19,19 +21,19 @@ public ColourMultiplier(int colour) { } @Override - public boolean load() { + public boolean load(CCRenderState state) { if (colour == -1) { - CCRenderState.setColour(-1); + state.setColour(-1); return false; } - CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + state.pipeline.addDependency(state.colourAttrib); return true; } @Override - public void operate() { - CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colour)); + public void operate(CCRenderState state) { + state.setColour(ColourRGBA.multiply(state.colour, colour)); } @Override diff --git a/src/main/java/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java index aec0443..c0c4a37 100644 --- a/src/main/java/codechicken/lib/render/RenderUtils.java +++ b/src/main/java/codechicken/lib/render/RenderUtils.java @@ -151,7 +151,7 @@ public static void drawCuboidOutline(Cuboid6 c) { var2.draw(); } - public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { + public static void renderFluidCuboid(CCRenderState state, Cuboid6 bound, IIcon tex, double res) { renderFluidQuad( // bottom new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), @@ -196,6 +196,10 @@ public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { res); } + public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { + renderFluidCuboid(CCRenderState.instance(), bound, tex, res); + } + public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1, double ty2) { double[] points = new double[] { x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009 }; @@ -249,17 +253,21 @@ public static boolean shouldRenderFluid(FluidStack stack) { * @param stack The fluid stack to render * @return The icon of the fluid */ - public static IIcon prepareFluidRender(FluidStack stack, int alpha) { + public static IIcon prepareFluidRender(CCRenderState state, FluidStack stack, int alpha) { GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); Fluid fluid = stack.getFluid(); - CCRenderState.setColour(fluid.getColor(stack) << 8 | alpha); + state.setColour(fluid.getColor(stack) << 8 | alpha); TextureUtils.bindAtlas(fluid.getSpriteNumber()); return TextureUtils.safeIcon(fluid.getIcon(stack)); } + public static IIcon prepareFluidRender(FluidStack stack, int alpha) { + return prepareFluidRender(CCRenderState.instance(), stack, alpha); + } + /** * Re-enables lighting and disables blending. */ @@ -283,21 +291,27 @@ public static double fluidDensityToAlpha(double density) { * this determines the height. * @param res The resolution to render at. */ - public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { + public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double density, + double res) { if (!shouldRenderFluid(stack)) return; int alpha = 255; if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255); else bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * density; - IIcon tex = prepareFluidRender(stack, alpha); - CCRenderState.startDrawing(); - renderFluidCuboid(bound, tex, res); - CCRenderState.draw(); + IIcon tex = prepareFluidRender(state, stack, alpha); + state.startDrawing(); + renderFluidCuboid(state, bound, tex, res); + state.draw(); postFluidRender(); } - public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) { + public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { + renderFluidCuboid(CCRenderState.instance(), stack, bound, density, res); + } + + public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double density, + double res) { if (!shouldRenderFluid(stack)) return; int alpha = 255; @@ -308,18 +322,22 @@ public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double d rect.h = height; } - IIcon tex = prepareFluidRender(stack, alpha); - CCRenderState.startDrawing(); + IIcon tex = prepareFluidRender(state, stack, alpha); + state.startDrawing(); renderFluidQuad( new Vector3(rect.x, rect.y + rect.h, 0), new Vector3(rect.w, 0, 0), new Vector3(0, -rect.h, 0), tex, res); - CCRenderState.draw(); + state.draw(); postFluidRender(); } + public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) { + renderFluidGauge(CCRenderState.instance(), stack, rect, density, res); + } + /** * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately */ diff --git a/src/main/java/codechicken/lib/render/uv/UVTransformation.java b/src/main/java/codechicken/lib/render/uv/UVTransformation.java index 8e96173..d7ca168 100644 --- a/src/main/java/codechicken/lib/render/uv/UVTransformation.java +++ b/src/main/java/codechicken/lib/render/uv/UVTransformation.java @@ -23,13 +23,13 @@ public UVTransformationList with(UVTransformation t) { } @Override - public boolean load() { + public boolean load(CCRenderState state) { return !isRedundant(); } @Override - public void operate() { - apply(CCRenderState.vert.uv); + public void operate(CCRenderState state) { + apply(state.vert.uv); } @Override diff --git a/src/main/java/codechicken/lib/vec/BlockCoord.java b/src/main/java/codechicken/lib/vec/BlockCoord.java index adcecbc..a631eff 100644 --- a/src/main/java/codechicken/lib/vec/BlockCoord.java +++ b/src/main/java/codechicken/lib/vec/BlockCoord.java @@ -146,20 +146,10 @@ public int getSide(int side) { public BlockCoord setSide(int s, int v) { switch (s) { - case 0: - case 1: - y = v; - break; - case 2: - case 3: - z = v; - break; - case 4: - case 5: - x = v; - break; - default: - throw new IndexOutOfBoundsException("Switch Falloff"); + case 0, 1 -> y = v; + case 2, 3 -> z = v; + case 4, 5 -> x = v; + default -> throw new IndexOutOfBoundsException("Switch Falloff"); } return this; } diff --git a/src/main/java/codechicken/lib/vec/Transformation.java b/src/main/java/codechicken/lib/vec/Transformation.java index 7d9aa72..a7cca46 100644 --- a/src/main/java/codechicken/lib/vec/Transformation.java +++ b/src/main/java/codechicken/lib/vec/Transformation.java @@ -38,15 +38,15 @@ public TransformationList with(Transformation t) { public abstract void glApply(); @Override - public boolean load() { - CCRenderState.pipeline.addRequirement(CCRenderState.normalAttrib.operationID()); + public boolean load(CCRenderState state) { + state.pipeline.addRequirement(CCRenderState.normalAttrib.operationID()); return !isRedundant(); } @Override - public void operate() { - apply(CCRenderState.vert.vec); - if (CCRenderState.normalAttrib.active) applyN(CCRenderState.normal); + public void operate(CCRenderState state) { + apply(state.vert.vec); + if (CCRenderState.normalAttrib.active) applyN(state.normal); } @Override From dd1abf7ac4f8918576ae393aca184f8e4414f579 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Thu, 21 Dec 2023 16:11:05 -0800 Subject: [PATCH 186/219] Angelica Compat Depends on https://github.com/GTNewHorizons/CodeChickenLib/pull/14 --- build.gradle | 29 +++++------------- dependencies.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 61608 -> 63375 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 12 +++++--- .../core/launch/CodeChickenCorePlugin.java | 3 +- src/main/resources/mcmod.info | 2 +- 7 files changed, 22 insertions(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index 4e31dc8..50c3291 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1700844281 +//version: 1702141377 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -28,27 +28,12 @@ import java.util.concurrent.TimeUnit buildscript { repositories { - mavenCentral() - - maven { - name 'forge' - url 'https://maven.minecraftforge.net' - } maven { // GTNH RetroFuturaGradle and ASM Fork name "GTNH Maven" url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - maven { - name 'sonatype' - url 'https://oss.sonatype.org/content/repositories/snapshots/' - } - maven { - name 'Scala CI dependencies' - url 'https://repo1.maven.org/maven2/' - } - mavenLocal() } } @@ -69,7 +54,7 @@ plugins { id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.26' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -628,7 +613,7 @@ repositories { } maven { name = "ic2" - url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + url = getURL("https://maven2.ic2.player.to/", "https://maven.ic2.player.to/") content { includeGroup "net.industrial-craft" } @@ -687,6 +672,8 @@ configurations.all { substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + + substitute module('org.scala-lang:scala-library:2.11.1') using module('org.scala-lang:scala-library:2.11.5') because('To allow mixing with Java 8 targets') } } @@ -793,12 +780,12 @@ ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies" } dependencies { - def lwjgl3ifyVersion = '1.5.1' + def lwjgl3ifyVersion = '1.5.7' if (modId != 'lwjgl3ify') { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.17') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35') } java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} @@ -1310,7 +1297,7 @@ def addCurseForgeRelation(String type, String name) { // Updating -def buildscriptGradleVersion = "8.2.1" +def buildscriptGradleVersion = "8.5" tasks.named('wrapper', Wrapper).configure { gradleVersion = buildscriptGradleVersion diff --git a/dependencies.gradle b/dependencies.gradle index 3d93d59..2acc808 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ // Add your dependencies here dependencies { - api('com.github.GTNewHorizons:CodeChickenLib:1.1.9:dev') + api('com.github.GTNewHorizons:CodeChickenLib:1.2.0:dev') } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba7710deaf9f98673a68957ea02138b60d0a..033e24c4cdf41af1ab109bc7f253b2b887023340 100644 GIT binary patch delta 21856 zcmY(pb8Ie5)b?B3wr$(C-Cf%@?qb)rZDZHAd)IcmYh%~=p6{IZBgnaoP&k4a{& zS#w>#$^-C(Tku8=J49k2nL;->2uKtZ2nc(Mi5&qz#l+oO!_~yo!qv^hUfkNk%+A7< z$;{rw%`HtsUmIT&<2xL}5=NX^y$O;|$~RbH3)fdvzNjTrt*)GwOQcNFAi_C2*OLu> zE;mTv?XZ9ZFpwcsiA*b>@qUxw+Brv2W)p`@WtTU-`*C%<)&6#QYxD!+47q1MpD>LZ zdlU_bs==zy%ADO7_fHjtTl;4N9761!)7P2zp(TP=fs&@% z2rQj{iD#*+Cga-2CeyvAPj-ObcA`OjCDQ=>3TL>}&aAGNYa6zh3Gq+MC~)I-8i?Oe zulJDDA{RcbfS+4OdIZPP`b@sFk!$-%O}#A}3K4EQ%_OcHr59PpwP#p+IXp!PZaD0km$w5sU+f zcSXdhMBy1>H<75xo8VN9(0Ah90`Y3#`*FfXrBE1FMtkCxyywO^T%o9p)cdd@dWJ$M zb#0ctE7SYwAANI5xILKir=oe}L3GnsOsujPv`3NVlFPQIrP%bTi*@rv6Ph14FGK6B zFj}IZxwP)W!UL^Ke#bx|?2T2Q7~2Cjol}Mp@$GclT|_TG1Rhd1p9Js|TDXpVa$4S_ z)*t=BEiwG?7Dh6-xSUr<%(Zu*ASN_PX&*5!X{!glxfm?&BwmSk2l*;v*}W|ZNa zptrk+ecNCV!)XtX^$f06@6AR_i_=v!!B=a5MZTW>Gul}U_fGf%43DLw3`77&uU&Wb zy%@{}T%2m>R#RQ&v&;Z)^ zBET1m`=13qQSJgyarvDLmcVjx;@t`l64ZEd`I;Rr66}-~Df;;*R==-zF z1$QY|uKT;!lT+#TA}EyM&?jK&D~draYK^=FoY(glEiA@hm)aTW)TThrK5hv@{Lg&w zTfU4p|pfkMmGpm14$p_1lFj=0jOQevLDk%HJ zKAY0KmluLIZMxl4!MQ2h)~I=q9=}HppU9k8#0+wTd9E46ss!L7>=HoWG-#tnl#3o^ zKjN_~OVM^2OOd)u#V#rfQm>xthBE}FbV!w?Ly@U3VSOMBlO=1r=y9}rfN2Zz7_0fB)50Ra&Ok-|x@5d;GP zfrbD95&AFUErGjTJ0eN3{#3#eix~T&&Ba0AN~GUZ8F1p8zxDOlYB6g3K7;(& zo(!i&GoRbC{w~Y{Xh1KqedOOK6(mLN}03N&Dum}q~1DAW88U*E^7gro9 zW~t}$R%-w3Ck+5(RqQKskBH4}N=9ApR6$cun! zPRiWwK<4aT#{Z5mI@;d`@n>S*t=Wbsnk^4nX`jIC&iXvECz5N#L6s^1~jE4s;Bjn~aF zIfzeAXQ9dg=P^RO0rzF>WExgaidOH^y!n2x!AhVNW^A1=C;5KBmw?mU-jDZ!y>E~^ zp}v)*fpNyOffgLgk;E074y-W`Lhd_R`s5B;Psj6)xL@>^tQDjU2kHPqRDZ0lPN=s9 z)qx(I8*80;XYFA!@d?iw%^TJy41YkzbBsw9s_Sx9subHnhG0#9l>%|#4 zNeJV}J{!x(RD+0+cgY)#FT|-UfzUvlUlOq>VsG~$ohvH27{35{!)lqDhOUoPuo~*n zI(f%kr%A`x*|4YJ-qW)fSf}}^Z|P2*NKI$OGwGLH9+UcxY)on0D_#LhLZ!I;#oird z8QXkse;EhaTyd<#K=95+1;O)ptP0_GpnxUg1DFaZHL!>U_&Q>f129auPuu>5CL03* zwbnYA>C7~B)bjvK9%e5Gxd6+mo7Yt;Cp^f*>~Lm8|1fB%zA0)ZN2( za>Meg*j{lzb{bmMq8s%BtpBpPdYWa!nj%W-`Z(>?%i|{1$MY%kAYFhFkNg9wH~Cgq zDGkqQtL4)Fo>Wsvljp|UIVcy68j?J|YP*WZV7!Xa$s2GJ&jDkzKt3Eon=Q7%Q4mQ) zharJXn}d~BcN&{(lIS=L5y^}(A~`<)4;x!i+)d;OaaOeXr8r?M@V#B>18z3ziAcxS z9y|Eyl_|BQIc8t}oKwV%S|bP&)tpXG2S&BLC^QTf`6=ZaXQ;8q5gjdKGED?&KHK+C z@C&-w6C}VANYIyi_A@no~1hUt?=zM%JC(Otq8?w_jwIgQb9X@^^^S(k|pY>v1W=BF>-{ceOHx zK9Q~1cYZRvoeQF3Kws*`Sq6?@=@`AkVwK((TI0gOyMz;)Fc%lV1%XoNMYK;Vw z++TJLDNJ482E{``Rh+*$4-aY>DfFarNyS4d<&JhNda~F%D2N8~rE=cXrkECI=L728 z!EFNLd$%P4#PbQD8kjWwQOA>sfp1G$M=C=`GaRH%UG+)SmPMz@d7R?)?RA?w z4gVDX%F^0zk*t1=lKax8BYhXC(}4AOK9p!f=jCwqwDRoF%6qf)yj{x>{zBMikb{ah z;gB2F1rPAnt~xFDM!uy#2L~rU>cuu}!DC5Q&ri0kb`M3R%gU$&s z0Pyu$!0r9Rc|{ygG91KOsisiqTUwaxMWVU+Zho?w^dJ5wr|6e{$&xEq7V|Q~O?E0H z+%6m`FhVzV3v81kYitTr2hM)vAE&}%kS5+{*UzFL-on2^`WW%q1E}_HCx~W?n5Zuj^NmJF9$E$Kq{;qNAQkI0xMw7KF0+czq zHK$1@u_!R9-{^S4#s9dmx2NMO^;hqe(?ng2c9Jo2N=wrJKAhzfZ||b%R^09mb#iz- zBGf5Mbr{014uILu6GoNWGapFxSu$MC4sPkY<(fHxLy?@#_gZwFj`i<>3XU0DEGc9!xI5 z2ly^D>2hN7CIJDpaXbC90FgnW02GSS5J5#FjD6g&*IXfz{w3}+nC7?j1ArW-b=;T9C z(L!J;K-pnA3Kyjxl4BJt7j<>)S2m+P|CpA==(V?{GcB6ZqodGoO6qrS1hmKKXEdzd z)XcsJzw~Y-vo79#1oj7t+-x6j`?dY>p6vG z;^v-JFqxAFO>NR)Lfzc!(+%W3>K8gz#o;@F!~eEPV&aH4$4-6E=>7A@rriV6BCzh? znq7l|)5mUMGqtIfX#ftzMGm_jy(4(R<%vHYj!APdrMe}LdT;hCor*%IewD#%Hrw@& zzIn{)su2kZgl;k{ zV}SaCEzxV3NuO0DbO+jxK@s@}4t!28cV+%rR~^4Bnby1`fPjXDjZ{WLyjzSq=rY{o zv1Ch~Y*ZVmGFV&xFkrXDSR&AjXmi{okDM>z@>4G>E*jdD2=BB52#fp`>UG&8ebmd= zs(ecC5tt{nxAOXrs4u!<^$m~r2ocYy<{sZ8Fa@}F-eYun>Cq=@|IhN^9V>6I`fNt@OGY$m1fc1-TTvIwX~W~sK4n4o|oe*vg#4mxn+-# zb&xbBB7ldGz`>r@COOp9fgA6{Dh?}u8mbVp+S*{W1=w3@FRAEtx-8#~)-9bIuUX8D^HKp6y?mj=gK;4&E;7o8ChzwZ5FSqK=jn6v!KI*W?79> zQ0^Vj2XHe4D)DrZwIP48)&{W9I6C(un@$yv$Sf>6@F9^^t;2S)G)G{M_mmzuB6~>*+_oO z($@}p zKR)5!d)SaTBHauLd1Q~>F23&I^+!~FEMo{+s2B*AgnsAA@L0Dh)ZW@h$=^0NLAeSM!m=>GcE7RVYUe0x;3g=9I&cIP_E=( zW&o#(ykuvLwwbwF_mQKcuU>;nW|QA=ND#j_TxChy2(hKfy``TfOipdh=7SEI@>dhs3o#mB%##zEe6x9WcKP6meJ1)Fja-7^YB-HFfR?#B znNWTtIBYs^_;H9a&p7SDOz~K|t$)r~yWOWy+^q~hc%U8+Cb;@n8;KQJBQpW_i>16K zWN3SK)Be83GUM!J&G}T!nn36|>nEe*83M9&P;8#%j9y@%pSKF;6y=J~g>~PS%4j5J zJGW$a-K#Z(P)>#&EE@MQ{-GfeG5xk!PEGWD||y2igdwFE#Y(;Fvv^JMX22X z>kMSTk0fac6SXW$}Wzv0me@f!-De&mGv>F^ytxOa@q{-$>GaLa1;UAUZRZ7Sf1$Z7p4 z7}`H4%<>xXNlvx+Iu0ca`SGX>L1xt>#whAu8Xs=)HM}s9No+&r(9M93vmraaUl7d> zpqibNJgF#qiRG9p4%V9^6|khiZv5~a760UNlsX{dP5%bSG9RQBlGxupe!`c3>90LM zyFdTBx=o0RBn$}1`Kq3Jb(@YA4v~)DLl_odwL`%s0hA}hq-fYYo2C4iVj_N%j%agq zu#<8ie$SFlYp}qMhk#@XCt2cHi%g+<0;j%f!|RmX-7OHjxnpz z@M!|aOw&**MBQVbej)b@xSv?DZ^KC)!s$4~2|<9_L}Is(#LF-IHuvEhLw+|-o~&sl z8_mv?oIE({rZ20|pP{SN+VCAEQ1;v;^~|a31074Lm=U}y-*ZuBt4$5ctEbVXu~AmQ zzeAlr@9i8lc6UZ^P7{zmXbz`cPiY>53O=s_r4$;Si@As3*X&119RuHF)}DRR){ehD z%fbOl7qSl7uDZV|ANNL^A5D2;1mO7sN){%FJ~{=dZ!xK`{Vuk^X(CxBuzVdoJbUMS zPA)IxLxak8sW&t-ZGo(5#S5V};F`yY6$sSI399U?X4i2w8S`8iwT*ax4TBfk`MJ$^ ztU-@_1qeO)PI9?L4?4Dow6&D?_yVYI-|zuHb3|#bZcGHI^bC{aN`@!cv;OcoHZBW3 z(I!xQ>V1_@BeflFC8FEr2HI|C%ea#FkzjU`9zZwo-4Kf)F&_M+$MX5V0y%U8OFqEz zn;W->Uetl598!Z1n|~j`a!BZ&2b~&TRk5wEY3ZIYT_Dwa0MWFScKX6KSHJWv-YnxK(jIDP*zv0_SGrh&Tol?j`Lx2&j3$G5eS? zDNs5!ZCnj-`Pb_sgm`RM^S0u^eheWhd143k;!MG3IaVQ)CjFM7C^hR&rKuK@xhqHX zu%PG;@|6=+8MGU9&*;t~7>Es+E%CC7+Y7z-`!m*_tWC6h=69@ECv@v9bkCqw;I$-J z2BP<0uUg;e2>!n7KSn6_+df`n&3VU99 zzNTsNyyS`XpZ>HfB~(p5j9Q^DnOu>nd%>{vZ;s?WH!Vxn?4#_$;;LGJmKtQ8S}m}h zyHr=R{QntzwWZYWoz7Dx?>wsmsqjr?hmJy`H^H!rUAD=k#1*FHH(f`6O)_10`6v|< z5*O6<0l9Kn$r|BGyh}&kf<$D)M8?lNniz|#;wcGhM1xsOlx}IsE}ZA?q>SZQn=;s{ z$aSg@AA#5x;*3A2RdySUh`@bK?#M?~H^t^{1x_j$)PaiNf^VJVt zi&>_zFZZ84%j9De^VhCJ+Cw-%;FdrdgUM(Z)UxrAzINst028Q}OLDalgiZMaJybs{ zg_a>boUPI}T8dw)*#<{$gk`*(eZ?gsoYa-Jg>8-@O8jzeb|)PP$;cy*Y{|?;rY+c^ ze$c*o^Tyz_;YKH_*m>eR8puDn(mAPGgk0?{TGNYqjPiD^40S8b|1AjWN~tT|tj^mR zr2A7|eSQ-GJVFMB9E)`I9zmL3o{l*BL1=0;N+4~YaMB72!@xNOM6C$O0aA5rlw!=Y z6++eJjB@@t2Wrxvu#i(BZ0pQdU&wwKpN@T@-m=FpRdYZ@+d& zW%bn5FU3jnLsdByIyqz;xg{PbVc}(~Q_A}+L@5IR2TaxcqKM$sm8c8u^)EdXjKd}k z5BUke5DJ5RgLtK6Ert21ln85&6g$fcDtCJ+Z10@wJhI7)loxSGUkp2?G+CD~k&>EW% zh`IK3bAUoB==UjQxn!nLO(PNagOs_TR-=9Pl?ue6t;AoE#f^RhtZ5)CM0zkz4CQO! zzqLu98pvHbUL&nz+&(sHe)nG@kGbEDW zZ3JT?h#&p)kNqbMw1p)Zo;h;V-k_R+m?t6`SNgSihi#em$2WKAhEjeX&Yf9oQe4=O zUHDR&!*?#=(g3gMUePU>nJUE8i?b&y1?i=#@9z{kZ5LDQAs4hF7IaMd>OVD9q&?{wNbLo(XPJLwfM|9t zkf5KR6xCvqLSU!JGV=;zlNm>VB+P`aPrU)z2kk+i8qbCDd>iO5o;LPu`Fl6qK&J6I zq|YA9kQs7=WTM{C*5n6`!jGgm&l8Hz1d|gXK6sS3NH=XBcs*gMezm86bov`rdy4k9 z>jotKHqH<8COo1K`tpe02>+JJw{~t@ZAsOW!=1>*AxB`qih=yu(WQle5#=uk1Cw#2 zWbtwsMvZ?DDf|CuGhaYul1rBcc9h3metcLiL)Md(%oxu(R>k^3Mc^9!C`keaCM#K1 zg{vU)^YYqG=}^9~a5SF(Cc0^NqFQdHm8y85Yar1 zfoIyguCTA7%Wm#yP+$`P7^tA&?0Wr@Td*OziHicH8y`KIAOCgo2QUGp9kkhRH9ez3 zBKaKMGX~yzVLt5cY_=+)(n((>p`T8{J`pR4YCtmN3k{h=j4_@&pbp#^!DOyHXc<_r zG5SmPj($V&<$MR_!?U}cCp=MmJ7aLQoz_cE{;+>R_8L-T_ZL$Ga5`BXF7eY0%6zXY z`WN;{OLRKY;iv}tR0eTCpOB-1>8XQ>w0-4L;L59}9+Z72MIQoiqS&{VA&+f6M1v{2 zR_?Nw8!K*D`M`ai+@VD)eWvMDHuqGV$j@NzJg<{D!mscjUy`Z=K?J@~X#YuzjH&Cc z+sI!oooF1n_CS6E${au8lS-+U)(16DDQ%k?x+Ww?u8hkUJ7so@B?8RkmYF#H)$7UD z$}m-jzp6}9;uxKkTJ4AfENh$BT zP-B*tSh`asnMxUdl{!}LwB+xcVIJfjJ70pjYM<4*H65)>nPMi%mBflTa&}T&I_i!P zjdlddYuFXqqN*jv>{5MK%^v{e27utfbmxRTl;*NYW|CVEzflZD zgP8)Z70aM;@*pH8c&6GyXbb|=%7L!Hc=t42{y6+hF}u86Sa1v6q#l%W7&04Nx#m@H zRWhJte1ka3mSenPX&6H9h)JE6fYI1!+e`;R+(Quh5HMDF0kEQJyLa1g0?=PwXQbS zGTc63X|XVQGx&z=SP0i>(O^n$YFT$DFUfHo;xeVraR%XXBjoa;>N0%BbvqwS+W0Y< zJ>Ag?%}QOn>>wq+t2C?0L-;gV=C&7sG^}e(PQ?y~cP*{0;EbGleX8leCq%qG6hyo|0*55FeT5;md;Q%hJZc3ev~~x8?9;eQ3valO3wLr+H}+eIdF0*V zwmNoQ-JqiNj?LTY)azF%s8#45sMmaCntu;65Nq$R^xxoi{rrB=5FbwKV*ao(hk4TI zDNDOun{rGTd7Y}8lL2U)f(+HGzz{E39Z%&WTuz{ecx>4O$FKK}zsOYq$n;rY}R(~v|;_R@LN{iRWjQz5l zJ*p9i<=lP@*>L3A>dW46m5sNQeFmAs_oo)eCjh?A^ zEfvx~{3qJx??0P9tzX;}f_PENV21VYF&FQDj7oMzJE<&8krpzIyWd?Gx$!Ay9ot_!tQo z$tiw}9LuRbRV6eMnVlO^4|5FRq=0=|;>KxAv!;j%bz3Rvq%965iG zaqWpQGU_}2gw(Y-P9KpTI%P9BYcBwp^%AQMN1o9r7bLGH%&b(E*@>I$C9lW`yQ#&; zv#G$pyc(^d5g7{K=12g!Vd(2J&Oxr9904TxV<=EbBe=f?Sk!Ptp-#_MK;l@q_0JMO?%>?zq4UjP3 zNKZtGt(d!ph)QLVFXI1g`81hVEcyNi9bu=4RB!=yl$TU+#tQy;(9;v{e~vMy(wdPF z5}QVv#!^V76k)T=-`&&_NENmGxnBO6z-Qt}vgWv7g#V#A@>7DxH-k#IxaD>7%isIx z5v=%nd>Lm3f!Eovh%iVx^BqUykwtt*!BZD#k&N=ntlQyaFv;E{O`^V}IuCWhQF zERb}dC!%ITuC-yP&q}1!rnqA+h$;YfSSwqq9L0r%e1EkQ+_(qBzE8|er?X9J>+^uF z#G3~^51(1;{hX&c63)-mIK%@i%{U*eq3OiynLy>aI3^{icFKqmFBTs$1xsII9e@j} z*GJ@%75X0k=6(Dtzgk7qqnv<8%f^nWXEx97X>#-uj(WE;F+<3_)Yt#DB60qIG~5{r z8SEA=2*?vB2nfml^Z-bJ|1ly@XCJ6ipv_4K8j)lu%q^tRB*f7uG9eUn5Oge(dnig$ zvRo{|Mp`|pimmHb^;$eG#p>`|ID^$B?P^xrZ0mNeZ0%kG-t<~+`+hoaXQiNie_teQ zzw8~!o$vPHZv6NSmU(aX#rxF|w^JFX z!-y(yak${&q2i6b`Cceb__9pMF*yO+eC5>qFq9}z<}|`1aAY{a*SkNK=x!0@Kh2!k z+lLLHdOH4>_o_^kXyL6e!!zm~dGb+y(SGHvF{6JbLH_Y~2Gc1iGV%RgieX@MfAYBU zqjngepuy)A*GGsxN1)oMUhKP2aE!_xTX}Rno^##InEivE3tZ zL!LMZvi;u6e1)EDz^nHcx$RaQl+)hQ+lPXb8&5vWZ!yF#%NNNDcKb0rv0(4*SoSx( zoYiF~+YN6~Gq>@v=aZEjF0KZrZe#JUu~r3uBqKJICxoq7u(Oe(G#M7c%L;3pT_jAe zv#A>ihqdo3w1V&W<~uwVqd|E4GZl)>h4G;!bnfWjUnI%*_Zgg}mUNlghH_@CGuSLn zezRcf<=B;$O3}oBPZFNt;z=UNOEbUFbMUWSOi1x$p4LKtg6k7i@>A>v!)JJPI99d+ zD};El&|aB#A*6r$y0>D-^}!E<4(q6}!^+K=KzLuKjCnG3M%@E9T>kR)QQXcxf6giZ z!(|dCIf^K8xVE66yJptMK%hnil5Rw--AJ%fow}E@&X9*{m)vgbK|#0uy3H&}Ot_$q zV9POiDc4N}O|Ey1_ly}5VWfsU9vLM75agW2=&X`nCp=4^=v0tVzKsD4>zp)uIi{rL z_gHU@S(O{hyRo!kq^M1-X8Ay239spe9R>Ma^&GeH+99MamIa*HGA`w5%gWhysFDZ7 zJWymyjdaoeuwKjJZsDBJS&I#f<}hB{tKXbR5V7z%mdZV>$0R+NfN~t&g^_1KQMP=@ z0$yYGA?jy_`9*t)FbMKB4grX}AGk57`%`9=OBC1N1&X(4G8WP+o>l3XAb|!q&+DE+YY3dMlwR)4qSYFtGz*nt-z9{X zs>3HQb6=H$n&AMbw_#!=b5G`|P~Vjnd1|K~tx;pU$uT6OYIj5^x}5$^z94zZ<%WqcMDX zWLa#3?VN-ny>2`P6>{H!>B2eqn?L_73V}*(U!`SL!W2AMLQE0>Wd);)mQrF6X^gwM zff6J0tt1AP8Ow&5kf)O2Dzvgi0JX7hjPX8=0DZ*p$SDB@1!e-WIZ!Gy6W#&hjvv_qGrbX@Pp`~nr}8x}CL-2og}PeYLH0DGa#rtgsIBtIhqS8% ziKxI;8VOfZWv2&FPejr+?Hi^i;H#KURZyT%cIp%?FmI?124nWCQy_PP)h!iejAyGz`+&75-w$F}_j7tc>3S!(R&G&3kr$v1z!Kr?TuaxQ@i-k)lL4^dImINWY zdGIIRP@>WZgm26rz0nro8_U}Y9 zX0BJKD|WzH285?!*so8o?;6qD#Y)jVYJ%u;qHZqsGf7`sUh#v90G3=Bq|7Q@=K?cx zcJn#&Viv#8ET1uEmkp;o;n#x2PvY%O;@FR2)Sq|}n)M@SY+Jcjn6HM?9xmto&J~xm z8^rJSvm3;u6V*U;4c8148Voi}OAphi%vaUG>HYt3C$N4-Dkh+69jOVo1eCboKJ$Tg zS$V%O%I!-@;r-=j{NU{aO|g4xeNs`=-Q^(Gy-dfdlXZ4tKBL}$yBdnBWmB{cP~{0s zl`4c$gTr&L*f=V}#}LtNyG}rhq@t$g+1>HPhhj&B#!5;{;?NYIGW&%+_s$yA*TB-$ZaIF9OUi7PfC}YLvearoj5$^0Y<1LVxokAvnZ) zM%T}Bwy0felzZGVHu0E}P)Vpaf4J3x9sB5IiS`%m;cfcY<#q!8r0NYiV*dL~+Wl4Y zxq5HyY16^69i@}*1{5)d@!m0c?^a;HQigykKE(acR+RvF*yup6tp^D&5X%&@egPg` ziAGP}N}6D>sKP%{Ok|#$O%>A!?W(U`&K4gWU){VYsG>t#{mi3;QNZnRGgGgxj=y(x z%t5MUN1%>OA!-x2>OzZkN4DpmgwwS5Wahto;Ew9?_mh>!867Sb)LR@Ep z>NRon%Cs!3SM(GY6*XCE6Gp+r)d1hPn_w>4VS1f|>JS&Z^~UQ+ZIx#6n%x!$oVuUg zT_4b7G$RDl8BClll60OnF^CRP;d2&XCPwjegYmkXuGbt{{bVt78k$j!qAiienp;xHDmFv7OZ26E4EhGs-^X1tFQPL z$$LSdd!bQ*CWX>uta+Arakra9%rzAAepvWw5hnXA|DYPoio2^$E=1W$aZ3NhWUoQJ z8Z|w>!&QQ$r=Il9{f1SFIlxn$a2A$UmE1MLCpXm2l5MJ11%8}_ciIsblVxe-mqiVq zXkoK!8Yg#+x`5K{#t?SutnmBE%#Wd*dDp)A&DVF$bZc=5kET^V#-H;XF6NUmrXZ!h zS3xOSf40#Ee&d493pYau8hO&Sfg7H9N?W{v=zXe7q7k`#*JwexD?qGYYLo@9lhXEJ z2W1a6s_Ym?dm~-NbTz>mh*?!>LYwZRLwP)RKLvI`r{`}Rd@!4Y9-9vo)@<2_Ls!-l1E zVtRHDyW#{@ee^`IhyW@DQ1(pt@?QaJx+ejWY!DM!I3Bh+o$%i`2sP4eit04Z`lp{} zxgv`XvvmBss7k?0+ZK{iXG&-zV=(GM-r7Q_H)B}v35ZE%yUo0#C}^5(b@>VJdxALE zurS?xe6=D+H%;Ibg1l9|1~tsNtk2h7Fgd@#3Ln z1aX}3BB{dvR_j@q{KFr`Y2H$TIPo|?x?iis{E4WHTx7qnxXpCZvsSEii9`-e%385lrBM z116vxn zm3*0dGhBt{wqKc!7cyVFIjkxb1U;0^=)CMCMSPvoC%L(P-pSPBzh4yk@ZQ0jkU-`n zw$(`7!ZG6I)L16VkEVyTpJ$ICBo0?)X6)gzz~?F3rZOV!0hUILRmXBU2O=_QO!#Iz z{iBDV(*WWTT*OHZHggN!mjTIDhhFBmSk|>D&Mdgeu2umo;4gmEc*Sf*%4JyzzPB@? zu8ho^;S8ylqmLBaJ&V_Gi~zoWU$}J1Im|uSlgAmpLNdrzr^8P$`J^<*xbj`%WZvQLE0mV>d0WSd{}7OhMVv5A`d>5EY4<`Fz=uhJKez(vD{)Q*?rn{8>OaW>^BD`pKnRbH`_ z=^80(xlRU_@Ja0hx48M`2RL`7;fsJ}fX*fD!p@6o(cC`<+)QX$tL3iT>Fu?%63Tb# zv(#aZKaVW47X+k$g)5Wn&}${y?3fG_I>I9Lgw&2(g5C!ZZ$fFibNg(hC<*@S#26Y7 zYmcOiF4j%?z>5;Kiwd|d7+;)1b{a87jL|On#s^c|GMqelms-41qRrq9ep-ocfHks# z9C7({s->UkEV77@_*^nHJ+Scf?9w|_OKr1H(WWQc zsJsUv$lcMC-UnNF`NTN$OEllhCRfSi#D6^NlM7cs?$1PtdX&=Wf0)TNye(Lh($Zdf z@VOIcRu+_hl40{_P=YZ#>ppr2pr>t^gSkq#5D1-yl}7oGuYc7iGn$`1qG~%oWG%Xu zHZ7{$gL!b;+5N=5#1zgJH5~Q0Um`#cGu}yFx7E5~%;D^rpaK#;K zxjVmp_+m!~K)!l47L9LmBB%gER~*o1KbOsx?&D)4D+wVeroC z0}nNTs_=_9R888C!T`x{+)>5yiz>7M1hskfu7&t27}Z_q8I5=i?AzcJ%f15bIl&>UN}+1v2~@y3 z24(W6%M9T{8;c`ac=`Eb#OucK~H;$hEj>TESERX4&q$s_iJ;f7_z8%-ZMB;>)42E1a!S#@aSTSg z|Azl*GoNbLVzA`}C{6uG%FvW-kjAW$l4wt4)3sPRCG9Yv167M`iSr8}%Y~o~iGNEA zK*S0wY$dXSPh_2Mucjrp#{^p7H%uehxFvc9)`?|LoRj{pa0s%M`g=c7_9u_;Mhi6I zth_iqba~S?bCWMAX04r13lnQTL$DQyyD9j$1|!8mhx6zLumI3_&5g$$b_ez??16P& ze@s+*OvcQ4K#=_>t3_8zcDbZ=ROfdT*uvSgRFAa2Mu)a6z=`DKzNq!h={6c?ayi}e zme~Q*?SAz*JyC8{x(jFKfJoVCR_avcr)P7Ou#nOWAwnvMTrf#IO` zdg<)t3A(a^SoAmnq&SBw4qNpFy#Yk!>05bBE>GKpia!44$)Tr$GPEPd{EoK-) z&Cg*DklOwul80AmU(tS0f>fI)c}ruYwJmiI;o74Z=zXbCmSxHih%MK+{m;Ul z;-I+bLf4fj=+UD{51qi{HqGh2t(eGQQgdP9Jk@(^;k^3d%>5&m%&Jaa4p%m*f=Cv$ zj$kmku|LHS{B4bvIFJi9P!r5s0g~lpa6tYJ@C)>@9KJg|wIwp3T8Rp>zv4g2Ajo## zaDJ|0NoP0*y{7j{r7WD#)xc>9LPu!n>LI4^x;C?LNTORJnO{~|<|MG^xlK#RE`Xq1 zh{p(^UzYh4WuXR>{(ssy>#!=ewvEF^Qo0)i>F!24wsc5`g3?F{k^|C6Z@Oa>iga%f zkPZpibh8npQyTH(&-Gg|^Vd8x_qv;&nx4ZQb8EXlV|ZK86|b1{ zfAqV01k)Qs^Q0V{*+jWZpapzDalYi$L;lK3(3=i2y1}Y-Z_?2OPQ&rbQN>w*Ck%JC3c_c@hn$n{M`XVmG{>)N0 z;}Wge(51AR47ePKh8n3RY}zSQz3)C_4j2?ya zsiiW+edY$YeR85xZ|u(rn(j0f9VhAXxcmIyUcOCnZ1XAx54wZI;XoZI$ix~|5$-T> zA`DwV+jy46gYj+$f1zuwG!5v}#UvYh!3{O$ewXu}0GoN-Ge?2!$QqXD@4g8Od^6aNAAu5ZWywAQH{&^Ue%WSjK%l_oQ+ztd?9nS`MO!5SsuWY0^uIimoF*M z&iFosh4i*pX`qN}Dyul~W}n2i;{o%_qO(l{xt5cA3kwrea&W`8 z>CJw5!(OFTIDKHfTH!TgLD$*&w2{mviHGW!o*0l=-@P#(m{P(nGWC7hGxHDl2Wn9qA|1V!B%4*2{o|S2WCT6M3THCPoYEMYgz3hyD)NaaB^( ztLRqJw=BrOYC@}M2;4Z4BY#f7)p5>mp5Rt{nI?uZFogLdtt>GC#WCeXEltO;^67_G z4SnTL6B4o12U-au0Xav^5w^#_S!Vdw+1`vinsZO{^kT?dpcev$W8N*u*C{7PvAq^i zW%H_40B1>cvq^izJ0}!|nMg}VM=(gca*X}Hc@D#=I7!gR^$l^R%a5DdUf1W}!p)VI zqa#|LX^HDyU3v6c^zAOyXB3Ggworwf){A4URq>z`b3X3dg6;J1+9mzB=8Ds$B?A5# z-{EX=qj{L7n$qR~PPZ_EcU-~dkkTGeYs*zxSiT_lc>yiXFizfx3J1~rUSzCj0T*v8 zuk5guc9hE7YCBLHOd}bt85EGhh!_s#UtF-Gd@Ro^L@zVrv`Mzz-{(k1t z-04kgHcZ0nBEDqAQMQ|rm-Ex>@y5Ya^A(M_dP!!`j0$%pvHZywTguD?MUL-PXTK6YS)PTV3|$HzR%PUF2`Hg1Y&=hCaEp`UiX97-8X5 ztd#SIQPJ~&XQi$sXYTXYc7DZ!PN$+rQDW4h9myTI8Rn0*ciQ`!Nq$VX{zk7wZ9l`u zlCe-sdwJ)XVuT5iEunw_aC8XUArTOhvZG?3T$E%*>VOY@~W~61Tb4{M$_2%t)d^wi|sSZ4!XMf)%rFs{@&+lOuf1KwZ?*^ z)}e%r;N|EtePFJbPqXpTFrtHj>%=;xpL3{6E+APg=&J+213&RgLz}!LoIapFCOE^v zkU6*kQGKSZtG=l3)qn-ZM#LPU4u7NYxDeAH{#42oolYWs5VJwcry}f}99tJT@IhxU zDd=WE^n~Nv;HXnq?2i=x8mFx7XTvW$u&`lI?DY#jHT$&XkHwnxY|;j&P;?0{7@>*O zFt%Vr70aTT=HG{Xcs-$k=iv*ONR;|CP31pZoOBG%305DF;-^MqR2-@(B{AVJcyqci zH8SF1;=gmPICNvFXWyV?c7!v}0n2Q6Gd$YG08ICAbCdebhaXL8R3rhEW@PIXIgTZa zV2xLmKcc|beM8fSUT{!L6G4w+{%L(sTP0`S4Yvc5O*nt zmk)okOR>)3v>=!EN{p@DFe(o2Yo{9ye4Guxs*!bXXQJE}&4z-!^5VV(uE>o^e3gg| zh%)Hwt*&$&{_+0lwM0=-`LD_0QzlgL{D;pUjKAAzGA4O$%;ULP=t8U_mkL_69*6Fc z*q%%^8`am;E$&6I(t zvTHa?4}HDNz#hqouHUvrrn8sNk+M&T&G8Kt6;3`)cPWA_yrl^RXrc}Cm9-*~>dA0l z&O04iF5p^v1q3%;R$fS3gN`^~iD-K|*Ws3@s_?z`!Vu~*4^7G?(aR&rrV$!pn0SL9 zi9UcK>&D9tN_ZQuJrNxmICfZil!mXcA*=VOAB8XCYp|r!Fa$r|8i}9#f!&&H4wkGQ zp9&Qoe@sR?e!LzMaIA$vxGK95LLb*nPe5x;AasczzmH@she5b5`|K{-L$6J1jU&{9 zAMb&5{D2viUgU{8eWqMI8#M*q_SRvL`On;ONxZVdjIPdfRh23ro__}zwvhYheY!@ z4H4yhvfZ$RvfTpI`SBncOOM&vuOm@&g6fcrVmk+)lH#po+A|dsN5&Z~ zD|oRz{2F{Pb0_FxR6q6?=;CjQ4!gbJJMizj2Ks!L&zGdHz6awW+mc2pw1T^{kz0-B zkj)tp^@KN~%z$i%*;nuEh-vggG=kSjF2t`BwW39y8U|W1EHONP6iWixSiJG(0Af!% zec!ImzxAvPXToc7~B_+5J5M;^zeLw^KkS%r#`ym}-l!Cy9$+5E} z{a00pwqMw^-?L7}i>wfL(a~!2_(N~W!CD@b3x+o0j#N~=y$A&>sf4}H)hY%*WL|4t z%Xn!Tc$sK^(v+$4Z+FwO1G5e!6qnlB4kU1az{aQ6b9#vzv`h)wsCTj=$Jdb!&G>Gi zi(J)a+`wug^>Yt{A(<1{DayAcTx5fv$}seT>O1k6pF-+mx{6w^hQ>0Ra~aO@Z&Q<0 z?vWqQ>gtp|>$>OAjtfcXi?F4ND2t1WQT65sY}B~EO=Pd@P88J|OVmFIHM4iH_aTBq zwFRLp;q?T_Z}wn(5P=X zg5XGh5Iogb7g4FrudD~JDZzP_#$ov_dH`xKe0rwPzrdg~IBSG_TK{{L4_}`{0Ss@O z^LIx%mWy&BU?$9|*@HPJ4uL<)uQri%=>a$njDAskaMrZ1`tt!2Zhva4` zwMS>xiN(UjuZGlQg4c9yNhJlJ({ja>4Wz zNM@`G0*2o$SLG#%k2N_{M`%l*Vy~|@UeGWuajuV(?xEI*b;%4H`(- zQ|kiDq3;D#&Ik$$+YZb8`=%C*>Fan&?vP(a4QAl%?4&uCO5XL zuGhT{_@^Jb!gCfR&A9WMVZvUjInE7ws!457l>+@=#)HBvMT;R^)n8~L)sqsS0wtd1 z{w4E8oKgmevKW_{$vWFOFIfn$KSh3JLoRY>YI{}<%L3TV=$0tS0&fA0m7+d}hjr=@ zkI4h~^VRqPI=BbG-oIJ%jz z9zJH!qhNG=9Iq2CC?tGBm`wJ(?R@dzT_FQh9gKP&VJ0Tbg!Ax-0{fFQ-0mCr^^4Od($0}Nko>Bu4Vk}yVb}#oRB^*w(>L+y#ea{|; zQgt$l#=T;(5E*L#O=}%;RO35T&xqUZs5&q{vm_F>6rd^OBJX&X)vC-I$M-ssL$O;ZYQ9Q@{ zPJo%AzM#&z^t%W?God^WYc9;GX$ie;%n6(rShMHw?Xk{haM%Nj3+LHJu{G$h$I+9h zpvFuJPQ@=fN?Ci?O^EqRu5D7-@r7;GwHyOlU%XcyN06^e+A7Xy^3&PTlciuid7uz5Q+5yl`Zxss_vKw3s%wl0F4htX+s(GQ1c zR!nGCt|JhOtIWjEsfK{s%0Vw&ML@qTGR*x@M2%A_7QuU(g+tWoSj|17I_J@S zK!k+0@?-VY0&Y9}$CclA;PNX|LTajnnN0!n&eNE+_kjk+S6-4hT2GNd#I+uaBG~`( zw`|&CC;Y$umXL%Ma_WDZ;obS+-5<~(o!5}SEh^Ig-xCk=XoU{)dy5jZ;|h7yP6FZG zRstQn-&bW^DIw`A_>jhJN|2KGedq?jfE;djVCQt9IC^|8P_J11x&?7l;cX-(?5UrvB599zuG*$nafC z5N_IixM>#*BFVk4;$>1olsEAq@_Uq^+5G#E#~vN^AKNAVn5e7Z9=h8-0U5f}N&O@C zy>l1k`U4a#{RgDlXQci^eEA3X>*HS_4#aPt9Yor5*L(ySxT|*dL8`kLAO~N_Av_1{ zpyGkMChPsp>#|2+saXn*W}1l%E-`^Wje+55lObUS$u{x_dzr2cPO@mE&y_i%S5 fG^k?sFOY;(>nZBpy&)lq-kn)QNJxuo|7raXi5||I delta 20086 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/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + 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. @@ -197,6 +197,10 @@ if "$cygwin" || "$msys" ; then 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, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 2bf2827..b544ccb 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -192,7 +192,8 @@ public void hyperlinkUpdate(HyperlinkEvent event) { public String[] getASMTransformerClass() { versionCheck(mcVersion, "CodeChickenCore"); return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.core.asm.TweakTransformer", - "codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer" }; + "codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer", + "codechicken.lib.asm.RedirectorTransformer" }; } @Override diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index e5c2574..dbfad36 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -7,6 +7,6 @@ "version": "${modVersion}", "mcversion": "${minecraftVersion}", "url": "http://www.minecraftforum.net/topic/909223", - "authorList": ["ChickenBones"] + "authorList": ["ChickenBones", "GTNH Team"] }] } From 7b0ab2182339b05ba6d9c4fe08e286cf23a5106c Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 8 Jan 2024 21:24:42 +0000 Subject: [PATCH 187/219] [ci skip] upgraded build system --- build.gradle | 33 +++++++++++++----------------- gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 43462 bytes gradlew | 17 +++++++-------- settings.gradle | 9 ++++---- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index 50c3291..952a3c5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1702141377 +//version: 1704650211 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -31,8 +31,7 @@ buildscript { maven { // GTNH RetroFuturaGradle and ASM Fork name "GTNH Maven" - url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + url "https://nexus.gtnewhorizons.com/repository/public/" } mavenLocal() } @@ -49,12 +48,12 @@ plugins { id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.palantir.git-version' version '3.0.0' apply false - id 'de.undercouch.download' version '5.4.0' + id 'de.undercouch.download' version '5.5.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.26' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -118,7 +117,7 @@ propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") propertyDefaultIfUnset("usesMavenPublishing", true) -propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") +propertyDefaultIfUnset("mavenPublishUrl", "https://nexus.gtnewhorizons.com/repository/releases/") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -573,13 +572,15 @@ afterEvaluate { repositories { maven { - name 'Overmind forge repo mirror' - url 'https://gregtech.overminddl1.com/' + name = "GTNH Maven" + url = "https://nexus.gtnewhorizons.com/repository/public/" + // Links for convenience: + // Simple HTML browsing: https://nexus.gtnewhorizons.com/service/rest/repository/browse/releases/ + // Rich web UI browsing: https://nexus.gtnewhorizons.com/#browse/browse:releases } maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' } maven { name 'sonatype' @@ -960,8 +961,7 @@ if (usesShadowedDependencies.toBoolean()) { configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) tasks.named("jar", Jar) { - enabled = false - finalizedBy(tasks.shadowJar) + archiveClassifier.set('dev-preshadow') } tasks.named("reobfJar", ReobfuscatedJar) { inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) @@ -970,11 +970,6 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { - tasks.named(runTask).configure { - dependsOn("shadowJar") - } - } } ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar ext.publishableObfJar = tasks.reobfJar @@ -1178,7 +1173,7 @@ publishing { if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { maven { url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") credentials { username = System.getenv("MAVEN_USER") ?: "NONE" password = System.getenv("MAVEN_PASSWORD") ?: "NONE" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NBa;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHdv(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95JG|l1#sAU|>I6NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8qLrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz 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 /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +145,7 @@ 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=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +202,11 @@ 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, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# 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" \ diff --git a/settings.gradle b/settings.gradle index 01ea5f1..8a66026 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,10 +4,9 @@ pluginManagement { maven { // RetroFuturaGradle name "GTNH Maven" - url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + url "https://nexus.gtnewhorizons.com/repository/public/" mavenContent { - includeGroup("com.gtnewhorizons.retrofuturagradle") + includeGroupByRegex("com\\.gtnewhorizons\\..+") } } gradlePluginPortal() @@ -17,8 +16,8 @@ pluginManagement { } plugins { - id 'com.diffplug.blowdryerSetup' version '1.6.0' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' // Provides java toolchains + id 'com.diffplug.blowdryerSetup' version '1.7.1' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains } blowdryerSetup { From 87168007d7b3423a2b4b13e12669507c4a3d5f9e Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 8 Jan 2024 21:24:44 +0000 Subject: [PATCH 188/219] [ci skip] upgraded build system --- build.gradle | 34 ++++++++++------------- gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 29 +++++++++++-------- settings.gradle | 9 +++--- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/build.gradle b/build.gradle index bdbaeb9..952a3c5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1702141377 +//version: 1704650211 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -31,8 +31,7 @@ buildscript { maven { // GTNH RetroFuturaGradle and ASM Fork name "GTNH Maven" - url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + url "https://nexus.gtnewhorizons.com/repository/public/" } mavenLocal() } @@ -49,12 +48,12 @@ plugins { id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.palantir.git-version' version '3.0.0' apply false - id 'de.undercouch.download' version '5.4.0' + id 'de.undercouch.download' version '5.5.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.26' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -118,7 +117,7 @@ propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") propertyDefaultIfUnset("usesMavenPublishing", true) -propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") +propertyDefaultIfUnset("mavenPublishUrl", "https://nexus.gtnewhorizons.com/repository/releases/") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -573,13 +572,15 @@ afterEvaluate { repositories { maven { - name 'Overmind forge repo mirror' - url 'https://gregtech.overminddl1.com/' + name = "GTNH Maven" + url = "https://nexus.gtnewhorizons.com/repository/public/" + // Links for convenience: + // Simple HTML browsing: https://nexus.gtnewhorizons.com/service/rest/repository/browse/releases/ + // Rich web UI browsing: https://nexus.gtnewhorizons.com/#browse/browse:releases } maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' } maven { name 'sonatype' @@ -960,8 +961,7 @@ if (usesShadowedDependencies.toBoolean()) { configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) tasks.named("jar", Jar) { - enabled = false - finalizedBy(tasks.shadowJar) + archiveClassifier.set('dev-preshadow') } tasks.named("reobfJar", ReobfuscatedJar) { inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) @@ -970,11 +970,6 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { - tasks.named(runTask).configure { - dependsOn("shadowJar") - } - } } ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar ext.publishableObfJar = tasks.reobfJar @@ -1178,7 +1173,7 @@ publishing { if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { maven { url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") credentials { username = System.getenv("MAVEN_USER") ?: "NONE" password = System.getenv("MAVEN_PASSWORD") ?: "NONE" @@ -1608,4 +1603,3 @@ if (file('addon.late.local.gradle.kts').exists()) { } else if (file('addon.late.local.gradle').exists()) { apply from: 'addon.late.local.gradle' } - diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 61574 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 ScNgau(U?ep-K_E5zy1%ZQTdPn diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 17a8ddc..1af9e09 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# 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"' +# 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 @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + 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. @@ -144,7 +145,7 @@ 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=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# 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" \ diff --git a/settings.gradle b/settings.gradle index 01ea5f1..8a66026 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,10 +4,9 @@ pluginManagement { maven { // RetroFuturaGradle name "GTNH Maven" - url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + url "https://nexus.gtnewhorizons.com/repository/public/" mavenContent { - includeGroup("com.gtnewhorizons.retrofuturagradle") + includeGroupByRegex("com\\.gtnewhorizons\\..+") } } gradlePluginPortal() @@ -17,8 +16,8 @@ pluginManagement { } plugins { - id 'com.diffplug.blowdryerSetup' version '1.6.0' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' // Provides java toolchains + id 'com.diffplug.blowdryerSetup' version '1.7.1' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains } blowdryerSetup { From c5b859466078baba7248b6b840761006391d1ca6 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Thu, 11 Jan 2024 23:14:18 +0100 Subject: [PATCH 189/219] update bs+gitignore --- .gitignore | 1 + build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 558ad12..40fb5e4 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ whitelist.json *.ipr *.iws src/main/resources/mixins.*.json +*.bat diff --git a/build.gradle b/build.gradle index 952a3c5..3eb19a2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1704650211 +//version: 1704751096 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -786,7 +786,7 @@ dependencies { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4') } java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} From 4e743ba64b5abfce87fb44dab0c92879c1b812ac Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Thu, 11 Jan 2024 23:15:32 +0100 Subject: [PATCH 190/219] update bs --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 952a3c5..3eb19a2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1704650211 +//version: 1704751096 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -786,7 +786,7 @@ dependencies { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4') } java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} From 4686fe8fa11a4514d25c48b8f4e1ecb4d458034a Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sun, 4 Feb 2024 19:57:37 +0000 Subject: [PATCH 191/219] [ci skip] upgraded build system --- build.gradle | 1604 +--------------------- gradle.properties | 167 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 20 +- settings.gradle | 10 +- 5 files changed, 149 insertions(+), 1654 deletions(-) diff --git a/build.gradle b/build.gradle index 3eb19a2..e57a16f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,1605 +1,5 @@ -//version: 1704751096 -/* - DO NOT CHANGE THIS FILE! - Also, you may replace this file at any time if there is an update available. - Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/build.gradle for updates. - */ +//version: 1707058017 - -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute -import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar -import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask -import com.gtnewhorizons.retrofuturagradle.util.Distribution -import com.matthewprenger.cursegradle.CurseArtifact -import com.matthewprenger.cursegradle.CurseRelation -import com.modrinth.minotaur.dependencies.ModDependency -import com.modrinth.minotaur.dependencies.VersionDependency -import org.gradle.internal.logging.text.StyledTextOutput.Style -import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.gradle.internal.xml.XmlTransformer -import org.jetbrains.gradle.ext.Application -import org.jetbrains.gradle.ext.Gradle - -import javax.inject.Inject -import java.nio.file.Files -import java.nio.file.Paths -import java.util.concurrent.TimeUnit - -buildscript { - repositories { - maven { - // GTNH RetroFuturaGradle and ASM Fork - name "GTNH Maven" - url "https://nexus.gtnewhorizons.com/repository/public/" - } - mavenLocal() - } -} plugins { - id 'java-library' - id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" - id 'eclipse' - id 'scala' - id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false - id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false - id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.palantir.git-version' version '3.0.0' apply false - id 'de.undercouch.download' version '5.5.0' - id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version - id 'com.modrinth.minotaur' version '2.+' apply false - id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27' -} - -print("You might want to check out './gradlew :faq' if your build fails.\n") - -boolean settingsupdated = verifySettingsGradle() -settingsupdated = verifyGitAttributes() || settingsupdated -if (settingsupdated) - throw new GradleException("Settings has been updated, please re-run task.") - -// In submodules, .git is a file pointing to the real git dir -if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { - apply plugin: 'com.palantir.git-version' -} - -def out = services.get(StyledTextOutputFactory).create('an-output') - -def projectJavaVersion = JavaLanguageVersion.of(8) - -boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false -boolean disableCheckstyle = project.hasProperty("disableCheckstyle") ? project.disableCheckstyle.toBoolean() : false - -final String CHECKSTYLE_CONFIG = """ - - - - - - - - - - - -""" - -checkPropertyExists("modName") -checkPropertyExists("modId") -checkPropertyExists("modGroup") -checkPropertyExists("autoUpdateBuildScript") -checkPropertyExists("minecraftVersion") -checkPropertyExists("forgeVersion") -checkPropertyExists("replaceGradleTokenInFile") -checkPropertyExists("gradleTokenVersion") -checkPropertyExists("apiPackage") -checkPropertyExists("accessTransformersFile") -checkPropertyExists("usesMixins") -checkPropertyExists("mixinPlugin") -checkPropertyExists("mixinsPackage") -checkPropertyExists("coreModClass") -checkPropertyExists("containsMixinsAndOrCoreModOnly") -checkPropertyExists("usesShadowedDependencies") -checkPropertyExists("developmentEnvironmentUserName") - -propertyDefaultIfUnset("generateGradleTokenClass", "") -propertyDefaultIfUnset("includeWellKnownRepositories", true) -propertyDefaultIfUnset("noPublishedSources", false) -propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) -propertyDefaultIfUnset("forceEnableMixins", false) -propertyDefaultIfUnset("channel", "stable") -propertyDefaultIfUnset("mappingsVersion", "12") -propertyDefaultIfUnset("usesMavenPublishing", true) -propertyDefaultIfUnset("mavenPublishUrl", "https://nexus.gtnewhorizons.com/repository/releases/") -propertyDefaultIfUnset("modrinthProjectId", "") -propertyDefaultIfUnset("modrinthRelations", "") -propertyDefaultIfUnset("curseForgeProjectId", "") -propertyDefaultIfUnset("curseForgeRelations", "") -propertyDefaultIfUnset("minimizeShadowedDependencies", true) -propertyDefaultIfUnset("relocateShadowedDependencies", true) -// Deprecated properties (kept for backwards compat) -propertyDefaultIfUnset("gradleTokenModId", "") -propertyDefaultIfUnset("gradleTokenModName", "") -propertyDefaultIfUnset("gradleTokenGroupName", "") - -propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only -propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only - -// this is meant to be set using the user wide property file. by default we do nothing. -propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" - -project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts -if (!disableSpotless) { - apply plugin: 'com.diffplug.spotless' - apply from: Blowdryer.file('spotless.gradle') -} - -if (!disableCheckstyle) { - apply plugin: 'checkstyle' - tasks.named("checkstylePatchedMc") { enabled = false } - tasks.named("checkstyleMcLauncher") { enabled = false } - tasks.named("checkstyleIdeVirtualMain") { enabled = false } - tasks.named("checkstyleInjectedTags") { enabled = false } - checkstyle { - config = resources.text.fromString(CHECKSTYLE_CONFIG) - } -} - -String javaSourceDir = "src/main/java/" -String scalaSourceDir = "src/main/scala/" -String kotlinSourceDir = "src/main/kotlin/" - -if (usesShadowedDependencies.toBoolean()) { - apply plugin: "com.github.johnrengelman.shadow" -} - -java { - toolchain { - if (enableModernJavaSyntax.toBoolean()) { - languageVersion.set(JavaLanguageVersion.of(17)) - } else { - languageVersion.set(projectJavaVersion) - } - vendor.set(JvmVendorSpec.AZUL) - } - if (!noPublishedSources) { - withSourcesJar() - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = "UTF-8" -} - -tasks.withType(ScalaCompile).configureEach { - options.encoding = "UTF-8" -} - -pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { - // If Kotlin is enabled in the project - kotlin { - jvmToolchain(8) - } - // Kotlin hacks our source sets, so we hack Kotlin's tasks - def disabledKotlinTaskList = [ - "kaptGenerateStubsMcLauncherKotlin", - "kaptGenerateStubsPatchedMcKotlin", - "kaptGenerateStubsInjectedTagsKotlin", - "compileMcLauncherKotlin", - "compilePatchedMcKotlin", - "compileInjectedTagsKotlin", - "kaptMcLauncherKotlin", - "kaptPatchedMcKotlin", - "kaptInjectedTagsKotlin", - "kspMcLauncherKotlin", - "kspPatchedMcKotlin", - "kspInjectedTagsKotlin", - ] - tasks.configureEach { task -> - if (task.name in disabledKotlinTaskList) { - task.enabled = false - } - } -} - -configurations { - create("runtimeOnlyNonPublishable") { - description = "Runtime only dependencies that are not published alongside the jar" - canBeConsumed = false - canBeResolved = false - } - - create("devOnlyNonPublishable") { - description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" - canBeConsumed = false - canBeResolved = false - } - compileOnly.extendsFrom(devOnlyNonPublishable) - runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) -} - -if (enableModernJavaSyntax.toBoolean()) { - repositories { - mavenCentral { - mavenContent { - includeGroup("me.eigenraven.java8unsupported") - } - } - } - - dependencies { - annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' - // workaround for https://github.com/bsideup/jabel/issues/174 - annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' - compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { - transitive = false // We only care about the 1 annotation class - } - // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. - patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') - } - - tasks.withType(JavaCompile).configureEach { - if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) { - return - } - sourceCompatibility = 17 // for the IDE support - options.release.set(8) - - javaCompiler.set(javaToolchains.compilerFor { - languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.AZUL) - }) - } -} - -eclipse { - classpath { - downloadSources = true - downloadJavadoc = true - } -} - -final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char) -final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char) - -String targetPackageJava = javaSourceDir + modGroupPath -String targetPackageScala = scalaSourceDir + modGroupPath -String targetPackageKotlin = kotlinSourceDir + modGroupPath -if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) -} - -if (apiPackage) { - targetPackageJava = javaSourceDir + modGroupPath + "/" + apiPackagePath - targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath - targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath - if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) - } -} - -if (accessTransformersFile) { - for (atFile in accessTransformersFile.split(" ")) { - String targetFile = "src/main/resources/META-INF/" + atFile.trim() - if (!getFile(targetFile).exists()) { - throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) - } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) - } -} else { - boolean atsFound = false - for (File at : sourceSets.getByName("main").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - atsFound = true - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) - } - } - for (File at : sourceSets.getByName("api").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - atsFound = true - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) - } - } - if (atsFound) { - logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name") - } -} - -if (usesMixins.toBoolean()) { - if (mixinsPackage.isEmpty()) { - throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") - } - final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/") - final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/") - - targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath - targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath - targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath - if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) - } - - if (!mixinPlugin.isEmpty()) { - String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" - String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" - String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".kt" - if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { - throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) - } - } -} - -if (coreModClass) { - final String coreModPath = coreModClass.toString().replaceAll("\\.", "/") - String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java" - String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java" - String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".kt" - if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { - throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) - } -} - -configurations.configureEach { - resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) - - // Make sure GregTech build won't time out - System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String) - System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String) -} - -// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version -try { - 'git config core.fileMode false'.execute() -} -catch (Exception ignored) { - out.style(Style.Failure).println("git isn't installed at all") -} - -// Pulls version first from the VERSION env and then git tag -String identifiedVersion -String versionOverride = System.getenv("VERSION") ?: null -try { - // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty - if (versionOverride == null) { - def gitDetails = versionDetails() - def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning - String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') - if (branchName.startsWith('origin/')) { - branchName = branchName.minus('origin/') - } - branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver - identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' - if (gitDetails.commitDistance > 0) { - identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" - if (isDirty) { - identifiedVersion += "-dirty" - } - } else if (isDirty) { - identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" - } - } else { - identifiedVersion = versionOverride - } -} -catch (Exception ignored) { - out.style(Style.Failure).text( - 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' + - 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + - 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)' - ) - versionOverride = 'NO-GIT-TAG-SET' - identifiedVersion = versionOverride -} -version = identifiedVersion -ext { - modVersion = identifiedVersion -} - -if (identifiedVersion == versionOverride) { - out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') -} - -group = "com.github.GTNewHorizons" -if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - base { - archivesName = customArchiveBaseName - } -} else { - base { - archivesName = modId - } -} - - -minecraft { - if (replaceGradleTokenInFile) { - for (f in replaceGradleTokenInFile.split(',')) { - tagReplacementFiles.add f - } - } - if (gradleTokenModId) { - injectedTags.put gradleTokenModId, modId - } - if (gradleTokenModName) { - injectedTags.put gradleTokenModName, modName - } - if (gradleTokenVersion) { - injectedTags.put gradleTokenVersion, modVersion - } - if (gradleTokenGroupName) { - injectedTags.put gradleTokenGroupName, modGroup - } - if (enableGenericInjection.toBoolean()) { - injectMissingGenerics.set(true) - } - - username = developmentEnvironmentUserName.toString() - - lwjgl3Version = "3.3.2" - - // Enable assertions in the current mod - extraRunJvmArguments.add("-ea:${modGroup}") - - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - extraRunJvmArguments.addAll([ - "-Dmixin.debug.countInjections=true", - "-Dmixin.debug.verbose=true", - "-Dmixin.debug.export=true" - ]) - } - } - - // Blowdryer is present in some old mod builds, do not propagate it further as a dependency - // IC2 has no reobf jars in its Maven - groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"]) -} - -if (generateGradleTokenClass) { - tasks.injectTags.outputClassName.set(generateGradleTokenClass) -} - -// Custom reobf auto-mappings -configurations.configureEach { - dependencies.configureEach { dep -> - if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) { - if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") { - // https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971 - project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971") - } - } - } - def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) - if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { - resolutionStrategy.eachDependency { DependencyResolveDetails details -> - // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server - if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { - details.useVersion '2388750' - details.because 'Pick obfuscated jar' - } - } - } -} - -// Ensure tests have access to minecraft classes -sourceSets { - test { - java { - compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output - runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output - } - } -} - -if (file('addon.gradle.kts').exists()) { - apply from: 'addon.gradle.kts' -} else if (file('addon.gradle').exists()) { - apply from: 'addon.gradle' -} - -// File for local tweaks not commited to Git -if (file('addon.local.gradle.kts').exists()) { - apply from: 'addon.local.gradle.kts' -} else if (file('addon.local.gradle').exists()) { - apply from: 'addon.local.gradle' -} - -// Allow unsafe repos but warn -repositories.configureEach { repo -> - if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { - if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) { - logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'") - repo.allowInsecureProtocol = true - } - } -} - -if (file('repositories.gradle.kts').exists()) { - apply from: 'repositories.gradle.kts' -} else if (file('repositories.gradle').exists()) { - apply from: 'repositories.gradle' -} else { - logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") - throw new RuntimeException("Missing repositories.gradle[.kts]") -} - -configurations { - runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) - testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) - for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - if (usesShadowedDependencies.toBoolean()) { - config.extendsFrom(shadowImplementation) - // TODO: remove Compile after all uses are refactored to Implementation - config.extendsFrom(shadeCompile) - config.extendsFrom(shadowCompile) - } - } - // A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api" - create("compile") { - description = "Deprecated: use api or implementation instead, gets put in api" - canBeConsumed = false - canBeResolved = false - visible = false - } - create("testCompile") { - description = "Deprecated: use testImplementation instead" - canBeConsumed = false - canBeResolved = false - visible = false - } - api.extendsFrom(compile) - testImplementation.extendsFrom(testCompile) -} - -afterEvaluate { - if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) { - logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`") - logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle") - } -} - -repositories { - maven { - name = "GTNH Maven" - url = "https://nexus.gtnewhorizons.com/repository/public/" - // Links for convenience: - // Simple HTML browsing: https://nexus.gtnewhorizons.com/service/rest/repository/browse/releases/ - // Rich web UI browsing: https://nexus.gtnewhorizons.com/#browse/browse:releases - } - maven { - name 'Overmind forge repo mirror' - url 'https://gregtech.overminddl1.com/' - } - maven { - name 'sonatype' - url 'https://oss.sonatype.org/content/repositories/snapshots/' - content { - includeGroup "org.lwjgl" - } - } - if (includeWellKnownRepositories.toBoolean()) { - exclusiveContent { - forRepository { - maven { - name "CurseMaven" - url "https://cursemaven.com" - } - } - filter { - includeGroup "curse.maven" - } - } - exclusiveContent { - forRepository { - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - } - } - filter { - includeGroup "maven.modrinth" - } - } - maven { - name = "ic2" - url = getURL("https://maven2.ic2.player.to/", "https://maven.ic2.player.to/") - content { - includeGroup "net.industrial-craft" - } - metadataSources { - mavenPom() - artifact() - } - } - maven { - name "MMD Maven" - url "https://maven.mcmoddev.com/" - } - } -} - -def mixinProviderGroup = "io.github.legacymoddingmc" -def mixinProviderModule = "unimixins" -def mixinProviderVersion = "0.1.13" -def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" -def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" -ext.mixinProviderSpec = mixinProviderSpec - -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' - -dependencies { - if (usesMixins.toBoolean()) { - annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') - annotationProcessor('com.google.guava:guava:24.1.1-jre') - annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor(mixinProviderSpec) - if (usesMixinDebug.toBoolean()) { - runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') - } - } - if (usesMixins.toBoolean()) { - implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) - } else if (forceEnableMixins.toBoolean()) { - runtimeOnlyNonPublishable(mixinProviderSpec) - } -} - -pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - if (usesMixins.toBoolean()) { - dependencies { - kapt(mixinProviderSpec) - } - } -} - -// Replace old mixin mods with unimixins -// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier -configurations.all { - resolutionStrategy.dependencySubstitution { - substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") - - substitute module('org.scala-lang:scala-library:2.11.1') using module('org.scala-lang:scala-library:2.11.5') because('To allow mixing with Java 8 targets') - } -} - -dependencies { - constraints { - def minGtnhLibVersion = "0.0.13" - implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - } -} - -if (file('dependencies.gradle.kts').exists()) { - apply from: 'dependencies.gradle.kts' -} else if (file('dependencies.gradle').exists()) { - apply from: 'dependencies.gradle' -} else { - logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") - throw new RuntimeException("Missing dependencies.gradle[.kts]") -} - -tasks.register('generateAssets') { - group = "GTNH Buildscript" - description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" - onlyIf { usesMixins.toBoolean() } - doLast { - def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") - if (!mixinConfigFile.exists()) { - def mixinPluginLine = "" - if (!mixinPlugin.isEmpty()) { - // We might not have a mixin plugin if we're using early/late mixins - mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ - } - - mixinConfigFile.text = """{ - "required": true, - "minVersion": "0.8.5-GTNH", - "package": "${modGroup}.${mixinsPackage}",${mixinPluginLine} - "refmap": "${mixingConfigRefMap}", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "mixins": [], - "client": [], - "server": [] -} -""" - } - } -} - -if (usesMixins.toBoolean()) { - tasks.named("processResources").configure { - dependsOn("generateAssets") - } - - tasks.named("compileJava", JavaCompile).configure { - options.compilerArgs += [ - // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code - "-XDenableSunApiLintControl", - "-XDignore.symbol.file" - ] - } -} - -tasks.named("processResources", ProcessResources).configure { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.mcVersion - exclude("spotless.gradle") - - // replace stuff in mcmod.info, nothing else. replaces ${key} with value in text - filesMatching("mcmod.info") { - expand "minecraftVersion": project.minecraft.mcVersion, - "modVersion": modVersion, - "modId": modId, - "modName": modName - } - - if (usesMixins.toBoolean()) { - dependsOn("compileJava", "compileScala") - } -} - -ext.java17Toolchain = (JavaToolchainSpec spec) -> { - spec.languageVersion.set(JavaLanguageVersion.of(17)) - spec.vendor.set(JvmVendorSpec.matching("jetbrains")) -} - -ext.java17DependenciesCfg = configurations.create("java17Dependencies") { - extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution - canBeConsumed = false -} -ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { - canBeConsumed = false -} - -dependencies { - def lwjgl3ifyVersion = '1.5.7' - if (modId != 'lwjgl3ify') { - java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") - } - if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4') - } - - java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} -} - -ext.java17JvmArgs = [ - // Java 9+ support - "--illegal-access=warn", - "-Djava.security.manager=allow", - "-Dfile.encoding=UTF-8", - "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", - "--add-opens", "java.base/java.net=ALL-UNNAMED", - "--add-opens", "java.base/java.nio=ALL-UNNAMED", - "--add-opens", "java.base/java.io=ALL-UNNAMED", - "--add-opens", "java.base/java.lang=ALL-UNNAMED", - "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", - "--add-opens", "java.base/java.text=ALL-UNNAMED", - "--add-opens", "java.base/java.util=ALL-UNNAMED", - "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", - "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", - "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", - "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", - "--add-modules", "jdk.dynalink", - "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", - "--add-modules", "java.sql.rowset", - "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" -] - -ext.hotswapJvmArgs = [ - // DCEVM advanced hot reload - "-XX:+AllowEnhancedClassRedefinition", - "-XX:HotswapAgent=fatjar" -] - -ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { - group = "GTNH Buildscript" - description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" - def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' - def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} - def targetFilename = "hotswap-agent.jar" - onlyIf { - !targetFolderProvider.get().file(targetFilename).asFile.exists() - } - doLast { - def targetFolder = targetFolderProvider.get() - targetFolder.asFile.mkdirs() - download.run { - src hsaUrl - dest targetFolder.file(targetFilename).asFile - overwrite false - tempAndMove true - } - } -} - -public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { - // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable - private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); - - @Input - public boolean getEnableHotswap() { return enableHotswap } - @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") - public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } - - @Inject - public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { - super(side, gradle) - - this.lwjglVersion = 3 - this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) - this.extraJvmArgs.addAll(project.java17JvmArgs) - this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) - - this.classpath(project.java17PatchDependenciesCfg) - if (side == Distribution.CLIENT) { - this.classpath(project.minecraftTasks.lwjgl3Configuration) - } - // Use a raw provider instead of map to not create a dependency on the task - this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) - this.classpath.filter { file -> - !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 - } - this.classpath(project.java17DependenciesCfg) - } - - public void setup(Project project) { - super.setup(project) - if (project.usesMixins.toBoolean()) { - this.extraJvmArgs.addAll(project.provider(() -> { - def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) - mixinCfg.canBeConsumed = false - mixinCfg.transitive = false - enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] - })) - } - } -} - -def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") -runClient17Task.configure { - setup(project) - group = "Modded Minecraft" - description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" - dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') - mainClass = "GradleStart" - username = minecraft.username - userUUID = minecraft.userUUID -} - -def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") -runServer17Task.configure { - setup(project) - group = "Modded Minecraft" - description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" - dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') - mainClass = "GradleStartServer" - extraArgs.add("nogui") -} - -def getManifestAttributes() { - def manifestAttributes = [:] - if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } - - if (accessTransformersFile) { - manifestAttributes += ["FMLAT": accessTransformersFile.toString()] - } - - if (coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } - - if (usesMixins.toBoolean()) { - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod": !containsMixinsAndOrCoreModOnly.toBoolean() - ] - } - return manifestAttributes -} - -tasks.named("jar", Jar).configure { - manifest { - attributes(getManifestAttributes()) - } -} - -if (usesShadowedDependencies.toBoolean()) { - tasks.named("shadowJar", ShadowJar).configure { - manifest { - attributes(getManifestAttributes()) - } - - if (minimizeShadowedDependencies.toBoolean()) { - minimize() // This will only allow shading for actually used classes - } - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile, - project.configurations.shadeCompile - ] - archiveClassifier.set('dev') - if (relocateShadowedDependencies.toBoolean()) { - relocationPrefix = modGroup + ".shadow" - enableRelocation = true - } - } - configurations.runtimeElements.outgoing.artifacts.clear() - configurations.apiElements.outgoing.artifacts.clear() - configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) - configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) - tasks.named("jar", Jar) { - archiveClassifier.set('dev-preshadow') - } - tasks.named("reobfJar", ReobfuscatedJar) { - inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) - } - AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") - javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { - skip() - } -} -ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar -ext.publishableObfJar = tasks.reobfJar - -tasks.register('apiJar', Jar) { - from(sourceSets.main.allSource) { - include modGroupPath + "/" + apiPackagePath + '/**' - } - - from(sourceSets.main.output) { - include modGroupPath + "/" + apiPackagePath + '/**' - } - - from(sourceSets.main.resources.srcDirs) { - include("LICENSE") - } - - getArchiveClassifier().set('api') -} - -artifacts { - if (!noPublishedSources) { - archives tasks.named("sourcesJar") - } - if (apiPackage) { - archives tasks.named("apiJar") - } -} - -idea { - module { - downloadJavadoc = true - downloadSources = true - inheritOutputDirs = true - } - project { - settings { - if (ideaOverrideBuildType != "") { - delegateActions { - if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { - delegateBuildRunToGradle = true - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE - } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { - delegateBuildRunToGradle = false - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM - } else { - throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') - } - } - } - runConfigurations { - "0. Build and Test"(Gradle) { - taskNames = ["build"] - } - "1. Run Client"(Gradle) { - taskNames = ["runClient"] - } - "2. Run Server"(Gradle) { - taskNames = ["runServer"] - } - "1a. Run Client (Java 17)"(Gradle) { - taskNames = ["runClient17"] - } - "2a. Run Server (Java 17)"(Gradle) { - taskNames = ["runServer17"] - } - "1b. Run Client (Java 17, Hotswap)"(Gradle) { - taskNames = ["runClient17"] - envs = ["HOTSWAP": "true"] - } - "2b. Run Server (Java 17, Hotswap)"(Gradle) { - taskNames = ["runServer17"] - envs = ["HOTSWAP": "true"] - } - "3. Run Obfuscated Client"(Gradle) { - taskNames = ["runObfClient"] - } - "4. Run Obfuscated Server"(Gradle) { - taskNames = ["runObfServer"] - } - if (!disableSpotless) { - "5. Apply spotless"(Gradle) { - taskNames = ["spotlessApply"] - } - } - def coreModArgs = "" - if (coreModClass) { - coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"' - } - "Run Client (IJ Native)"(Application) { - mainClass = "GradleStart" - moduleName = project.name + ".ideVirtualMain" - afterEvaluate { - workingDirectory = tasks.runClient.workingDir.absolutePath - programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') - jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + - ' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + - coreModArgs - } - } - "Run Server (IJ Native)"(Application) { - mainClass = "GradleStartServer" - moduleName = project.name + ".ideVirtualMain" - afterEvaluate { - workingDirectory = tasks.runServer.workingDir.absolutePath - programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') - jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + - ' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + - coreModArgs - } - } - } - compiler.javac { - afterEvaluate { - javacAdditionalOptions = "-encoding utf8" - moduleJavacAdditionalOptions = [ - (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') - ] - } - } - withIDEADir { File ideaDir -> - if (!ideaDir.path.contains(".idea")) { - // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory - ideaDir = new File(ideaDir, ".idea") - } - if (ideaDir.isDirectory()) { - def miscFile = new File(ideaDir, "misc.xml") - if (miscFile.isFile()) { - boolean dirty = false - def miscTransformer = new XmlTransformer() - miscTransformer.addAction { root -> - Node rootNode = root.asNode() - def rootManager = rootNode - .component.find { it.@name == 'ProjectRootManager' } - if (!rootManager) { - rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) - dirty = true - } - def output = rootManager.output - if (!output) { - output = rootManager.appendNode('output') - dirty = true - } - if (!output.@url) { - // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. - // This is a sensible default for most setups - output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' - dirty = true - } - } - def result = miscTransformer.transform(miscFile.text) - if (dirty) { - miscFile.write(result) - } - } else { - miscFile.text = """ - - - - - -""" - } - } - } - } - } -} - -tasks.named("processIdeaSettings").configure { - dependsOn("injectTags") -} - -tasks.named("ideVirtualMainClasses").configure { - // Make IntelliJ "Build project" build the mod jars - dependsOn("jar", "reobfJar") - if (!disableSpotless) { - dependsOn("spotlessCheck") - } -} - -// workaround variable hiding in pom processing -def projectConfigs = project.configurations - -publishing { - publications { - create("maven", MavenPublication) { - from components.java - - if (apiPackage) { - artifact apiJar - } - - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group - artifactId = System.getenv("ARTIFACT_ID") ?: project.name - // Using the identified version, not project.version as it has the prepended 1.7.10 - version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - } - } - repositories { - if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { - maven { - url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" - } - } - } - } -} - -if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { - apply plugin: 'com.modrinth.minotaur' - - File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") - - modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = modrinthProjectId - versionNumber = identifiedVersion - versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" - changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" - uploadFile = publishableObfJar - additionalFiles = getSecondaryArtifacts() - gameVersions = [minecraftVersion] - loaders = ["forge"] - debugMode = false - } - - if (modrinthRelations.size() != 0) { - String[] deps = modrinthRelations.split(";") - deps.each { dep -> - if (dep.size() == 0) { - return - } - String[] parts = dep.split(":") - String[] qual = parts[0].split("-") - addModrinthDep(qual[0], qual[1], parts[1]) - } - } - if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "unimixins") - } - tasks.modrinth.dependsOn(build) - tasks.publish.dependsOn(tasks.modrinth) -} - -if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) { - apply plugin: 'com.matthewprenger.cursegradle' - - File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") - - curseforge { - apiKey = System.getenv("CURSEFORGE_TOKEN") - project { - id = curseForgeProjectId - if (changelogFile.exists()) { - changelogType = "markdown" - changelog = changelogFile - } - releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" - addGameVersion minecraftVersion - addGameVersion "Forge" - mainArtifact publishableObfJar - for (artifact in getSecondaryArtifacts()) addArtifact artifact - } - - options { - javaIntegration = false - forgeGradleIntegration = false - debug = false - } - } - - if (curseForgeRelations.size() != 0) { - String[] deps = curseForgeRelations.split(";") - deps.each { dep -> - if (dep.size() == 0) { - return - } - String[] parts = dep.split(":") - addCurseForgeRelation(parts[0], parts[1]) - } - } - if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "unimixins") - } - tasks.curseforge.dependsOn(build) - tasks.publish.dependsOn(tasks.curseforge) -} - -def addModrinthDep(String scope, String type, String name) { - com.modrinth.minotaur.dependencies.Dependency dep; - if (!(scope in ["required", "optional", "incompatible", "embedded"])) { - throw new Exception("Invalid modrinth dependency scope: " + scope) - } - switch (type) { - case "project": - dep = new ModDependency(name, scope) - break - case "version": - dep = new VersionDependency(name, scope) - break - default: - throw new Exception("Invalid modrinth dependency type: " + type) - } - project.modrinth.dependencies.add(dep) -} - -def addCurseForgeRelation(String type, String name) { - if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { - throw new Exception("Invalid CurseForge relation type: " + type) - } - CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact - CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation())) - rel."$type"(name) -} - -// Updating - -def buildscriptGradleVersion = "8.5" - -tasks.named('wrapper', Wrapper).configure { - gradleVersion = buildscriptGradleVersion -} - -tasks.register('updateBuildScript') { - group = 'GTNH Buildscript' - description = 'Updates the build script to the latest version' - - if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { - dependsOn('wrapper') - } - - doLast { - if (performBuildScriptUpdate()) return - - print("Build script already up-to-date!") - } -} - -if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) { - if (autoUpdateBuildScript.toBoolean()) { - performBuildScriptUpdate() - } else { - out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") - if (gradle.gradleVersion != buildscriptGradleVersion) { - out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") - } - } -} - -// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large -tasks.register('faq') { - group = 'GTNH Buildscript' - description = 'Prints frequently asked questions about building a project' - - doLast { - print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + - "Or you can manually check if the versions are still on the distributing sites - " + - "the links can be found in repositories.gradle and build.gradle:repositories, " + - "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + - "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + - "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + - "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + - "Java 9 or later.") - } -} - -static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle") -} - -static URL exampleSettingsGradleUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example") -} - -static URL exampleGitAttributesUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes") -} - - -boolean verifyGitAttributes() { - def gitattributesFile = getFile(".gitattributes") - if (!gitattributesFile.exists()) { - println("Downloading default .gitattributes") - exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } } - exec { - workingDir '.' - commandLine 'git', 'add', '--renormalize', '.' - } - return true - } - return false -} - -boolean verifySettingsGradle() { - def settingsFile = getFile("settings.gradle") - if (!settingsFile.exists()) { - println("Downloading default settings.gradle") - exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } - return true - } - return false -} - -boolean performBuildScriptUpdate() { - if (isNewBuildScriptVersionAvailable()) { - def buildscriptFile = getFile("build.gradle") - availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } - def out = services.get(StyledTextOutputFactory).create('buildscript-update-output') - out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") - boolean settingsupdated = verifySettingsGradle() - settingsupdated = verifyGitAttributes() || settingsupdated - if (settingsupdated) - throw new GradleException("Settings has been updated, please re-run task.") - return true - } - return false -} - -boolean isNewBuildScriptVersionAvailable() { - Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] - - String currentBuildScript = getFile("build.gradle").getText() - String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScriptHash - try { - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - availableBuildScriptHash = getVersionHash(availableBuildScript) - } catch (IOException e) { - logger.warn("Could not check for buildscript update availability: {}", e.message) - return false - } - - boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash - return !isUpToDate -} - -static String getVersionHash(String buildScriptContent) { - String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") - if (versionLine != null) { - return versionLine.split(": ").last() - } - return "" -} - -// Parameter Deobfuscation - -tasks.register('deobfParams') { - group = 'GTNH Buildscript' - description = 'Rename all obfuscated parameter names inherited from Minecraft classes' - doLast { // TODO - - String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" - String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" - String paramsCSV = "$mcpDir/params.csv" - - download.run { - src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" - dest mcpZIP - overwrite false - } - - if (!file(paramsCSV).exists()) { - println("Extracting MCP archive ...") - copy { - from(zipTree(mcpZIP)) - into(mcpDir) - } - } - - println("Parsing params.csv ...") - Map params = new HashMap<>() - Files.lines(Paths.get(paramsCSV)).forEach { line -> - String[] cells = line.split(",") - if (cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) { - params.put(cells[0], cells[1]) - } - } - - out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!") - out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.") - } -} - -static int replaceParams(File file, Map params) { - int fileCount = 0 - - if (file.isDirectory()) { - for (File f : file.listFiles()) { - fileCount += replaceParams(f, params) - } - return fileCount - } - println("Visiting ${file.getName()} ...") - try { - String content = new String(Files.readAllBytes(file.toPath())) - int hash = content.hashCode() - params.forEach { key, value -> - content = content.replaceAll(key, value) - } - if (hash != content.hashCode()) { - Files.write(file.toPath(), content.getBytes("UTF-8")) - return 1 - } - } catch (Exception e) { - e.printStackTrace() - } - return 0 -} - -// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) - -def deobf(String sourceURL) { - try { - URL url = new URL(sourceURL) - String fileName = url.getFile() - - //get rid of directories: - int lastSlash = fileName.lastIndexOf("/") - if (lastSlash > 0) { - fileName = fileName.substring(lastSlash + 1) - } - //get rid of extension: - if (fileName.endsWith(".jar") || fileName.endsWith(".litemod")) { - fileName = fileName.substring(0, fileName.lastIndexOf(".")) - } - - String hostName = url.getHost() - if (hostName.startsWith("www.")) { - hostName = hostName.substring(4) - } - List parts = Arrays.asList(hostName.split("\\.")) - Collections.reverse(parts) - hostName = String.join(".", parts) - - return deobf(sourceURL, "$hostName/$fileName") - } catch (Exception ignored) { - return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") - } -} - -def deobfMaven(String repoURL, String mavenDep) { - if (!repoURL.endsWith("/")) { - repoURL += "/" - } - String[] parts = mavenDep.split(":") - parts[0] = parts[0].replace('.', '/') - def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" - return deobf(jarURL) -} - -def deobfCurse(String curseDep) { - return dependencies.rfg.deobf("curse.maven:$curseDep") -} - -// The method above is to be preferred. Use this method if the filename is not at the end of the URL. -def deobf(String sourceURL, String rawFileName) { - String bon2Version = "2.5.1" - String fileName = URLDecoder.decode(rawFileName, "UTF-8") - String cacheDir = "$project.gradle.gradleUserHomeDir/caches" - String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" - - download.run { - src sourceURL - dest obfFile - quiet true - overwrite false - } - return dependencies.rfg.deobf(files(obfFile)) -} -// Helper methods - -def checkPropertyExists(String propertyName) { - if (!project.hasProperty(propertyName)) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") - } -} - -def propertyDefaultIfUnset(String propertyName, defaultValue) { - if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { - project.ext.setProperty(propertyName, defaultValue) - } -} - -def getFile(String relativePath) { - return new File(projectDir, relativePath) -} - -def getSecondaryArtifacts() { - // Because noPublishedSources from the beginning of the script is somehow not visible here... - boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - def secondaryArtifacts = [publishableDevJar] - if (!noPublishedSources) secondaryArtifacts += [sourcesJar] - if (apiPackage) secondaryArtifacts += [apiJar] - return secondaryArtifacts -} - -def getURL(String main, String fallback) { - return pingURL(main, 10000) ? main : fallback -} - -// credit: https://stackoverflow.com/a/3584332 -def pingURL(String url, int timeout) { - url = url.replaceFirst("^https", "http") // Otherwise an exception may be thrown on invalid SSL certificates. - try { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection() - connection.setConnectTimeout(timeout) - connection.setReadTimeout(timeout) - connection.setRequestMethod("HEAD") - int responseCode = connection.getResponseCode() - return 200 <= responseCode && responseCode <= 399 - } catch (IOException ignored) { - return false - } -} - -// For easier scripting of things that require variables defined earlier in the buildscript -if (file('addon.late.gradle.kts').exists()) { - apply from: 'addon.late.gradle.kts' -} else if (file('addon.late.gradle').exists()) { - apply from: 'addon.late.gradle' -} - -// File for local tweaks not commited to Git -if (file('addon.late.local.gradle.kts').exists()) { - apply from: 'addon.late.local.gradle.kts' -} else if (file('addon.late.local.gradle').exists()) { - apply from: 'addon.late.local.gradle' + id 'com.gtnewhorizons.gtnhconvention' } diff --git a/gradle.properties b/gradle.properties index bc5ab4e..6d8ad4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,85 +1,134 @@ +# ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable. +# LOCAL to test local config updates. +gtnh.settings.blowdryerTag = 0.2.0 + +# Human-readable mod name, available for mcmod.info population. modName = CodeChicken Core -# This is a case-sensitive string to identify your mod. Convention is to use lower case. +# Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation. +# Conventionally lowercase. modId = CodeChickenCore +# Root package of the mod, used to find various classes in other properties, +# mcmod.info substitution, enabling assertions in run tasks, etc. modGroup = codechicken -# WHY is there no version field? -# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the -# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/ +# Whether to use modGroup as the maven publishing group. +# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods. +useModGroupForPublishing = false -# Will update your build.gradle automatically whenever an update is available +# Updates your build.gradle and settings.gradle automatically whenever an update is available. autoUpdateBuildScript = false +# Version of Minecraft to target minecraftVersion = 1.7.10 + +# Version of Minecraft Forge to target forgeVersion = 10.13.4.1614 -# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you -# restart Minecraft in development. Choose this dependent on your mod: -# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name -# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty +# Specify an MCP channel for dependency deobfuscation and the deobfParams task. +channel = stable + +# Specify an MCP mappings version for dependency deobfuscation and the deobfParams task. +mappingsVersion = 12 + +# Defines other MCP mappings for dependency deobfuscation. +remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ + +# Select a default username for testing your mod. You can always override this per-run by running +# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE. developmentEnvironmentUserName = Developer -# Generate a class with String fields for the mod id, name, version and group name named with the fields below +# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8. +# See https://github.com/bsideup/jabel for details on how this works. +enableModernJavaSyntax = false + +# Enables injecting missing generics into the decompiled source code for a better coding experience. +# Turns most publicly visible List, Map, etc. into proper List, Map types. +enableGenericInjection = false + +# Generate a class with a String field for the mod version named as defined below. +# If generateGradleTokenClass is empty or not missing, no such class will be generated. +# If gradleTokenVersion is empty or missing, the field will not be present in the class. generateGradleTokenClass = codechicken.core.asm.Tags + +# Name of the token containing the project's current version to generate/replace. +gradleTokenVersion = VERSION + +# [DEPRECATED] Mod ID replacement token. gradleTokenModId = MODID + +# [DEPRECATED] Mod name replacement token. gradleTokenModName = MODNAME -gradleTokenVersion = VERSION -gradleTokenGroupName = GROUPNAME + # [DEPRECATED] -# Multiple source files can be defined here by providing a comma-seperated list: Class1.java,Class2.java,Class3.java +# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java # public static final String VERSION = "GRADLETOKEN_VERSION"; # The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's -# version in @Mod([...], version = VERSION, [...]) -# Leave these properties empty to skip individual token replacements +# version in @Mod([...], version = VERSION, [...]). +# Leave these properties empty to skip individual token replacements. replaceGradleTokenInFile = # In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can # leave this property empty. -# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api +# Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api apiPackage = # Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ -# Example value: mymodid_at.cfg +# There can be multiple files in a space-separated list. +# Example value: mymodid_at.cfg nei_at.cfg accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = false -# Specify the location of your implementation of IMixinPlugin. Leave it empty otherwise. + +# Adds some debug arguments like verbose output and class export. +usesMixinDebug = false + +# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. mixinPlugin = + # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! mixinsPackage = + # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! # This parameter is for legacy compatibility only -# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin +# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin coreModClass = core.launch.CodeChickenCorePlugin + # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! containsMixinsAndOrCoreModOnly = true -# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your -# responsibility check the licence and request permission for distribution, if required. +# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins. +forceEnableMixins = false + +# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your +# responsibility to check the license and request permission for distribution if required. usesShadowedDependencies = false -# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. +# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access +# their own classes, making the minimization unreliable. +minimizeShadowedDependencies = true -# The project's numeric ID on CurseForge. You can find this in the About Project box. -# Leave this empty if you don't want to publish on CurseForge. -curseForgeProjectId = 746279 +# If disabled, won't rename the shadowed classes. +relocateShadowedDependencies = true -# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. -# Syntax: type1:name1;type2:name2;... -# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], -# and the name is the CurseForge project id of the other mod. -# curseForgeRelations = +# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. +includeWellKnownRepositories = true +# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. +# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables. +# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle. +usesMavenPublishing = true -# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token. +# Maven repository to publish the mod to. +# mavenPublishUrl = https://nexus.gtnewhorizons.com/repository/releases/ +# Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token. +# # The project's ID on Modrinth. Can be either the slug or the ID. -# Leave this empty if you don't want to publish on Modrinth. - +# Leave this empty if you don't want to publish to Modrinth. modrinthProjectId = codechickencore-unofficial # The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. @@ -87,6 +136,56 @@ modrinthProjectId = codechickencore-unofficial # Where scope can be one of [required, optional, incompatible, embedded], # type can be one of [project, version], # and the name is the Modrinth project or version slug/id of the other mod. +# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech +# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true +modrinthRelations = -# modrinthRelations = +# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. +# +# The project's numeric ID on CurseForge. You can find this in the About Project box. +# Leave this empty if you don't want to publish on CurseForge. +curseForgeProjectId = 746279 +# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. +# Syntax: type1:name1;type2:name2;... +# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], +# and the name is the CurseForge project slug of the other mod. +# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft +# Note: UniMixins is automatically set as a required dependency if usesMixins = true. +curseForgeRelations = + +# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older +# projects. New projects should not use this parameter. +# customArchiveBaseName = + +# Optional parameter to have the build automatically fail if an illegal version is used. +# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'. +# The check is ONLY performed if the version is a git tag. +# Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+ +# versionPattern = + +# Uncomment to prevent the source code from being published. +# noPublishedSources = true + +# Uncomment this to disable Spotless checks. +# This should only be uncommented to keep it easier to sync with upstream/other forks. +# That is, if there is no other active fork/upstream, NEVER change this. +# disableSpotless = true + +# Uncomment this to disable Checkstyle checks (currently wildcard import check). +# disableCheckstyle = true + +# Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle" +# (force use delegated build). +# This is meant to be set in $HOME/.gradle/gradle.properties. +# e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build. +# WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want! +# Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you. +# ideaOverrideBuildType = idea + +# Whether IDEA should run spotless checks when pressing the Build button. +# This is meant to be set in $HOME/.gradle/gradle.properties. +# ideaCheckSpotlessOnBuild = true + +# Non-GTNH properties +gradleTokenGroupName = GROUPNAME diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e09..a80b22c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..25da30d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +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 @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +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 diff --git a/settings.gradle b/settings.gradle index 8a66026..e8946ad 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,7 @@ pluginManagement { name "GTNH Maven" url "https://nexus.gtnewhorizons.com/repository/public/" mavenContent { + includeGroup("com.gtnewhorizons") includeGroupByRegex("com\\.gtnewhorizons\\..+") } } @@ -16,12 +17,7 @@ pluginManagement { } plugins { - id 'com.diffplug.blowdryerSetup' version '1.7.1' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.8' } -blowdryerSetup { - repoSubfolder 'gtnhShared' - github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0') - //devLocal '.' // Use this when testing config updates locally -} + From ce1830d7b5d497e6161620dc0451680491576229 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sun, 4 Feb 2024 19:57:39 +0000 Subject: [PATCH 192/219] [ci skip] upgraded build system --- build.gradle | 1604 +--------------------- gradle.properties | 173 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 20 +- settings.gradle | 10 +- 5 files changed, 149 insertions(+), 1660 deletions(-) diff --git a/build.gradle b/build.gradle index 3eb19a2..e57a16f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,1605 +1,5 @@ -//version: 1704751096 -/* - DO NOT CHANGE THIS FILE! - Also, you may replace this file at any time if there is an update available. - Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/build.gradle for updates. - */ +//version: 1707058017 - -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute -import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar -import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask -import com.gtnewhorizons.retrofuturagradle.util.Distribution -import com.matthewprenger.cursegradle.CurseArtifact -import com.matthewprenger.cursegradle.CurseRelation -import com.modrinth.minotaur.dependencies.ModDependency -import com.modrinth.minotaur.dependencies.VersionDependency -import org.gradle.internal.logging.text.StyledTextOutput.Style -import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.gradle.internal.xml.XmlTransformer -import org.jetbrains.gradle.ext.Application -import org.jetbrains.gradle.ext.Gradle - -import javax.inject.Inject -import java.nio.file.Files -import java.nio.file.Paths -import java.util.concurrent.TimeUnit - -buildscript { - repositories { - maven { - // GTNH RetroFuturaGradle and ASM Fork - name "GTNH Maven" - url "https://nexus.gtnewhorizons.com/repository/public/" - } - mavenLocal() - } -} plugins { - id 'java-library' - id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" - id 'eclipse' - id 'scala' - id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false - id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false - id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.palantir.git-version' version '3.0.0' apply false - id 'de.undercouch.download' version '5.5.0' - id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version - id 'com.modrinth.minotaur' version '2.+' apply false - id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27' -} - -print("You might want to check out './gradlew :faq' if your build fails.\n") - -boolean settingsupdated = verifySettingsGradle() -settingsupdated = verifyGitAttributes() || settingsupdated -if (settingsupdated) - throw new GradleException("Settings has been updated, please re-run task.") - -// In submodules, .git is a file pointing to the real git dir -if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { - apply plugin: 'com.palantir.git-version' -} - -def out = services.get(StyledTextOutputFactory).create('an-output') - -def projectJavaVersion = JavaLanguageVersion.of(8) - -boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false -boolean disableCheckstyle = project.hasProperty("disableCheckstyle") ? project.disableCheckstyle.toBoolean() : false - -final String CHECKSTYLE_CONFIG = """ - - - - - - - - - - - -""" - -checkPropertyExists("modName") -checkPropertyExists("modId") -checkPropertyExists("modGroup") -checkPropertyExists("autoUpdateBuildScript") -checkPropertyExists("minecraftVersion") -checkPropertyExists("forgeVersion") -checkPropertyExists("replaceGradleTokenInFile") -checkPropertyExists("gradleTokenVersion") -checkPropertyExists("apiPackage") -checkPropertyExists("accessTransformersFile") -checkPropertyExists("usesMixins") -checkPropertyExists("mixinPlugin") -checkPropertyExists("mixinsPackage") -checkPropertyExists("coreModClass") -checkPropertyExists("containsMixinsAndOrCoreModOnly") -checkPropertyExists("usesShadowedDependencies") -checkPropertyExists("developmentEnvironmentUserName") - -propertyDefaultIfUnset("generateGradleTokenClass", "") -propertyDefaultIfUnset("includeWellKnownRepositories", true) -propertyDefaultIfUnset("noPublishedSources", false) -propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) -propertyDefaultIfUnset("forceEnableMixins", false) -propertyDefaultIfUnset("channel", "stable") -propertyDefaultIfUnset("mappingsVersion", "12") -propertyDefaultIfUnset("usesMavenPublishing", true) -propertyDefaultIfUnset("mavenPublishUrl", "https://nexus.gtnewhorizons.com/repository/releases/") -propertyDefaultIfUnset("modrinthProjectId", "") -propertyDefaultIfUnset("modrinthRelations", "") -propertyDefaultIfUnset("curseForgeProjectId", "") -propertyDefaultIfUnset("curseForgeRelations", "") -propertyDefaultIfUnset("minimizeShadowedDependencies", true) -propertyDefaultIfUnset("relocateShadowedDependencies", true) -// Deprecated properties (kept for backwards compat) -propertyDefaultIfUnset("gradleTokenModId", "") -propertyDefaultIfUnset("gradleTokenModName", "") -propertyDefaultIfUnset("gradleTokenGroupName", "") - -propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only -propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only - -// this is meant to be set using the user wide property file. by default we do nothing. -propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" - -project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts -if (!disableSpotless) { - apply plugin: 'com.diffplug.spotless' - apply from: Blowdryer.file('spotless.gradle') -} - -if (!disableCheckstyle) { - apply plugin: 'checkstyle' - tasks.named("checkstylePatchedMc") { enabled = false } - tasks.named("checkstyleMcLauncher") { enabled = false } - tasks.named("checkstyleIdeVirtualMain") { enabled = false } - tasks.named("checkstyleInjectedTags") { enabled = false } - checkstyle { - config = resources.text.fromString(CHECKSTYLE_CONFIG) - } -} - -String javaSourceDir = "src/main/java/" -String scalaSourceDir = "src/main/scala/" -String kotlinSourceDir = "src/main/kotlin/" - -if (usesShadowedDependencies.toBoolean()) { - apply plugin: "com.github.johnrengelman.shadow" -} - -java { - toolchain { - if (enableModernJavaSyntax.toBoolean()) { - languageVersion.set(JavaLanguageVersion.of(17)) - } else { - languageVersion.set(projectJavaVersion) - } - vendor.set(JvmVendorSpec.AZUL) - } - if (!noPublishedSources) { - withSourcesJar() - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = "UTF-8" -} - -tasks.withType(ScalaCompile).configureEach { - options.encoding = "UTF-8" -} - -pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { - // If Kotlin is enabled in the project - kotlin { - jvmToolchain(8) - } - // Kotlin hacks our source sets, so we hack Kotlin's tasks - def disabledKotlinTaskList = [ - "kaptGenerateStubsMcLauncherKotlin", - "kaptGenerateStubsPatchedMcKotlin", - "kaptGenerateStubsInjectedTagsKotlin", - "compileMcLauncherKotlin", - "compilePatchedMcKotlin", - "compileInjectedTagsKotlin", - "kaptMcLauncherKotlin", - "kaptPatchedMcKotlin", - "kaptInjectedTagsKotlin", - "kspMcLauncherKotlin", - "kspPatchedMcKotlin", - "kspInjectedTagsKotlin", - ] - tasks.configureEach { task -> - if (task.name in disabledKotlinTaskList) { - task.enabled = false - } - } -} - -configurations { - create("runtimeOnlyNonPublishable") { - description = "Runtime only dependencies that are not published alongside the jar" - canBeConsumed = false - canBeResolved = false - } - - create("devOnlyNonPublishable") { - description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" - canBeConsumed = false - canBeResolved = false - } - compileOnly.extendsFrom(devOnlyNonPublishable) - runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) -} - -if (enableModernJavaSyntax.toBoolean()) { - repositories { - mavenCentral { - mavenContent { - includeGroup("me.eigenraven.java8unsupported") - } - } - } - - dependencies { - annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' - // workaround for https://github.com/bsideup/jabel/issues/174 - annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' - compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { - transitive = false // We only care about the 1 annotation class - } - // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. - patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') - } - - tasks.withType(JavaCompile).configureEach { - if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) { - return - } - sourceCompatibility = 17 // for the IDE support - options.release.set(8) - - javaCompiler.set(javaToolchains.compilerFor { - languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.AZUL) - }) - } -} - -eclipse { - classpath { - downloadSources = true - downloadJavadoc = true - } -} - -final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char) -final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char) - -String targetPackageJava = javaSourceDir + modGroupPath -String targetPackageScala = scalaSourceDir + modGroupPath -String targetPackageKotlin = kotlinSourceDir + modGroupPath -if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) -} - -if (apiPackage) { - targetPackageJava = javaSourceDir + modGroupPath + "/" + apiPackagePath - targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath - targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath - if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) - } -} - -if (accessTransformersFile) { - for (atFile in accessTransformersFile.split(" ")) { - String targetFile = "src/main/resources/META-INF/" + atFile.trim() - if (!getFile(targetFile).exists()) { - throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) - } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) - } -} else { - boolean atsFound = false - for (File at : sourceSets.getByName("main").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - atsFound = true - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) - } - } - for (File at : sourceSets.getByName("api").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - atsFound = true - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) - } - } - if (atsFound) { - logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name") - } -} - -if (usesMixins.toBoolean()) { - if (mixinsPackage.isEmpty()) { - throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") - } - final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/") - final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/") - - targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath - targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath - targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath - if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { - throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) - } - - if (!mixinPlugin.isEmpty()) { - String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" - String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" - String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".kt" - if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { - throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) - } - } -} - -if (coreModClass) { - final String coreModPath = coreModClass.toString().replaceAll("\\.", "/") - String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java" - String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java" - String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".kt" - if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) { - throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin) - } -} - -configurations.configureEach { - resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) - - // Make sure GregTech build won't time out - System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String) - System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String) -} - -// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version -try { - 'git config core.fileMode false'.execute() -} -catch (Exception ignored) { - out.style(Style.Failure).println("git isn't installed at all") -} - -// Pulls version first from the VERSION env and then git tag -String identifiedVersion -String versionOverride = System.getenv("VERSION") ?: null -try { - // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty - if (versionOverride == null) { - def gitDetails = versionDetails() - def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning - String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') - if (branchName.startsWith('origin/')) { - branchName = branchName.minus('origin/') - } - branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver - identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' - if (gitDetails.commitDistance > 0) { - identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" - if (isDirty) { - identifiedVersion += "-dirty" - } - } else if (isDirty) { - identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" - } - } else { - identifiedVersion = versionOverride - } -} -catch (Exception ignored) { - out.style(Style.Failure).text( - 'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' + - 'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' + - 'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)' - ) - versionOverride = 'NO-GIT-TAG-SET' - identifiedVersion = versionOverride -} -version = identifiedVersion -ext { - modVersion = identifiedVersion -} - -if (identifiedVersion == versionOverride) { - out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') -} - -group = "com.github.GTNewHorizons" -if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - base { - archivesName = customArchiveBaseName - } -} else { - base { - archivesName = modId - } -} - - -minecraft { - if (replaceGradleTokenInFile) { - for (f in replaceGradleTokenInFile.split(',')) { - tagReplacementFiles.add f - } - } - if (gradleTokenModId) { - injectedTags.put gradleTokenModId, modId - } - if (gradleTokenModName) { - injectedTags.put gradleTokenModName, modName - } - if (gradleTokenVersion) { - injectedTags.put gradleTokenVersion, modVersion - } - if (gradleTokenGroupName) { - injectedTags.put gradleTokenGroupName, modGroup - } - if (enableGenericInjection.toBoolean()) { - injectMissingGenerics.set(true) - } - - username = developmentEnvironmentUserName.toString() - - lwjgl3Version = "3.3.2" - - // Enable assertions in the current mod - extraRunJvmArguments.add("-ea:${modGroup}") - - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - extraRunJvmArguments.addAll([ - "-Dmixin.debug.countInjections=true", - "-Dmixin.debug.verbose=true", - "-Dmixin.debug.export=true" - ]) - } - } - - // Blowdryer is present in some old mod builds, do not propagate it further as a dependency - // IC2 has no reobf jars in its Maven - groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"]) -} - -if (generateGradleTokenClass) { - tasks.injectTags.outputClassName.set(generateGradleTokenClass) -} - -// Custom reobf auto-mappings -configurations.configureEach { - dependencies.configureEach { dep -> - if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) { - if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") { - // https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971 - project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971") - } - } - } - def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) - if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { - resolutionStrategy.eachDependency { DependencyResolveDetails details -> - // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server - if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { - details.useVersion '2388750' - details.because 'Pick obfuscated jar' - } - } - } -} - -// Ensure tests have access to minecraft classes -sourceSets { - test { - java { - compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output - runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output - } - } -} - -if (file('addon.gradle.kts').exists()) { - apply from: 'addon.gradle.kts' -} else if (file('addon.gradle').exists()) { - apply from: 'addon.gradle' -} - -// File for local tweaks not commited to Git -if (file('addon.local.gradle.kts').exists()) { - apply from: 'addon.local.gradle.kts' -} else if (file('addon.local.gradle').exists()) { - apply from: 'addon.local.gradle' -} - -// Allow unsafe repos but warn -repositories.configureEach { repo -> - if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { - if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) { - logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'") - repo.allowInsecureProtocol = true - } - } -} - -if (file('repositories.gradle.kts').exists()) { - apply from: 'repositories.gradle.kts' -} else if (file('repositories.gradle').exists()) { - apply from: 'repositories.gradle' -} else { - logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") - throw new RuntimeException("Missing repositories.gradle[.kts]") -} - -configurations { - runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) - testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) - for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - if (usesShadowedDependencies.toBoolean()) { - config.extendsFrom(shadowImplementation) - // TODO: remove Compile after all uses are refactored to Implementation - config.extendsFrom(shadeCompile) - config.extendsFrom(shadowCompile) - } - } - // A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api" - create("compile") { - description = "Deprecated: use api or implementation instead, gets put in api" - canBeConsumed = false - canBeResolved = false - visible = false - } - create("testCompile") { - description = "Deprecated: use testImplementation instead" - canBeConsumed = false - canBeResolved = false - visible = false - } - api.extendsFrom(compile) - testImplementation.extendsFrom(testCompile) -} - -afterEvaluate { - if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) { - logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`") - logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle") - } -} - -repositories { - maven { - name = "GTNH Maven" - url = "https://nexus.gtnewhorizons.com/repository/public/" - // Links for convenience: - // Simple HTML browsing: https://nexus.gtnewhorizons.com/service/rest/repository/browse/releases/ - // Rich web UI browsing: https://nexus.gtnewhorizons.com/#browse/browse:releases - } - maven { - name 'Overmind forge repo mirror' - url 'https://gregtech.overminddl1.com/' - } - maven { - name 'sonatype' - url 'https://oss.sonatype.org/content/repositories/snapshots/' - content { - includeGroup "org.lwjgl" - } - } - if (includeWellKnownRepositories.toBoolean()) { - exclusiveContent { - forRepository { - maven { - name "CurseMaven" - url "https://cursemaven.com" - } - } - filter { - includeGroup "curse.maven" - } - } - exclusiveContent { - forRepository { - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - } - } - filter { - includeGroup "maven.modrinth" - } - } - maven { - name = "ic2" - url = getURL("https://maven2.ic2.player.to/", "https://maven.ic2.player.to/") - content { - includeGroup "net.industrial-craft" - } - metadataSources { - mavenPom() - artifact() - } - } - maven { - name "MMD Maven" - url "https://maven.mcmoddev.com/" - } - } -} - -def mixinProviderGroup = "io.github.legacymoddingmc" -def mixinProviderModule = "unimixins" -def mixinProviderVersion = "0.1.13" -def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" -def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" -ext.mixinProviderSpec = mixinProviderSpec - -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' - -dependencies { - if (usesMixins.toBoolean()) { - annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') - annotationProcessor('com.google.guava:guava:24.1.1-jre') - annotationProcessor('com.google.code.gson:gson:2.8.6') - annotationProcessor(mixinProviderSpec) - if (usesMixinDebug.toBoolean()) { - runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') - } - } - if (usesMixins.toBoolean()) { - implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) - } else if (forceEnableMixins.toBoolean()) { - runtimeOnlyNonPublishable(mixinProviderSpec) - } -} - -pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - if (usesMixins.toBoolean()) { - dependencies { - kapt(mixinProviderSpec) - } - } -} - -// Replace old mixin mods with unimixins -// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier -configurations.all { - resolutionStrategy.dependencySubstitution { - substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") - - substitute module('org.scala-lang:scala-library:2.11.1') using module('org.scala-lang:scala-library:2.11.5') because('To allow mixing with Java 8 targets') - } -} - -dependencies { - constraints { - def minGtnhLibVersion = "0.0.13" - implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - } -} - -if (file('dependencies.gradle.kts').exists()) { - apply from: 'dependencies.gradle.kts' -} else if (file('dependencies.gradle').exists()) { - apply from: 'dependencies.gradle' -} else { - logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") - throw new RuntimeException("Missing dependencies.gradle[.kts]") -} - -tasks.register('generateAssets') { - group = "GTNH Buildscript" - description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" - onlyIf { usesMixins.toBoolean() } - doLast { - def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") - if (!mixinConfigFile.exists()) { - def mixinPluginLine = "" - if (!mixinPlugin.isEmpty()) { - // We might not have a mixin plugin if we're using early/late mixins - mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ - } - - mixinConfigFile.text = """{ - "required": true, - "minVersion": "0.8.5-GTNH", - "package": "${modGroup}.${mixinsPackage}",${mixinPluginLine} - "refmap": "${mixingConfigRefMap}", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "mixins": [], - "client": [], - "server": [] -} -""" - } - } -} - -if (usesMixins.toBoolean()) { - tasks.named("processResources").configure { - dependsOn("generateAssets") - } - - tasks.named("compileJava", JavaCompile).configure { - options.compilerArgs += [ - // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code - "-XDenableSunApiLintControl", - "-XDignore.symbol.file" - ] - } -} - -tasks.named("processResources", ProcessResources).configure { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.mcVersion - exclude("spotless.gradle") - - // replace stuff in mcmod.info, nothing else. replaces ${key} with value in text - filesMatching("mcmod.info") { - expand "minecraftVersion": project.minecraft.mcVersion, - "modVersion": modVersion, - "modId": modId, - "modName": modName - } - - if (usesMixins.toBoolean()) { - dependsOn("compileJava", "compileScala") - } -} - -ext.java17Toolchain = (JavaToolchainSpec spec) -> { - spec.languageVersion.set(JavaLanguageVersion.of(17)) - spec.vendor.set(JvmVendorSpec.matching("jetbrains")) -} - -ext.java17DependenciesCfg = configurations.create("java17Dependencies") { - extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution - canBeConsumed = false -} -ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { - canBeConsumed = false -} - -dependencies { - def lwjgl3ifyVersion = '1.5.7' - if (modId != 'lwjgl3ify') { - java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") - } - if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4') - } - - java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} -} - -ext.java17JvmArgs = [ - // Java 9+ support - "--illegal-access=warn", - "-Djava.security.manager=allow", - "-Dfile.encoding=UTF-8", - "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", - "--add-opens", "java.base/java.net=ALL-UNNAMED", - "--add-opens", "java.base/java.nio=ALL-UNNAMED", - "--add-opens", "java.base/java.io=ALL-UNNAMED", - "--add-opens", "java.base/java.lang=ALL-UNNAMED", - "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", - "--add-opens", "java.base/java.text=ALL-UNNAMED", - "--add-opens", "java.base/java.util=ALL-UNNAMED", - "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", - "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", - "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", - "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", - "--add-modules", "jdk.dynalink", - "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", - "--add-modules", "java.sql.rowset", - "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" -] - -ext.hotswapJvmArgs = [ - // DCEVM advanced hot reload - "-XX:+AllowEnhancedClassRedefinition", - "-XX:HotswapAgent=fatjar" -] - -ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { - group = "GTNH Buildscript" - description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" - def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' - def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} - def targetFilename = "hotswap-agent.jar" - onlyIf { - !targetFolderProvider.get().file(targetFilename).asFile.exists() - } - doLast { - def targetFolder = targetFolderProvider.get() - targetFolder.asFile.mkdirs() - download.run { - src hsaUrl - dest targetFolder.file(targetFilename).asFile - overwrite false - tempAndMove true - } - } -} - -public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { - // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable - private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); - - @Input - public boolean getEnableHotswap() { return enableHotswap } - @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") - public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } - - @Inject - public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { - super(side, gradle) - - this.lwjglVersion = 3 - this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) - this.extraJvmArgs.addAll(project.java17JvmArgs) - this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) - - this.classpath(project.java17PatchDependenciesCfg) - if (side == Distribution.CLIENT) { - this.classpath(project.minecraftTasks.lwjgl3Configuration) - } - // Use a raw provider instead of map to not create a dependency on the task - this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) - this.classpath.filter { file -> - !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 - } - this.classpath(project.java17DependenciesCfg) - } - - public void setup(Project project) { - super.setup(project) - if (project.usesMixins.toBoolean()) { - this.extraJvmArgs.addAll(project.provider(() -> { - def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) - mixinCfg.canBeConsumed = false - mixinCfg.transitive = false - enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] - })) - } - } -} - -def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") -runClient17Task.configure { - setup(project) - group = "Modded Minecraft" - description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" - dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') - mainClass = "GradleStart" - username = minecraft.username - userUUID = minecraft.userUUID -} - -def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") -runServer17Task.configure { - setup(project) - group = "Modded Minecraft" - description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" - dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') - mainClass = "GradleStartServer" - extraArgs.add("nogui") -} - -def getManifestAttributes() { - def manifestAttributes = [:] - if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } - - if (accessTransformersFile) { - manifestAttributes += ["FMLAT": accessTransformersFile.toString()] - } - - if (coreModClass) { - manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] - } - - if (usesMixins.toBoolean()) { - manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod": !containsMixinsAndOrCoreModOnly.toBoolean() - ] - } - return manifestAttributes -} - -tasks.named("jar", Jar).configure { - manifest { - attributes(getManifestAttributes()) - } -} - -if (usesShadowedDependencies.toBoolean()) { - tasks.named("shadowJar", ShadowJar).configure { - manifest { - attributes(getManifestAttributes()) - } - - if (minimizeShadowedDependencies.toBoolean()) { - minimize() // This will only allow shading for actually used classes - } - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile, - project.configurations.shadeCompile - ] - archiveClassifier.set('dev') - if (relocateShadowedDependencies.toBoolean()) { - relocationPrefix = modGroup + ".shadow" - enableRelocation = true - } - } - configurations.runtimeElements.outgoing.artifacts.clear() - configurations.apiElements.outgoing.artifacts.clear() - configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) - configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) - tasks.named("jar", Jar) { - archiveClassifier.set('dev-preshadow') - } - tasks.named("reobfJar", ReobfuscatedJar) { - inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) - } - AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") - javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { - skip() - } -} -ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar -ext.publishableObfJar = tasks.reobfJar - -tasks.register('apiJar', Jar) { - from(sourceSets.main.allSource) { - include modGroupPath + "/" + apiPackagePath + '/**' - } - - from(sourceSets.main.output) { - include modGroupPath + "/" + apiPackagePath + '/**' - } - - from(sourceSets.main.resources.srcDirs) { - include("LICENSE") - } - - getArchiveClassifier().set('api') -} - -artifacts { - if (!noPublishedSources) { - archives tasks.named("sourcesJar") - } - if (apiPackage) { - archives tasks.named("apiJar") - } -} - -idea { - module { - downloadJavadoc = true - downloadSources = true - inheritOutputDirs = true - } - project { - settings { - if (ideaOverrideBuildType != "") { - delegateActions { - if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { - delegateBuildRunToGradle = true - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE - } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { - delegateBuildRunToGradle = false - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM - } else { - throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') - } - } - } - runConfigurations { - "0. Build and Test"(Gradle) { - taskNames = ["build"] - } - "1. Run Client"(Gradle) { - taskNames = ["runClient"] - } - "2. Run Server"(Gradle) { - taskNames = ["runServer"] - } - "1a. Run Client (Java 17)"(Gradle) { - taskNames = ["runClient17"] - } - "2a. Run Server (Java 17)"(Gradle) { - taskNames = ["runServer17"] - } - "1b. Run Client (Java 17, Hotswap)"(Gradle) { - taskNames = ["runClient17"] - envs = ["HOTSWAP": "true"] - } - "2b. Run Server (Java 17, Hotswap)"(Gradle) { - taskNames = ["runServer17"] - envs = ["HOTSWAP": "true"] - } - "3. Run Obfuscated Client"(Gradle) { - taskNames = ["runObfClient"] - } - "4. Run Obfuscated Server"(Gradle) { - taskNames = ["runObfServer"] - } - if (!disableSpotless) { - "5. Apply spotless"(Gradle) { - taskNames = ["spotlessApply"] - } - } - def coreModArgs = "" - if (coreModClass) { - coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"' - } - "Run Client (IJ Native)"(Application) { - mainClass = "GradleStart" - moduleName = project.name + ".ideVirtualMain" - afterEvaluate { - workingDirectory = tasks.runClient.workingDir.absolutePath - programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') - jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + - ' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + - coreModArgs - } - } - "Run Server (IJ Native)"(Application) { - mainClass = "GradleStartServer" - moduleName = project.name + ".ideVirtualMain" - afterEvaluate { - workingDirectory = tasks.runServer.workingDir.absolutePath - programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') - jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + - ' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + - coreModArgs - } - } - } - compiler.javac { - afterEvaluate { - javacAdditionalOptions = "-encoding utf8" - moduleJavacAdditionalOptions = [ - (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') - ] - } - } - withIDEADir { File ideaDir -> - if (!ideaDir.path.contains(".idea")) { - // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory - ideaDir = new File(ideaDir, ".idea") - } - if (ideaDir.isDirectory()) { - def miscFile = new File(ideaDir, "misc.xml") - if (miscFile.isFile()) { - boolean dirty = false - def miscTransformer = new XmlTransformer() - miscTransformer.addAction { root -> - Node rootNode = root.asNode() - def rootManager = rootNode - .component.find { it.@name == 'ProjectRootManager' } - if (!rootManager) { - rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) - dirty = true - } - def output = rootManager.output - if (!output) { - output = rootManager.appendNode('output') - dirty = true - } - if (!output.@url) { - // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. - // This is a sensible default for most setups - output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' - dirty = true - } - } - def result = miscTransformer.transform(miscFile.text) - if (dirty) { - miscFile.write(result) - } - } else { - miscFile.text = """ - - - - - -""" - } - } - } - } - } -} - -tasks.named("processIdeaSettings").configure { - dependsOn("injectTags") -} - -tasks.named("ideVirtualMainClasses").configure { - // Make IntelliJ "Build project" build the mod jars - dependsOn("jar", "reobfJar") - if (!disableSpotless) { - dependsOn("spotlessCheck") - } -} - -// workaround variable hiding in pom processing -def projectConfigs = project.configurations - -publishing { - publications { - create("maven", MavenPublication) { - from components.java - - if (apiPackage) { - artifact apiJar - } - - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group - artifactId = System.getenv("ARTIFACT_ID") ?: project.name - // Using the identified version, not project.version as it has the prepended 1.7.10 - version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - } - } - repositories { - if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { - maven { - url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" - } - } - } - } -} - -if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { - apply plugin: 'com.modrinth.minotaur' - - File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") - - modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = modrinthProjectId - versionNumber = identifiedVersion - versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" - changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" - uploadFile = publishableObfJar - additionalFiles = getSecondaryArtifacts() - gameVersions = [minecraftVersion] - loaders = ["forge"] - debugMode = false - } - - if (modrinthRelations.size() != 0) { - String[] deps = modrinthRelations.split(";") - deps.each { dep -> - if (dep.size() == 0) { - return - } - String[] parts = dep.split(":") - String[] qual = parts[0].split("-") - addModrinthDep(qual[0], qual[1], parts[1]) - } - } - if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "unimixins") - } - tasks.modrinth.dependsOn(build) - tasks.publish.dependsOn(tasks.modrinth) -} - -if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) { - apply plugin: 'com.matthewprenger.cursegradle' - - File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") - - curseforge { - apiKey = System.getenv("CURSEFORGE_TOKEN") - project { - id = curseForgeProjectId - if (changelogFile.exists()) { - changelogType = "markdown" - changelog = changelogFile - } - releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" - addGameVersion minecraftVersion - addGameVersion "Forge" - mainArtifact publishableObfJar - for (artifact in getSecondaryArtifacts()) addArtifact artifact - } - - options { - javaIntegration = false - forgeGradleIntegration = false - debug = false - } - } - - if (curseForgeRelations.size() != 0) { - String[] deps = curseForgeRelations.split(";") - deps.each { dep -> - if (dep.size() == 0) { - return - } - String[] parts = dep.split(":") - addCurseForgeRelation(parts[0], parts[1]) - } - } - if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "unimixins") - } - tasks.curseforge.dependsOn(build) - tasks.publish.dependsOn(tasks.curseforge) -} - -def addModrinthDep(String scope, String type, String name) { - com.modrinth.minotaur.dependencies.Dependency dep; - if (!(scope in ["required", "optional", "incompatible", "embedded"])) { - throw new Exception("Invalid modrinth dependency scope: " + scope) - } - switch (type) { - case "project": - dep = new ModDependency(name, scope) - break - case "version": - dep = new VersionDependency(name, scope) - break - default: - throw new Exception("Invalid modrinth dependency type: " + type) - } - project.modrinth.dependencies.add(dep) -} - -def addCurseForgeRelation(String type, String name) { - if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { - throw new Exception("Invalid CurseForge relation type: " + type) - } - CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact - CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation())) - rel."$type"(name) -} - -// Updating - -def buildscriptGradleVersion = "8.5" - -tasks.named('wrapper', Wrapper).configure { - gradleVersion = buildscriptGradleVersion -} - -tasks.register('updateBuildScript') { - group = 'GTNH Buildscript' - description = 'Updates the build script to the latest version' - - if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { - dependsOn('wrapper') - } - - doLast { - if (performBuildScriptUpdate()) return - - print("Build script already up-to-date!") - } -} - -if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) { - if (autoUpdateBuildScript.toBoolean()) { - performBuildScriptUpdate() - } else { - out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") - if (gradle.gradleVersion != buildscriptGradleVersion) { - out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") - } - } -} - -// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large -tasks.register('faq') { - group = 'GTNH Buildscript' - description = 'Prints frequently asked questions about building a project' - - doLast { - print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + - "Or you can manually check if the versions are still on the distributing sites - " + - "the links can be found in repositories.gradle and build.gradle:repositories, " + - "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + - "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + - "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + - "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + - "Java 9 or later.") - } -} - -static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle") -} - -static URL exampleSettingsGradleUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example") -} - -static URL exampleGitAttributesUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes") -} - - -boolean verifyGitAttributes() { - def gitattributesFile = getFile(".gitattributes") - if (!gitattributesFile.exists()) { - println("Downloading default .gitattributes") - exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } } - exec { - workingDir '.' - commandLine 'git', 'add', '--renormalize', '.' - } - return true - } - return false -} - -boolean verifySettingsGradle() { - def settingsFile = getFile("settings.gradle") - if (!settingsFile.exists()) { - println("Downloading default settings.gradle") - exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } - return true - } - return false -} - -boolean performBuildScriptUpdate() { - if (isNewBuildScriptVersionAvailable()) { - def buildscriptFile = getFile("build.gradle") - availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } - def out = services.get(StyledTextOutputFactory).create('buildscript-update-output') - out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") - boolean settingsupdated = verifySettingsGradle() - settingsupdated = verifyGitAttributes() || settingsupdated - if (settingsupdated) - throw new GradleException("Settings has been updated, please re-run task.") - return true - } - return false -} - -boolean isNewBuildScriptVersionAvailable() { - Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] - - String currentBuildScript = getFile("build.gradle").getText() - String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScriptHash - try { - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - availableBuildScriptHash = getVersionHash(availableBuildScript) - } catch (IOException e) { - logger.warn("Could not check for buildscript update availability: {}", e.message) - return false - } - - boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash - return !isUpToDate -} - -static String getVersionHash(String buildScriptContent) { - String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") - if (versionLine != null) { - return versionLine.split(": ").last() - } - return "" -} - -// Parameter Deobfuscation - -tasks.register('deobfParams') { - group = 'GTNH Buildscript' - description = 'Rename all obfuscated parameter names inherited from Minecraft classes' - doLast { // TODO - - String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" - String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" - String paramsCSV = "$mcpDir/params.csv" - - download.run { - src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" - dest mcpZIP - overwrite false - } - - if (!file(paramsCSV).exists()) { - println("Extracting MCP archive ...") - copy { - from(zipTree(mcpZIP)) - into(mcpDir) - } - } - - println("Parsing params.csv ...") - Map params = new HashMap<>() - Files.lines(Paths.get(paramsCSV)).forEach { line -> - String[] cells = line.split(",") - if (cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) { - params.put(cells[0], cells[1]) - } - } - - out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!") - out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.") - } -} - -static int replaceParams(File file, Map params) { - int fileCount = 0 - - if (file.isDirectory()) { - for (File f : file.listFiles()) { - fileCount += replaceParams(f, params) - } - return fileCount - } - println("Visiting ${file.getName()} ...") - try { - String content = new String(Files.readAllBytes(file.toPath())) - int hash = content.hashCode() - params.forEach { key, value -> - content = content.replaceAll(key, value) - } - if (hash != content.hashCode()) { - Files.write(file.toPath(), content.getBytes("UTF-8")) - return 1 - } - } catch (Exception e) { - e.printStackTrace() - } - return 0 -} - -// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) - -def deobf(String sourceURL) { - try { - URL url = new URL(sourceURL) - String fileName = url.getFile() - - //get rid of directories: - int lastSlash = fileName.lastIndexOf("/") - if (lastSlash > 0) { - fileName = fileName.substring(lastSlash + 1) - } - //get rid of extension: - if (fileName.endsWith(".jar") || fileName.endsWith(".litemod")) { - fileName = fileName.substring(0, fileName.lastIndexOf(".")) - } - - String hostName = url.getHost() - if (hostName.startsWith("www.")) { - hostName = hostName.substring(4) - } - List parts = Arrays.asList(hostName.split("\\.")) - Collections.reverse(parts) - hostName = String.join(".", parts) - - return deobf(sourceURL, "$hostName/$fileName") - } catch (Exception ignored) { - return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") - } -} - -def deobfMaven(String repoURL, String mavenDep) { - if (!repoURL.endsWith("/")) { - repoURL += "/" - } - String[] parts = mavenDep.split(":") - parts[0] = parts[0].replace('.', '/') - def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" - return deobf(jarURL) -} - -def deobfCurse(String curseDep) { - return dependencies.rfg.deobf("curse.maven:$curseDep") -} - -// The method above is to be preferred. Use this method if the filename is not at the end of the URL. -def deobf(String sourceURL, String rawFileName) { - String bon2Version = "2.5.1" - String fileName = URLDecoder.decode(rawFileName, "UTF-8") - String cacheDir = "$project.gradle.gradleUserHomeDir/caches" - String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" - - download.run { - src sourceURL - dest obfFile - quiet true - overwrite false - } - return dependencies.rfg.deobf(files(obfFile)) -} -// Helper methods - -def checkPropertyExists(String propertyName) { - if (!project.hasProperty(propertyName)) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties") - } -} - -def propertyDefaultIfUnset(String propertyName, defaultValue) { - if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { - project.ext.setProperty(propertyName, defaultValue) - } -} - -def getFile(String relativePath) { - return new File(projectDir, relativePath) -} - -def getSecondaryArtifacts() { - // Because noPublishedSources from the beginning of the script is somehow not visible here... - boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - def secondaryArtifacts = [publishableDevJar] - if (!noPublishedSources) secondaryArtifacts += [sourcesJar] - if (apiPackage) secondaryArtifacts += [apiJar] - return secondaryArtifacts -} - -def getURL(String main, String fallback) { - return pingURL(main, 10000) ? main : fallback -} - -// credit: https://stackoverflow.com/a/3584332 -def pingURL(String url, int timeout) { - url = url.replaceFirst("^https", "http") // Otherwise an exception may be thrown on invalid SSL certificates. - try { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection() - connection.setConnectTimeout(timeout) - connection.setReadTimeout(timeout) - connection.setRequestMethod("HEAD") - int responseCode = connection.getResponseCode() - return 200 <= responseCode && responseCode <= 399 - } catch (IOException ignored) { - return false - } -} - -// For easier scripting of things that require variables defined earlier in the buildscript -if (file('addon.late.gradle.kts').exists()) { - apply from: 'addon.late.gradle.kts' -} else if (file('addon.late.gradle').exists()) { - apply from: 'addon.late.gradle' -} - -// File for local tweaks not commited to Git -if (file('addon.late.local.gradle.kts').exists()) { - apply from: 'addon.late.local.gradle.kts' -} else if (file('addon.late.local.gradle').exists()) { - apply from: 'addon.late.local.gradle' + id 'com.gtnewhorizons.gtnhconvention' } diff --git a/gradle.properties b/gradle.properties index 24279a2..1849951 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,92 +1,134 @@ +# ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable. +# LOCAL to test local config updates. +gtnh.settings.blowdryerTag = 0.2.0 + +# Human-readable mod name, available for mcmod.info population. modName = CodeChickenLib -# This is a case-sensitive string to identify your mod. Convention is to use lower case. +# Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation. +# Conventionally lowercase. modId = CodeChickenLib +# Root package of the mod, used to find various classes in other properties, +# mcmod.info substitution, enabling assertions in run tasks, etc. modGroup = codechicken -# WHY is there no version field? -# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the -# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/ +# Whether to use modGroup as the maven publishing group. +# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods. +useModGroupForPublishing = false -# Will update your build.gradle automatically whenever an update is available +# Updates your build.gradle and settings.gradle automatically whenever an update is available. autoUpdateBuildScript = false +# Version of Minecraft to target minecraftVersion = 1.7.10 + +# Version of Minecraft Forge to target forgeVersion = 10.13.4.1614 -# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you -# restart Minecraft in development. Choose this dependent on your mod: -# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name -# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty +# Specify an MCP channel for dependency deobfuscation and the deobfParams task. +channel = stable + +# Specify an MCP mappings version for dependency deobfuscation and the deobfParams task. +mappingsVersion = 12 + +# Defines other MCP mappings for dependency deobfuscation. +remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ + +# Select a default username for testing your mod. You can always override this per-run by running +# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE. developmentEnvironmentUserName = Developer -# Enables using modern java syntax (up to version 17) via Jabel, while still targetting JVM 8. +# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8. # See https://github.com/bsideup/jabel for details on how this works. enableModernJavaSyntax = true -# Enables injecting missing generics into the decompiled source code for a better coding experience -# Turns most publically visible List, Map, etc. into proper List, Map types +# Enables injecting missing generics into the decompiled source code for a better coding experience. +# Turns most publicly visible List, Map, etc. into proper List, Map types. enableGenericInjection = true +# Generate a class with a String field for the mod version named as defined below. +# If generateGradleTokenClass is empty or not missing, no such class will be generated. +# If gradleTokenVersion is empty or missing, the field will not be present in the class. +generateGradleTokenClass = -# Define a source file of your project with: +# Name of the token containing the project's current version to generate/replace. +gradleTokenVersion = + +# [DEPRECATED] Mod ID replacement token. +gradleTokenModId = + +# [DEPRECATED] Mod name replacement token. +gradleTokenModName = + +# [DEPRECATED] +# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java # public static final String VERSION = "GRADLETOKEN_VERSION"; # The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's -# version in @Mod([...], version = VERSION, [...]) -# Leave these properties empty to skip individual token replacements +# version in @Mod([...], version = VERSION, [...]). +# Leave these properties empty to skip individual token replacements. replaceGradleTokenInFile = -gradleTokenModId = -gradleTokenModName = -gradleTokenVersion = -gradleTokenGroupName = -# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can +# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can # leave this property empty. -# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api +# Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api apiPackage = # Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ -# Example value: mymodid_at.cfg +# There can be multiple files in a space-separated list. +# Example value: mymodid_at.cfg nei_at.cfg accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = false -# Specify the location of your implementation of IMixinPlugin. Leave it empty otherwise. + +# Adds some debug arguments like verbose output and class export. +usesMixinDebug = false + +# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. mixinPlugin = + # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! mixinsPackage = + # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! # This parameter is for legacy compatibility only -# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin +# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin coreModClass = + # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! containsMixinsAndOrCoreModOnly = -# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your -# responsibility check the licence and request permission for distribution, if required. +# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins. +forceEnableMixins = false + +# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your +# responsibility to check the license and request permission for distribution if required. usesShadowedDependencies = false +# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access +# their own classes, making the minimization unreliable. +minimizeShadowedDependencies = true -# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. +# If disabled, won't rename the shadowed classes. +relocateShadowedDependencies = true -# The project's numeric ID on CurseForge. You can find this in the About Project box. -# Leave this empty if you don't want to publish on CurseForge. -curseForgeProjectId = 746280 - -# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. -# Syntax: type1:name1;type2:name2;... -# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], -# and the name is the CurseForge project id of the other mod. -# curseForgeRelations = +# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. +includeWellKnownRepositories = true +# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. +# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables. +# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle. +usesMavenPublishing = true -# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token. +# Maven repository to publish the mod to. +# mavenPublishUrl = https://nexus.gtnewhorizons.com/repository/releases/ +# Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token. +# # The project's ID on Modrinth. Can be either the slug or the ID. -# Leave this empty if you don't want to publish on Modrinth. - +# Leave this empty if you don't want to publish to Modrinth. modrinthProjectId = codechickenlib-unofficial # The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. @@ -94,5 +136,56 @@ modrinthProjectId = codechickenlib-unofficial # Where scope can be one of [required, optional, incompatible, embedded], # type can be one of [project, version], # and the name is the Modrinth project or version slug/id of the other mod. +# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech +# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true +modrinthRelations = -# modrinthRelations = +# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. +# +# The project's numeric ID on CurseForge. You can find this in the About Project box. +# Leave this empty if you don't want to publish on CurseForge. +curseForgeProjectId = 746280 + +# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. +# Syntax: type1:name1;type2:name2;... +# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], +# and the name is the CurseForge project slug of the other mod. +# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft +# Note: UniMixins is automatically set as a required dependency if usesMixins = true. +curseForgeRelations = + +# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older +# projects. New projects should not use this parameter. +# customArchiveBaseName = + +# Optional parameter to have the build automatically fail if an illegal version is used. +# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'. +# The check is ONLY performed if the version is a git tag. +# Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+ +# versionPattern = + +# Uncomment to prevent the source code from being published. +# noPublishedSources = true + +# Uncomment this to disable Spotless checks. +# This should only be uncommented to keep it easier to sync with upstream/other forks. +# That is, if there is no other active fork/upstream, NEVER change this. +# disableSpotless = true + +# Uncomment this to disable Checkstyle checks (currently wildcard import check). +# disableCheckstyle = true + +# Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle" +# (force use delegated build). +# This is meant to be set in $HOME/.gradle/gradle.properties. +# e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build. +# WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want! +# Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you. +# ideaOverrideBuildType = idea + +# Whether IDEA should run spotless checks when pressing the Build button. +# This is meant to be set in $HOME/.gradle/gradle.properties. +# ideaCheckSpotlessOnBuild = true + +# Non-GTNH properties +gradleTokenGroupName = diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e09..a80b22c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..25da30d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +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 @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +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 diff --git a/settings.gradle b/settings.gradle index 8a66026..e8946ad 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,7 @@ pluginManagement { name "GTNH Maven" url "https://nexus.gtnewhorizons.com/repository/public/" mavenContent { + includeGroup("com.gtnewhorizons") includeGroupByRegex("com\\.gtnewhorizons\\..+") } } @@ -16,12 +17,7 @@ pluginManagement { } plugins { - id 'com.diffplug.blowdryerSetup' version '1.7.1' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.8' } -blowdryerSetup { - repoSubfolder 'gtnhShared' - github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0') - //devLocal '.' // Use this when testing config updates locally -} + From 7f78ceb9219a79251d3e6e499cc492b6ccf330ed Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 1 Jul 2024 12:33:39 -0700 Subject: [PATCH 193/219] Bye bye DepLoader --- gradle.properties | 14 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- .../codechicken/core/CCUpdateChecker.java | 101 +--- .../core/asm/CodeChickenCoreModContainer.java | 3 - .../core/internal/CCCEventHandler.java | 2 - .../core/launch/CodeChickenCorePlugin.java | 1 - .../codechicken/core/launch/DepLoader.java | 479 +----------------- 8 files changed, 22 insertions(+), 582 deletions(-) diff --git a/gradle.properties b/gradle.properties index 6d8ad4b..4b3f1f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,7 +33,7 @@ channel = stable mappingsVersion = 12 # Defines other MCP mappings for dependency deobfuscation. -remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ +remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ # Select a default username for testing your mod. You can always override this per-run by running # `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE. @@ -55,12 +55,6 @@ generateGradleTokenClass = codechicken.core.asm.Tags # Name of the token containing the project's current version to generate/replace. gradleTokenVersion = VERSION -# [DEPRECATED] Mod ID replacement token. -gradleTokenModId = MODID - -# [DEPRECATED] Mod name replacement token. -gradleTokenModName = MODNAME - # [DEPRECATED] # Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java # public static final String VERSION = "GRADLETOKEN_VERSION"; @@ -114,7 +108,7 @@ minimizeShadowedDependencies = true # If disabled, won't rename the shadowed classes. relocateShadowedDependencies = true -# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. +# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories. includeWellKnownRepositories = true # Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. @@ -123,7 +117,7 @@ includeWellKnownRepositories = true usesMavenPublishing = true # Maven repository to publish the mod to. -# mavenPublishUrl = https://nexus.gtnewhorizons.com/repository/releases/ +# mavenPublishUrl = https\://nexus.gtnewhorizons.com/repository/releases/ # Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token. # @@ -187,5 +181,3 @@ curseForgeRelations = # This is meant to be set in $HOME/.gradle/gradle.properties. # ideaCheckSpotlessOnBuild = true -# Non-GTNH properties -gradleTokenGroupName = GROUPNAME diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22c..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index e8946ad..6fe010c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.8' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23' } diff --git a/src/main/java/codechicken/core/CCUpdateChecker.java b/src/main/java/codechicken/core/CCUpdateChecker.java index 25b67d0..ca69f93 100644 --- a/src/main/java/codechicken/core/CCUpdateChecker.java +++ b/src/main/java/codechicken/core/CCUpdateChecker.java @@ -1,113 +1,22 @@ package codechicken.core; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.ArrayList; - -import net.minecraft.client.Minecraft; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.StatCollector; - import com.google.common.base.Function; -import codechicken.core.launch.CodeChickenCorePlugin; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.versioning.ComparableVersion; import cpw.mods.fml.relauncher.FMLInjectionData; public class CCUpdateChecker { - private static final ArrayList updates = new ArrayList(); - - private static class ThreadUpdateCheck extends Thread { - - private final URL url; - private final Function handler; - - public ThreadUpdateCheck(URL url, Function handler) { - this.url = url; - this.handler = handler; - - setName("CodeChicken Update Checker"); - } - - @Override - public void run() { - try { - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("GET"); - conn.setConnectTimeout(5000); - conn.setReadTimeout(5000); - BufferedReader read = new BufferedReader(new InputStreamReader(conn.getInputStream())); - String ret = read.readLine(); - read.close(); - if (ret == null) ret = ""; - handler.apply(ret); - } catch (SocketTimeoutException ignored) {} catch (UnknownHostException ignored) {} catch (IOException iox) { - iox.printStackTrace(); - } - } - } - - public static void tick() { - Minecraft mc = Minecraft.getMinecraft(); - if (!mc.inGameHasFocus) return; - - synchronized (updates) { - for (String s : updates) mc.thePlayer.addChatMessage(new ChatComponentText(s)); - updates.clear(); - } - } + public static void tick() {} - public static void addUpdateMessage(String s) { - synchronized (updates) { - updates.add(s); - } - } + public static void addUpdateMessage(String s) {} public static String mcVersion() { return (String) FMLInjectionData.data()[4]; } - public static void updateCheck(final String mod, final String version) { - updateCheck( - "http://www.chickenbones.net/Files/notification/version.php?" + "version=" - + mcVersion() - + "&" - + "file=" - + mod, - new Function() { + public static void updateCheck(final String mod, final String version) {} - @Override - public Void apply(String ret) { - if (!ret.startsWith("Ret: ")) { - CodeChickenCorePlugin.logger - .error("Failed to check update for " + mod + " returned: " + ret); - return null; - } - ComparableVersion newversion = new ComparableVersion(ret.substring(5)); - if (newversion.compareTo(new ComparableVersion(version)) > 0) addUpdateMessage( - StatCollector.translateToLocalFormatted("codechickencore.update", newversion, mod)); - return null; - } - }); - } - - public static void updateCheck(String mod) { - updateCheck(mod, Loader.instance().getIndexedModList().get(mod).getVersion()); - } + public static void updateCheck(String mod) {} - public static void updateCheck(String url, Function handler) { - try { - new ThreadUpdateCheck(new URL(url), handler).start(); - } catch (MalformedURLException e) { - CodeChickenCorePlugin.logger.error("Malformed URL: " + url, e); - } - } + public static void updateCheck(String url, Function handler) {} } diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index 2907b25..1ba1463 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -9,7 +9,6 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -import codechicken.core.CCUpdateChecker; import codechicken.core.ClientUtils; import codechicken.core.featurehack.LiquidTextures; import codechicken.core.internal.CCCEventHandler; @@ -75,8 +74,6 @@ public void preInit(FMLPreInitializationEvent event) { @Subscribe public void init(FMLInitializationEvent event) { if (event.getSide().isClient()) { - if (config.getTag("checkUpdates").getBooleanValue(true)) CCUpdateChecker.updateCheck(getModId()); - ClientUtils.enhanceSupportersList("CodeChickenCore"); FMLCommonHandler.instance().bus().register(new CCCEventHandler()); diff --git a/src/main/java/codechicken/core/internal/CCCEventHandler.java b/src/main/java/codechicken/core/internal/CCCEventHandler.java index 62515e4..65f25b3 100644 --- a/src/main/java/codechicken/core/internal/CCCEventHandler.java +++ b/src/main/java/codechicken/core/internal/CCCEventHandler.java @@ -2,7 +2,6 @@ import net.minecraftforge.client.event.GuiScreenEvent; -import codechicken.core.CCUpdateChecker; import codechicken.core.GuiModListScroll; import cpw.mods.fml.client.GuiModList; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -19,7 +18,6 @@ public class CCCEventHandler { @SubscribeEvent public void clientTick(TickEvent.ClientTickEvent event) { if (event.phase == Phase.END) { - CCUpdateChecker.tick(); renderTime++; } } diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index b544ccb..9289479 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -56,7 +56,6 @@ public CodeChickenCorePlugin() { minecraftDir = (File) FMLInjectionData.data()[6]; currentMcVersion = (String) FMLInjectionData.data()[4]; - DepLoader.load(); injectDeobfPlugin(); } diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index 8a728e4..8f3272d 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -1,63 +1,17 @@ package codechicken.core.launch; -import java.awt.Desktop; -import java.awt.Dialog.ModalityType; -import java.awt.Dimension; -import java.awt.GraphicsEnvironment; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.Closeable; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.InterruptedIOException; -import java.lang.reflect.Field; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; import javax.swing.Box; import javax.swing.JDialog; -import javax.swing.JEditorPane; -import javax.swing.JLabel; import javax.swing.JOptionPane; -import javax.swing.JProgressBar; -import javax.swing.WindowConstants; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; - -import net.minecraft.launchwrapper.LaunchClassLoader; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import cpw.mods.fml.common.versioning.ComparableVersion; -import cpw.mods.fml.relauncher.FMLInjectionData; -import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; -import sun.misc.URLClassPath; -import sun.net.util.URLUtil; /** * For autodownloading stuff. This is really unoriginal, mostly ripped off FML, credits to cpw. @@ -65,10 +19,6 @@ @MCVersion("1.7.10") public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { - private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); - private static final String owner = "CB's DepLoader"; - private static DepLoadInst inst; - public interface IDownloadDisplay { void resetProgress(int sizeGuess); @@ -89,140 +39,39 @@ public interface IDownloadDisplay { @SuppressWarnings("serial") public static class Downloader extends JOptionPane implements IDownloadDisplay { - private JDialog container; - private JLabel currentActivity; - private JProgressBar progress; boolean stopIt; Thread pokeThread; private Box makeProgressPanel() { - Box box = Box.createVerticalBox(); - box.add(Box.createRigidArea(new Dimension(0, 10))); - JLabel welcomeLabel = new JLabel( - "" + owner - + " is setting up your minecraft environment"); - box.add(welcomeLabel); - welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); - welcomeLabel = new JLabel( - "Please wait, " + owner + " has some tasks to do before you can play"); - welcomeLabel.setAlignmentY(LEFT_ALIGNMENT); - box.add(welcomeLabel); - box.add(Box.createRigidArea(new Dimension(0, 10))); - currentActivity = new JLabel("Currently doing ..."); - box.add(currentActivity); - box.add(Box.createRigidArea(new Dimension(0, 10))); - progress = new JProgressBar(0, 100); - progress.setStringPainted(true); - box.add(progress); - box.add(Box.createRigidArea(new Dimension(0, 30))); - return box; + return null; } @Override public JDialog makeDialog() { - if (container != null) return container; - - setMessageType(JOptionPane.INFORMATION_MESSAGE); - setMessage(makeProgressPanel()); - setOptions(new Object[] { "Stop" }); - addPropertyChangeListener(new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getSource() == Downloader.this && evt.getPropertyName() == VALUE_PROPERTY) { - requestClose("This will stop minecraft from launching\nAre you sure you want to do this?"); - } - } - }); - container = new JDialog(null, "Hello", ModalityType.MODELESS); - container.setResizable(false); - container.setLocationRelativeTo(null); - container.add(this); - this.updateUI(); - container.pack(); - container.setMinimumSize(container.getPreferredSize()); - container.setVisible(true); - container.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - container.addWindowListener(new WindowAdapter() { - - @Override - public void windowClosing(WindowEvent e) { - requestClose( - "Closing this window will stop minecraft from launching\nAre you sure you wish to do this?"); - } - }); - return container; + return null; } - protected void requestClose(String message) { - int shouldClose = JOptionPane.showConfirmDialog( - container, - message, - "Are you sure you want to stop?", - JOptionPane.YES_NO_OPTION, - JOptionPane.WARNING_MESSAGE); - if (shouldClose == JOptionPane.YES_OPTION) container.dispose(); - - stopIt = true; - if (pokeThread != null) pokeThread.interrupt(); - } + protected void requestClose(String message) {} @Override - public void updateProgressString(String progressUpdate, Object... data) { - // FMLLog.finest(progressUpdate, data); - if (currentActivity != null) currentActivity.setText(String.format(progressUpdate, data)); - } + public void updateProgressString(String progressUpdate, Object... data) {} @Override - public void resetProgress(int sizeGuess) { - if (progress != null) progress.getModel().setRangeProperties(0, 0, 0, sizeGuess, false); - } + public void resetProgress(int sizeGuess) {} @Override - public void updateProgress(int fullLength) { - if (progress != null) progress.getModel().setValue(fullLength); - } + public void updateProgress(int fullLength) {} @Override - public void setPokeThread(Thread currentThread) { - this.pokeThread = currentThread; - } + public void setPokeThread(Thread currentThread) {} @Override public boolean shouldStopIt() { - return stopIt; + return true; } @Override - public void showErrorDialog(String name, String url) { - JEditorPane ep = new JEditorPane( - "text/html", - "" + owner - + " was unable to download required library " - + name - + "
Check your internet connection and try restarting or download it manually from" - + "
" - + url - + " and put it in your mods folder" - + ""); - - ep.setEditable(false); - ep.setOpaque(false); - ep.addHyperlinkListener(new HyperlinkListener() { - - @Override - public void hyperlinkUpdate(HyperlinkEvent event) { - try { - if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) - Desktop.getDesktop().browse(event.getURL().toURI()); - } catch (Exception e) {} - } - }); - - JOptionPane.showMessageDialog(null, ep, "A download error has occurred", JOptionPane.ERROR_MESSAGE); - } + public void showErrorDialog(String name, String url) {} } public static class DummyDownloader implements IDownloadDisplay { @@ -298,316 +147,12 @@ public Dependency(String url, VersionedFile file, boolean coreLib) { public static class DepLoadInst { - private File modsDir; - private File v_modsDir; - private IDownloadDisplay downloadMonitor; - private JDialog popupWindow; - - private Map depMap = new HashMap(); - private HashSet depSet = new HashSet(); - - public DepLoadInst() { - String mcVer = (String) FMLInjectionData.data()[4]; - File mcDir = (File) FMLInjectionData.data()[6]; - - modsDir = new File(mcDir, "mods"); - v_modsDir = new File(mcDir, "mods/" + mcVer); - if (!v_modsDir.exists()) v_modsDir.mkdirs(); - } - - private void addClasspath(String name) { - try { - ((LaunchClassLoader) DepLoader.class.getClassLoader()) - .addURL(new File(v_modsDir, name).toURI().toURL()); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } + public DepLoadInst() {} - private void deleteMod(File mod) { - if (mod.delete()) return; - - try { - ClassLoader cl = DepLoader.class.getClassLoader(); - URL url = mod.toURI().toURL(); - Field f_ucp = URLClassLoader.class.getDeclaredField("ucp"); - Field f_loaders = URLClassPath.class.getDeclaredField("loaders"); - Field f_lmap = URLClassPath.class.getDeclaredField("lmap"); - f_ucp.setAccessible(true); - f_loaders.setAccessible(true); - f_lmap.setAccessible(true); - - URLClassPath ucp = (URLClassPath) f_ucp.get(cl); - Closeable loader = ((Map) f_lmap.get(ucp)).remove(URLUtil.urlNoFragString(url)); - if (loader != null) { - loader.close(); - ((List) f_loaders.get(ucp)).remove(loader); - } - } catch (Exception e) { - e.printStackTrace(); - } - - if (!mod.delete()) { - mod.deleteOnExit(); - String msg = owner + " was unable to delete file " - + mod.getPath() - + " the game will now try to delete it on exit. If this dialog appears again, delete it manually."; - CodeChickenCorePlugin.logger.error(msg); - if (!GraphicsEnvironment.isHeadless()) - JOptionPane.showMessageDialog(null, msg, "An update error has occurred", JOptionPane.ERROR_MESSAGE); - - System.exit(1); - } - } - - private void download(Dependency dep) { - popupWindow = (JDialog) downloadMonitor.makeDialog(); - File libFile = new File(v_modsDir, dep.file.filename); - try { - URL libDownload = new URL(dep.url + '/' + dep.file.filename); - downloadMonitor.updateProgressString("Downloading file %s", libDownload.toString()); - CodeChickenCorePlugin.logger.debug("Downloading file " + libDownload); - URLConnection connection = libDownload.openConnection(); - connection.setConnectTimeout(5000); - connection.setReadTimeout(5000); - connection.setRequestProperty("User-Agent", "" + owner + " Downloader"); - int sizeGuess = connection.getContentLength(); - download(connection.getInputStream(), sizeGuess, libFile); - downloadMonitor.updateProgressString("Download complete"); - CodeChickenCorePlugin.logger.trace("Download complete"); - - scanDepInfo(libFile); - } catch (Exception e) { - libFile.delete(); - if (downloadMonitor.shouldStopIt()) { - CodeChickenCorePlugin.logger - .error("You have stopped the downloading operation before it could complete"); - System.exit(1); - return; - } - downloadMonitor.showErrorDialog(dep.file.filename, dep.url + '/' + dep.file.filename); - throw new RuntimeException("A download error occured", e); - } - } - - private void download(InputStream is, int sizeGuess, File target) throws Exception { - if (sizeGuess > downloadBuffer.capacity()) throw new Exception( - String.format( - "The file %s is too large to be downloaded by " + owner + " - the download is invalid", - target.getName())); - - downloadBuffer.clear(); - - int bytesRead, fullLength = 0; - - downloadMonitor.resetProgress(sizeGuess); - try { - downloadMonitor.setPokeThread(Thread.currentThread()); - byte[] smallBuffer = new byte[1024]; - while ((bytesRead = is.read(smallBuffer)) >= 0) { - downloadBuffer.put(smallBuffer, 0, bytesRead); - fullLength += bytesRead; - if (downloadMonitor.shouldStopIt()) { - break; - } - downloadMonitor.updateProgress(fullLength); - } - is.close(); - downloadMonitor.setPokeThread(null); - downloadBuffer.limit(fullLength); - downloadBuffer.position(0); - } catch (InterruptedIOException e) { - // We were interrupted by the stop button. We're stopping now.. clear interruption flag. - Thread.interrupted(); - throw new Exception("Stop"); - } catch (IOException e) { - throw e; - } - - try { - /* - * String cksum = generateChecksum(downloadBuffer); if (cksum.equals(validationHash)) { - */ - if (!target.exists()) target.createNewFile(); - - downloadBuffer.position(0); - FileOutputStream fos = new FileOutputStream(target); - fos.getChannel().write(downloadBuffer); - fos.close(); - /* - * } else { throw new RuntimeException(String. - * format("The downloaded file %s has an invalid checksum %s (expecting %s). The download did not succeed correctly and the file has been deleted. Please try launching again." - * , target.getName(), cksum, validationHash)); } - */ - } catch (Exception e) { - throw e; - } - } - - private String checkExisting(Dependency dep) { - for (File f : modsDir.listFiles()) { - VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); - if (!vfile.matches() || !vfile.name.equals(dep.file.name)) continue; - - if (f.renameTo(new File(v_modsDir, f.getName()))) continue; - - deleteMod(f); - } - - for (File f : v_modsDir.listFiles()) { - VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern); - if (!vfile.matches() || !vfile.name.equals(dep.file.name)) continue; - - int cmp = vfile.version.compareTo(dep.file.version); - if (cmp < 0) { - CodeChickenCorePlugin.logger.warn("Deleted old version " + f.getName()); - deleteMod(f); - return null; - } - if (cmp > 0) { - CodeChickenCorePlugin.logger.warn( - "Warning: version of " + dep.file.name - + ", " - + vfile.version - + " is newer than request " - + dep.file.version); - return f.getName(); - } - return f.getName(); // found dependency - } - return null; - } - - public void load() { - scanDepInfos(); - if (depMap.isEmpty()) return; - - loadDeps(); - activateDeps(); - } - - private void activateDeps() { - for (Dependency dep : depMap.values()) if (dep.coreLib) addClasspath(dep.existing); - } - - private void loadDeps() { - downloadMonitor = FMLLaunchHandler.side().isClient() ? new Downloader() : new DummyDownloader(); - try { - while (!depSet.isEmpty()) { - Iterator it = depSet.iterator(); - Dependency dep = depMap.get(it.next()); - it.remove(); - load(dep); - } - } finally { - if (popupWindow != null) { - popupWindow.setVisible(false); - popupWindow.dispose(); - } - } - } - - private void load(Dependency dep) { - dep.existing = checkExisting(dep); - if (dep.existing == null) // download dep - { - download(dep); - dep.existing = dep.file.filename; - } - } - - private List modFiles() { - List list = new LinkedList(); - list.addAll(Arrays.asList(modsDir.listFiles())); - list.addAll(Arrays.asList(v_modsDir.listFiles())); - return list; - } - - private void scanDepInfos() { - for (File file : modFiles()) { - if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) continue; - - scanDepInfo(file); - } - } - - private void scanDepInfo(File file) { - try { - ZipFile zip = new ZipFile(file); - ZipEntry e = zip.getEntry("dependancies.info"); - if (e == null) e = zip.getEntry("dependencies.info"); - if (e != null) loadJSon(zip.getInputStream(e)); - zip.close(); - } catch (Exception e) { - CodeChickenCorePlugin.logger - .error("Failed to load dependencies.info from " + file.getName() + " as JSON"); - e.printStackTrace(); - } - } - - private void loadJSon(InputStream input) throws IOException { - InputStreamReader reader = new InputStreamReader(input); - JsonElement root = new JsonParser().parse(reader); - if (root.isJsonArray()) loadJSonArr(root); - else loadJson(root.getAsJsonObject()); - reader.close(); - } - - private void loadJSonArr(JsonElement root) throws IOException { - for (JsonElement node : root.getAsJsonArray()) loadJson(node.getAsJsonObject()); - } - - private void loadJson(JsonObject node) throws IOException { - boolean obfuscated = ((LaunchClassLoader) DepLoader.class.getClassLoader()) - .getClassBytes("net.minecraft.world.World") == null; - - String testClass = node.get("class").getAsString(); - if (DepLoader.class.getResource("/" + testClass.replace('.', '/') + ".class") != null) return; - - String repo = node.get("repo").getAsString(); - String filename = node.get("file").getAsString(); - if (!obfuscated && node.has("dev")) filename = node.get("dev").getAsString(); - - boolean coreLib = node.has("coreLib") && node.get("coreLib").getAsBoolean(); - - Pattern pattern = null; - try { - if (node.has("pattern")) pattern = Pattern.compile(node.get("pattern").getAsString()); - } catch (PatternSyntaxException e) { - CodeChickenCorePlugin.logger.error("Invalid filename pattern: " + node.get("pattern")); - e.printStackTrace(); - } - if (pattern == null) pattern = Pattern.compile("(\\w+).*?([\\d\\.]+)[-\\w]*\\.[^\\d]+"); - - VersionedFile file = new VersionedFile(filename, pattern); - if (!file.matches()) throw new RuntimeException("Invalid filename format for dependency: " + filename); - - addDep(new Dependency(repo, file, coreLib)); - } - - private void addDep(Dependency newDep) { - if (mergeNew(depMap.get(newDep.file.name), newDep)) { - depMap.put(newDep.file.name, newDep); - depSet.add(newDep.file.name); - } - } - - private boolean mergeNew(Dependency oldDep, Dependency newDep) { - if (oldDep == null) return true; - - Dependency newest = newDep.file.version.compareTo(oldDep.file.version) > 0 ? newDep : oldDep; - newest.coreLib = newDep.coreLib || oldDep.coreLib; - - return newest == newDep; - } + public void load() {} } - public static void load() { - if (inst == null) { - inst = new DepLoadInst(); - inst.load(); - } - } + public static void load() {} @Override public String[] getASMTransformerClass() { From 183e658bb491baf225fae81e1a71a9a78be12659 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Wed, 3 Jul 2024 08:24:09 -0700 Subject: [PATCH 194/219] merge CCL --- ccl/.git-blame-ignore-revs | 2 - ccl/.gitattributes | 44 -- ccl/.github/workflows/build-and-test.yml | 13 - ccl/.github/workflows/release-tags.yml | 14 - ccl/.gitignore | 38 -- ccl/CODEOWNERS | 3 - ccl/LICENSE | 502 ------------------ ccl/README.md | 4 - ccl/build.gradle | 5 - ccl/dependencies.gradle | 5 - ccl/gradle.properties | 191 ------- ccl/gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 0 bytes ccl/gradle/wrapper/gradle-wrapper.properties | 7 - ccl/gradlew | 249 --------- ccl/gradlew.bat | 92 ---- ccl/jitpack.yml | 2 - ccl/repositories.gradle | 4 - ccl/settings.gradle | 23 - dependencies.gradle | 1 - gradle.properties | 4 +- .../core/commands/CoreCommand.java | 4 +- .../java/codechicken/lib/asm/ASMBlock.java | 0 .../java/codechicken/lib/asm/ASMHelper.java | 0 .../java/codechicken/lib/asm/ASMInit.java | 0 .../java/codechicken/lib/asm/ASMReader.java | 0 .../codechicken/lib/asm/CC_ClassWriter.java | 0 .../lib/asm/ClassConstantPoolParser.java | 0 .../lib/asm/ClassHeirachyManager.java | 0 .../lib/asm/ImportantInsnVisitor.java | 0 .../codechicken/lib/asm/InsnComparator.java | 0 .../codechicken/lib/asm/InsnListSection.java | 0 .../lib/asm/LocalVariablesSorterVisitor.java | 0 .../lib/asm/ModularASMTransformer.java | 0 .../java/codechicken/lib/asm/ObfMapping.java | 0 .../lib/asm/RedirectorTransformer.java | 0 .../java/codechicken/lib/colour/Colour.java | 0 .../codechicken/lib/colour/ColourARGB.java | 0 .../codechicken/lib/colour/ColourRGBA.java | 0 .../lib/colour/CustomGradient.java | 0 .../codechicken/lib/config/ConfigFile.java | 0 .../codechicken/lib/config/ConfigTag.java | 0 .../lib/config/ConfigTagParent.java | 0 .../lib/config/DefaultingConfigFile.java | 0 .../lib/config/SimpleProperties.java | 0 .../codechicken/lib/data/MCDataInput.java | 0 .../lib/data/MCDataInputStream.java | 0 .../codechicken/lib/data/MCDataOutput.java | 0 .../lib/data/MCDataOutputStream.java | 0 .../lib/data/MCDataOutputWrapper.java | 0 .../java/codechicken/lib/gui/Canvas9Seg.java | 0 .../java/codechicken/lib/gui/GuiDraw.java | 0 .../lib/inventory/ContainerExtended.java | 0 .../lib/inventory/ContainerSynchronised.java | 0 .../lib/inventory/IContainerSyncVar.java | 0 .../lib/inventory/IntegerSync.java | 0 .../lib/inventory/InventoryCopy.java | 0 .../lib/inventory/InventoryNBT.java | 0 .../lib/inventory/InventoryRange.java | 0 .../lib/inventory/InventorySimple.java | 0 .../lib/inventory/InventoryUtils.java | 0 .../codechicken/lib/inventory/ItemKey.java | 0 .../codechicken/lib/inventory/SlotDummy.java | 0 .../lib/inventory/SlotDummyOutput.java | 0 .../lib/inventory/SlotHandleClicks.java | 0 .../java/codechicken/lib/lighting/LC.java | 0 .../codechicken/lib/lighting/LightMatrix.java | 0 .../codechicken/lib/lighting/LightModel.java | 0 .../lib/lighting/PlanarLightMatrix.java | 0 .../lib/lighting/PlanarLightModel.java | 0 .../lib/lighting/SimpleBrightnessModel.java | 0 .../java/codechicken/lib/math/MathHelper.java | 0 .../lib/packet/ICustomPacketTile.java | 0 .../codechicken/lib/packet/PacketCustom.java | 0 .../lib/raytracer/ExtendedMOP.java | 0 .../lib/raytracer/IndexedCuboid6.java | 0 .../codechicken/lib/raytracer/RayTracer.java | 0 .../codechicken/lib/render/BlockRenderer.java | 0 .../java/codechicken/lib/render/CCModel.java | 0 .../lib/render/CCModelLibrary.java | 0 .../lib/render/CCRenderPipeline.java | 0 .../codechicken/lib/render/CCRenderState.java | 0 .../lib/render/ColourMultiplier.java | 0 .../lib/render/EntityDigIconFX.java | 0 .../codechicken/lib/render/FontUtils.java | 0 .../codechicken/lib/render/IFaceRenderer.java | 0 .../lib/render/ManagedTextureFX.java | 0 .../lib/render/PlaceholderTexture.java | 0 .../codechicken/lib/render/QBImporter.java | 0 .../codechicken/lib/render/RenderUtils.java | 0 .../codechicken/lib/render/ShaderProgram.java | 0 .../lib/render/SpriteSheetManager.java | 0 .../lib/render/TextureDataHolder.java | 0 .../codechicken/lib/render/TextureFX.java | 0 .../lib/render/TextureSpecial.java | 0 .../codechicken/lib/render/TextureUtils.java | 0 .../java/codechicken/lib/render/Vertex5.java | 0 .../lib/render/uv/IconTransformation.java | 0 .../render/uv/MultiIconTransformation.java | 0 .../java/codechicken/lib/render/uv/UV.java | 0 .../codechicken/lib/render/uv/UVRotation.java | 0 .../codechicken/lib/render/uv/UVScale.java | 0 .../lib/render/uv/UVTransformation.java | 0 .../lib/render/uv/UVTransformationList.java | 0 .../lib/render/uv/UVTranslation.java | 0 .../codechicken/lib/tool/LibDownloader.java | 0 .../lib/tool/MCStripTransformer.java | 0 .../main/java/codechicken/lib/tool/Main.java | 0 .../lib/tool/StripClassLoader.java | 0 .../java/codechicken/lib/tool/ToolMain.java | 0 .../lib/tool/module/JOptModule.java | 0 .../lib/tool/module/ModuleQBConverter.java | 0 .../java/codechicken/lib/util/Copyable.java | 0 .../java/codechicken/lib/util/LangProxy.java | 0 .../java/codechicken/lib/vec/AxisCycle.java | 0 .../java/codechicken/lib/vec/BlockCoord.java | 0 .../java/codechicken/lib/vec/Cuboid6.java | 0 .../java/codechicken/lib/vec/CuboidCoord.java | 0 .../codechicken/lib/vec/ITransformation.java | 0 .../IrreversibleTransformationException.java | 0 .../main/java/codechicken/lib/vec/Line3.java | 0 .../java/codechicken/lib/vec/Matrix4.java | 0 .../main/java/codechicken/lib/vec/Quat.java | 0 .../java/codechicken/lib/vec/Rectangle4i.java | 0 .../lib/vec/RedundantTransformation.java | 0 .../java/codechicken/lib/vec/Rotation.java | 0 .../main/java/codechicken/lib/vec/Scale.java | 0 .../main/java/codechicken/lib/vec/SwapYZ.java | 0 .../codechicken/lib/vec/Transformation.java | 0 .../lib/vec/TransformationList.java | 0 .../java/codechicken/lib/vec/Translation.java | 0 .../lib/vec/VariableTransformation.java | 0 .../java/codechicken/lib/vec/Vector3.java | 0 .../codechicken/lib/world/ChunkExtension.java | 0 .../codechicken/lib/world/IChunkLoadTile.java | 0 .../lib/world/TileChunkLoadHook.java | 0 .../codechicken/lib/world/WorldExtension.java | 0 .../lib/world/WorldExtensionInstantiator.java | 0 .../lib/world/WorldExtensionManager.java | 0 138 files changed, 4 insertions(+), 1203 deletions(-) delete mode 100644 ccl/.git-blame-ignore-revs delete mode 100644 ccl/.gitattributes delete mode 100644 ccl/.github/workflows/build-and-test.yml delete mode 100644 ccl/.github/workflows/release-tags.yml delete mode 100644 ccl/.gitignore delete mode 100644 ccl/CODEOWNERS delete mode 100644 ccl/LICENSE delete mode 100644 ccl/README.md delete mode 100644 ccl/build.gradle delete mode 100644 ccl/dependencies.gradle delete mode 100644 ccl/gradle.properties delete mode 100644 ccl/gradle/wrapper/gradle-wrapper.jar delete mode 100644 ccl/gradle/wrapper/gradle-wrapper.properties delete mode 100755 ccl/gradlew delete mode 100644 ccl/gradlew.bat delete mode 100644 ccl/jitpack.yml delete mode 100644 ccl/repositories.gradle delete mode 100644 ccl/settings.gradle rename {ccl/src => src}/main/java/codechicken/lib/asm/ASMBlock.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ASMHelper.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ASMInit.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ASMReader.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/CC_ClassWriter.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ClassConstantPoolParser.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ClassHeirachyManager.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ImportantInsnVisitor.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/InsnComparator.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/InsnListSection.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ModularASMTransformer.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/ObfMapping.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/asm/RedirectorTransformer.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/colour/Colour.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/colour/ColourARGB.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/colour/ColourRGBA.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/colour/CustomGradient.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/config/ConfigFile.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/config/ConfigTag.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/config/ConfigTagParent.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/config/DefaultingConfigFile.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/config/SimpleProperties.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/data/MCDataInput.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/data/MCDataInputStream.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/data/MCDataOutput.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/data/MCDataOutputStream.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/data/MCDataOutputWrapper.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/gui/Canvas9Seg.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/gui/GuiDraw.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/ContainerExtended.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/ContainerSynchronised.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/IContainerSyncVar.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/IntegerSync.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/InventoryCopy.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/InventoryNBT.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/InventoryRange.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/InventorySimple.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/InventoryUtils.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/ItemKey.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/SlotDummy.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/SlotDummyOutput.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/inventory/SlotHandleClicks.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/lighting/LC.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/lighting/LightMatrix.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/lighting/LightModel.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/lighting/PlanarLightMatrix.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/lighting/PlanarLightModel.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/math/MathHelper.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/packet/ICustomPacketTile.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/packet/PacketCustom.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/raytracer/ExtendedMOP.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/raytracer/IndexedCuboid6.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/raytracer/RayTracer.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/BlockRenderer.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/CCModel.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/CCModelLibrary.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/CCRenderPipeline.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/CCRenderState.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/ColourMultiplier.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/EntityDigIconFX.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/FontUtils.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/IFaceRenderer.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/ManagedTextureFX.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/PlaceholderTexture.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/QBImporter.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/RenderUtils.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/ShaderProgram.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/SpriteSheetManager.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/TextureDataHolder.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/TextureFX.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/TextureSpecial.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/TextureUtils.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/Vertex5.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/IconTransformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/MultiIconTransformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/UV.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/UVRotation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/UVScale.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/UVTransformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/UVTransformationList.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/render/uv/UVTranslation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/LibDownloader.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/MCStripTransformer.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/Main.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/StripClassLoader.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/ToolMain.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/module/JOptModule.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/tool/module/ModuleQBConverter.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/util/Copyable.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/util/LangProxy.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/AxisCycle.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/BlockCoord.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Cuboid6.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/CuboidCoord.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/ITransformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/IrreversibleTransformationException.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Line3.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Matrix4.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Quat.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Rectangle4i.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/RedundantTransformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Rotation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Scale.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/SwapYZ.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Transformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/TransformationList.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Translation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/VariableTransformation.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/vec/Vector3.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/world/ChunkExtension.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/world/IChunkLoadTile.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/world/TileChunkLoadHook.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/world/WorldExtension.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/world/WorldExtensionInstantiator.java (100%) rename {ccl/src => src}/main/java/codechicken/lib/world/WorldExtensionManager.java (100%) diff --git a/ccl/.git-blame-ignore-revs b/ccl/.git-blame-ignore-revs deleted file mode 100644 index 3563c3d..0000000 --- a/ccl/.git-blame-ignore-revs +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore spotlessApply reformat -a4515fbef8382f0f961ade90ca82c85d924fc06d diff --git a/ccl/.gitattributes b/ccl/.gitattributes deleted file mode 100644 index fd2792b..0000000 --- a/ccl/.gitattributes +++ /dev/null @@ -1,44 +0,0 @@ -* text eol=lf - -*.[jJ][aA][rR] binary - -*.[pP][nN][gG] binary -*.[jJ][pP][gG] binary -*.[jJ][pP][eE][gG] binary -*.[gG][iI][fF] binary -*.[tT][iI][fF] binary -*.[tT][iI][fF][fF] binary -*.[iI][cC][oO] binary -*.[sS][vV][gG] text -*.[eE][pP][sS] binary -*.[xX][cC][fF] binary - -*.[kK][aA][rR] binary -*.[mM]4[aA] binary -*.[mM][iI][dD] binary -*.[mM][iI][dD][iI] binary -*.[mM][pP]3 binary -*.[oO][gG][gG] binary -*.[rR][aA] binary - -*.7[zZ] binary -*.[gG][zZ] binary -*.[tT][aA][rR] binary -*.[tT][gG][zZ] binary -*.[zZ][iI][pP] binary - -*.[tT][cC][nN] binary -*.[sS][oO] binary -*.[dD][lL][lL] binary -*.[dD][yY][lL][iI][bB] binary -*.[pP][sS][dD] binary -*.[tT][tT][fF] binary -*.[oO][tT][fF] binary - -*.[pP][aA][tT][cC][hH] -text - -*.[bB][aA][tT] text eol=crlf -*.[cC][mM][dD] text eol=crlf -*.[pP][sS]1 text eol=crlf - -*[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary diff --git a/ccl/.github/workflows/build-and-test.yml b/ccl/.github/workflows/build-and-test.yml deleted file mode 100644 index 3ee2f68..0000000 --- a/ccl/.github/workflows/build-and-test.yml +++ /dev/null @@ -1,13 +0,0 @@ - -name: Build and test - -on: - pull_request: - branches: [ master, main ] - push: - branches: [ master, main ] - -jobs: - build-and-test: - uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master - secrets: inherit diff --git a/ccl/.github/workflows/release-tags.yml b/ccl/.github/workflows/release-tags.yml deleted file mode 100644 index e4c0be6..0000000 --- a/ccl/.github/workflows/release-tags.yml +++ /dev/null @@ -1,14 +0,0 @@ - -name: Release tagged build - -on: - push: - tags: [ '*' ] - -permissions: - contents: write - -jobs: - release-tags: - uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master - secrets: inherit diff --git a/ccl/.gitignore b/ccl/.gitignore deleted file mode 100644 index 5e80e0a..0000000 --- a/ccl/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -.gradle -.settings -/.idea/ -/.vscode/ -/run/ -/build/ -/eclipse/ -.classpath -.project -/bin/ -/config/ -/crash-reports/ -/logs/ -options.txt -/saves/ -usernamecache.json -banned-ips.json -banned-players.json -eula.txt -ops.json -server.properties -servers.dat -usercache.json -whitelist.json -/out/ -*.iml -*.ipr -*.iws -src/main/resources/mixins.*([!.]).json -*.bat -*.DS_Store -!gradlew.bat -.factorypath -addon.local.gradle -addon.local.gradle.kts -addon.late.local.gradle -addon.late.local.gradle.kts -layout.json diff --git a/ccl/CODEOWNERS b/ccl/CODEOWNERS deleted file mode 100644 index a6b5f68..0000000 --- a/ccl/CODEOWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Any Github changes require admin approval -/.github/** @GTNewHorizons/admin - diff --git a/ccl/LICENSE b/ccl/LICENSE deleted file mode 100644 index 31b791c..0000000 --- a/ccl/LICENSE +++ /dev/null @@ -1,502 +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) 2013 Chicken-Bones - - 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. - - {signature of Ty Coon}, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/ccl/README.md b/ccl/README.md deleted file mode 100644 index 9864c48..0000000 --- a/ccl/README.md +++ /dev/null @@ -1,4 +0,0 @@ -CodeChickenLib -============== -Formerly known as CodeChickenCore-Public, this is a library of systems to help make various aspects of minecraft modding easier. -It contains libraries for 3D math and transformations, model rendering, packets, config, colours, asm and a few other things. \ No newline at end of file diff --git a/ccl/build.gradle b/ccl/build.gradle deleted file mode 100644 index e57a16f..0000000 --- a/ccl/build.gradle +++ /dev/null @@ -1,5 +0,0 @@ -//version: 1707058017 - -plugins { - id 'com.gtnewhorizons.gtnhconvention' -} diff --git a/ccl/dependencies.gradle b/ccl/dependencies.gradle deleted file mode 100644 index b6456d0..0000000 --- a/ccl/dependencies.gradle +++ /dev/null @@ -1,5 +0,0 @@ -// Add your dependencies here - -dependencies { - -} diff --git a/ccl/gradle.properties b/ccl/gradle.properties deleted file mode 100644 index 1849951..0000000 --- a/ccl/gradle.properties +++ /dev/null @@ -1,191 +0,0 @@ -# ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable. -# LOCAL to test local config updates. -gtnh.settings.blowdryerTag = 0.2.0 - -# Human-readable mod name, available for mcmod.info population. -modName = CodeChickenLib - -# Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation. -# Conventionally lowercase. -modId = CodeChickenLib - -# Root package of the mod, used to find various classes in other properties, -# mcmod.info substitution, enabling assertions in run tasks, etc. -modGroup = codechicken - -# Whether to use modGroup as the maven publishing group. -# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods. -useModGroupForPublishing = false - -# Updates your build.gradle and settings.gradle automatically whenever an update is available. -autoUpdateBuildScript = false - -# Version of Minecraft to target -minecraftVersion = 1.7.10 - -# Version of Minecraft Forge to target -forgeVersion = 10.13.4.1614 - -# Specify an MCP channel for dependency deobfuscation and the deobfParams task. -channel = stable - -# Specify an MCP mappings version for dependency deobfuscation and the deobfParams task. -mappingsVersion = 12 - -# Defines other MCP mappings for dependency deobfuscation. -remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ - -# Select a default username for testing your mod. You can always override this per-run by running -# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE. -developmentEnvironmentUserName = Developer - -# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8. -# See https://github.com/bsideup/jabel for details on how this works. -enableModernJavaSyntax = true - -# Enables injecting missing generics into the decompiled source code for a better coding experience. -# Turns most publicly visible List, Map, etc. into proper List, Map types. -enableGenericInjection = true - -# Generate a class with a String field for the mod version named as defined below. -# If generateGradleTokenClass is empty or not missing, no such class will be generated. -# If gradleTokenVersion is empty or missing, the field will not be present in the class. -generateGradleTokenClass = - -# Name of the token containing the project's current version to generate/replace. -gradleTokenVersion = - -# [DEPRECATED] Mod ID replacement token. -gradleTokenModId = - -# [DEPRECATED] Mod name replacement token. -gradleTokenModName = - -# [DEPRECATED] -# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java -# public static final String VERSION = "GRADLETOKEN_VERSION"; -# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's -# version in @Mod([...], version = VERSION, [...]). -# Leave these properties empty to skip individual token replacements. -replaceGradleTokenInFile = - -# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can -# leave this property empty. -# Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api -apiPackage = - -# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ -# There can be multiple files in a space-separated list. -# Example value: mymodid_at.cfg nei_at.cfg -accessTransformersFile = - -# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! -usesMixins = false - -# Adds some debug arguments like verbose output and class export. -usesMixinDebug = false - -# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. -mixinPlugin = - -# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! -mixinsPackage = - -# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! -# This parameter is for legacy compatibility only -# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin -coreModClass = - -# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class -# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! -containsMixinsAndOrCoreModOnly = - -# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins. -forceEnableMixins = false - -# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your -# responsibility to check the license and request permission for distribution if required. -usesShadowedDependencies = false - -# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access -# their own classes, making the minimization unreliable. -minimizeShadowedDependencies = true - -# If disabled, won't rename the shadowed classes. -relocateShadowedDependencies = true - -# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. -includeWellKnownRepositories = true - -# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. -# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables. -# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle. -usesMavenPublishing = true - -# Maven repository to publish the mod to. -# mavenPublishUrl = https://nexus.gtnewhorizons.com/repository/releases/ - -# Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token. -# -# The project's ID on Modrinth. Can be either the slug or the ID. -# Leave this empty if you don't want to publish to Modrinth. -modrinthProjectId = codechickenlib-unofficial - -# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. -# Syntax: scope1-type1:name1;scope2-type2:name2;... -# Where scope can be one of [required, optional, incompatible, embedded], -# type can be one of [project, version], -# and the name is the Modrinth project or version slug/id of the other mod. -# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech -# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true -modrinthRelations = - -# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. -# -# The project's numeric ID on CurseForge. You can find this in the About Project box. -# Leave this empty if you don't want to publish on CurseForge. -curseForgeProjectId = 746280 - -# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. -# Syntax: type1:name1;type2:name2;... -# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], -# and the name is the CurseForge project slug of the other mod. -# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft -# Note: UniMixins is automatically set as a required dependency if usesMixins = true. -curseForgeRelations = - -# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older -# projects. New projects should not use this parameter. -# customArchiveBaseName = - -# Optional parameter to have the build automatically fail if an illegal version is used. -# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'. -# The check is ONLY performed if the version is a git tag. -# Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+ -# versionPattern = - -# Uncomment to prevent the source code from being published. -# noPublishedSources = true - -# Uncomment this to disable Spotless checks. -# This should only be uncommented to keep it easier to sync with upstream/other forks. -# That is, if there is no other active fork/upstream, NEVER change this. -# disableSpotless = true - -# Uncomment this to disable Checkstyle checks (currently wildcard import check). -# disableCheckstyle = true - -# Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle" -# (force use delegated build). -# This is meant to be set in $HOME/.gradle/gradle.properties. -# e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build. -# WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want! -# Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you. -# ideaOverrideBuildType = idea - -# Whether IDEA should run spotless checks when pressing the Build button. -# This is meant to be set in $HOME/.gradle/gradle.properties. -# ideaCheckSpotlessOnBuild = true - -# Non-GTNH properties -gradleTokenGroupName = diff --git a/ccl/gradle/wrapper/gradle-wrapper.jar b/ccl/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index d64cd4917707c1f8861d8cb53dd15194d4248596..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43462 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 diff --git a/ccl/gradle/wrapper/gradle-wrapper.properties b/ccl/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a80b22c..0000000 --- a/ccl/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/ccl/gradlew b/ccl/gradlew deleted file mode 100755 index 1aa94a4..0000000 --- a/ccl/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - 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/ccl/gradlew.bat b/ccl/gradlew.bat deleted file mode 100644 index 25da30d..0000000 --- a/ccl/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/ccl/jitpack.yml b/ccl/jitpack.yml deleted file mode 100644 index 09bbb51..0000000 --- a/ccl/jitpack.yml +++ /dev/null @@ -1,2 +0,0 @@ -before_install: - - ./gradlew setupCIWorkspace \ No newline at end of file diff --git a/ccl/repositories.gradle b/ccl/repositories.gradle deleted file mode 100644 index 45729e1..0000000 --- a/ccl/repositories.gradle +++ /dev/null @@ -1,4 +0,0 @@ -// Add any additional repositiroes for your dependencies here - -repositories { -} diff --git a/ccl/settings.gradle b/ccl/settings.gradle deleted file mode 100644 index e8946ad..0000000 --- a/ccl/settings.gradle +++ /dev/null @@ -1,23 +0,0 @@ - -pluginManagement { - repositories { - maven { - // RetroFuturaGradle - name "GTNH Maven" - url "https://nexus.gtnewhorizons.com/repository/public/" - mavenContent { - includeGroup("com.gtnewhorizons") - includeGroupByRegex("com\\.gtnewhorizons\\..+") - } - } - gradlePluginPortal() - mavenCentral() - mavenLocal() - } -} - -plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.8' -} - - diff --git a/dependencies.gradle b/dependencies.gradle index 2acc808..2767713 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,4 @@ // Add your dependencies here dependencies { - api('com.github.GTNewHorizons:CodeChickenLib:1.2.0:dev') } diff --git a/gradle.properties b/gradle.properties index 4b3f1f2..c614939 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,11 +41,11 @@ developmentEnvironmentUserName = Developer # Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8. # See https://github.com/bsideup/jabel for details on how this works. -enableModernJavaSyntax = false +enableModernJavaSyntax = true # Enables injecting missing generics into the decompiled source code for a better coding experience. # Turns most publicly visible List, Map, etc. into proper List, Map types. -enableGenericInjection = false +enableGenericInjection = true # Generate a class with a String field for the mod version named as defined below. # If generateGradleTokenClass is empty or not missing, no such class will be generated. diff --git a/src/main/java/codechicken/core/commands/CoreCommand.java b/src/main/java/codechicken/core/commands/CoreCommand.java index 606c230..9d4e3d8 100644 --- a/src/main/java/codechicken/core/commands/CoreCommand.java +++ b/src/main/java/codechicken/core/commands/CoreCommand.java @@ -112,12 +112,12 @@ public int compareTo(Object arg0) { } @Override - public List getCommandAliases() { + public List getCommandAliases() { return null; } @Override - public List addTabCompletionOptions(ICommandSender var1, String[] var2) { + public List addTabCompletionOptions(ICommandSender var1, String[] var2) { return null; } diff --git a/ccl/src/main/java/codechicken/lib/asm/ASMBlock.java b/src/main/java/codechicken/lib/asm/ASMBlock.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ASMBlock.java rename to src/main/java/codechicken/lib/asm/ASMBlock.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ASMHelper.java b/src/main/java/codechicken/lib/asm/ASMHelper.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ASMHelper.java rename to src/main/java/codechicken/lib/asm/ASMHelper.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ASMInit.java b/src/main/java/codechicken/lib/asm/ASMInit.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ASMInit.java rename to src/main/java/codechicken/lib/asm/ASMInit.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ASMReader.java b/src/main/java/codechicken/lib/asm/ASMReader.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ASMReader.java rename to src/main/java/codechicken/lib/asm/ASMReader.java diff --git a/ccl/src/main/java/codechicken/lib/asm/CC_ClassWriter.java b/src/main/java/codechicken/lib/asm/CC_ClassWriter.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/CC_ClassWriter.java rename to src/main/java/codechicken/lib/asm/CC_ClassWriter.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java b/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java rename to src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java rename to src/main/java/codechicken/lib/asm/ClassHeirachyManager.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java b/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java rename to src/main/java/codechicken/lib/asm/ImportantInsnVisitor.java diff --git a/ccl/src/main/java/codechicken/lib/asm/InsnComparator.java b/src/main/java/codechicken/lib/asm/InsnComparator.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/InsnComparator.java rename to src/main/java/codechicken/lib/asm/InsnComparator.java diff --git a/ccl/src/main/java/codechicken/lib/asm/InsnListSection.java b/src/main/java/codechicken/lib/asm/InsnListSection.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/InsnListSection.java rename to src/main/java/codechicken/lib/asm/InsnListSection.java diff --git a/ccl/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java b/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java rename to src/main/java/codechicken/lib/asm/LocalVariablesSorterVisitor.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ModularASMTransformer.java rename to src/main/java/codechicken/lib/asm/ModularASMTransformer.java diff --git a/ccl/src/main/java/codechicken/lib/asm/ObfMapping.java b/src/main/java/codechicken/lib/asm/ObfMapping.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/ObfMapping.java rename to src/main/java/codechicken/lib/asm/ObfMapping.java diff --git a/ccl/src/main/java/codechicken/lib/asm/RedirectorTransformer.java b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/asm/RedirectorTransformer.java rename to src/main/java/codechicken/lib/asm/RedirectorTransformer.java diff --git a/ccl/src/main/java/codechicken/lib/colour/Colour.java b/src/main/java/codechicken/lib/colour/Colour.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/colour/Colour.java rename to src/main/java/codechicken/lib/colour/Colour.java diff --git a/ccl/src/main/java/codechicken/lib/colour/ColourARGB.java b/src/main/java/codechicken/lib/colour/ColourARGB.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/colour/ColourARGB.java rename to src/main/java/codechicken/lib/colour/ColourARGB.java diff --git a/ccl/src/main/java/codechicken/lib/colour/ColourRGBA.java b/src/main/java/codechicken/lib/colour/ColourRGBA.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/colour/ColourRGBA.java rename to src/main/java/codechicken/lib/colour/ColourRGBA.java diff --git a/ccl/src/main/java/codechicken/lib/colour/CustomGradient.java b/src/main/java/codechicken/lib/colour/CustomGradient.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/colour/CustomGradient.java rename to src/main/java/codechicken/lib/colour/CustomGradient.java diff --git a/ccl/src/main/java/codechicken/lib/config/ConfigFile.java b/src/main/java/codechicken/lib/config/ConfigFile.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/config/ConfigFile.java rename to src/main/java/codechicken/lib/config/ConfigFile.java diff --git a/ccl/src/main/java/codechicken/lib/config/ConfigTag.java b/src/main/java/codechicken/lib/config/ConfigTag.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/config/ConfigTag.java rename to src/main/java/codechicken/lib/config/ConfigTag.java diff --git a/ccl/src/main/java/codechicken/lib/config/ConfigTagParent.java b/src/main/java/codechicken/lib/config/ConfigTagParent.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/config/ConfigTagParent.java rename to src/main/java/codechicken/lib/config/ConfigTagParent.java diff --git a/ccl/src/main/java/codechicken/lib/config/DefaultingConfigFile.java b/src/main/java/codechicken/lib/config/DefaultingConfigFile.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/config/DefaultingConfigFile.java rename to src/main/java/codechicken/lib/config/DefaultingConfigFile.java diff --git a/ccl/src/main/java/codechicken/lib/config/SimpleProperties.java b/src/main/java/codechicken/lib/config/SimpleProperties.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/config/SimpleProperties.java rename to src/main/java/codechicken/lib/config/SimpleProperties.java diff --git a/ccl/src/main/java/codechicken/lib/data/MCDataInput.java b/src/main/java/codechicken/lib/data/MCDataInput.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/data/MCDataInput.java rename to src/main/java/codechicken/lib/data/MCDataInput.java diff --git a/ccl/src/main/java/codechicken/lib/data/MCDataInputStream.java b/src/main/java/codechicken/lib/data/MCDataInputStream.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/data/MCDataInputStream.java rename to src/main/java/codechicken/lib/data/MCDataInputStream.java diff --git a/ccl/src/main/java/codechicken/lib/data/MCDataOutput.java b/src/main/java/codechicken/lib/data/MCDataOutput.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/data/MCDataOutput.java rename to src/main/java/codechicken/lib/data/MCDataOutput.java diff --git a/ccl/src/main/java/codechicken/lib/data/MCDataOutputStream.java b/src/main/java/codechicken/lib/data/MCDataOutputStream.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/data/MCDataOutputStream.java rename to src/main/java/codechicken/lib/data/MCDataOutputStream.java diff --git a/ccl/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java b/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/data/MCDataOutputWrapper.java rename to src/main/java/codechicken/lib/data/MCDataOutputWrapper.java diff --git a/ccl/src/main/java/codechicken/lib/gui/Canvas9Seg.java b/src/main/java/codechicken/lib/gui/Canvas9Seg.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/gui/Canvas9Seg.java rename to src/main/java/codechicken/lib/gui/Canvas9Seg.java diff --git a/ccl/src/main/java/codechicken/lib/gui/GuiDraw.java b/src/main/java/codechicken/lib/gui/GuiDraw.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/gui/GuiDraw.java rename to src/main/java/codechicken/lib/gui/GuiDraw.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/ContainerExtended.java b/src/main/java/codechicken/lib/inventory/ContainerExtended.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/ContainerExtended.java rename to src/main/java/codechicken/lib/inventory/ContainerExtended.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java b/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/ContainerSynchronised.java rename to src/main/java/codechicken/lib/inventory/ContainerSynchronised.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java b/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java rename to src/main/java/codechicken/lib/inventory/IContainerSyncVar.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/IntegerSync.java b/src/main/java/codechicken/lib/inventory/IntegerSync.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/IntegerSync.java rename to src/main/java/codechicken/lib/inventory/IntegerSync.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/InventoryCopy.java b/src/main/java/codechicken/lib/inventory/InventoryCopy.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/InventoryCopy.java rename to src/main/java/codechicken/lib/inventory/InventoryCopy.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/InventoryNBT.java b/src/main/java/codechicken/lib/inventory/InventoryNBT.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/InventoryNBT.java rename to src/main/java/codechicken/lib/inventory/InventoryNBT.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/InventoryRange.java b/src/main/java/codechicken/lib/inventory/InventoryRange.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/InventoryRange.java rename to src/main/java/codechicken/lib/inventory/InventoryRange.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/InventorySimple.java b/src/main/java/codechicken/lib/inventory/InventorySimple.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/InventorySimple.java rename to src/main/java/codechicken/lib/inventory/InventorySimple.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/InventoryUtils.java b/src/main/java/codechicken/lib/inventory/InventoryUtils.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/InventoryUtils.java rename to src/main/java/codechicken/lib/inventory/InventoryUtils.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/ItemKey.java b/src/main/java/codechicken/lib/inventory/ItemKey.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/ItemKey.java rename to src/main/java/codechicken/lib/inventory/ItemKey.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/SlotDummy.java b/src/main/java/codechicken/lib/inventory/SlotDummy.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/SlotDummy.java rename to src/main/java/codechicken/lib/inventory/SlotDummy.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java b/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/SlotDummyOutput.java rename to src/main/java/codechicken/lib/inventory/SlotDummyOutput.java diff --git a/ccl/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java b/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/inventory/SlotHandleClicks.java rename to src/main/java/codechicken/lib/inventory/SlotHandleClicks.java diff --git a/ccl/src/main/java/codechicken/lib/lighting/LC.java b/src/main/java/codechicken/lib/lighting/LC.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/lighting/LC.java rename to src/main/java/codechicken/lib/lighting/LC.java diff --git a/ccl/src/main/java/codechicken/lib/lighting/LightMatrix.java b/src/main/java/codechicken/lib/lighting/LightMatrix.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/lighting/LightMatrix.java rename to src/main/java/codechicken/lib/lighting/LightMatrix.java diff --git a/ccl/src/main/java/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/lighting/LightModel.java rename to src/main/java/codechicken/lib/lighting/LightModel.java diff --git a/ccl/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java rename to src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java diff --git a/ccl/src/main/java/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/lighting/PlanarLightModel.java rename to src/main/java/codechicken/lib/lighting/PlanarLightModel.java diff --git a/ccl/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java rename to src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java diff --git a/ccl/src/main/java/codechicken/lib/math/MathHelper.java b/src/main/java/codechicken/lib/math/MathHelper.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/math/MathHelper.java rename to src/main/java/codechicken/lib/math/MathHelper.java diff --git a/ccl/src/main/java/codechicken/lib/packet/ICustomPacketTile.java b/src/main/java/codechicken/lib/packet/ICustomPacketTile.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/packet/ICustomPacketTile.java rename to src/main/java/codechicken/lib/packet/ICustomPacketTile.java diff --git a/ccl/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/packet/PacketCustom.java rename to src/main/java/codechicken/lib/packet/PacketCustom.java diff --git a/ccl/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java b/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/raytracer/ExtendedMOP.java rename to src/main/java/codechicken/lib/raytracer/ExtendedMOP.java diff --git a/ccl/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java b/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java rename to src/main/java/codechicken/lib/raytracer/IndexedCuboid6.java diff --git a/ccl/src/main/java/codechicken/lib/raytracer/RayTracer.java b/src/main/java/codechicken/lib/raytracer/RayTracer.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/raytracer/RayTracer.java rename to src/main/java/codechicken/lib/raytracer/RayTracer.java diff --git a/ccl/src/main/java/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/BlockRenderer.java rename to src/main/java/codechicken/lib/render/BlockRenderer.java diff --git a/ccl/src/main/java/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/CCModel.java rename to src/main/java/codechicken/lib/render/CCModel.java diff --git a/ccl/src/main/java/codechicken/lib/render/CCModelLibrary.java b/src/main/java/codechicken/lib/render/CCModelLibrary.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/CCModelLibrary.java rename to src/main/java/codechicken/lib/render/CCModelLibrary.java diff --git a/ccl/src/main/java/codechicken/lib/render/CCRenderPipeline.java b/src/main/java/codechicken/lib/render/CCRenderPipeline.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/CCRenderPipeline.java rename to src/main/java/codechicken/lib/render/CCRenderPipeline.java diff --git a/ccl/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/CCRenderState.java rename to src/main/java/codechicken/lib/render/CCRenderState.java diff --git a/ccl/src/main/java/codechicken/lib/render/ColourMultiplier.java b/src/main/java/codechicken/lib/render/ColourMultiplier.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/ColourMultiplier.java rename to src/main/java/codechicken/lib/render/ColourMultiplier.java diff --git a/ccl/src/main/java/codechicken/lib/render/EntityDigIconFX.java b/src/main/java/codechicken/lib/render/EntityDigIconFX.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/EntityDigIconFX.java rename to src/main/java/codechicken/lib/render/EntityDigIconFX.java diff --git a/ccl/src/main/java/codechicken/lib/render/FontUtils.java b/src/main/java/codechicken/lib/render/FontUtils.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/FontUtils.java rename to src/main/java/codechicken/lib/render/FontUtils.java diff --git a/ccl/src/main/java/codechicken/lib/render/IFaceRenderer.java b/src/main/java/codechicken/lib/render/IFaceRenderer.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/IFaceRenderer.java rename to src/main/java/codechicken/lib/render/IFaceRenderer.java diff --git a/ccl/src/main/java/codechicken/lib/render/ManagedTextureFX.java b/src/main/java/codechicken/lib/render/ManagedTextureFX.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/ManagedTextureFX.java rename to src/main/java/codechicken/lib/render/ManagedTextureFX.java diff --git a/ccl/src/main/java/codechicken/lib/render/PlaceholderTexture.java b/src/main/java/codechicken/lib/render/PlaceholderTexture.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/PlaceholderTexture.java rename to src/main/java/codechicken/lib/render/PlaceholderTexture.java diff --git a/ccl/src/main/java/codechicken/lib/render/QBImporter.java b/src/main/java/codechicken/lib/render/QBImporter.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/QBImporter.java rename to src/main/java/codechicken/lib/render/QBImporter.java diff --git a/ccl/src/main/java/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/RenderUtils.java rename to src/main/java/codechicken/lib/render/RenderUtils.java diff --git a/ccl/src/main/java/codechicken/lib/render/ShaderProgram.java b/src/main/java/codechicken/lib/render/ShaderProgram.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/ShaderProgram.java rename to src/main/java/codechicken/lib/render/ShaderProgram.java diff --git a/ccl/src/main/java/codechicken/lib/render/SpriteSheetManager.java b/src/main/java/codechicken/lib/render/SpriteSheetManager.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/SpriteSheetManager.java rename to src/main/java/codechicken/lib/render/SpriteSheetManager.java diff --git a/ccl/src/main/java/codechicken/lib/render/TextureDataHolder.java b/src/main/java/codechicken/lib/render/TextureDataHolder.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/TextureDataHolder.java rename to src/main/java/codechicken/lib/render/TextureDataHolder.java diff --git a/ccl/src/main/java/codechicken/lib/render/TextureFX.java b/src/main/java/codechicken/lib/render/TextureFX.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/TextureFX.java rename to src/main/java/codechicken/lib/render/TextureFX.java diff --git a/ccl/src/main/java/codechicken/lib/render/TextureSpecial.java b/src/main/java/codechicken/lib/render/TextureSpecial.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/TextureSpecial.java rename to src/main/java/codechicken/lib/render/TextureSpecial.java diff --git a/ccl/src/main/java/codechicken/lib/render/TextureUtils.java b/src/main/java/codechicken/lib/render/TextureUtils.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/TextureUtils.java rename to src/main/java/codechicken/lib/render/TextureUtils.java diff --git a/ccl/src/main/java/codechicken/lib/render/Vertex5.java b/src/main/java/codechicken/lib/render/Vertex5.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/Vertex5.java rename to src/main/java/codechicken/lib/render/Vertex5.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/IconTransformation.java b/src/main/java/codechicken/lib/render/uv/IconTransformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/IconTransformation.java rename to src/main/java/codechicken/lib/render/uv/IconTransformation.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java b/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java rename to src/main/java/codechicken/lib/render/uv/MultiIconTransformation.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/UV.java b/src/main/java/codechicken/lib/render/uv/UV.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/UV.java rename to src/main/java/codechicken/lib/render/uv/UV.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/UVRotation.java b/src/main/java/codechicken/lib/render/uv/UVRotation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/UVRotation.java rename to src/main/java/codechicken/lib/render/uv/UVRotation.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/UVScale.java b/src/main/java/codechicken/lib/render/uv/UVScale.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/UVScale.java rename to src/main/java/codechicken/lib/render/uv/UVScale.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/UVTransformation.java b/src/main/java/codechicken/lib/render/uv/UVTransformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/UVTransformation.java rename to src/main/java/codechicken/lib/render/uv/UVTransformation.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/UVTransformationList.java b/src/main/java/codechicken/lib/render/uv/UVTransformationList.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/UVTransformationList.java rename to src/main/java/codechicken/lib/render/uv/UVTransformationList.java diff --git a/ccl/src/main/java/codechicken/lib/render/uv/UVTranslation.java b/src/main/java/codechicken/lib/render/uv/UVTranslation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/render/uv/UVTranslation.java rename to src/main/java/codechicken/lib/render/uv/UVTranslation.java diff --git a/ccl/src/main/java/codechicken/lib/tool/LibDownloader.java b/src/main/java/codechicken/lib/tool/LibDownloader.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/LibDownloader.java rename to src/main/java/codechicken/lib/tool/LibDownloader.java diff --git a/ccl/src/main/java/codechicken/lib/tool/MCStripTransformer.java b/src/main/java/codechicken/lib/tool/MCStripTransformer.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/MCStripTransformer.java rename to src/main/java/codechicken/lib/tool/MCStripTransformer.java diff --git a/ccl/src/main/java/codechicken/lib/tool/Main.java b/src/main/java/codechicken/lib/tool/Main.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/Main.java rename to src/main/java/codechicken/lib/tool/Main.java diff --git a/ccl/src/main/java/codechicken/lib/tool/StripClassLoader.java b/src/main/java/codechicken/lib/tool/StripClassLoader.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/StripClassLoader.java rename to src/main/java/codechicken/lib/tool/StripClassLoader.java diff --git a/ccl/src/main/java/codechicken/lib/tool/ToolMain.java b/src/main/java/codechicken/lib/tool/ToolMain.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/ToolMain.java rename to src/main/java/codechicken/lib/tool/ToolMain.java diff --git a/ccl/src/main/java/codechicken/lib/tool/module/JOptModule.java b/src/main/java/codechicken/lib/tool/module/JOptModule.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/module/JOptModule.java rename to src/main/java/codechicken/lib/tool/module/JOptModule.java diff --git a/ccl/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java b/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java rename to src/main/java/codechicken/lib/tool/module/ModuleQBConverter.java diff --git a/ccl/src/main/java/codechicken/lib/util/Copyable.java b/src/main/java/codechicken/lib/util/Copyable.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/util/Copyable.java rename to src/main/java/codechicken/lib/util/Copyable.java diff --git a/ccl/src/main/java/codechicken/lib/util/LangProxy.java b/src/main/java/codechicken/lib/util/LangProxy.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/util/LangProxy.java rename to src/main/java/codechicken/lib/util/LangProxy.java diff --git a/ccl/src/main/java/codechicken/lib/vec/AxisCycle.java b/src/main/java/codechicken/lib/vec/AxisCycle.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/AxisCycle.java rename to src/main/java/codechicken/lib/vec/AxisCycle.java diff --git a/ccl/src/main/java/codechicken/lib/vec/BlockCoord.java b/src/main/java/codechicken/lib/vec/BlockCoord.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/BlockCoord.java rename to src/main/java/codechicken/lib/vec/BlockCoord.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Cuboid6.java b/src/main/java/codechicken/lib/vec/Cuboid6.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Cuboid6.java rename to src/main/java/codechicken/lib/vec/Cuboid6.java diff --git a/ccl/src/main/java/codechicken/lib/vec/CuboidCoord.java b/src/main/java/codechicken/lib/vec/CuboidCoord.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/CuboidCoord.java rename to src/main/java/codechicken/lib/vec/CuboidCoord.java diff --git a/ccl/src/main/java/codechicken/lib/vec/ITransformation.java b/src/main/java/codechicken/lib/vec/ITransformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/ITransformation.java rename to src/main/java/codechicken/lib/vec/ITransformation.java diff --git a/ccl/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java b/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java rename to src/main/java/codechicken/lib/vec/IrreversibleTransformationException.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Line3.java b/src/main/java/codechicken/lib/vec/Line3.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Line3.java rename to src/main/java/codechicken/lib/vec/Line3.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Matrix4.java b/src/main/java/codechicken/lib/vec/Matrix4.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Matrix4.java rename to src/main/java/codechicken/lib/vec/Matrix4.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Quat.java b/src/main/java/codechicken/lib/vec/Quat.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Quat.java rename to src/main/java/codechicken/lib/vec/Quat.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Rectangle4i.java b/src/main/java/codechicken/lib/vec/Rectangle4i.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Rectangle4i.java rename to src/main/java/codechicken/lib/vec/Rectangle4i.java diff --git a/ccl/src/main/java/codechicken/lib/vec/RedundantTransformation.java b/src/main/java/codechicken/lib/vec/RedundantTransformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/RedundantTransformation.java rename to src/main/java/codechicken/lib/vec/RedundantTransformation.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Rotation.java b/src/main/java/codechicken/lib/vec/Rotation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Rotation.java rename to src/main/java/codechicken/lib/vec/Rotation.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Scale.java b/src/main/java/codechicken/lib/vec/Scale.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Scale.java rename to src/main/java/codechicken/lib/vec/Scale.java diff --git a/ccl/src/main/java/codechicken/lib/vec/SwapYZ.java b/src/main/java/codechicken/lib/vec/SwapYZ.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/SwapYZ.java rename to src/main/java/codechicken/lib/vec/SwapYZ.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Transformation.java b/src/main/java/codechicken/lib/vec/Transformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Transformation.java rename to src/main/java/codechicken/lib/vec/Transformation.java diff --git a/ccl/src/main/java/codechicken/lib/vec/TransformationList.java b/src/main/java/codechicken/lib/vec/TransformationList.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/TransformationList.java rename to src/main/java/codechicken/lib/vec/TransformationList.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Translation.java b/src/main/java/codechicken/lib/vec/Translation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Translation.java rename to src/main/java/codechicken/lib/vec/Translation.java diff --git a/ccl/src/main/java/codechicken/lib/vec/VariableTransformation.java b/src/main/java/codechicken/lib/vec/VariableTransformation.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/VariableTransformation.java rename to src/main/java/codechicken/lib/vec/VariableTransformation.java diff --git a/ccl/src/main/java/codechicken/lib/vec/Vector3.java b/src/main/java/codechicken/lib/vec/Vector3.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/vec/Vector3.java rename to src/main/java/codechicken/lib/vec/Vector3.java diff --git a/ccl/src/main/java/codechicken/lib/world/ChunkExtension.java b/src/main/java/codechicken/lib/world/ChunkExtension.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/world/ChunkExtension.java rename to src/main/java/codechicken/lib/world/ChunkExtension.java diff --git a/ccl/src/main/java/codechicken/lib/world/IChunkLoadTile.java b/src/main/java/codechicken/lib/world/IChunkLoadTile.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/world/IChunkLoadTile.java rename to src/main/java/codechicken/lib/world/IChunkLoadTile.java diff --git a/ccl/src/main/java/codechicken/lib/world/TileChunkLoadHook.java b/src/main/java/codechicken/lib/world/TileChunkLoadHook.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/world/TileChunkLoadHook.java rename to src/main/java/codechicken/lib/world/TileChunkLoadHook.java diff --git a/ccl/src/main/java/codechicken/lib/world/WorldExtension.java b/src/main/java/codechicken/lib/world/WorldExtension.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/world/WorldExtension.java rename to src/main/java/codechicken/lib/world/WorldExtension.java diff --git a/ccl/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java b/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java rename to src/main/java/codechicken/lib/world/WorldExtensionInstantiator.java diff --git a/ccl/src/main/java/codechicken/lib/world/WorldExtensionManager.java b/src/main/java/codechicken/lib/world/WorldExtensionManager.java similarity index 100% rename from ccl/src/main/java/codechicken/lib/world/WorldExtensionManager.java rename to src/main/java/codechicken/lib/world/WorldExtensionManager.java From 37402535900f44d2d9c9c4c1a56ad7063400dd1e Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 1 Jul 2024 09:32:50 -0700 Subject: [PATCH 195/219] Maybe more backwards compatible (#16) * Maybe more backwards compatible --- gradle.properties | 3 + .../lib/asm/RedirectorTransformer.java | 17 +- .../java/codechicken/lib/gui/Canvas9Seg.java | 6 +- .../codechicken/lib/lighting/LightMatrix.java | 4 +- .../codechicken/lib/lighting/LightModel.java | 2 +- .../lib/lighting/PlanarLightMatrix.java | 2 +- .../lib/lighting/PlanarLightModel.java | 2 +- .../lib/lighting/SimpleBrightnessModel.java | 2 +- .../codechicken/lib/render/BlockRenderer.java | 10 +- .../java/codechicken/lib/render/CCModel.java | 4 +- .../lib/render/CCRenderPipeline.java | 2 +- .../codechicken/lib/render/CCRenderState.java | 167 ++++++++++-------- .../lib/render/ColourMultiplier.java | 4 +- .../codechicken/lib/render/RenderUtils.java | 10 +- 14 files changed, 132 insertions(+), 103 deletions(-) diff --git a/gradle.properties b/gradle.properties index c614939..d701e4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -55,6 +55,9 @@ generateGradleTokenClass = codechicken.core.asm.Tags # Name of the token containing the project's current version to generate/replace. gradleTokenVersion = VERSION +# [DEPRECATED] Mod Group replacement token. +gradleTokenGroupName = + # [DEPRECATED] # Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java # public static final String VERSION = "GRADLETOKEN_VERSION"; diff --git a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java index 0d9d107..fb925d7 100644 --- a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java +++ b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java @@ -119,11 +119,9 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) changed = true; } - } else if (node.getOpcode() == Opcodes.INVOKESTATIC && node instanceof MethodInsnNode mNode) { - if (redirectedMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) { - mNode.name = mNode.name + "Static"; - changed = true; - } else if (redirectedSimpleMethods.contains(mNode.name) && mNode.owner.equals(RenderStateClass)) { + } else if (node instanceof MethodInsnNode mNode) { + if (node.getOpcode() == Opcodes.INVOKESTATIC && redirectedSimpleMethods.contains(mNode.name) + && mNode.owner.equals(RenderStateClass)) { mn.instructions.insertBefore( mNode, new MethodInsnNode( @@ -132,8 +130,15 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) "instance", "()Lcodechicken/lib/render/CCRenderState;")); mNode.setOpcode(Opcodes.INVOKEVIRTUAL); + mNode.name = mNode.name + "Instance"; changed = true; - } + } else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && mNode.owner.equals(RenderStateClass) + && (redirectedSimpleMethods.contains(mNode.name) + || redirectedMethods.contains(mNode.name))) { + // Handle mods that updated to previously new API + mNode.name = mNode.name + "Instance"; + changed = true; + } } } } diff --git a/src/main/java/codechicken/lib/gui/Canvas9Seg.java b/src/main/java/codechicken/lib/gui/Canvas9Seg.java index 15b3f22..b468b42 100644 --- a/src/main/java/codechicken/lib/gui/Canvas9Seg.java +++ b/src/main/java/codechicken/lib/gui/Canvas9Seg.java @@ -64,15 +64,15 @@ private void drawSeg(int[] sw, int[] sh, int seg) { public void draw(CCRenderState state, int x, int y, int w, int h) { CCRenderState.changeTexture(tex); - state.reset(); - state.startDrawing(); + state.resetInstance(); + state.startDrawingInstance(); int[] sw = new int[] { x, x + seg_w[0], x + w - seg_w[2], x + w }; int[] sh = new int[] { y, y + seg_h[0], y + h - seg_h[2], y + h }; for (int seg = 0; seg < 9; seg++) drawSeg(sw, sh, seg); - state.draw(); + state.drawInstance(); } public void draw(int x, int y, int w, int h) { diff --git a/src/main/java/codechicken/lib/lighting/LightMatrix.java b/src/main/java/codechicken/lib/lighting/LightMatrix.java index d6fe986..ea7054e 100644 --- a/src/main/java/codechicken/lib/lighting/LightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/LightMatrix.java @@ -128,8 +128,8 @@ public void operate(CCRenderState state) { float[] a = ao(lc.side); float f = (a[0] * lc.fa + a[1] * lc.fb + a[2] * lc.fc + a[3] * lc.fd); int[] b = brightness(lc.side); - state.setColour(ColourRGBA.multiplyC(state.colour, f)); - state.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); + state.setColourInstance(ColourRGBA.multiplyC(state.colour, f)); + state.setBrightnessInstance((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); } @Override diff --git a/src/main/java/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java index 8766737..4aead9d 100644 --- a/src/main/java/codechicken/lib/lighting/LightModel.java +++ b/src/main/java/codechicken/lib/lighting/LightModel.java @@ -88,7 +88,7 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - state.setColour(apply(state.colour, state.normal)); + state.setColourInstance(apply(state.colour, state.normal)); } @Override diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java index 798d382..17ac278 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java @@ -47,7 +47,7 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { super.operate(state); - state.setBrightness(brightness(state.side)); + state.setBrightnessInstance(brightness(state.side)); } @Override diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java index 280d962..ba4100f 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java @@ -27,7 +27,7 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - state.setColour(ColourRGBA.multiply(state.colour, colours[state.side])); + state.setColourInstance(ColourRGBA.multiply(state.colour, colours[state.side])); } @Override diff --git a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java index c557993..21c05ff 100644 --- a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java +++ b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java @@ -46,7 +46,7 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - state.setBrightness(sample(state.side)); + state.setBrightnessInstance(sample(state.side)); } @Override diff --git a/src/main/java/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java index 09f7a8b..9393e6e 100644 --- a/src/main/java/codechicken/lib/render/BlockRenderer.java +++ b/src/main/java/codechicken/lib/render/BlockRenderer.java @@ -154,7 +154,7 @@ public void prepareVertex(CCRenderState state) { // public static void renderFullBlock(int sideMask) { public static void renderFullBlock(CCRenderState state, int sideMask) { - state.setModel(fullBlock); + state.setModelInstance(fullBlock); renderFaces(state, sideMask); } @@ -171,8 +171,8 @@ public static void renderFullBlock(int sideMask) { public static void renderFaces(CCRenderState state, int sideMask) { if (sideMask == 0x3F) return; for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) { - state.setVertexRange(s * 4, (s + 1) * 4); - state.render(); + state.setVertexRangeInstance(s * 4, (s + 1) * 4); + state.renderInstance(); } } @@ -191,10 +191,10 @@ public static void renderFaces(int sideMask) { public static void renderCuboid(CCRenderState state, Cuboid6 bounds, int sideMask) { if (sideMask == 0x3F) return; - state.setModel(face); + state.setModelInstance(face); for (int s = 0; s < 6; s++) if ((sideMask & 1 << s) == 0) { face.loadCuboidFace(bounds, s); - state.render(); + state.renderInstance(); } } diff --git a/src/main/java/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java index b9a5e4b..662bf89 100644 --- a/src/main/java/codechicken/lib/render/CCModel.java +++ b/src/main/java/codechicken/lib/render/CCModel.java @@ -467,8 +467,8 @@ public void render(CCRenderState.IVertexOperation... ops) { * @param ops Operations to apply */ public void render(CCRenderState state, int start, int end, CCRenderState.IVertexOperation... ops) { - state.setPipeline(this, start, end, ops); - state.render(); + state.setPipelineInstance(this, start, end, ops); + state.renderInstance(); } public void render(int start, int end, CCRenderState.IVertexOperation... ops) { diff --git a/src/main/java/codechicken/lib/render/CCRenderPipeline.java b/src/main/java/codechicken/lib/render/CCRenderPipeline.java index 9d9d521..7d54d2a 100644 --- a/src/main/java/codechicken/lib/render/CCRenderPipeline.java +++ b/src/main/java/codechicken/lib/render/CCRenderPipeline.java @@ -49,7 +49,7 @@ public void build() { public void render() { rebuild(); - renderState.render(); + renderState.renderInstance(); } } diff --git a/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java index 39655f0..77337dd 100644 --- a/src/main/java/codechicken/lib/render/CCRenderState.java +++ b/src/main/java/codechicken/lib/render/CCRenderState.java @@ -193,8 +193,8 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - if (normalRef != null) state.setNormal(normalRef[state.vertexIndex]); - else state.setNormal(Rotation.axes[state.side]); + if (normalRef != null) state.setNormalInstance(normalRef[state.vertexIndex]); + else state.setNormalInstance(Rotation.axes[state.side]); } }; public static VertexAttribute colourAttrib = new VertexAttribute<>() { @@ -214,8 +214,9 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - if (colourRef != null) state.setColour(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex])); - else state.setColour(state.baseColour); + if (colourRef != null) + state.setColourInstance(ColourRGBA.multiply(state.baseColour, colourRef[state.vertexIndex])); + else state.setColourInstance(state.baseColour); } }; public static VertexAttribute lightingAttrib = new VertexAttribute<>() { @@ -241,7 +242,7 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - state.setColour(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex])); + state.setColourInstance(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex])); } }; public static VertexAttribute sideAttrib = new VertexAttribute<>() { @@ -326,11 +327,15 @@ public void operate(CCRenderState state) { public boolean hasBrightness; public int brightness; - // attrute storage + // attribute storage public int side; public LC lc = new LC(); - public void reset() { + public static void reset() { + instance().resetInstance(); + } + + public void resetInstance() { model = null; pipeline.reset(); useNormals = hasNormal = hasBrightness = hasColour = false; @@ -338,27 +343,27 @@ public void reset() { baseColour = alphaOverride = -1; } - public void setPipeline(IVertexOperation... ops) { + public void setPipelineInstance(IVertexOperation... ops) { pipeline.setPipeline(ops); } @Deprecated - public static void setPipelineStatic(IVertexOperation... ops) { - instance().setPipeline(ops); + public static void setPipeline(IVertexOperation... ops) { + instance().setPipelineInstance(ops); } - public void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) { + public void setPipelineInstance(IVertexSource model, int start, int end, IVertexOperation... ops) { pipeline.reset(); - setModel(model, start, end); + setModelInstance(model, start, end); pipeline.setPipeline(ops); } @Deprecated - public static void setPipelineStatic(IVertexSource model, int start, int end, IVertexOperation... ops) { - instance().setPipeline(model, start, end, ops); + public static void setPipeline(IVertexSource model, int start, int end, IVertexOperation... ops) { + instance().setPipelineInstance(model, start, end, ops); } - public void bindModel(IVertexSource model) { + public void bindModelInstance(IVertexSource model) { if (this.model != model) { this.model = model; pipeline.rebuild(); @@ -366,74 +371,74 @@ public void bindModel(IVertexSource model) { } @Deprecated - public static void bindModelStatic(IVertexSource model) { - instance().bindModel(model); + public static void bindModel(IVertexSource model) { + instance().bindModelInstance(model); } - public void setModel(IVertexSource source) { - setModel(source, 0, source.getVertices().length); + public void setModelInstance(IVertexSource source) { + setModelInstance(source, 0, source.getVertices().length); } @Deprecated - public static void setModelStatic(IVertexSource source) { - instance().setModel(source); + public static void setModel(IVertexSource source) { + instance().setModelInstance(source); } - public void setModel(IVertexSource source, int start, int end) { - bindModel(source); - setVertexRange(start, end); + public void setModelInstance(IVertexSource source, int start, int end) { + bindModelInstance(source); + setVertexRangeInstance(start, end); } @Deprecated - public static void setModelStatic(IVertexSource source, int start, int end) { - instance().setModel(source, start, end); + public static void setModel(IVertexSource source, int start, int end) { + instance().setModelInstance(source, start, end); } - public void setVertexRange(int start, int end) { + public void setVertexRangeInstance(int start, int end) { firstVertexIndex = start; lastVertexIndex = end; } @Deprecated - public static void setVertexRangeStatic(int start, int end) { - instance().setVertexRange(start, end); + public static void setVertexRange(int start, int end) { + instance().setVertexRangeInstance(start, end); } - public void render(IVertexOperation... ops) { - setPipeline(ops); - render(); + public void renderInstance(IVertexOperation... ops) { + setPipelineInstance(ops); + renderInstance(); } @Deprecated - public static void renderStatic(IVertexOperation... ops) { - instance().render(ops); + public static void render(IVertexOperation... ops) { + instance().renderInstance(ops); } - public void render() { + public void renderInstance() { Vertex5[] verts = model.getVertices(); for (vertexIndex = firstVertexIndex; vertexIndex < lastVertexIndex; vertexIndex++) { model.prepareVertex(this); vert.set(verts[vertexIndex]); - runPipeline(); - writeVert(); + runPipelineInstance(); + writeVertInstance(); } } @Deprecated - public static void renderStatic() { - instance().render(); + public static void render() { + instance().renderInstance(); } - public void runPipeline() { + public void runPipelineInstance() { pipeline.operate(); } @Deprecated - public static void runPipelineStatic() { - instance().runPipeline(); + public static void runPipeline() { + instance().runPipelineInstance(); } - public void writeVert() { + public void writeVertInstance() { if (hasNormal) Tessellator.instance.setNormal((float) normal.x, (float) normal.y, (float) normal.z); if (hasColour) Tessellator.instance.setColorRGBA( colour >>> 24, @@ -445,71 +450,83 @@ public void writeVert() { } @Deprecated - public static void writeVertStatic() { - instance().writeVert(); + public static void writeVert() { + instance().writeVertInstance(); } - public void setNormal(double x, double y, double z) { + public void setNormalInstance(double x, double y, double z) { hasNormal = true; normal.set(x, y, z); } @Deprecated - public static void setNormalStatic(double x, double y, double z) { - instance().setNormal(x, y, z); + public static void setNormal(double x, double y, double z) { + instance().setNormalInstance(x, y, z); } - public void setNormal(Vector3 n) { + public void setNormalInstance(Vector3 n) { hasNormal = true; normal.set(n); } @Deprecated - public static void setNormalStatic(Vector3 n) { - instance().setNormal(n); + public static void setNormal(Vector3 n) { + instance().setNormalInstance(n); } - public void setColour(int c) { + public void setColourInstance(int c) { hasColour = true; colour = c; } @Deprecated - public static void setColourStatic(int c) { - instance().setColour(c); + public static void setColour(int c) { + instance().setColourInstance(c); } - public void setBrightness(int b) { + public void setBrightnessInstance(int b) { hasBrightness = true; brightness = b; } @Deprecated - public static void setBrightnessStatic(int b) { - instance().setBrightness(b); + public static void setBrightness(int b) { + instance().setBrightnessInstance(b); } - public void setBrightness(IBlockAccess world, int x, int y, int z) { - setBrightness(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z)); + public void setBrightnessInstance(IBlockAccess world, int x, int y, int z) { + setBrightnessInstance(world.getBlock(x, y, z).getMixedBrightnessForBlock(world, x, y, z)); } @Deprecated - public static void setBrightnessStatic(IBlockAccess world, int x, int y, int z) { - instance().setBrightness(world, x, y, z); + public static void setBrightness(IBlockAccess world, int x, int y, int z) { + instance().setBrightnessInstance(world, x, y, z); + } + + public static void pullLightMap() { + instance().pullLightmapInstance(); + } + + public void pullLightmapInstance() { + setBrightnessInstance((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX); } - public void pullLightmap() { - setBrightness((int) OpenGlHelper.lastBrightnessY << 16 | (int) OpenGlHelper.lastBrightnessX); + public static void pushLightmap() { + instance().pushLightmapInstance(); } - public void pushLightmap() { + public void pushLightmapInstance() { OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness & 0xFFFF, brightness >>> 16); } /** * Compact helper for setting dynamic rendering context. Uses normals and doesn't compute lighting */ - public void setDynamic() { + public static void setDynamic() { + instance().setDynamicInstance(); + } + + public void setDynamicInstance() { useNormals = true; computeLighting = false; } @@ -522,16 +539,16 @@ public static void changeTexture(ResourceLocation texture) { Minecraft.getMinecraft().renderEngine.bindTexture(texture); } - public void startDrawing() { - startDrawing(7); + public void startDrawingInstance() { + startDrawingInstance(7); } @Deprecated - public static void startDrawingStatic() { - instance().startDrawing(); + public static void startDrawing() { + instance().startDrawingInstance(); } - public void startDrawing(int mode) { + public void startDrawingInstance(int mode) { Tessellator.instance.startDrawing(mode); if (hasColour) Tessellator.instance.setColorRGBA( colour >>> 24, @@ -542,11 +559,15 @@ public void startDrawing(int mode) { } @Deprecated - public static void startDrawingStatic(int mode) { - instance().startDrawing(mode); + public static void startDrawing(int mode) { + instance().startDrawingInstance(mode); + } + + public static void draw() { + Tessellator.instance.draw(); } - public void draw() { + public void drawInstance() { Tessellator.instance.draw(); } } diff --git a/src/main/java/codechicken/lib/render/ColourMultiplier.java b/src/main/java/codechicken/lib/render/ColourMultiplier.java index 292048c..c764f89 100644 --- a/src/main/java/codechicken/lib/render/ColourMultiplier.java +++ b/src/main/java/codechicken/lib/render/ColourMultiplier.java @@ -23,7 +23,7 @@ public ColourMultiplier(int colour) { @Override public boolean load(CCRenderState state) { if (colour == -1) { - state.setColour(-1); + state.setColourInstance(-1); return false; } @@ -33,7 +33,7 @@ public boolean load(CCRenderState state) { @Override public void operate(CCRenderState state) { - state.setColour(ColourRGBA.multiply(state.colour, colour)); + state.setColourInstance(ColourRGBA.multiply(state.colour, colour)); } @Override diff --git a/src/main/java/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java index c0c4a37..5762f31 100644 --- a/src/main/java/codechicken/lib/render/RenderUtils.java +++ b/src/main/java/codechicken/lib/render/RenderUtils.java @@ -259,7 +259,7 @@ public static IIcon prepareFluidRender(CCRenderState state, FluidStack stack, in GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); Fluid fluid = stack.getFluid(); - state.setColour(fluid.getColor(stack) << 8 | alpha); + state.setColourInstance(fluid.getColor(stack) << 8 | alpha); TextureUtils.bindAtlas(fluid.getSpriteNumber()); return TextureUtils.safeIcon(fluid.getIcon(stack)); } @@ -300,9 +300,9 @@ public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cubo else bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * density; IIcon tex = prepareFluidRender(state, stack, alpha); - state.startDrawing(); + state.startDrawingInstance(); renderFluidCuboid(state, bound, tex, res); - state.draw(); + state.drawInstance(); postFluidRender(); } @@ -323,14 +323,14 @@ public static void renderFluidGauge(CCRenderState state, FluidStack stack, Recta } IIcon tex = prepareFluidRender(state, stack, alpha); - state.startDrawing(); + state.startDrawingInstance(); renderFluidQuad( new Vector3(rect.x, rect.y + rect.h, 0), new Vector3(rect.w, 0, 0), new Vector3(0, -rect.h, 0), tex, res); - state.draw(); + state.drawInstance(); postFluidRender(); } From cba2e0f642001e7ae3df04be98209e9ce063ec9b Mon Sep 17 00:00:00 2001 From: Caedis Date: Wed, 3 Jul 2024 22:52:42 -0500 Subject: [PATCH 196/219] Fix casing --- src/main/java/codechicken/lib/render/CCRenderState.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java index 77337dd..aa07caa 100644 --- a/src/main/java/codechicken/lib/render/CCRenderState.java +++ b/src/main/java/codechicken/lib/render/CCRenderState.java @@ -101,7 +101,7 @@ public static VertexAttribute getAttribute(int index) { /** * Management class for a vertex attrute such as colour, normal etc This class should handle the loading of the * attrute from an array provided by IVertexSource.getAttributes or the computation of this attrute from others - * + * * @param The array type for this attrute eg. int[], Vector3[] */ public abstract static class VertexAttribute implements IVertexOperation { @@ -146,7 +146,7 @@ public interface IVertexSource { /** * Gets an array of vertex attrutes - * + * * @param attr The vertex attrute to get * @param The attrute array type * @return An array, or null if not computed @@ -503,7 +503,7 @@ public static void setBrightness(IBlockAccess world, int x, int y, int z) { instance().setBrightnessInstance(world, x, y, z); } - public static void pullLightMap() { + public static void pullLightmap() { instance().pullLightmapInstance(); } From 549f76974755784d9ae45fdf8ae9ceb452ff31e5 Mon Sep 17 00:00:00 2001 From: Dream Master Date: Wed, 17 Jul 2024 16:47:04 +0700 Subject: [PATCH 197/219] update --- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43453 bytes gradlew | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch delta 34118 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 delta 34176 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 SGW6ptSs!X7{rG*o_g?|vpSEZK diff --git a/gradlew b/gradlew index 1aa94a4..b740cf1 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From ea4f68d16350ecab4f8033a2fd5a3f3a3dce69d9 Mon Sep 17 00:00:00 2001 From: tth05 <36999320+tth05@users.noreply.github.com> Date: Thu, 18 Jul 2024 16:37:30 +0200 Subject: [PATCH 198/219] Add map to provide fast access to all config tags in sub-tree (#18) --- .../lib/config/ConfigTagParent.java | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/src/main/java/codechicken/lib/config/ConfigTagParent.java b/src/main/java/codechicken/lib/config/ConfigTagParent.java index 79514b9..8d000b2 100644 --- a/src/main/java/codechicken/lib/config/ConfigTagParent.java +++ b/src/main/java/codechicken/lib/config/ConfigTagParent.java @@ -6,8 +6,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.TreeMap; public abstract class ConfigTagParent { @@ -21,25 +23,30 @@ public TagOrderComparator(int sortMode) { } public int compare(ConfigTag o1, ConfigTag o2) { - if (o1.position != o2.position) return compareInt(o1.position, o2.position); + if (o1.position != o2.position) return Integer.compare(o1.position, o2.position); if (o1.brace != o2.brace) return o1.brace ? 1 : -1; // braced one goes after - switch (sortMode) { - case 1: - if (o1.value == o2.value) return 0; - if (o1.value == null) return 1; - if (o2.value == null) return -1; - return o1.value.compareTo(o2.value); - default: - return o1.name.compareTo(o2.name); + + if (sortMode == 1) { + if (Objects.equals(o1.value, o2.value)) return 0; + if (o1.value == null) return 1; + if (o2.value == null) return -1; + return o1.value.compareTo(o2.value); + } else { + return o1.name.compareTo(o2.name); } } - private int compareInt(int a, int b) { - return a == b ? 0 : a < b ? -1 : 1; - } } - private TreeMap childtags = new TreeMap(); + /** + * The immediate child tags of this tag + */ + private final TreeMap childtags = new TreeMap<>(); + /** + * A map of all tags in the tree, meaning all tags in this tag and all tags in child tags (recursively). Allows for + * quick access to any tag in the tree, without the need to traverse the tree part by part. + */ + private final Map allTagsInTree = new HashMap<>(); public String comment; /** * 0 = name, 1 = value @@ -88,7 +95,7 @@ public boolean hasChildTags() { } public boolean containsTag(String tagname) { - return getTag(tagname, false) != null; + return allTagsInTree.get(tagname) != null; } public ConfigTag getNewTag(String tagname) { @@ -96,6 +103,12 @@ public ConfigTag getNewTag(String tagname) { } public ConfigTag getTag(String tagname, boolean create) { + ConfigTag tag = allTagsInTree.get(tagname); + if (tag == null && create) return getTagRecursive(tagname, create); + return tag; + } + + public ConfigTag getTagRecursive(String tagname, boolean create) { int dotpos = tagname.indexOf("."); String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos); ConfigTag basetag = childtags.get(basetagname); @@ -115,6 +128,8 @@ public ConfigTag getTag(String tagname) { } public boolean removeTag(String tagname) { + removeChildFromFlatMap(tagname); + ConfigTag tag = getTag(tagname, false); if (tag == null) return false; @@ -131,6 +146,22 @@ public boolean removeTag(String tagname) { public void addChild(ConfigTag tag) { childtags.put(tag.name, tag); + + addChildToFlatMap(tag.name, tag); + } + + private void addChildToFlatMap(String path, ConfigTag tag) { + allTagsInTree.put(path, tag); + + // Stupid cast but these two garbage classes are interlinked anyway + if ((this instanceof ConfigTag t) && t.parent != null) t.parent.addChildToFlatMap(t.name + "." + path, tag); + } + + private void removeChildFromFlatMap(String path) { + allTagsInTree.remove(path); + + // Stupid cast but these two garbage classes are interlinked anyway + if ((this instanceof ConfigTag t) && t.parent != null) t.parent.removeChildFromFlatMap(t.name + "." + path); } public ArrayList getSortedTagList() { From c9d29a5c8e104dad455437fde3e05b45ced982b1 Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:19:33 +0200 Subject: [PATCH 199/219] fix logic of the ClassConstantPoolParser (#20) --- src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java b/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java index 299e185..dffcfbe 100644 --- a/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java +++ b/src/main/java/codechicken/lib/asm/ClassConstantPoolParser.java @@ -83,7 +83,7 @@ public boolean find(byte[] basicClass) { if (strLen == bytes.length) { for (int j = index + 3; j < index + 3 + strLen; j++) { if (basicClass[j] != bytes[j - (index + 3)]) { - break label; + continue label; } } return true; From 0f37937ada5d78b4afec8af3f07602ea5f21a8bb Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sun, 1 Sep 2024 22:46:57 +0200 Subject: [PATCH 200/219] update --- gradle.properties | 13 ++++++++++++- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 5 ++++- gradlew.bat | 2 ++ settings.gradle | 2 +- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index d701e4b..5960bc0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -79,6 +79,11 @@ accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = false +# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main. +# This can speed up compile times thanks to not running the mixin annotation processor on all input sources. +# Mixin classes will have access to "main" classes, but not the other way around. +separateMixinSourceSet = + # Adds some debug arguments like verbose output and class export. usesMixinDebug = false @@ -111,9 +116,15 @@ minimizeShadowedDependencies = true # If disabled, won't rename the shadowed classes. relocateShadowedDependencies = true -# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories. +# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories. includeWellKnownRepositories = true +# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated +# list of strings, with the acceptable keys being(case does not matter): +# cursemaven +# modrinth +excludeWellKnownRepositories = + # Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. # Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables. # If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch delta 8703 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 Ojj7^59?Sdh$^Qpp*~F>< delta 8662 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..09523c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf1..f5feea6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # 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 +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 25da30d..9d21a21 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/settings.gradle b/settings.gradle index 6fe010c..242692e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.26' } From 99b815c12efc1899862ca222bfc92a7f3933d403 Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Sun, 6 Oct 2024 13:33:56 +0200 Subject: [PATCH 201/219] Reduce RAM allocations during rendering (#22) * edit doc for fluid rendering method + clamp fillRate of the tank between 0 and 1 * init all static fields in the static block * remove object instantiation that is never used in the following method and assign local variables * reduce object allocation spam in CCModelLibrary.getRenderMatrix * fix error in local V value * remove all object instantiation during rendering to minimize RAM allocation in RenderUtils --- .../lib/render/CCModelLibrary.java | 8 +- .../codechicken/lib/render/RenderUtils.java | 396 ++++++++++-------- .../java/codechicken/lib/vec/Matrix4.java | 30 +- .../java/codechicken/lib/vec/Vector3.java | 10 +- 4 files changed, 264 insertions(+), 180 deletions(-) diff --git a/src/main/java/codechicken/lib/render/CCModelLibrary.java b/src/main/java/codechicken/lib/render/CCModelLibrary.java index 7806fa7..f2da368 100644 --- a/src/main/java/codechicken/lib/render/CCModelLibrary.java +++ b/src/main/java/codechicken/lib/render/CCModelLibrary.java @@ -5,7 +5,6 @@ import codechicken.lib.vec.Matrix4; import codechicken.lib.vec.Quat; import codechicken.lib.vec.Rotation; -import codechicken.lib.vec.Scale; import codechicken.lib.vec.Vector3; public class CCModelLibrary { @@ -82,7 +81,12 @@ private static void addIcosahedronTriangle(Vector3 vec1, double u1, double v1, V i++; } + @Deprecated public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) { - return new Matrix4().translate(position).apply(new Scale(scale)).apply(rotation); + return new Matrix4().translate(position).scale(scale).apply(rotation); + } + + public static Matrix4 getRenderMatrix(double posX, double posY, double posZ, Rotation rotation, double scale) { + return new Matrix4().translate(posX, posY, posZ).scale(scale).apply(rotation); } } diff --git a/src/main/java/codechicken/lib/render/RenderUtils.java b/src/main/java/codechicken/lib/render/RenderUtils.java index 5762f31..57cfb32 100644 --- a/src/main/java/codechicken/lib/render/RenderUtils.java +++ b/src/main/java/codechicken/lib/render/RenderUtils.java @@ -13,6 +13,7 @@ import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; +import net.minecraft.util.MathHelper; import net.minecraftforge.client.IItemRenderer; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fluids.Fluid; @@ -26,87 +27,130 @@ public class RenderUtils { - static Vector3[] vectors = new Vector3[8]; - static RenderItem uniformRenderItem = new RenderItem() { - - public boolean shouldBob() { - return false; - } - }; + static RenderItem uniformRenderItem; static EntityItem entityItem; static { - for (int i = 0; i < vectors.length; i++) vectors[i] = new Vector3(); + uniformRenderItem = new RenderItem() { + public boolean shouldBob() { + return false; + } + }; uniformRenderItem.setRenderManager(RenderManager.instance); - entityItem = new EntityItem(null); entityItem.hoverStart = 0; } + @Deprecated public static void renderFluidQuad(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 point4, IIcon icon, double res) { + // spotless:off renderFluidQuad( - point2, - vectors[0].set(point4).subtract(point1), - vectors[1].set(point1).subtract(point2), - icon, - res); + point2.x, point2.y, point2.z, + point4.x - point1.x, point4.y - point1.y, point4.z - point1.z, + point1.x - point2.x, point1.y - point2.y, point1.z - point2.z, + icon, res); } /** * Draws a tessellated quadrilateral bottom to top, left to right - * + * * @param base The bottom left corner of the quad * @param wide The bottom of the quad * @param high The left side of the quad * @param res Units per icon */ + @Deprecated public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIcon icon, double res) { - Tessellator t = Tessellator.instance; + renderFluidQuad( + base.x, base.y, base.z, + wide.x, wide.y, wide.z, + wide.x, wide.y, wide.z, + icon, res); + } - double u1 = icon.getMinU(); + /** + * Draws a tessellated quadrilateral bottom to top, left to right + *

    + * base : The bottom left corner of the quad + *

    + * wide : The bottom of the quad + *

    + * high : The left side of the quad + *

    + * res : Units per icon + */ + public static void renderFluidQuad( + double baseX, double baseY, double baseZ, + double wideX, double wideY, double wideZ, + double highX, double highY, double highZ, + IIcon icon, double res) { + + Tessellator tessellator = Tessellator.instance; + + double u = icon.getMinU(); double du = icon.getMaxU() - icon.getMinU(); - double v2 = icon.getMaxV(); + double v = icon.getMinV(); double dv = icon.getMaxV() - icon.getMinV(); - double wlen = wide.mag(); - double hlen = high.mag(); + double wideLen = Math.sqrt(wideX * wideX + wideY * wideY + wideZ * wideZ); + double highLen = Math.sqrt(highX * highX + highY * highY + highZ * highZ); double x = 0; - while (x < wlen) { - double rx = wlen - x; + while (x < wideLen) { + double rx = wideLen - x; if (rx > res) rx = res; double y = 0; - while (y < hlen) { - double ry = hlen - y; + while (y < highLen) { + double ry = highLen - y; if (ry > res) ry = res; - Vector3 dx1 = vectors[2].set(wide).multiply(x / wlen); - Vector3 dx2 = vectors[3].set(wide).multiply((x + rx) / wlen); - Vector3 dy1 = vectors[4].set(high).multiply(y / hlen); - Vector3 dy2 = vectors[5].set(high).multiply((y + ry) / hlen); - - t.addVertexWithUV( - base.x + dx1.x + dy2.x, - base.y + dx1.y + dy2.y, - base.z + dx1.z + dy2.z, - u1, - v2 - ry / res * dv); - t.addVertexWithUV(base.x + dx1.x + dy1.x, base.y + dx1.y + dy1.y, base.z + dx1.z + dy1.z, u1, v2); - t.addVertexWithUV( - base.x + dx2.x + dy1.x, - base.y + dx2.y + dy1.y, - base.z + dx2.z + dy1.z, - u1 + rx / res * du, - v2); - t.addVertexWithUV( - base.x + dx2.x + dy2.x, - base.y + dx2.y + dy2.y, - base.z + dx2.z + dy2.z, - u1 + rx / res * du, - v2 - ry / res * dv); + final double mult1 = x / wideLen; + double dx1X = wideX * mult1; + double dx1Y = wideY * mult1; + double dx1Z = wideZ * mult1; + + final double mult2 = (x + rx) / wideLen; + double dx2X = wideX * mult2; + double dx2Y = wideY * mult2; + double dx2Z = wideZ * mult2; + + final double mult3 = y / highLen; + double dy1X = highX * mult3; + double dy1Y = highY * mult3; + double dy1Z = highZ * mult3; + + final double mult4 = (y + ry) / highLen; + double dy2X = highX * mult4; + double dy2Y = highY * mult4; + double dy2Z = highZ * mult4; + + tessellator.addVertexWithUV( + baseX + dx1X + dy2X, + baseY + dx1Y + dy2Y, + baseZ + dx1Z + dy2Z, + u, + v + ry / res * dv); + tessellator.addVertexWithUV( + baseX + dx1X + dy1X, + baseY + dx1Y + dy1Y, + baseZ + dx1Z + dy1Z, + u, + v); + tessellator.addVertexWithUV( + baseX + dx2X + dy1X, + baseY + dx2Y + dy1Y, + baseZ + dx2Z + dy1Z, + u + rx / res * du, + v); + tessellator.addVertexWithUV( + baseX + dx2X + dy2X, + baseY + dx2Y + dy2Y, + baseZ + dx2Z + dy2Z, + u + rx / res * du, + v + ry / res * dv); y += ry; } @@ -115,132 +159,130 @@ public static void renderFluidQuad(Vector3 base, Vector3 wide, Vector3 high, IIc } } - public static void translateToWorldCoords(Entity entity, float frame) { - double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame; - double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame; - double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame; - + public static void translateToWorldCoords(Entity entity, float partialTicks) { + double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks; + double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks; + double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks; GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ); } public static void drawCuboidOutline(Cuboid6 c) { - Tessellator var2 = Tessellator.instance; - var2.startDrawing(3); - var2.addVertex(c.min.x, c.min.y, c.min.z); - var2.addVertex(c.max.x, c.min.y, c.min.z); - var2.addVertex(c.max.x, c.min.y, c.max.z); - var2.addVertex(c.min.x, c.min.y, c.max.z); - var2.addVertex(c.min.x, c.min.y, c.min.z); - var2.draw(); - var2.startDrawing(3); - var2.addVertex(c.min.x, c.max.y, c.min.z); - var2.addVertex(c.max.x, c.max.y, c.min.z); - var2.addVertex(c.max.x, c.max.y, c.max.z); - var2.addVertex(c.min.x, c.max.y, c.max.z); - var2.addVertex(c.min.x, c.max.y, c.min.z); - var2.draw(); - var2.startDrawing(1); - var2.addVertex(c.min.x, c.min.y, c.min.z); - var2.addVertex(c.min.x, c.max.y, c.min.z); - var2.addVertex(c.max.x, c.min.y, c.min.z); - var2.addVertex(c.max.x, c.max.y, c.min.z); - var2.addVertex(c.max.x, c.min.y, c.max.z); - var2.addVertex(c.max.x, c.max.y, c.max.z); - var2.addVertex(c.min.x, c.min.y, c.max.z); - var2.addVertex(c.min.x, c.max.y, c.max.z); - var2.draw(); + Tessellator tess = Tessellator.instance; + tess.startDrawing(3); + tess.addVertex(c.min.x, c.min.y, c.min.z); + tess.addVertex(c.max.x, c.min.y, c.min.z); + tess.addVertex(c.max.x, c.min.y, c.max.z); + tess.addVertex(c.min.x, c.min.y, c.max.z); + tess.addVertex(c.min.x, c.min.y, c.min.z); + tess.draw(); + tess.startDrawing(3); + tess.addVertex(c.min.x, c.max.y, c.min.z); + tess.addVertex(c.max.x, c.max.y, c.min.z); + tess.addVertex(c.max.x, c.max.y, c.max.z); + tess.addVertex(c.min.x, c.max.y, c.max.z); + tess.addVertex(c.min.x, c.max.y, c.min.z); + tess.draw(); + tess.startDrawing(1); + tess.addVertex(c.min.x, c.min.y, c.min.z); + tess.addVertex(c.min.x, c.max.y, c.min.z); + tess.addVertex(c.max.x, c.min.y, c.min.z); + tess.addVertex(c.max.x, c.max.y, c.min.z); + tess.addVertex(c.max.x, c.min.y, c.max.z); + tess.addVertex(c.max.x, c.max.y, c.max.z); + tess.addVertex(c.min.x, c.min.y, c.max.z); + tess.addVertex(c.min.x, c.max.y, c.max.z); + tess.draw(); } public static void renderFluidCuboid(CCRenderState state, Cuboid6 bound, IIcon tex, double res) { + renderFluidCuboid(bound, tex, res); + } + + public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { + final double minX = bound.min.x; + final double minY = bound.min.y; + final double minZ = bound.min.z; + final double maxX = bound.max.x; + final double maxY = bound.max.y; + final double maxZ = bound.max.z; renderFluidQuad( // bottom - new Vector3(bound.min.x, bound.min.y, bound.min.z), - new Vector3(bound.max.x, bound.min.y, bound.min.z), - new Vector3(bound.max.x, bound.min.y, bound.max.z), - new Vector3(bound.min.x, bound.min.y, bound.max.z), - tex, - res); + minX, minY, minZ, + maxX - minX, 0, 0, + 0, 0, maxZ - minZ, + tex, res); renderFluidQuad( // top - new Vector3(bound.min.x, bound.max.y, bound.min.z), - new Vector3(bound.min.x, bound.max.y, bound.max.z), - new Vector3(bound.max.x, bound.max.y, bound.max.z), - new Vector3(bound.max.x, bound.max.y, bound.min.z), - tex, - res); + minX, maxY, minZ, + 0, 0, maxZ - minZ, + maxX - minX, 0, 0, + tex, res); renderFluidQuad( // -x - new Vector3(bound.min.x, bound.max.y, bound.min.z), - new Vector3(bound.min.x, bound.min.y, bound.min.z), - new Vector3(bound.min.x, bound.min.y, bound.max.z), - new Vector3(bound.min.x, bound.max.y, bound.max.z), - tex, - res); + minX, maxY, minZ, + 0, minY - maxY, 0, + 0, 0, maxZ - minZ, + tex, res); renderFluidQuad( // +x - new Vector3(bound.max.x, bound.max.y, bound.max.z), - new Vector3(bound.max.x, bound.min.y, bound.max.z), - new Vector3(bound.max.x, bound.min.y, bound.min.z), - new Vector3(bound.max.x, bound.max.y, bound.min.z), - tex, - res); + maxX, maxY, maxZ, + 0, minY - maxY, 0, + 0, 0, minZ - maxZ, + tex, res); renderFluidQuad( // -z - new Vector3(bound.max.x, bound.max.y, bound.min.z), - new Vector3(bound.max.x, bound.min.y, bound.min.z), - new Vector3(bound.min.x, bound.min.y, bound.min.z), - new Vector3(bound.min.x, bound.max.y, bound.min.z), - tex, - res); + maxX, maxY, minZ, + 0, minY - maxY, 0, + minX - maxX, 0, 0, + tex, res); renderFluidQuad( // +z - new Vector3(bound.min.x, bound.max.y, bound.max.z), - new Vector3(bound.min.x, bound.min.y, bound.max.z), - new Vector3(bound.max.x, bound.min.y, bound.max.z), - new Vector3(bound.max.x, bound.max.y, bound.max.z), - tex, - res); - } - - public static void renderFluidCuboid(Cuboid6 bound, IIcon tex, double res) { - renderFluidCuboid(CCRenderState.instance(), bound, tex, res); + minX, maxY, maxZ, + 0, minY - maxY, 0, + maxX - minX, 0, 0, + tex, res); } + // spotless:on public static void renderBlockOverlaySide(int x, int y, int z, int side, double tx1, double tx2, double ty1, double ty2) { - double[] points = new double[] { x - 0.009, x + 1.009, y - 0.009, y + 1.009, z - 0.009, z + 1.009 }; - Tessellator tessellator = Tessellator.instance; + final double minX = x - 0.009; + final double maxX = x + 1.009; + final double minY = y - 0.009; + final double maxY = y + 1.009; + final double minZ = z - 0.009; + final double maxZ = z + 1.009; switch (side) { case 0: - tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty1); - tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty1); - tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2); - tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2); + tessellator.addVertexWithUV(minX, minY, minZ, tx1, ty1); + tessellator.addVertexWithUV(maxX, minY, minZ, tx2, ty1); + tessellator.addVertexWithUV(maxX, minY, maxZ, tx2, ty2); + tessellator.addVertexWithUV(minX, minY, maxZ, tx1, ty2); break; case 1: - tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1); - tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1); - tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty2); - tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty2); + tessellator.addVertexWithUV(maxX, maxY, minZ, tx2, ty1); + tessellator.addVertexWithUV(minX, maxY, minZ, tx1, ty1); + tessellator.addVertexWithUV(minX, maxY, maxZ, tx1, ty2); + tessellator.addVertexWithUV(maxX, maxY, maxZ, tx2, ty2); break; case 2: - tessellator.addVertexWithUV(points[0], points[3], points[4], tx2, ty1); - tessellator.addVertexWithUV(points[1], points[3], points[4], tx1, ty1); - tessellator.addVertexWithUV(points[1], points[2], points[4], tx1, ty2); - tessellator.addVertexWithUV(points[0], points[2], points[4], tx2, ty2); + tessellator.addVertexWithUV(minX, maxY, minZ, tx2, ty1); + tessellator.addVertexWithUV(maxX, maxY, minZ, tx1, ty1); + tessellator.addVertexWithUV(maxX, minY, minZ, tx1, ty2); + tessellator.addVertexWithUV(minX, minY, minZ, tx2, ty2); break; case 3: - tessellator.addVertexWithUV(points[1], points[3], points[5], tx2, ty1); - tessellator.addVertexWithUV(points[0], points[3], points[5], tx1, ty1); - tessellator.addVertexWithUV(points[0], points[2], points[5], tx1, ty2); - tessellator.addVertexWithUV(points[1], points[2], points[5], tx2, ty2); + tessellator.addVertexWithUV(maxX, maxY, maxZ, tx2, ty1); + tessellator.addVertexWithUV(minX, maxY, maxZ, tx1, ty1); + tessellator.addVertexWithUV(minX, minY, maxZ, tx1, ty2); + tessellator.addVertexWithUV(maxX, minY, maxZ, tx2, ty2); break; case 4: - tessellator.addVertexWithUV(points[0], points[3], points[5], tx2, ty1); - tessellator.addVertexWithUV(points[0], points[3], points[4], tx1, ty1); - tessellator.addVertexWithUV(points[0], points[2], points[4], tx1, ty2); - tessellator.addVertexWithUV(points[0], points[2], points[5], tx2, ty2); + tessellator.addVertexWithUV(minX, maxY, maxZ, tx2, ty1); + tessellator.addVertexWithUV(minX, maxY, minZ, tx1, ty1); + tessellator.addVertexWithUV(minX, minY, minZ, tx1, ty2); + tessellator.addVertexWithUV(minX, minY, maxZ, tx2, ty2); break; case 5: - tessellator.addVertexWithUV(points[1], points[3], points[4], tx2, ty1); - tessellator.addVertexWithUV(points[1], points[3], points[5], tx1, ty1); - tessellator.addVertexWithUV(points[1], points[2], points[5], tx1, ty2); - tessellator.addVertexWithUV(points[1], points[2], points[4], tx2, ty2); + tessellator.addVertexWithUV(maxX, maxY, minZ, tx2, ty1); + tessellator.addVertexWithUV(maxX, maxY, maxZ, tx1, ty1); + tessellator.addVertexWithUV(maxX, minY, maxZ, tx1, ty2); + tessellator.addVertexWithUV(maxX, minY, minZ, tx2, ty2); break; } } @@ -276,66 +318,76 @@ public static void postFluidRender() { GL11.glDisable(GL11.GL_BLEND); } - public static double fluidDensityToAlpha(double density) { - return Math.pow(density, 0.4); + public static double fluidDensityToAlpha(double d) { + return Math.pow(d, 0.4); } /** * Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal - * to density/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to density. + * to fillRate/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to fillRate. * Warning, bound will be mutated if the fluid is a liquid - * - * @param stack The fluid to render. - * @param bound The box within which the fluid is contained. - * @param density The volume of fluid / the capacity of the tank. For gases this determines the alpha, for liquids - * this determines the height. - * @param res The resolution to render at. + * + * @param stack The fluid to render. + * @param bound The bounding box within which the fluid is contained. + * @param fillRate The volume of fluid / the capacity of the tank. This is a double between 0 and 1. + * @param res The resolution to render at. */ - public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double density, + public static void renderFluidCuboid(CCRenderState state, FluidStack stack, Cuboid6 bound, double fillRate, double res) { if (!shouldRenderFluid(stack)) return; + fillRate = MathHelper.clamp_double(fillRate, 0d, 1d); int alpha = 255; - if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255); - else bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * density; + if (stack.getFluid().isGaseous()) { + alpha = (int) (fluidDensityToAlpha(fillRate) * 255); + } else { + bound.max.y = bound.min.y + (bound.max.y - bound.min.y) * fillRate; + } IIcon tex = prepareFluidRender(state, stack, alpha); state.startDrawingInstance(); - renderFluidCuboid(state, bound, tex, res); + renderFluidCuboid(bound, tex, res); state.drawInstance(); postFluidRender(); } - public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double density, double res) { - renderFluidCuboid(CCRenderState.instance(), stack, bound, density, res); + /** + * Renders a fluid within a bounding box. If the fluid is a liquid it will render as a normal tank with height equal + * to fillRate/bound.height. If the fluid is a gas, it will render the full box with an alpha equal to fillRate. + * Warning, bound will be mutated if the fluid is a liquid + * + * @param stack The fluid to render. + * @param bound The bounding box within which the fluid is contained. + * @param fillRate The volume of fluid / the capacity of the tank. This is a double between 0 and 1. + * @param res The resolution to render at. + */ + public static void renderFluidCuboid(FluidStack stack, Cuboid6 bound, double fillRate, double res) { + renderFluidCuboid(CCRenderState.instance(), stack, bound, fillRate, res); } - public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double density, + public static void renderFluidGauge(CCRenderState state, FluidStack stack, Rectangle4i rect, double fillRate, double res) { if (!shouldRenderFluid(stack)) return; + fillRate = MathHelper.clamp_double(fillRate, 0d, 1d); int alpha = 255; - if (stack.getFluid().isGaseous()) alpha = (int) (fluidDensityToAlpha(density) * 255); - else { - int height = (int) (rect.h * density); + if (stack.getFluid().isGaseous()) { + alpha = (int) (fluidDensityToAlpha(fillRate) * 255); + } else { + int height = (int) (rect.h * fillRate); rect.y += rect.h - height; rect.h = height; } IIcon tex = prepareFluidRender(state, stack, alpha); state.startDrawingInstance(); - renderFluidQuad( - new Vector3(rect.x, rect.y + rect.h, 0), - new Vector3(rect.w, 0, 0), - new Vector3(0, -rect.h, 0), - tex, - res); + renderFluidQuad(rect.x, rect.y + rect.h, 0, rect.w, 0, 0, 0, -rect.h, 0, tex, res); state.drawInstance(); postFluidRender(); } - public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double density, double res) { - renderFluidGauge(CCRenderState.instance(), stack, rect, density, res); + public static void renderFluidGauge(FluidStack stack, Rectangle4i rect, double fillRate, double res) { + renderFluidGauge(CCRenderState.instance(), stack, rect, fillRate, res); } /** @@ -347,7 +399,7 @@ public static void renderItemUniform(ItemStack item) { /** * Renders items and blocks in the world at 0,0,0 with transformations that size them appropriately - * + * * @param spin The spin angle of the item around the y axis in degrees */ public static void renderItemUniform(ItemStack item, double spin) { diff --git a/src/main/java/codechicken/lib/vec/Matrix4.java b/src/main/java/codechicken/lib/vec/Matrix4.java index 0d51d52..47e5ea8 100644 --- a/src/main/java/codechicken/lib/vec/Matrix4.java +++ b/src/main/java/codechicken/lib/vec/Matrix4.java @@ -19,7 +19,10 @@ public class Matrix4 extends Transformation implements Copyable { .asDoubleBuffer(); // m - public double m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; + public double m00, m01, m02, m03; + public double m10, m11, m12, m13; + public double m20, m21, m22, m23; + public double m30, m31, m32, m33; public Matrix4() { m00 = m11 = m22 = m33 = 1; @@ -65,6 +68,15 @@ public Matrix4 translate(Vector3 vec) { return this; } + public Matrix4 translate(double x, double y, double z) { + m03 += m00 * x + m01 * y + m02 * z; + m13 += m10 * x + m11 * y + m12 * z; + m23 += m20 * x + m21 * y + m22 * z; + m33 += m30 * x + m31 * y + m32 * z; + + return this; + } + public Matrix4 scale(Vector3 vec) { m00 *= vec.x; m10 *= vec.x; @@ -82,6 +94,22 @@ public Matrix4 scale(Vector3 vec) { return this; } + public Matrix4 scale(double scale) { + m00 *= scale; + m10 *= scale; + m20 *= scale; + m30 *= scale; + m01 *= scale; + m11 *= scale; + m21 *= scale; + m31 *= scale; + m02 *= scale; + m12 *= scale; + m22 *= scale; + m32 *= scale; + return this; + } + public Matrix4 rotate(double angle, Vector3 axis) { double c = Math.cos(angle); double s = Math.sin(angle); diff --git a/src/main/java/codechicken/lib/vec/Vector3.java b/src/main/java/codechicken/lib/vec/Vector3.java index 5e907c0..dcc508c 100644 --- a/src/main/java/codechicken/lib/vec/Vector3.java +++ b/src/main/java/codechicken/lib/vec/Vector3.java @@ -29,10 +29,10 @@ public class Vector3 implements Copyable { public Vector3() {} - public Vector3(double d, double d1, double d2) { - x = d; - y = d1; - z = d2; + public Vector3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; } public Vector3(Vector3 vec) { @@ -398,7 +398,7 @@ public boolean equals(Object o) { /** * Equals method with tolerance - * + * * @return true if this is equal to v within +-1E-5 */ public boolean equalsT(Vector3 v) { From 39ed6607a6a5c0eb37f35589345c67327c9fd58b Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sun, 6 Oct 2024 13:35:38 +0200 Subject: [PATCH 202/219] update --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 242692e..3d3ba12 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.26' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27' } From 162de447d5c2ddfda782eb63da23c064883724ea Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Sun, 6 Oct 2024 13:49:00 +0200 Subject: [PATCH 203/219] Change ASM dump folder (#21) * minor changes to RedirectorTransformer and class dumping * don't print the stacktrace when failing to write class --- .../lib/asm/RedirectorTransformer.java | 120 ++++++++---------- 1 file changed, 54 insertions(+), 66 deletions(-) diff --git a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java index fb925d7..c5df6d6 100644 --- a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java +++ b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java @@ -23,11 +23,12 @@ import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.util.ASMifier; import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceClassVisitor; -public class RedirectorTransformer implements IClassTransformer { +import codechicken.core.launch.CodeChickenCorePlugin; + +public class RedirectorTransformer implements IClassTransformer, Opcodes { private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("ccl.dumpClass", "false")); private static final String RenderStateClass = "codechicken/lib/render/CCRenderState"; @@ -90,66 +91,63 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) cr.accept(cn, 0); boolean changed = false; + // spotless:off for (MethodNode mn : cn.methods) { for (AbstractInsnNode node : mn.instructions.toArray()) { if (node instanceof FieldInsnNode fNode) { - if (node.getOpcode() == Opcodes.GETSTATIC && redirectedFields.contains(fNode.name) - && fNode.owner.equals(RenderStateClass)) { - mn.instructions.insertBefore( - fNode, - new MethodInsnNode( - Opcodes.INVOKESTATIC, - fNode.owner, - "instance", - "()Lcodechicken/lib/render/CCRenderState;")); - fNode.setOpcode(Opcodes.GETFIELD); + if (node.getOpcode() == GETSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) { + mn.instructions.insertBefore(fNode, + new MethodInsnNode( + INVOKESTATIC, + fNode.owner, + "instance", + "()Lcodechicken/lib/render/CCRenderState;", + false)); + fNode.setOpcode(GETFIELD); changed = true; - } else if (node.getOpcode() == Opcodes.PUTSTATIC - && (redirectedFields.contains(fNode.name) && fNode.owner.equals(RenderStateClass))) { - InsnList beforePut = new InsnList(); - beforePut.add( - new MethodInsnNode( - Opcodes.INVOKESTATIC, - fNode.owner, - "instance", - "()Lcodechicken/lib/render/CCRenderState;")); - beforePut.add(new InsnNode(Opcodes.SWAP)); - mn.instructions.insertBefore(fNode, beforePut); - fNode.setOpcode(Opcodes.PUTFIELD); - changed = true; - - } + } else if (node.getOpcode() == PUTSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) { + InsnList list = new InsnList(); + list.add(new MethodInsnNode( + INVOKESTATIC, + fNode.owner, + "instance", + "()Lcodechicken/lib/render/CCRenderState;", + false)); + list.add(new InsnNode(SWAP)); + mn.instructions.insertBefore(fNode, list); + fNode.setOpcode(PUTFIELD); + changed = true; + } } else if (node instanceof MethodInsnNode mNode) { - if (node.getOpcode() == Opcodes.INVOKESTATIC && redirectedSimpleMethods.contains(mNode.name) - && mNode.owner.equals(RenderStateClass)) { - mn.instructions.insertBefore( - mNode, - new MethodInsnNode( - Opcodes.INVOKESTATIC, - mNode.owner, - "instance", - "()Lcodechicken/lib/render/CCRenderState;")); - mNode.setOpcode(Opcodes.INVOKEVIRTUAL); + if (node.getOpcode() == INVOKESTATIC && RenderStateClass.equals(mNode.owner) && redirectedSimpleMethods.contains(mNode.name)) { + mn.instructions.insertBefore(mNode, + new MethodInsnNode( + INVOKESTATIC, + mNode.owner, + "instance", + "()Lcodechicken/lib/render/CCRenderState;", + false)); + mNode.setOpcode(INVOKEVIRTUAL); mNode.name = mNode.name + "Instance"; changed = true; - } else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL && mNode.owner.equals(RenderStateClass) - && (redirectedSimpleMethods.contains(mNode.name) - || redirectedMethods.contains(mNode.name))) { - // Handle mods that updated to previously new API - mNode.name = mNode.name + "Instance"; - changed = true; - } + } else if (node.getOpcode() == INVOKEVIRTUAL && RenderStateClass.equals(mNode.owner) + && (redirectedSimpleMethods.contains(mNode.name) || redirectedMethods.contains(mNode.name))) { + // Handle mods that updated to previously new API + mNode.name = mNode.name + "Instance"; + changed = true; + } } } } + // spotless:on if (changed) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cn.accept(cw); final byte[] bytes = cw.toByteArray(); if (DUMP_CLASSES) { - saveTransformedClass(bytes, transformedName); - saveTransformedClass(basicClass, transformedName + "_original"); + saveTransformedClass(basicClass, transformedName + "_PRE"); + saveTransformedClass(bytes, transformedName + "_POST"); } return bytes; } @@ -158,13 +156,9 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) private File outputDir = null; - private void saveTransformedClass(final byte[] data, final String transformedName) { - if (!DUMP_CLASSES) { - return; - } - + private void saveTransformedClass(final byte[] data, final String classname) { if (outputDir == null) { - outputDir = new File(Launch.minecraftHome, "ASM_REDIRECTOR"); + outputDir = new File(Launch.minecraftHome, "ASM_CCL" + File.separatorChar + "REDIRECTOR"); try { FileUtils.deleteDirectory(outputDir); } catch (IOException ignored) {} @@ -173,40 +167,34 @@ private void saveTransformedClass(final byte[] data, final String transformedNam outputDir.mkdirs(); } } - - final String fileName = transformedName.replace('.', File.separatorChar); + final String fileName = classname.replace('.', File.separatorChar); final File classFile = new File(outputDir, fileName + ".class"); final File bytecodeFile = new File(outputDir, fileName + "_BYTE.txt"); - final File asmifiedFile = new File(outputDir, fileName + "_ASM.txt"); final File outDir = classFile.getParentFile(); if (!outDir.exists()) { + // noinspection ResultOfMethodCallIgnored outDir.mkdirs(); } if (classFile.exists()) { + // noinspection ResultOfMethodCallIgnored classFile.delete(); } try (final OutputStream output = Files.newOutputStream(classFile.toPath())) { output.write(data); + CodeChickenCorePlugin.logger.info("Saved class (byte[]) to " + classFile.toPath()); } catch (IOException e) { - e.printStackTrace(); + CodeChickenCorePlugin.logger.error("Could not save class (byte[]) " + classname); } if (bytecodeFile.exists()) { + // noinspection ResultOfMethodCallIgnored bytecodeFile.delete(); } try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) { final ClassReader classReader = new ClassReader(data); classReader.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(output)), 0); + CodeChickenCorePlugin.logger.info("Saved class (bytecode) to " + bytecodeFile.toPath()); } catch (IOException e) { - e.printStackTrace(); - } - if (asmifiedFile.exists()) { - asmifiedFile.delete(); - } - try (final OutputStream output = Files.newOutputStream(asmifiedFile.toPath())) { - final ClassReader classReader = new ClassReader(data); - classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(output)), 0); - } catch (IOException e) { - e.printStackTrace(); + CodeChickenCorePlugin.logger.error("Could not save class (bytecode) " + classname); } } } From 7bf5935f691d5f72f4fb81bd442136d6f4461ba3 Mon Sep 17 00:00:00 2001 From: Maya <10861407+serenibyss@users.noreply.github.com> Date: Mon, 11 Nov 2024 04:15:39 -0600 Subject: [PATCH 204/219] add issue templates --- .github/ISSUE_TEMPLATE/000-report-bug.yml | 62 +++++++++++++++++++ .../ISSUE_TEMPLATE/001-request-feature.yml | 28 +++++++++ 2 files changed, 90 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/000-report-bug.yml create mode 100644 .github/ISSUE_TEMPLATE/001-request-feature.yml diff --git a/.github/ISSUE_TEMPLATE/000-report-bug.yml b/.github/ISSUE_TEMPLATE/000-report-bug.yml new file mode 100644 index 0000000..f2b2710 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/000-report-bug.yml @@ -0,0 +1,62 @@ +name: Report Bug +description: "Report a bug." +body: + - type: markdown + attributes: + value: "A bug/crash report with sufficient information and logs to reproduce and track down." + - type: input + id: discord + attributes: + label: Your GTNH Discord Username + description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info. + placeholder: "Example: Fake#1234" + - type: input + id: version + attributes: + label: Mod Version + description: "What version of the Mod are you using?" + placeholder: "Example: 1.0.0" + validations: + required: true + - type: textarea + id: report + attributes: + label: Bug Report + description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log." + placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox." + validations: + required: true + - type: dropdown + id: java + attributes: + label: Java Version + description: What Java version are you using? It's worth mentioning that if you play on Java9+ you should try update to latest minor release (e.g. prefer Java 17.0.6 over 17.0.2) of that version. + options: + - Java 8 + - Java 9 + - Java 11 + - Java 17 + - Java 19 + - Java 20 + - Java 21 + - Other (Please Specify) + validations: + required: true + - type: textarea + id: modlist + attributes: + label: Mod List or GTNH Pack Version + description: "List of mods, ideally a minimal reproducible set (can be retrieved from latest.log). If using GTNH please indicate pack version and any changed mods, not the entire modlist." + placeholder: "List of mods or GTNH Pack version goes here" + validations: + required: true + - type: checkboxes + id: final + attributes: + label: Final Checklist + description: Certify that you read things + options: + - label: "I have searched the issues and haven't found a similar issue." + required: true + + diff --git a/.github/ISSUE_TEMPLATE/001-request-feature.yml b/.github/ISSUE_TEMPLATE/001-request-feature.yml new file mode 100644 index 0000000..cb325a1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/001-request-feature.yml @@ -0,0 +1,28 @@ +name: Feature Request +description: "Request a feature." +body: + - type: markdown + attributes: + value: "Please use this form to request features. We ask you check if it was already requested though" + - type: input + id: discord + attributes: + label: Your GTNH Discord Username + description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info. + placeholder: "Example: Wumpus#1234" + - type: textarea + id: request + attributes: + label: Feature Request + description: "Relevant information, as well as relevant images" + placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox." + validations: + required: true + - type: checkboxes + id: final + attributes: + label: Final Checklist + description: Certify that you read things + options: + - label: "I have searched the issues and haven't found a similar issue." + required: true From 22dfc1360e62e6d643c701ec98ef060ab05d7824 Mon Sep 17 00:00:00 2001 From: glowredman <35727266+glowredman@users.noreply.github.com> Date: Wed, 13 Nov 2024 07:47:10 +0100 Subject: [PATCH 205/219] Allow colorful Tooltips (#24) --- settings.gradle | 2 +- .../java/codechicken/lib/gui/GuiDraw.java | 38 ++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/settings.gradle b/settings.gradle index 3d3ba12..aa612ad 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29' } diff --git a/src/main/java/codechicken/lib/gui/GuiDraw.java b/src/main/java/codechicken/lib/gui/GuiDraw.java index d68e043..380e6d9 100644 --- a/src/main/java/codechicken/lib/gui/GuiDraw.java +++ b/src/main/java/codechicken/lib/gui/GuiDraw.java @@ -162,6 +162,11 @@ public static void drawMultilineTip(int x, int y, List list) { } public static void drawMultilineTip(FontRenderer font, int x, int y, List list) { + drawMultilineTip(font, x, y, list, 0xf0100010, 0xf0100010, 0x505000ff, 0x5028007F); + } + + public static void drawMultilineTip(FontRenderer font, int x, int y, List list, int bgStart, int bgEnd, + int borderStart, int borderEnd) { if (list.isEmpty()) return; GL11.glDisable(GL12.GL_RESCALE_NORMAL); @@ -189,7 +194,7 @@ else if (x > displaySize().width - w - 8) { y = (int) MathHelper.clip(y, 8, displaySize().height - 8 - h); gui.incZLevel(300); - drawTooltipBox(x - 4, y - 4, w + 7, h + 7); + drawTooltipBox(x - 4, y - 4, w + 7, h + 7, bgStart, bgEnd, borderStart, borderEnd); for (String s : list) { ITooltipLineHandler line = getTipLine(s); if (line != null) { @@ -210,18 +215,23 @@ else if (x > displaySize().width - w - 8) { } public static void drawTooltipBox(int x, int y, int w, int h) { - int bg = 0xf0100010; - drawGradientRect(x + 1, y, w - 1, 1, bg, bg); - drawGradientRect(x + 1, y + h, w - 1, 1, bg, bg); - drawGradientRect(x + 1, y + 1, w - 1, h - 1, bg, bg); // center - drawGradientRect(x, y + 1, 1, h - 1, bg, bg); - drawGradientRect(x + w, y + 1, 1, h - 1, bg, bg); - int grad1 = 0x505000ff; - int grad2 = 0x5028007F; - drawGradientRect(x + 1, y + 2, 1, h - 3, grad1, grad2); - drawGradientRect(x + w - 1, y + 2, 1, h - 3, grad1, grad2); - - drawGradientRect(x + 1, y + 1, w - 1, 1, grad1, grad1); - drawGradientRect(x + 1, y + h - 1, w - 1, 1, grad2, grad2); + drawTooltipBox(x, y, w, h, 0xf0100010, 0xf0100010, 0x505000ff, 0x5028007F); + } + + public static void drawTooltipBox(int x, int y, int w, int h, int bgStart, int bgEnd, int borderStart, + int borderEnd) { + // spotless:off + // draw background + drawGradientRect(x + 1, y, w - 1, 1, bgStart, bgStart); // top + drawGradientRect(x + 1, y + h, w - 1, 1, bgEnd, bgEnd); // bottom + drawGradientRect(x + 1, y + 1, w - 1, h - 1, bgStart, bgEnd); // center + drawGradientRect(x, y + 1, 1, h - 1, bgStart, bgEnd); // left + drawGradientRect(x + w, y + 1, 1, h - 1, bgStart, bgEnd); // right + // draw inner border + drawGradientRect(x + 1, y + 2, 1, h - 3, borderStart, borderEnd); // left + drawGradientRect(x + w - 1, y + 2, 1, h - 3, borderStart, borderEnd); // right + drawGradientRect(x + 1, y + 1, w - 1, 1, borderStart, borderStart); // top + drawGradientRect(x + 1, y + h - 1, w - 1, 1, borderEnd, borderEnd); // bottom + // spotless:on } } From 4e7eb37f3f5517baf87c849bbfc7a2fc5f781132 Mon Sep 17 00:00:00 2001 From: charagarlnad <27380203+charagarlnad@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:18:04 -0500 Subject: [PATCH 206/219] use ZipFile instead of ZipInputStream in ClassDiscoverer (#25) --- .../codechicken/core/ClassDiscoverer.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/codechicken/core/ClassDiscoverer.java b/src/main/java/codechicken/core/ClassDiscoverer.java index 1857997..5f4099c 100644 --- a/src/main/java/codechicken/core/ClassDiscoverer.java +++ b/src/main/java/codechicken/core/ClassDiscoverer.java @@ -1,13 +1,13 @@ package codechicken.core; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; +import java.util.zip.ZipFile; import net.minecraft.launchwrapper.Launch; @@ -114,21 +114,18 @@ private void findClasspathMods() { } private void readFromZipFile(File file) throws IOException { - FileInputStream fileinputstream = new FileInputStream(file); - ZipInputStream zipinputstream = new ZipInputStream(fileinputstream); - do { - ZipEntry zipentry = zipinputstream.getNextEntry(); - if (zipentry == null) { - break; - } - String fullname = zipentry.getName().replace('\\', '/'); - int pos = fullname.lastIndexOf('/'); - String name = pos == -1 ? fullname : fullname.substring(pos + 1); - if (!zipentry.isDirectory() && matcher.matches(name)) { - checkAddClass(fullname); + try (ZipFile zipFile = new ZipFile(file)) { + Enumeration zipEntries = zipFile.entries(); + while (zipEntries.hasMoreElements()) { + ZipEntry zipentry = zipEntries.nextElement(); + String fullname = zipentry.getName().replace('\\', '/'); + int pos = fullname.lastIndexOf('/'); + String name = pos == -1 ? fullname : fullname.substring(pos + 1); + if (!zipentry.isDirectory() && matcher.matches(name)) { + checkAddClass(fullname); + } } - } while (true); - fileinputstream.close(); + } } private void readFromDirectory(File directory, File basedirectory) { From 9d600169ac74c39b0350c88302959e6d22c652a8 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sun, 22 Dec 2024 01:38:26 +0100 Subject: [PATCH 207/219] update --- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 3990 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0..e2847c8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index aa612ad..0147a99 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.30' } From 1879ba2071fdf74390fd38440b612fba785a0827 Mon Sep 17 00:00:00 2001 From: mts2200 <82391229+mts2200@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:51:06 +0300 Subject: [PATCH 208/219] Improve NPE checks (#26) --- .../lib/world/WorldExtensionManager.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/codechicken/lib/world/WorldExtensionManager.java b/src/main/java/codechicken/lib/world/WorldExtensionManager.java index 4831dc5..8971ff0 100644 --- a/src/main/java/codechicken/lib/world/WorldExtensionManager.java +++ b/src/main/java/codechicken/lib/world/WorldExtensionManager.java @@ -79,17 +79,25 @@ public void onWorldUnLoad(WorldEvent.Unload event) { @SubscribeEvent public void onChunkWatch(Watch event) { - Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); - for (WorldExtension extension : worldMap.get(event.player.worldObj)) - extension.watchChunk(chunk, event.player); + WorldExtension[] extensions = worldMap.get(event.player.worldObj); + + if (extensions != null) { + Chunk chunk = event.player.worldObj + .getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); + for (WorldExtension extension : extensions) extension.watchChunk(chunk, event.player); + } } @SubscribeEvent @SideOnly(Side.CLIENT) public void onChunkUnWatch(UnWatch event) { - Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); - for (WorldExtension extension : worldMap.get(event.player.worldObj)) - extension.unwatchChunk(chunk, event.player); + WorldExtension[] extensions = worldMap.get(event.player.worldObj); + + if (extensions != null) { + Chunk chunk = event.player.worldObj + .getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); + for (WorldExtension extension : extensions) extension.unwatchChunk(chunk, event.player); + } } @SubscribeEvent @@ -110,7 +118,7 @@ public void serverTick(TickEvent.WorldTickEvent event) { } private static boolean initialised; - private static ArrayList extensionIntialisers = new ArrayList(); + private static ArrayList extensionIntialisers = new ArrayList<>(); public static void registerWorldExtension(WorldExtensionInstantiator init) { if (!initialised) init(); @@ -125,7 +133,7 @@ private static void init() { FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); } - private static HashMap worldMap = new HashMap(); + private static HashMap worldMap = new HashMap<>(); private static void onWorldLoad(World world) { WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()]; From b999279656c85ffa0b81e852cc9aedc083c44a47 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sat, 3 May 2025 16:08:02 -0700 Subject: [PATCH 209/219] More thread safe, again. (#30) --- repositories.gradle | 1 + .../lib/asm/RedirectorTransformer.java | 7 ++- .../codechicken/lib/lighting/LightModel.java | 4 +- .../lib/lighting/PlanarLightMatrix.java | 2 +- .../lib/lighting/PlanarLightModel.java | 4 +- .../lib/lighting/SimpleBrightnessModel.java | 2 +- .../codechicken/lib/render/BlockRenderer.java | 12 ++--- .../java/codechicken/lib/render/CCModel.java | 44 +++++++++---------- .../codechicken/lib/render/CCRenderState.java | 30 ++++++++++--- .../codechicken/lib/vec/Transformation.java | 8 ++-- 10 files changed, 70 insertions(+), 44 deletions(-) diff --git a/repositories.gradle b/repositories.gradle index 45729e1..51d4dea 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,4 +1,5 @@ // Add any additional repositiroes for your dependencies here repositories { + mavenLocal() } diff --git a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java index c5df6d6..fdda8b5 100644 --- a/src/main/java/codechicken/lib/asm/RedirectorTransformer.java +++ b/src/main/java/codechicken/lib/asm/RedirectorTransformer.java @@ -59,7 +59,12 @@ public class RedirectorTransformer implements IClassTransformer, Opcodes { "hasBrightness", "brightness", "side", - "lc" + "lc", + "normalAttrib", + "colourAttrib", + "lightCoordAttrib", + "sideAttrib", + "lightingAttrib" ); Collections.addAll(redirectedSimpleMethods, "reset", "pullLightmap", "pushLightmap", "setDynamic", "draw"); diff --git a/src/main/java/codechicken/lib/lighting/LightModel.java b/src/main/java/codechicken/lib/lighting/LightModel.java index 4aead9d..299c68c 100644 --- a/src/main/java/codechicken/lib/lighting/LightModel.java +++ b/src/main/java/codechicken/lib/lighting/LightModel.java @@ -81,8 +81,8 @@ public int apply(int colour, Vector3 normal) { public boolean load(CCRenderState state) { if (!state.computeLighting) return false; - state.pipeline.addDependency(CCRenderState.normalAttrib); - state.pipeline.addDependency(CCRenderState.colourAttrib); + state.pipeline.addDependency(CCRenderState.normalAttrib()); + state.pipeline.addDependency(CCRenderState.colourAttrib()); return true; } diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java index 17ac278..c75456c 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightMatrix.java @@ -40,7 +40,7 @@ public int brightness(int side) { @Override public boolean load(CCRenderState state) { - state.pipeline.addDependency(CCRenderState.sideAttrib); + state.pipeline.addDependency(CCRenderState.sideAttrib()); return true; } diff --git a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java index ba4100f..93f777f 100644 --- a/src/main/java/codechicken/lib/lighting/PlanarLightModel.java +++ b/src/main/java/codechicken/lib/lighting/PlanarLightModel.java @@ -20,8 +20,8 @@ public PlanarLightModel(int[] colours) { public boolean load(CCRenderState state) { if (!state.computeLighting) return false; - state.pipeline.addDependency(CCRenderState.sideAttrib); - state.pipeline.addDependency(CCRenderState.colourAttrib); + state.pipeline.addDependency(CCRenderState.sideAttrib()); + state.pipeline.addDependency(CCRenderState.colourAttrib()); return true; } diff --git a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java index 21c05ff..7c5d15d 100644 --- a/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java +++ b/src/main/java/codechicken/lib/lighting/SimpleBrightnessModel.java @@ -40,7 +40,7 @@ public int sample(int side) { @Override public boolean load(CCRenderState state) { - state.pipeline.addDependency(CCRenderState.sideAttrib); + state.pipeline.addDependency(CCRenderState.sideAttrib()); return true; } diff --git a/src/main/java/codechicken/lib/render/BlockRenderer.java b/src/main/java/codechicken/lib/render/BlockRenderer.java index 9393e6e..212f8f4 100644 --- a/src/main/java/codechicken/lib/render/BlockRenderer.java +++ b/src/main/java/codechicken/lib/render/BlockRenderer.java @@ -20,12 +20,12 @@ public Vertex5[] getVertices() { @Override public T getAttributes(CCRenderState.VertexAttribute attr) { - return attr == CCRenderState.lightCoordAttrib && lcComputed ? (T) lightCoords : null; + return attr == CCRenderState.lightCoordAttrib() && lcComputed ? (T) lightCoords : null; } @Override public boolean hasAttribute(CCRenderState.VertexAttribute attr) { - return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib && lcComputed; + return attr == CCRenderState.sideAttrib() || attr == CCRenderState.lightCoordAttrib() && lcComputed; } @Override @@ -136,12 +136,12 @@ public Vertex5[] getVertices() { @Override public T getAttributes(VertexAttribute attr) { - return attr == CCRenderState.lightCoordAttrib ? (T) lightCoords : null; + return attr == CCRenderState.lightCoordAttrib() ? (T) lightCoords : null; } @Override public boolean hasAttribute(VertexAttribute attr) { - return attr == CCRenderState.sideAttrib || attr == CCRenderState.lightCoordAttrib; + return attr == CCRenderState.sideAttrib() || attr == CCRenderState.lightCoordAttrib(); } @Override @@ -164,7 +164,7 @@ public static void renderFullBlock(int sideMask) { /** * Renders faces of a block-like model based on a sideMask. Eg for side 2, verts 8-11 will be rendered - * + * * @param sideMask A mask of faces not to render */ // public static void renderFaces(int sideMask) { @@ -184,7 +184,7 @@ public static void renderFaces(int sideMask) { /** * Renders faces of a cuboid with texture coordinates mapped to match a standard minecraft block - * + * * @param bounds The bounding cuboid to render * @param sideMask A mask of faces not to render */ diff --git a/src/main/java/codechicken/lib/render/CCModel.java b/src/main/java/codechicken/lib/render/CCModel.java index 662bf89..62cfd99 100644 --- a/src/main/java/codechicken/lib/render/CCModel.java +++ b/src/main/java/codechicken/lib/render/CCModel.java @@ -68,7 +68,7 @@ protected CCModel(int vertexMode) { } public Vector3[] normals() { - return getAttributes(CCRenderState.normalAttrib); + return getAttributes(CCRenderState.normalAttrib()); } @Override @@ -102,7 +102,7 @@ public T getOrAllocate(CCRenderState.VertexAttribute attrib) { /** * Each pixel corresponds to one unit of position when generating the model - * + * * @param i Vertex index to start generating at * @param x1 The minX bound of the box * @param y1 The minY bound of the box @@ -195,7 +195,7 @@ public CCModel generateBox(int i, double x1, double y1, double z1, double w, dou /** * Generates a box, uv mapped to be the same as a minecraft block with the same bounds - * + * * @param i The vertex index to start generating at * @param bounds The bounds of the block, 0 to 1 * @return The generated model. When rendering an icon will need to be supplied for the UV transformation. @@ -222,7 +222,7 @@ public CCModel generateBlock(int i, double x1, double y1, double z1, double x2, /** * Generates a box, uv mapped to be the same as a minecraft block with the same bounds - * + * * @param i The vertex index to start generating at * @param x1 minX * @param y1 minY @@ -311,7 +311,7 @@ public CCModel computeNormals() { /** * Computes the normals of all faces in the model. Uses the cross product of the vectors along 2 sides of the face - * + * * @param start The first vertex to generate normals for * @param length The number of vertices to generate normals for. Note this must be a multiple of 3 for triangles or * 4 for quads @@ -321,7 +321,7 @@ public CCModel computeNormals(int start, int length) { if (length % vp != 0 || start % vp != 0) throw new IllegalArgumentException("Cannot generate normals across polygons"); - Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib); + Vector3[] normals = getOrAllocate(CCRenderState.normalAttrib()); for (int k = 0; k < length; k += vp) { int i = k + start; Vector3 diff1 = verts[i + 1].vec.copy().subtract(verts[i].vec); @@ -336,14 +336,14 @@ public CCModel computeNormals(int start, int length) { /** * Computes lighting using the normals add a light model If the model is rotated, the lighting will no longer be * valid - * + * * @return The model */ public CCModel computeLighting(LightModel light) { Vector3[] normals = normals(); - int[] colours = getAttributes(CCRenderState.lightingAttrib); + int[] colours = getAttributes(CCRenderState.lightingAttrib()); if (colours == null) { - colours = getOrAllocate(CCRenderState.lightingAttrib); + colours = getOrAllocate(CCRenderState.lightingAttrib()); Arrays.fill(colours, -1); } for (int k = 0; k < verts.length; k++) colours[k] = light.apply(colours[k], normals[k]); @@ -351,18 +351,18 @@ public CCModel computeLighting(LightModel light) { } public CCModel setColour(int c) { - int[] colours = getOrAllocate(CCRenderState.colourAttrib); + int[] colours = getOrAllocate(CCRenderState.colourAttrib()); Arrays.fill(colours, c); return this; } /** * Computes the minecraft lighting coordinates for use with a LightMatrix - * + * * @return The model */ public CCModel computeLightCoords() { - LC[] lcs = getOrAllocate(CCRenderState.lightCoordAttrib); + LC[] lcs = getOrAllocate(CCRenderState.lightCoordAttrib()); Vector3[] normals = normals(); for (int i = 0; i < verts.length; i++) lcs[i] = new LC().compute(verts[i].vec, normals[i]); return this; @@ -370,7 +370,7 @@ public CCModel computeLightCoords() { /** * Averages all normals at the same position to produce a smooth lighting effect. - * + * * @return The model */ public CCModel smoothNormals() { @@ -461,7 +461,7 @@ public void render(CCRenderState.IVertexOperation... ops) { /** * Renders vertices start through start+length-1 of the model - * + * * @param start The first vertex index to render * @param end The vertex index to render until * @param ops Operations to apply @@ -520,7 +520,7 @@ public static void assertMatch(Matcher m, String s) { /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * + * * @param input An input stream to a obj file * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) * @param coordSystem The cooridnate system transformation to apply @@ -624,7 +624,7 @@ public static void quadulate(List polys, int[][] polyVerts) { /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * + * * @param res The resource for the obj file * @return A map of group names to models */ @@ -634,7 +634,7 @@ public static Map parseObjModels(ResourceLocation res) { /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * + * * @param res The resource for the obj file * @param coordSystem The cooridnate system transformation to apply * @return A map of group names to models @@ -652,7 +652,7 @@ public static Map parseObjModels(ResourceLocation res, Transfor /** * Parses vertices, texture coords, normals and polygons from a WaveFront Obj file - * + * * @param res The resource for the obj file * @param vertexMode The vertex mode to create the model for (GL_TRIANGLES or GL_QUADS) * @param coordSystem The cooridnate system transformation to apply @@ -678,7 +678,7 @@ public static CCModel createModel(List verts, List uvs, List 0; CCModel model = CCModel.newModel(vertexMode, polys.size()); - if (hasNormals) model.getOrAllocate(CCRenderState.normalAttrib); + if (hasNormals) model.getOrAllocate(CCRenderState.normalAttrib()); for (int i = 0; i < polys.size(); i++) { int[] ai = polys.get(i); @@ -807,7 +807,7 @@ public static void copy(CCModel src, int srcpos, CCModel dst, int destpos, int l /** * Generate models rotated to the other 5 sides of the block - * + * * @param models An array of 6 models * @param side The side of this model * @param point The rotation point @@ -822,7 +822,7 @@ public static void generateSidedModels(CCModel[] models, int side, Vector3 point /** * Generate models rotated to the other 3 horizontal of the block - * + * * @param models An array of 4 models * @param side The side of this model * @param point The rotation point @@ -841,7 +841,7 @@ public CCModel backfacedCopy() { /** * Generates copies of faces with clockwise vertices - * + * * @return The model */ public static CCModel generateBackface(CCModel src, int srcpos, CCModel dst, int destpos, int length) { diff --git a/src/main/java/codechicken/lib/render/CCRenderState.java b/src/main/java/codechicken/lib/render/CCRenderState.java index aa07caa..1eb74f1 100644 --- a/src/main/java/codechicken/lib/render/CCRenderState.java +++ b/src/main/java/codechicken/lib/render/CCRenderState.java @@ -169,7 +169,27 @@ default void prepareVertex() { } } - public static VertexAttribute normalAttrib = new VertexAttribute<>() { + public static VertexAttribute normalAttrib() { + return instances.get().normalAttrib; + } + + public static VertexAttribute colourAttrib() { + return instances.get().colourAttrib; + } + + public static VertexAttribute lightCoordAttrib() { + return instances.get().lightCoordAttrib; + } + + public static VertexAttribute sideAttrib() { + return instances.get().sideAttrib; + } + + public static VertexAttribute lightingAttrib() { + return instances.get().lightingAttrib; + } + + public VertexAttribute normalAttrib = new VertexAttribute<>() { private Vector3[] normalRef; @@ -197,7 +217,7 @@ public void operate(CCRenderState state) { else state.setNormalInstance(Rotation.axes[state.side]); } }; - public static VertexAttribute colourAttrib = new VertexAttribute<>() { + public VertexAttribute colourAttrib = new VertexAttribute<>() { private int[] colourRef; @@ -219,7 +239,7 @@ public void operate(CCRenderState state) { else state.setColourInstance(state.baseColour); } }; - public static VertexAttribute lightingAttrib = new VertexAttribute<>() { + public VertexAttribute lightingAttrib = new VertexAttribute<>() { private int[] colourRef; @@ -245,7 +265,7 @@ public void operate(CCRenderState state) { state.setColourInstance(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex])); } }; - public static VertexAttribute sideAttrib = new VertexAttribute<>() { + public VertexAttribute sideAttrib = new VertexAttribute<>() { private int[] sideRef; @@ -272,7 +292,7 @@ public void operate(CCRenderState state) { /** * Uses the position of the lightmatrix to compute LC if not provided */ - public static VertexAttribute lightCoordAttrib = new VertexAttribute<>() { + public VertexAttribute lightCoordAttrib = new VertexAttribute<>() { private LC[] lcRef; private final Vector3 vec = new Vector3(); // for computation diff --git a/src/main/java/codechicken/lib/vec/Transformation.java b/src/main/java/codechicken/lib/vec/Transformation.java index a7cca46..56b63c3 100644 --- a/src/main/java/codechicken/lib/vec/Transformation.java +++ b/src/main/java/codechicken/lib/vec/Transformation.java @@ -14,14 +14,14 @@ public abstract class Transformation extends ITransformation Date: Thu, 29 May 2025 19:26:51 +0000 Subject: [PATCH 210/219] modern java compat (#31) --- .../obfuscator/ObfuscationRun.java | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/main/java/codechicken/obfuscator/ObfuscationRun.java b/src/main/java/codechicken/obfuscator/ObfuscationRun.java index 6ae3854..a1ae74f 100644 --- a/src/main/java/codechicken/obfuscator/ObfuscationRun.java +++ b/src/main/java/codechicken/obfuscator/ObfuscationRun.java @@ -4,13 +4,15 @@ import java.io.File; import java.io.FileReader; import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.text.DecimalFormat; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.commons.RemappingClassAdapter; +import org.objectweb.asm.commons.Remapper; import org.objectweb.asm.tree.ClassNode; import com.google.common.base.Function; @@ -181,7 +183,40 @@ public long startTime() { public void remap(ClassNode cnode, ClassVisitor cv) { cstMappper.transform(cnode); - cnode.accept(new RemappingClassAdapter(cv, obfMapper)); + cnode.accept(newRemapper(cv, obfMapper)); + } + + private static ClassVisitor newRemapper(ClassVisitor visitor, Remapper remapper) { + try { + return theConstructor.newInstance(visitor, remapper); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static final Constructor theConstructor; + + static { + Class remapperClass; + try { + // noinspection unchecked + remapperClass = (Class) Class.forName("org.objectweb.asm.commons.ClassRemapper"); + } catch (ClassNotFoundException e) { + try { + // noinspection unchecked + remapperClass = (Class) Class + .forName("org.objectweb.asm.commons.RemappingClassAdapter"); + } catch (ClassNotFoundException ex) { + RuntimeException err = new RuntimeException(ex); + err.addSuppressed(e); + throw err; + } + } + try { + theConstructor = remapperClass.getConstructor(ClassVisitor.class, Remapper.class); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } } public static List getParents(ClassNode cnode) { From 850e2b9368bfd792137c0b1102a79be18c0c1745 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Thu, 29 May 2025 22:09:14 +0200 Subject: [PATCH 211/219] update --- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43705 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 5 ++--- settings.gradle | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5960bc0..2558c92 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ modId = CodeChickenCore modGroup = codechicken # Whether to use modGroup as the maven publishing group. -# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods. +# When false, com.github.GTNewHorizons is used. useModGroupForPublishing = false # Updates your build.gradle and settings.gradle automatically whenever an update is available. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..9bbc975c742b298b441bfb90dbc124400a3751b9 100644 GIT binary patch delta 34744 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 delta 34727 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�{ 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 a%EQ2*fnt2> /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -206,7 +205,7 @@ fi 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, +# * DEFAULT_JVM_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. diff --git a/settings.gradle b/settings.gradle index 0147a99..ff436f2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.30' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.38' } From acd863e748fa1575de9a081bf12373216199fa2c Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Thu, 7 Aug 2025 22:10:04 +0200 Subject: [PATCH 212/219] Speedup ClassDiscoverer by using ClassReader.SKIP_CODE (#33) --- .../java/codechicken/core/ClassDiscoverer.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/codechicken/core/ClassDiscoverer.java b/src/main/java/codechicken/core/ClassDiscoverer.java index 5f4099c..a2abe9b 100644 --- a/src/main/java/codechicken/core/ClassDiscoverer.java +++ b/src/main/java/codechicken/core/ClassDiscoverer.java @@ -11,6 +11,7 @@ import net.minecraft.launchwrapper.Launch; +import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; import com.google.common.collect.ImmutableList; @@ -22,6 +23,7 @@ import cpw.mods.fml.common.ModClassLoader; import cpw.mods.fml.relauncher.CoreModManager; +@SuppressWarnings("unused") public class ClassDiscoverer { public IStringMatcher matcher; @@ -35,17 +37,12 @@ public ClassDiscoverer(IStringMatcher matcher, Class... superclasses) { for (int i = 0; i < superclasses.length; i++) this.superclasses[i] = superclasses[i].getName().replace('.', '/'); - classes = new ArrayList>(); + classes = new ArrayList<>(); modClassLoader = (ModClassLoader) Loader.instance().getModClassLoader(); } public ClassDiscoverer(Class... superclasses) { - this(new IStringMatcher() { - - public boolean matches(String test) { - return true; - } - }, superclasses); + this(test -> true, superclasses); } public ArrayList> findClasses() { @@ -63,7 +60,7 @@ private void checkAddClass(String resource) { byte[] bytes = Launch.classLoader.getClassBytes(classname); if (bytes == null) return; - ClassNode cnode = ASMHelper.createClassNode(bytes); + ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.SKIP_CODE); for (String superclass : superclasses) if (!cnode.interfaces.contains(superclass) && !cnode.superName.equals(superclass)) return; @@ -86,7 +83,7 @@ private void findClasspathMods() { List knownLibraries = ImmutableList.builder().addAll(modClassLoader.getDefaultLibraries()) .addAll(CoreModManager.getLoadedCoremods()).build(); File[] minecraftSources = modClassLoader.getParentSources(); - HashSet searchedSources = new HashSet(); + HashSet searchedSources = new HashSet<>(); for (File minecraftSource : minecraftSources) { if (searchedSources.contains(minecraftSource.getAbsolutePath())) continue; searchedSources.add(minecraftSource.getAbsolutePath()); From 033009fed533819d3355aeee2c9c9bb9e13e15bc Mon Sep 17 00:00:00 2001 From: Dream Master Date: Fri, 8 Aug 2025 18:58:12 +0700 Subject: [PATCH 213/219] update --- gradle.properties | 2 +- settings.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2558c92..60abdc1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -145,7 +145,7 @@ modrinthProjectId = codechickencore-unofficial # type can be one of [project, version], # and the name is the Modrinth project or version slug/id of the other mod. # Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech -# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true +# Note: UniMixins is automatically set as a required dependency if usesMixins = true. modrinthRelations = # Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. diff --git a/settings.gradle b/settings.gradle index ff436f2..7622cde 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.38' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41' } From 5ad7ebe1ac4ae2b4eefca3d3ef3ac237a0a56adf Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Sat, 9 Aug 2025 23:51:19 +0200 Subject: [PATCH 214/219] further empty DepLoader (#34) Co-authored-by: Martin Robertz --- .../codechicken/core/launch/DepLoader.java | 154 +----------------- 1 file changed, 6 insertions(+), 148 deletions(-) diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java index 8f3272d..6daf3c6 100644 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ b/src/main/java/codechicken/core/launch/DepLoader.java @@ -1,159 +1,19 @@ package codechicken.core.launch; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.Box; -import javax.swing.JDialog; -import javax.swing.JOptionPane; - -import cpw.mods.fml.common.versioning.ComparableVersion; import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; /** - * For autodownloading stuff. This is really unoriginal, mostly ripped off FML, credits to cpw. + * This was used to download dependencies during runtime and inject them into the classloader. It is now hollowed out + * but kept in the mod so that if another mod copied-pasted this class into their mod, there is a chance this empty + * class will be loaded instead and it will do nothing. */ @MCVersion("1.7.10") public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { - public interface IDownloadDisplay { - - void resetProgress(int sizeGuess); - - void setPokeThread(Thread currentThread); - - void updateProgress(int fullLength); - - boolean shouldStopIt(); - - void updateProgressString(String string, Object... data); - - Object makeDialog(); - - void showErrorDialog(String name, String url); - } - - @SuppressWarnings("serial") - public static class Downloader extends JOptionPane implements IDownloadDisplay { - - boolean stopIt; - Thread pokeThread; - - private Box makeProgressPanel() { - return null; - } - - @Override - public JDialog makeDialog() { - return null; - } - - protected void requestClose(String message) {} - - @Override - public void updateProgressString(String progressUpdate, Object... data) {} - - @Override - public void resetProgress(int sizeGuess) {} - - @Override - public void updateProgress(int fullLength) {} - - @Override - public void setPokeThread(Thread currentThread) {} - - @Override - public boolean shouldStopIt() { - return true; - } - - @Override - public void showErrorDialog(String name, String url) {} - } - - public static class DummyDownloader implements IDownloadDisplay { - - @Override - public void resetProgress(int sizeGuess) {} - - @Override - public void setPokeThread(Thread currentThread) {} - - @Override - public void updateProgress(int fullLength) {} - - @Override - public boolean shouldStopIt() { - return false; - } - - @Override - public void updateProgressString(String string, Object... data) {} - - @Override - public Object makeDialog() { - return null; - } - - @Override - public void showErrorDialog(String name, String url) {} - } - - public static class VersionedFile { - - public final Pattern pattern; - public final String filename; - public final ComparableVersion version; - public final String name; - - public VersionedFile(String filename, Pattern pattern) { - this.pattern = pattern; - this.filename = filename; - Matcher m = pattern.matcher(filename); - if (m.matches()) { - name = m.group(1); - version = new ComparableVersion(m.group(2)); - } else { - name = null; - version = null; - } - } - - public boolean matches() { - return name != null; - } - } - - public static class Dependency { - - public String url; - public VersionedFile file; - - public String existing; - /** - * Flag set to add this dep to the classpath immediately because it is required for a coremod. - */ - public boolean coreLib; - - public Dependency(String url, VersionedFile file, boolean coreLib) { - this.url = url; - this.file = file; - this.coreLib = coreLib; - } - } - - public static class DepLoadInst { - - public DepLoadInst() {} - - public void load() {} - } - - public static void load() {} - @Override public String[] getASMTransformerClass() { return null; @@ -166,21 +26,19 @@ public String getModContainerClass() { @Override public String getSetupClass() { - return getClass().getName(); + return null; } @Override public void injectData(Map data) {} @Override - public Void call() { - load(); - + public String getAccessTransformerClass() { return null; } @Override - public String getAccessTransformerClass() { + public Void call() { return null; } } From 678970e48b7940a549d17419600917ee5ffd3148 Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:52:51 +0200 Subject: [PATCH 215/219] Delete DepLoader entirely (#35) --- .../codechicken/core/launch/DepLoader.java | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 src/main/java/codechicken/core/launch/DepLoader.java diff --git a/src/main/java/codechicken/core/launch/DepLoader.java b/src/main/java/codechicken/core/launch/DepLoader.java deleted file mode 100644 index 6daf3c6..0000000 --- a/src/main/java/codechicken/core/launch/DepLoader.java +++ /dev/null @@ -1,44 +0,0 @@ -package codechicken.core.launch; - -import java.util.Map; - -import cpw.mods.fml.relauncher.IFMLCallHook; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; - -/** - * This was used to download dependencies during runtime and inject them into the classloader. It is now hollowed out - * but kept in the mod so that if another mod copied-pasted this class into their mod, there is a chance this empty - * class will be loaded instead and it will do nothing. - */ -@MCVersion("1.7.10") -public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook { - - @Override - public String[] getASMTransformerClass() { - return null; - } - - @Override - public String getModContainerClass() { - return null; - } - - @Override - public String getSetupClass() { - return null; - } - - @Override - public void injectData(Map data) {} - - @Override - public String getAccessTransformerClass() { - return null; - } - - @Override - public Void call() { - return null; - } -} From 4e5bcf829c13b642b39613554d2504a516e3fbbb Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Tue, 11 Nov 2025 18:13:45 +0100 Subject: [PATCH 216/219] ASM Housekeeping (#36) --- build.gradle | 5 + .../asm/CodeChickenAccessTransformer.java | 33 ++--- .../core/asm/CodeChickenCoreModContainer.java | 10 -- .../asm/DefaultImplementationTransformer.java | 61 ++++---- .../core/asm/DelegatedTransformer.java | 92 ++++++++++-- .../core/asm/MCPDeobfuscationTransformer.java | 41 ++---- .../core/asm/TweakTransformer.java | 30 ++-- .../core/launch/CodeChickenCorePlugin.java | 136 +++++++----------- .../lib/asm/ClassHeirachyManager.java | 4 - .../lib/asm/ModularASMTransformer.java | 11 +- 10 files changed, 220 insertions(+), 203 deletions(-) diff --git a/build.gradle b/build.gradle index e57a16f..9915e20 100644 --- a/build.gradle +++ b/build.gradle @@ -3,3 +3,8 @@ plugins { id 'com.gtnewhorizons.gtnhconvention' } + +minecraft { + //extraRunJvmArguments.add("-Dccc.dev.runtimePublic=true") + //extraRunJvmArguments.add("-Dccc.dev.deobfuscate=true") +} diff --git a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java index 8b26c6c..552fef9 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenAccessTransformer.java @@ -5,32 +5,19 @@ import com.google.common.collect.ImmutableBiMap; -import codechicken.lib.asm.ObfMapping; import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; +// This AccessTransformer will make all minecraft classes public at runtime in MCP just as they are in modloader. +// You should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include +// access transformers. Such mods are doing the wrong thing and should be fixed. public class CodeChickenAccessTransformer extends AccessTransformer { - private static boolean makeAllPublic; - private static Field f_classNameBiMap; + private static final Field f_classNameBiMap; + @SuppressWarnings("FieldMayBeFinal") private static Object emptyMap = ImmutableBiMap.of(); - public CodeChickenAccessTransformer() throws IOException { - super(); - loadPublicConfig(); - } - - private void loadPublicConfig() { - if (ObfMapping.obfuscated) return; - - makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic").setComment( - "Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader." - + "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers." - + "\nSuch mods are doing the wrong thing and should be fixed.") - .getBooleanValue(false); - - if (!makeAllPublic) return; - + static { try { f_classNameBiMap = FMLDeobfuscatingRemapper.class.getDeclaredField("classNameBiMap"); f_classNameBiMap.setAccessible(true); @@ -39,16 +26,18 @@ private void loadPublicConfig() { } } + public CodeChickenAccessTransformer() throws IOException {} + @Override public byte[] transform(String name, String transformedName, byte[] bytes) { - boolean setPublic = makeAllPublic && name.startsWith("net.minecraft."); + boolean setPublic = name.startsWith("net.minecraft."); if (setPublic) setClassMap(name); bytes = super.transform(name, transformedName, bytes); if (setPublic) restoreClassMap(); return bytes; } - private void restoreClassMap() { + private static void restoreClassMap() { try { f_classNameBiMap.set(FMLDeobfuscatingRemapper.INSTANCE, emptyMap); } catch (Exception e) { @@ -56,7 +45,7 @@ private void restoreClassMap() { } } - private void setClassMap(String name) { + private static void setClassMap(String name) { try { f_classNameBiMap.set(FMLDeobfuscatingRemapper.INSTANCE, ImmutableBiMap.of(name.replace('.', '/'), "")); } catch (Exception e) { diff --git a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java index 1ba1463..450ce5b 100644 --- a/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/main/java/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -1,6 +1,5 @@ package codechicken.core.asm; -import java.io.File; import java.util.LinkedList; import java.util.List; @@ -13,7 +12,6 @@ import codechicken.core.featurehack.LiquidTextures; import codechicken.core.internal.CCCEventHandler; import codechicken.core.launch.CodeChickenCorePlugin; -import codechicken.lib.config.ConfigFile; import cpw.mods.fml.common.DummyModContainer; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.LoadController; @@ -26,14 +24,6 @@ public class CodeChickenCoreModContainer extends DummyModContainer { - public static ConfigFile config; - - public static void loadConfig() { - if (config == null) - config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg")) - .setComment("CodeChickenCore configuration file."); - } - public CodeChickenCoreModContainer() { super(getModMetadata()); } diff --git a/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java index 8d92b9f..641404a 100644 --- a/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java +++ b/src/main/java/codechicken/core/asm/DefaultImplementationTransformer.java @@ -7,35 +7,50 @@ import java.util.LinkedList; import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraft.launchwrapper.LaunchClassLoader; +import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.ClassHeirachyManager; import codechicken.lib.asm.ObfMapping; +import cpw.mods.fml.relauncher.FMLRelaunchLog; public class DefaultImplementationTransformer implements IClassTransformer { - private static LaunchClassLoader cl = (LaunchClassLoader) ClassHeirachyManager.class.getClassLoader(); + private static final HashMap impls = new HashMap<>(); - private static ClassNode getClassNode(String name) { - try { - return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.'))); - } catch (IOException e) { - throw new RuntimeException(e); + public static void registerDefaultImpl(String iname, String cname) { + if (impls.isEmpty()) { + String name = DefaultImplementationTransformer.class.getName(); + FMLRelaunchLog.finer("Registering transformer %s", name); + Launch.classLoader.registerTransformer(name); } + impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname)); + } + + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) { + if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes; + + ClassNode cnode = ASMHelper.createClassNode(bytes); + boolean changed = false; + for (String iname : cnode.interfaces) { + InterfaceImpl impl = impls.get(iname); + if (impl != null) changed |= impl.patch(cnode); + } + + return changed ? ASMHelper.createBytes(cnode, 0) : bytes; } static class InterfaceImpl { public final String iname; - public ArrayList impls = new ArrayList(); + public ArrayList impls = new ArrayList<>(); public InterfaceImpl(String iname, String cname) { this.iname = iname; - HashSet names = new HashSet(); + HashSet names = new HashSet<>(); ClassNode inode = getClassNode(iname); for (MethodNode method : inode.methods) names.add(method.name + method.desc); @@ -47,7 +62,7 @@ public InterfaceImpl(String iname, String cname) { } public boolean patch(ClassNode cnode) { - LinkedList names = new LinkedList(); + LinkedList names = new LinkedList<>(); for (MethodNode method : cnode.methods) { ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime(); names.add(m.s_name + m.s_desc); @@ -69,25 +84,13 @@ public boolean patch(ClassNode cnode) { } return changed; } - } - private static HashMap impls = new HashMap(); - - public static void registerDefaultImpl(String iname, String cname) { - impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname)); - } - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes; - - ClassNode cnode = ASMHelper.createClassNode(bytes); - boolean changed = false; - for (String iname : cnode.interfaces) { - InterfaceImpl impl = impls.get(iname); - if (impl != null) changed |= impl.patch(cnode); + private static ClassNode getClassNode(String name) { + try { + return ASMHelper.createClassNode(Launch.classLoader.getClassBytes(name.replace('/', '.'))); + } catch (IOException e) { + throw new RuntimeException(e); + } } - - return changed ? ASMHelper.createBytes(cnode, 0) : bytes; } } diff --git a/src/main/java/codechicken/core/asm/DelegatedTransformer.java b/src/main/java/codechicken/core/asm/DelegatedTransformer.java index eaf75dd..0b7f60f 100644 --- a/src/main/java/codechicken/core/asm/DelegatedTransformer.java +++ b/src/main/java/codechicken/core/asm/DelegatedTransformer.java @@ -1,7 +1,5 @@ package codechicken.core.asm; -import static codechicken.core.launch.CodeChickenCorePlugin.logger; - import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -11,7 +9,9 @@ import java.util.ArrayList; import java.util.Map; import java.util.Stack; +import java.util.jar.Attributes; import java.util.jar.JarFile; +import java.util.jar.Manifest; import java.util.zip.ZipEntry; import net.minecraft.launchwrapper.IClassTransformer; @@ -21,14 +21,18 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.Opcodes; +import codechicken.core.launch.CodeChickenCorePlugin; +import cpw.mods.fml.relauncher.FMLRelaunchLog; + public class DelegatedTransformer implements IClassTransformer { - private static ArrayList delegatedTransformers; - private static Method m_defineClass; - private static Field f_cachedClasses; + private static final ArrayList delegatedTransformers; + private static final Method m_defineClass; + private static final Field f_cachedClasses; + private static IClassTransformer[] transformers; - public DelegatedTransformer() { - delegatedTransformers = new ArrayList(); + static { + delegatedTransformers = new ArrayList<>(); try { m_defineClass = ClassLoader.class .getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE); @@ -41,14 +45,75 @@ public DelegatedTransformer() { } @Override - public byte[] transform(String name, String tname, byte[] bytes) { - if (bytes == null) return null; - for (IClassTransformer trans : delegatedTransformers) bytes = trans.transform(name, tname, bytes); - return bytes; + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if (basicClass == null) return null; + for (IClassTransformer t : transformers) { + basicClass = t.transform(name, transformedName, basicClass); + } + return basicClass; + } + + public static void load() { + scanModsForDelegatedTransformers(); + final int size = delegatedTransformers.size(); + if (size == 0) { + CodeChickenCorePlugin.logger + .debug("No delegated transformer found, skipping registration of main DelegatedTransformer."); + return; + } + CodeChickenCorePlugin.logger + .debug("Found " + size + " delegated transformers, registering main DelegatedTransformer."); + transformers = delegatedTransformers.toArray(new IClassTransformer[0]); + String name = DelegatedTransformer.class.getName(); + FMLRelaunchLog.finer("Registering transformer %s", name); + Launch.classLoader.registerTransformer(name); + } + + private static void scanModsForDelegatedTransformers() { + File modsDir = new File(CodeChickenCorePlugin.minecraftDir, "mods"); + if (modsDir.exists()) { + final File[] files = modsDir.listFiles(); + if (files != null) { + for (File file : files) { + scanMod(file); + } + } + } + File versionModsDir = new File( + CodeChickenCorePlugin.minecraftDir, + "mods/" + CodeChickenCorePlugin.currentMcVersion); + if (versionModsDir.exists()) { + final File[] files = versionModsDir.listFiles(); + if (files != null) { + for (File file : files) { + scanMod(file); + } + } + } + } + + private static void scanMod(File file) { + if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return; + + try { + try (JarFile jar = new JarFile(file)) { + Manifest manifest = jar.getManifest(); + if (manifest == null) return; + Attributes attr = manifest.getMainAttributes(); + if (attr == null) return; + + String transformer = attr.getValue("CCTransformer"); + if (transformer != null) { + addTransformer(transformer, jar, file); + } + } + } catch (Exception e) { + CodeChickenCorePlugin.logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e); + } } public static void addTransformer(String transformer, JarFile jar, File jarFile) { - logger.debug("Adding CCTransformer: " + transformer); + CodeChickenCorePlugin.logger.debug("Adding CCTransformer: " + transformer); try { byte[] bytes; bytes = Launch.classLoader.getClassBytes(transformer); @@ -107,7 +172,7 @@ private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile, byte[] depbytes = readFully(jar.getInputStream(entry)); defineDependancies(depbytes, jar, jarFile, depStack); - logger.debug("Defining dependancy: " + dependancy); + CodeChickenCorePlugin.logger.debug("Defining dependancy: " + dependancy); defineClass(dependancy.replace('/', '.'), depbytes); } @@ -128,7 +193,6 @@ public static byte[] readFully(InputStream stream) throws IOException { while ((r = stream.read()) != -1) { bos.write(r); } - return bos.toByteArray(); } } diff --git a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java index 9983017..5bb6abb 100644 --- a/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java +++ b/src/main/java/codechicken/core/asm/MCPDeobfuscationTransformer.java @@ -24,7 +24,6 @@ import com.google.common.collect.Multimap; import codechicken.lib.asm.ASMHelper; -import codechicken.lib.asm.ASMInit; import codechicken.lib.asm.CC_ClassWriter; import codechicken.lib.asm.ObfMapping; import codechicken.obfuscator.IHeirachyEvaluator; @@ -35,15 +34,11 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator { - static { - ASMInit.init(); - } - public static class LoadPlugin implements IFMLLoadingPlugin { @Override public String[] getASMTransformerClass() { - return new String[0]; + return null; } @Override @@ -118,26 +113,20 @@ private static List getTransformers() { } public static void load() { - CodeChickenCoreModContainer.loadConfig(); - - if (CodeChickenCoreModContainer.config.getTag("dev.deobfuscate") - .setComment("set to true to completely deobfuscate mcp names") - .getBooleanValue(!ObfMapping.obfuscated)) { - run = new ObfuscationRun( - false, - ObfMapping.MCPRemapper.getConfFiles(), - ObfuscationRun.fillDefaults(new HashMap())); - run.obf.setHeirachyEvaluator(instance); - run.setQuiet().parseMappings(); - Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";")); - - if (ObfMapping.obfuscated) { - ObfMapping.loadMCPRemapper(); - run.setSeargeConstants(); - getTransformers().add(instance); - } else { - getTransformers().add(0, instance); // insert transformer as first. - } + run = new ObfuscationRun( + false, + ObfMapping.MCPRemapper.getConfFiles(), + ObfuscationRun.fillDefaults(new HashMap())); + run.obf.setHeirachyEvaluator(instance); + run.setQuiet().parseMappings(); + Collections.addAll(excludedPackages, run.config.get("excludedPackages").split(";")); + + if (ObfMapping.obfuscated) { + ObfMapping.loadMCPRemapper(); + run.setSeargeConstants(); + getTransformers().add(instance); + } else { + getTransformers().add(0, instance); // insert transformer as first. } } diff --git a/src/main/java/codechicken/core/asm/TweakTransformer.java b/src/main/java/codechicken/core/asm/TweakTransformer.java index faa4c3e..02eb141 100644 --- a/src/main/java/codechicken/core/asm/TweakTransformer.java +++ b/src/main/java/codechicken/core/asm/TweakTransformer.java @@ -5,14 +5,15 @@ import java.util.Map; import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.launchwrapper.Launch; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; +import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.lib.asm.ASMBlock; -import codechicken.lib.asm.ASMInit; import codechicken.lib.asm.ASMReader; import codechicken.lib.asm.ModularASMTransformer; import codechicken.lib.asm.ModularASMTransformer.MethodReplacer; @@ -20,20 +21,29 @@ import codechicken.lib.asm.ModularASMTransformer.MethodWriter; import codechicken.lib.asm.ObfMapping; import codechicken.lib.config.ConfigTag; +import cpw.mods.fml.relauncher.FMLRelaunchLog; public class TweakTransformer implements IClassTransformer, Opcodes { - static { - ASMInit.init(); - } - - private static ModularASMTransformer transformer = new ModularASMTransformer(); - private static Map blocks = ASMReader.loadResource("/assets/codechickencore/asm/tweaks.asm"); + private static final ModularASMTransformer transformer = new ModularASMTransformer(); + private static final Map blocks = ASMReader + .loadResource("/assets/codechickencore/asm/tweaks.asm"); public static ConfigTag tweaks; public static void load() { - CodeChickenCoreModContainer.loadConfig(); - tweaks = CodeChickenCoreModContainer.config.getTag("tweaks") + loadTransformersFromConfig(); + if (transformer.isEmpty()) { + CodeChickenCorePlugin.logger + .debug("No tweaks parsed from config, skipping registration of TweakTransformer."); + return; + } + String name = TweakTransformer.class.getName(); + FMLRelaunchLog.finer("Registering transformer %s", name); + Launch.classLoader.registerTransformer(name); + } + + private static void loadTransformersFromConfig() { + tweaks = CodeChickenCorePlugin.config.getTag("tweaks") .setComment("Various tweaks that can be applied to game mechanics.").useBraces(); tweaks.removeTag("persistantLava"); @@ -103,7 +113,7 @@ public void transform(MethodNode mv) { } @Override - public byte[] transform(String name, String tname, byte[] bytes) { + public final byte[] transform(String name, String tname, byte[] bytes) { return transformer.transform(name, bytes); } } diff --git a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java index 9289479..a161722 100644 --- a/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java +++ b/src/main/java/codechicken/core/launch/CodeChickenCorePlugin.java @@ -9,9 +9,6 @@ import java.text.StringCharacterIterator; import java.util.List; import java.util.Map; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.jar.Manifest; import javax.swing.JEditorPane; import javax.swing.JOptionPane; @@ -21,48 +18,87 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import codechicken.core.asm.CodeChickenCoreModContainer; import codechicken.core.asm.DelegatedTransformer; import codechicken.core.asm.MCPDeobfuscationTransformer; import codechicken.core.asm.Tags; import codechicken.core.asm.TweakTransformer; +import codechicken.lib.config.ConfigFile; import codechicken.lib.config.ConfigTag; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.versioning.DefaultArtifactVersion; import cpw.mods.fml.common.versioning.VersionParser; import cpw.mods.fml.relauncher.CoreModManager; import cpw.mods.fml.relauncher.FMLInjectionData; -import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; -import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; -@TransformerExclusions(value = { "codechicken.core.asm", "codechicken.obfuscator" }) -@MCVersion("1.7.10") -public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook { +@IFMLLoadingPlugin.MCVersion("1.7.10") +@IFMLLoadingPlugin.TransformerExclusions({ "codechicken.core.asm", "codechicken.obfuscator", "codechicken.lib.asm", + "codechicken.lib.config" }) +public class CodeChickenCorePlugin implements IFMLLoadingPlugin { public static final String mcVersion = "[1.7.10]"; @Deprecated public static final String version = Tags.VERSION; + public static ConfigFile config; public static File minecraftDir; public static String currentMcVersion; public static Logger logger = LogManager.getLogger("CodeChickenCore"); public CodeChickenCorePlugin() { - if (minecraftDir != null) return; // get called twice, once for IFMLCallHook - + if (minecraftDir != null) return; minecraftDir = (File) FMLInjectionData.data()[6]; currentMcVersion = (String) FMLInjectionData.data()[4]; + config = new ConfigFile(new File(minecraftDir, "config/CodeChickenCore.cfg")) + .setComment("CodeChickenCore configuration file."); + if (Boolean.getBoolean("ccc.dev.deobfuscate")) { + injectDeobfPlugin(); + } + } + + @Override + public String[] getASMTransformerClass() { + versionCheck(mcVersion, "CodeChickenCore"); + return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.lib.asm.RedirectorTransformer" }; + } + + @Override + public String getAccessTransformerClass() { + if (Boolean.getBoolean("ccc.dev.runtimePublic")) { + return "codechicken.core.asm.CodeChickenAccessTransformer"; + } else { + return null; + } + } - injectDeobfPlugin(); + @Override + public String getModContainerClass() { + return "codechicken.core.asm.CodeChickenCoreModContainer"; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) { + ConfigTag checkRAM = CodeChickenCorePlugin.config.getTag("checks") + .setComment("Configuration options for checking various requirements for a modpack.").useBraces(); + if (checkRAM.getTag("checkRAM") + .setComment("If set to true, check RAM available for Minecraft before continuing to load") + .getBooleanValue(false)) { + systemCheck(checkRAM); + } + TweakTransformer.load(); + DelegatedTransformer.load(); } private void injectDeobfPlugin() { try { Class wrapperClass = Class.forName("cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper"); - Constructor wrapperConstructor = wrapperClass + Constructor wrapperConstructor = wrapperClass .getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class); Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins"); wrapperConstructor.setAccessible(true); @@ -76,7 +112,7 @@ private void injectDeobfPlugin() { 0, new String[0])); } catch (Exception e) { - logger.error("Failed to inject MCPDeobfuscation Transformer", e); + logger.error("Failed to inject FMLPluginWrapper for MCPDeobfuscation Transformer", e); } } @@ -186,74 +222,4 @@ public void hyperlinkUpdate(HyperlinkEvent event) { FMLCommonHandler.instance().exitJava(-98, true); } } - - @Override - public String[] getASMTransformerClass() { - versionCheck(mcVersion, "CodeChickenCore"); - return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.core.asm.TweakTransformer", - "codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer", - "codechicken.lib.asm.RedirectorTransformer" }; - } - - @Override - public String getAccessTransformerClass() { - return "codechicken.core.asm.CodeChickenAccessTransformer"; - } - - @Override - public String getModContainerClass() { - return "codechicken.core.asm.CodeChickenCoreModContainer"; - } - - @Override - public String getSetupClass() { - return getClass().getName(); - } - - @Override - public void injectData(Map data) {} - - @Override - public Void call() { - CodeChickenCoreModContainer.loadConfig(); - ConfigTag checkRAM; - checkRAM = CodeChickenCoreModContainer.config.getTag("checks") - .setComment("Configuration options for checking various requirements for a modpack.").useBraces(); - if (checkRAM.getTag("checkRAM") - .setComment("If set to true, check RAM available for Minecraft before continuing to load") - .getBooleanValue(false)) - systemCheck(checkRAM); - TweakTransformer.load(); - scanCodeChickenMods(); - - return null; - } - - private void scanCodeChickenMods() { - File modsDir = new File(minecraftDir, "mods"); - for (File file : modsDir.listFiles()) scanMod(file); - File versionModsDir = new File(minecraftDir, "mods/" + currentMcVersion); - if (versionModsDir.exists()) for (File file : versionModsDir.listFiles()) scanMod(file); - } - - private void scanMod(File file) { - if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return; - - try { - JarFile jar = new JarFile(file); - try { - Manifest manifest = jar.getManifest(); - if (manifest == null) return; - Attributes attr = manifest.getMainAttributes(); - if (attr == null) return; - - String transformer = attr.getValue("CCTransformer"); - if (transformer != null) DelegatedTransformer.addTransformer(transformer, jar, file); - } finally { - jar.close(); - } - } catch (Exception e) { - logger.error("CodeChickenCore: Failed to read jar file: " + file.getName(), e); - } - } } diff --git a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java index 0566378..88e8291 100644 --- a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java +++ b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java @@ -18,10 +18,6 @@ */ public class ClassHeirachyManager implements IClassTransformer { - static { - ASMInit.init(); - } - public static class SuperCache { String superclass; diff --git a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java index baa4eb6..83bd830 100644 --- a/src/main/java/codechicken/lib/asm/ModularASMTransformer.java +++ b/src/main/java/codechicken/lib/asm/ModularASMTransformer.java @@ -275,17 +275,22 @@ public void transform(ClassNode cnode) { } } - public HashMap transformers = new HashMap(); + public HashMap transformers = new HashMap<>(); public void add(ClassNodeTransformer t) { ClassNodeTransformerList list = transformers.get(t.className()); - if (list == null) transformers.put(t.className(), list = new ClassNodeTransformerList()); + if (list == null) { + transformers.put(t.className(), list = new ClassNodeTransformerList()); + } list.add(t); } + public boolean isEmpty() { + return transformers.isEmpty(); + } + public byte[] transform(String name, byte[] bytes) { if (bytes == null) return null; - ClassNodeTransformerList list = transformers.get(name); return list == null ? bytes : list.transform(bytes); } From bb98bdc6d4ed43a45e281f5a86d9f524b340bfbc Mon Sep 17 00:00:00 2001 From: TacoMagick <154838582+TacoMagick@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:21:20 +0000 Subject: [PATCH 217/219] Revert "Fix ItemStack packet id limited by short" (#23) (#37) Co-authored-by: RecursivePineapple --- src/main/java/codechicken/lib/packet/PacketCustom.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java index 67753d4..37cd108 100644 --- a/src/main/java/codechicken/lib/packet/PacketCustom.java +++ b/src/main/java/codechicken/lib/packet/PacketCustom.java @@ -351,9 +351,9 @@ public PacketCustom writeItemStack(ItemStack stack) { public PacketCustom writeItemStack(ItemStack stack, boolean large) { if (stack == null) { - writeInt(-1); + writeShort(-1); } else { - writeInt(Item.getIdFromItem(stack.getItem())); + writeShort(Item.getIdFromItem(stack.getItem())); if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); writeShort(stack.getItemDamage()); @@ -448,7 +448,7 @@ public ItemStack readItemStack() { public ItemStack readItemStack(boolean large) { ItemStack item = null; - int itemID = readInt(); + short itemID = readShort(); if (itemID >= 0) { int stackSize = large ? readInt() : readByte(); From bb008a12650568e1fbe72c3337181b0d979a5a74 Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:21:23 +0100 Subject: [PATCH 218/219] [Memory-opti:static allocations] Reduce allocations and speedup ClassHeirarchyManager (#39) --- gradle.properties | 10 +- settings.gradle | 2 +- .../lib/asm/ClassHeirachyManager.java | 213 ++++++++++-------- 3 files changed, 128 insertions(+), 97 deletions(-) diff --git a/gradle.properties b/gradle.properties index 60abdc1..c0aecb5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -90,7 +90,9 @@ usesMixinDebug = false # Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. mixinPlugin = -# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! +# Specify the package that contains all of your Mixins. The package must exist or +# the build will fail. If you have a package property defined in your mixins..json, +# it must match with this or the build will fail. mixinsPackage = # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! @@ -166,6 +168,12 @@ curseForgeRelations = # projects. New projects should not use this parameter. # customArchiveBaseName = +# Optional parameter to customize the default working directory used by the runClient* tasks. Relative to the project directory. +# runClientWorkingDirectory = run/client + +# Optional parameter to customize the default working directory used by the runServer* tasks. Relative to the project directory. +# runServerWorkingDirectory = run/server + # Optional parameter to have the build automatically fail if an illegal version is used. # This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'. # The check is ONLY performed if the version is a git tag. diff --git a/settings.gradle b/settings.gradle index 7622cde..e883289 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.48' } diff --git a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java index 88e8291..f14932d 100644 --- a/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java +++ b/src/main/java/codechicken/lib/asm/ClassHeirachyManager.java @@ -1,13 +1,12 @@ package codechicken.lib.asm; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import net.minecraft.launchwrapper.IClassTransformer; import net.minecraft.launchwrapper.Launch; -import net.minecraft.launchwrapper.LaunchClassLoader; +import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; @@ -18,43 +17,60 @@ */ public class ClassHeirachyManager implements IClassTransformer { - public static class SuperCache { + private static final Map superclasses = new ConcurrentHashMap<>(1000); - String superclass; - public HashSet parents = new HashSet(); - private boolean flattened; + static { + superclasses.put("java.lang.Object", ClassInfo.OBJECT); + } - public void add(String parent) { - parents.add(parent); + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) { + if (bytes == null) return null; + if (!superclasses.containsKey(transformedName)) { + declareASM(transformedName, bytes); } + return bytes; + } - public void flatten() { - if (flattened) return; + private static ClassInfo declareASM(String name, byte[] bytes) { + final ClassNode node = ASMHelper.createClassNode(bytes, ClassReader.SKIP_CODE); + final ClassInfo classInfo = new ClassInfo(node); + superclasses.put(name, classInfo); + return classInfo; + } - for (String s : new ArrayList(parents)) { - SuperCache c = declareClass(s); - if (c != null) { - c.flatten(); - parents.addAll(c.parents); - } - } - flattened = true; - } + private static ClassInfo declareReflection(String name) throws ClassNotFoundException { + final Class aclass = Class.forName(name); + final ClassInfo classInfo = new ClassInfo(aclass); + superclasses.put(name, classInfo); + return classInfo; } - public static HashMap superclasses = new HashMap(); - private static LaunchClassLoader cl = Launch.classLoader; + private static ClassInfo declareClass(String name) { + try { + byte[] bytes = Launch.classLoader.getClassBytes(unKey(name)); + if (bytes != null) { + return declareASM(name, bytes); + } + } catch (Exception ignored) {} + try { + return declareReflection(name); + } catch (ClassNotFoundException ignored) {} + return null; + } - public static String toKey(String name) { - if (ObfMapping.obfuscated) - name = FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.'); - return name; + private static String toKey(String name) { + if (ObfMapping.obfuscated) { + return FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.'); + } + return name.replace('/', '.'); } - public static String unKey(String name) { - if (ObfMapping.obfuscated) - name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); - return name; + private static String unKey(String name) { + if (ObfMapping.obfuscated) { + return FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); + } + return name.replace('/', '.'); } /** @@ -68,83 +84,90 @@ public static boolean classExtends(String name, String superclass) { if (name.equals(superclass)) return true; - SuperCache cache = declareClass(name); - if (cache == null) // just can't handle this - return false; + ClassInfo classInfo = superclasses.get(name); + if (classInfo == null) classInfo = declareClass(name); + if (classInfo == null) return false; - cache.flatten(); - return cache.parents.contains(superclass); + return classInfo.hasSuper(superclass); } - private static SuperCache declareClass(String name) { + public static String getSuperClass(String name, boolean runtime) { name = toKey(name); - SuperCache cache = superclasses.get(name); - - if (cache != null) return cache; - - try { - byte[] bytes = cl.getClassBytes(unKey(name)); - if (bytes != null) cache = declareASM(bytes); - } catch (Exception e) {} - - if (cache != null) return cache; - - try { - cache = declareReflection(name); - } catch (ClassNotFoundException e) {} - - return cache; - } - - private static SuperCache declareReflection(String name) throws ClassNotFoundException { - Class aclass = Class.forName(name); - SuperCache cache = getOrCreateCache(name); - if (aclass.isInterface()) cache.superclass = "java.lang.Object"; - else if (name.equals("java.lang.Object")) return cache; - else cache.superclass = toKey(aclass.getSuperclass().getName()); + ClassInfo classInfo = superclasses.get(name); + if (classInfo == null) classInfo = declareClass(name); + if (classInfo == null || classInfo.superclass == null) return "java.lang.Object"; - cache.add(cache.superclass); - for (Class iclass : aclass.getInterfaces()) cache.add(toKey(iclass.getName())); - - return cache; + final String s = classInfo.superclass; + if (!runtime) { + return FMLDeobfuscatingRemapper.INSTANCE.unmap(s); + } + return s; } - private static SuperCache declareASM(byte[] bytes) { - ClassNode node = ASMHelper.createClassNode(bytes); - String name = toKey(node.name); + private static class ClassInfo { - SuperCache cache = getOrCreateCache(name); - cache.superclass = toKey(node.superName.replace('/', '.')); - cache.add(cache.superclass); - for (String iclass : node.interfaces) cache.add(toKey(iclass.replace('/', '.'))); + public static final ClassInfo OBJECT = new ClassInfo(); - return cache; - } - - @Override - public byte[] transform(String name, String tname, byte[] bytes) { - if (bytes == null) return null; + public final String superclass; + public final String[] interfaces; + public ClassInfo parent; - if (!superclasses.containsKey(tname)) declareASM(bytes); - - return bytes; - } + private ClassInfo() { + this.superclass = null; + this.interfaces = null; + } - public static SuperCache getOrCreateCache(String name) { - SuperCache cache = superclasses.get(name); - if (cache == null) superclasses.put(name, cache = new SuperCache()); - return cache; - } + public ClassInfo(ClassNode node) { + if ("java/lang/Object".equals(node.superName)) { + superclass = "java.lang.Object"; + parent = OBJECT; + } else { + superclass = toKey(node.superName); + } + if (node.interfaces.isEmpty()) { + interfaces = null; + } else { + interfaces = new String[node.interfaces.size()]; + for (int i = 0; i < node.interfaces.size(); i++) { + interfaces[i] = toKey(node.interfaces.get(i)); + } + } + } - public static String getSuperClass(String name, boolean runtime) { - name = toKey(name); - SuperCache cache = declareClass(name); - if (cache == null) return "java.lang.Object"; + public ClassInfo(Class aclass) { + if (aclass.isInterface()) { + this.superclass = "java.lang.Object"; + this.parent = OBJECT; + } else { + final Class superclass = aclass.getSuperclass(); + if (superclass == null || "java.lang.Object".equals(superclass.getName())) { + this.superclass = "java.lang.Object"; + this.parent = OBJECT; + } else { + this.superclass = toKey(superclass.getName()); + } + } + final Class[] interfaces = aclass.getInterfaces(); + if (interfaces.length == 0) { + this.interfaces = null; + } else { + this.interfaces = new String[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + this.interfaces[i] = toKey(interfaces[i].getName()); + } + } + } - cache.flatten(); - String s = cache.superclass; - if (!runtime) s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s); - return s; + public boolean hasSuper(String superclass) { + if (this.superclass == null) return false; + if (this.superclass.equals(superclass)) return true; + ClassInfo parentInfo = this.parent; + if (parentInfo == null) parentInfo = superclasses.get(this.superclass); + if (parentInfo == null) parentInfo = declareClass(this.superclass); + if (parentInfo == null) return false; + this.parent = parentInfo; + return parentInfo.hasSuper(superclass); + } } } From 63f36ca3838a148fc69f6ee88fe9bf6d579bb409 Mon Sep 17 00:00:00 2001 From: boubou19 Date: Sun, 7 Dec 2025 17:17:57 +0100 Subject: [PATCH 219/219] Reapply "Fix ItemStack packet id limited by short" (#23) (#37) (#41) --- src/main/java/codechicken/lib/packet/PacketCustom.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/codechicken/lib/packet/PacketCustom.java b/src/main/java/codechicken/lib/packet/PacketCustom.java index 37cd108..67753d4 100644 --- a/src/main/java/codechicken/lib/packet/PacketCustom.java +++ b/src/main/java/codechicken/lib/packet/PacketCustom.java @@ -351,9 +351,9 @@ public PacketCustom writeItemStack(ItemStack stack) { public PacketCustom writeItemStack(ItemStack stack, boolean large) { if (stack == null) { - writeShort(-1); + writeInt(-1); } else { - writeShort(Item.getIdFromItem(stack.getItem())); + writeInt(Item.getIdFromItem(stack.getItem())); if (large) writeInt(stack.stackSize); else writeByte(stack.stackSize); writeShort(stack.getItemDamage()); @@ -448,7 +448,7 @@ public ItemStack readItemStack() { public ItemStack readItemStack(boolean large) { ItemStack item = null; - short itemID = readShort(); + int itemID = readInt(); if (itemID >= 0) { int stackSize = large ? readInt() : readByte();