From 397135f68774e0661d23cb608c893274635d6d6d Mon Sep 17 00:00:00 2001 From: Chicken-Bones Date: Mon, 15 Jul 2013 21:56:12 -0700 Subject: [PATCH 001/153] 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/153] 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/153] 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 class ClassHeirachyManager implements IClassTransformer { if (bytes == null) return null; if(!knownClasses.contains(name)) - { + { ClassNode node = ASMHelper.createClassNode(bytes); knownClasses.add(name); @@ -111,7 +116,7 @@ public class ClassHeirachyManager implements IClassTransformer 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/153] 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 @@ public class ObfMapping 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 class ObfMapping 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/153] 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 @@ public class ObfMapping 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/153] 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 class CCRenderState { 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 @@ public class RenderUtils 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 class WorldExtensionManager @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 @@ public class WorldExtensionManager 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/153] 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 class ConfigTag extends ConfigTagParent { 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 class ConfigTag extends ConfigTagParent 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 abstract class ConfigTagParent 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 abstract class ConfigTagParent 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 class WorldExtensionManager @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/153] 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 class NBTDataWrapper implements MCDataInput, MCDataOutput } @Override - public int readUnsignedShort() + public int readUShort() { return ((NBTTagShort)readTag()).data & 0xFFFF; } @@ -174,7 +174,7 @@ public class NBTDataWrapper implements MCDataInput, MCDataOutput } @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 final class PacketCustom implements MCDataInput, MCDataOutput } } - public int readUnsignedByte() + public int readUByte() { return readByte() & 0xFF; } - public int readUnsignedShort() + public int readUShort() { return readShort() & 0xFFFF; } @@ -859,9 +859,8 @@ public final class PacketCustom implements MCDataInput, MCDataOutput 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/153] 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 @@ import org.objectweb.asm.ClassWriter; 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 @@ public class CC_ClassWriter extends ClassWriter 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.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; @@ -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); - return classExtends(clazz, superclass); + if(!knownClasses.contains(name)) + new ClassHeirachyManager().transform(name, name, bytes); + + return classExtends(name, superclass); } public static boolean classExtends(String clazz, String superclass) @@ -58,33 +68,35 @@ public class ClassHeirachyManager implements IClassTransformer 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 @@ public class ClassHeirachyManager implements IClassTransformer 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/153] 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 @@ import net.minecraft.launchwrapper.LaunchClassLoader; */ 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 class ClassHeirachyManager implements IClassTransformer * @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/153] 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 class RenderUtils 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 class Cuboid6 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 class Cuboid6 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/153] 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 class CCModel 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 class CCModel 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/153] 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 abstract class Colour { 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/153] 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 abstract class 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/153] 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 static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.BLOCK_3 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 class RenderUtils 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 class RenderUtils 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 class RenderUtils 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 class RenderUtils 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 class RenderUtils * @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 class RenderUtils 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/153] 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 class RenderUtils { 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 class RenderUtils 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 class RenderUtils 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/153] 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 class RayTracer 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 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); + return block.collisionRayTrace(world, x, y, z, headVec, endVec); } private static double getBlockReachDistance_server(EntityPlayerMP player) From 7f42cd94e012256b908439fb24acc456d08a9080 Mon Sep 17 00:00:00 2001 From: Chicken Bones Date: Mon, 5 Aug 2013 08:23:26 +1000 Subject: [PATCH 018/153] 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 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.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.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.server.MinecraftServer; import net.minecraft.server.management.PlayerInstance; @@ -148,6 +151,7 @@ public final class PacketCustom implements MCDataInput, MCDataOutput public ClientPacketHandler(String channel) { super(channel); + NetClientHandlerHelper.register(); } @Override @@ -159,7 +163,7 @@ public final class PacketCustom implements MCDataInput, MCDataOutput @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 @@ public final class PacketCustom implements MCDataInput, MCDataOutput } } + 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/153] 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 @@ 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; -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 class MetaPacket extends Packet @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 class MetaPacket extends Packet { 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 @@ public final class PacketCustom implements MCDataInput, MCDataOutput { 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/153] 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 class CCModel 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 class CCModel 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 class UVScale implements IUVTransformation 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.BigDecimal; 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 class Vertex5 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/153] 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 class CCModel */ 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/153] 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 class CCModel 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 class CCModel * @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 class MultiIconTransformation implements IUVTransformation 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/153] 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 @@ import codechicken.lib.vec.Vector3; */ 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/153] 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 class TransformationList extends Transformation 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/153] 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/153] 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 class RayTracer MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid); if(mop != null && s_dist < c_dist) { - mop = new ExtendedMOP(mop, cuboid.data); + mop = new ExtendedMOP(mop, cuboid.data, s_dist); c_dist = s_dist; c_hit = mop; c_cuboid = cuboid; @@ -158,13 +169,30 @@ public class RayTracer return mop; } + public void 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 class RayTracer 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 class Rotation extends Transformation { 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 class Scale extends Transformation 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 abstract class Transformation 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 class TransformationList extends Transformation @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 class Translation extends Transformation 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/153] 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 class BlockCoord implements Comparable { 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 class RedundantTransformation extends Transformation 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/153] 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.entity.Entity; 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 class ExtendedMOP extends MovingObjectPosition 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 class ExtendedMOP extends MovingObjectPosition sideHit = mop.sideHit; subHit = mop.subHit; setData(data); + this.dist = dist; } public void setData(Object data) @@ -47,4 +49,10 @@ public class ExtendedMOP extends MovingObjectPosition 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/153] 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 class LangUtil 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 class LangUtil } try { - addLangFile(langRes.func_110527_b(), langID); + addLangFile(langRes.getInputStream(), langID); } catch(IOException e) { @@ -103,7 +103,8 @@ public class LangUtil 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 final class PacketCustom implements MCDataInput, MCDataOutput 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 class CCModel 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 class CCModel 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 class CCRenderState 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 class SpriteSheetManager { 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 class SpriteSheetManager 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 class TextureSpecial extends TextureAtlasSprite implements IIconRegister } @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 class TextureSpecial extends TextureAtlasSprite implements IIconRegister { 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 class TextureSpecial extends TextureAtlasSprite implements IIconRegister { 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 class TextureUtils 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 class TextureUtils 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/153] 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 class RedundantTransformation extends Transformation 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 class Rotation extends Transformation 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 class Scale extends Transformation @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 abstract class Transformation 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 class TransformationList extends Transformation @Override public TransformationList with(Transformation t) { - if(t instanceof RedundantTransformation) + if(t.isRedundant()) return this; mat = null;//matrix invalid @@ -89,7 +89,7 @@ public class TransformationList extends Transformation public TransformationList prepend(Transformation t) { - if(t instanceof RedundantTransformation) + if(t.isRedundant()) return this; mat = null;//matrix invalid @@ -103,25 +103,24 @@ public class TransformationList extends Transformation } 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 @@ public class TransformationList extends Transformation 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 class Translation extends Transformation @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/153] 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.IOException; 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 class CCModel } } + 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 class CCModel 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 class CCModel { 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 class CCRenderState 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/153] 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 @@ import net.minecraft.util.Vec3; 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 class CCModel 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 class TransformationList extends Transformation 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 class TransformationList extends Transformation 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 @@ public class TransformationList extends Transformation 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/153] 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.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. @@ -69,12 +71,14 @@ public class LangUtil 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 class LangUtil } @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/153] 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/153] 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 class CCModel */ 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/153] 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/153] 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 abstract class Colour { 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 class LangUtil 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 class RenderUtils 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 class RenderUtils 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 class RenderUtils 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 class RenderUtils break; } } - - @Deprecated - public static boolean shouldRenderLiquid(FluidStack stack) - { - return shouldRenderFluid(stack); - } public static boolean shouldRenderFluid(FluidStack stack) { @@ -272,12 +248,6 @@ public class RenderUtils 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 class RenderUtils */ 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 class RenderUtils 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 class RenderUtils 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 class Cuboid6 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 class Vector3 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/153] 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 class Cuboid6 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/153] 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 class Cuboid6 return this; } - public double side(int s) + public double getSide(int s) { switch(s) { case 0: return min.y; @@ -158,4 +158,18 @@ public class Cuboid6 } 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/153] 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 class RenderUtils 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 class TextureUtils } 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/153] 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 class EntityDigIconFX extends EntityFX 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/153] 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 class RayTracer 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 class RayTracer 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.Rectangle4i; 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/153] 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 @@ public class RayTracer 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 class RayTracer 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/153] 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 class EntityDigIconFX extends EntityFX 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/153] 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 class RayTracer 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/153] 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 class MathHelper { 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 class Rectangle4i { 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/153] 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 abstract class Transformation 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.BigDecimal; 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 class Vector3 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 class Vector3 { 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 class Vector3 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/153] 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 class BlockCoord implements Comparable return this; } - public double mag_() + public double mag() { return Math.sqrt(x*x+y*y+z*z); } @@ -177,6 +177,11 @@ public class BlockCoord implements Comparable { 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 class CuboidCoord 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/153] 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/153] 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.entity.player.EntityPlayer; 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 class InventoryCopy implements IInventory 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.inventory.IInventory; 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.IInventory; 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.entity.player.EntityPlayer; 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 @@ import net.minecraftforge.common.ForgeDirection; 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 class InventoryUtils 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 class InventoryUtils } /** - * - * @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 class InventoryUtils } /** - * - * @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 @@ public class InventoryUtils 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 @@ public class InventoryUtils } 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 @@ public class InventoryUtils } } + /** + * 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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils if(base != null) { stack.stackSize-=fit; - if(doMerge) + if(!simulate) { base.stackSize+=fit; inv.inv.setInventorySlotContents(slot, base); @@ -194,27 +223,53 @@ public class InventoryUtils } 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 class InventoryUtils 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 class InventoryUtils } } + /** + * 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 class InventoryUtils 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/153] 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 class MetaPacket extends Packet250CustomPayload } @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/153] 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 @@ package codechicken.lib.vec; 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 class CuboidCoord { 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.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; @@ -123,7 +124,7 @@ public class Rotation extends Transformation 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 class Rotation extends Transformation { 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 class Rotation extends Transformation { 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/153] 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 class MetaPacket extends Packet250CustomPayload @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/153] 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 @@ public class ASMReader 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 abstract class 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/153] 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/153] 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 class CCModel return model; } + private static 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 class UV 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 class BlockCoord implements Comparable { } + 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 class BlockCoord implements Comparable { 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 class CuboidCoord implements Iterable 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 class CuboidCoord implements Iterable 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 class Rectangle4i 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 class Rectangle4i 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 class Rectangle4i 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 class Vector3 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 class Vector3 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 class Vector3 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/153] 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 class QBImporter } } - private static final int[][] vertOrder = new int[][] {//clockwise because MC is left handed {3, 0}, {1, 0}, @@ -577,8 +576,6 @@ public class QBImporter public QBMatrix[] matrices; public boolean rightHanded; - - public RasterisedModel toRasterisedModel(int flags) { List qbImages = new ArrayList(); List> modelQuads = new ArrayList>(); @@ -727,29 +724,23 @@ public class QBImporter } 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/153] 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 class MCStripTransformer { @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/153] 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 @@ public class QBImporter 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 class CuboidCoord implements Iterable 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 class CuboidCoord implements Iterable 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 class CuboidCoord implements Iterable } } } - 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/153] 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 class RenderUtils 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 class RenderUtils 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 class RenderUtils 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/153] 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 class RenderUtils 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 @@ public class RenderUtils 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/153] Initial 1.7 commit --- codechicken/lib/asm/ASMHelper.java | 246 ++-- codechicken/lib/asm/ASMReader.java | 4 +- codechicken/lib/asm/ObfMapping.java | 266 ++-- 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 | 174 +-- codechicken/lib/lighting/LightModel.java | 93 +- .../lib/lighting/PlanarLightModel.java | 45 +- codechicken/lib/packet/MetaPacket.java | 91 -- codechicken/lib/packet/PacketCustom.java | 1283 +++++------------ codechicken/lib/raytracer/RayTracer.java | 16 +- codechicken/lib/render/BlockRenderer.java | 126 ++ codechicken/lib/render/CCModel.java | 401 +++--- codechicken/lib/render/CCRenderPipeline.java | 135 ++ codechicken/lib/render/CCRenderState.java | 456 ++++-- codechicken/lib/render/ColourModifier.java | 22 - codechicken/lib/render/ColourMultiplier.java | 47 +- 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 | 58 +- codechicken/lib/vec/Vector3.java | 3 +- codechicken/lib/world/ChunkExtension.java | 4 +- .../lib/world/WorldExtensionManager.java | 109 +- 72 files changed, 2967 insertions(+), 3335 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 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 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 class ASMHelper 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 class ASMHelper } return bytes; } - - public static byte[] injectMethods(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 class ASMHelper } return bytes; } - - public static String printInsnList(InsnList list) - { - InsnListPrinter p = new InsnListPrinter(); + + public static String printInsnList(InsnList list) { + InsnListPrinter p = new InsnListPrinter(); p.visitInsnList(list); return p.textString(); } - - public static String printInsn(AbstractInsnNode insn) - { + + public static String printInsn(AbstractInsnNode insn) { InsnListPrinter p = new InsnListPrinter(); p.visitInsn(insn); return p.textString(); } - - public static Map 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 @@ public class ASMReader 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 @@ 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 + public static class ObfRemapper extends Remapper { - boolean obf = true; - try - { - obf = ((LaunchClassLoader)ObfMapping.class.getClassLoader()).getClassBytes("net.minecraft.world.World") == null; + 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); + } } - catch(IOException iox) {} + + @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 { + boolean obf = true; + 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 codechicken.lib.math.MathHelper; 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.IOException; 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 @@ package codechicken.lib.data; 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 class MCOutputStreamWrapper implements MCDataOutput } 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 class MCOutputStreamWrapper implements MCDataOutput 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 @@ public class Canvas9Seg 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 class InventoryCopy implements IInventory 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 class InventoryCopy implements IInventory return true; } - public void openChest() + @Override + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -106,9 +107,8 @@ public class InventoryCopy implements IInventory return 64; } - @Override - public void onInventoryChanged() + public void markDirty() { } @@ -119,7 +119,7 @@ public class InventoryCopy implements IInventory } @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 @@ public class InventoryNBT implements IInventory 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 class InventoryNBT implements IInventory 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 class InventoryNBT implements IInventory } @Override - public void onInventoryChanged() + public void markDirty() { writeNBT(); } @@ -87,12 +87,12 @@ public class InventoryNBT implements IInventory } @Override - public void openChest() + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -103,7 +103,7 @@ public class InventoryNBT implements IInventory } @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 class InventorySimple implements IInventory 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 class InventorySimple implements IInventory } @Override - public void openChest() + public void openInventory() { } @Override - public void closeChest() + public void closeInventory() { } @@ -121,13 +121,13 @@ public class InventorySimple implements IInventory } @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 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.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 class InventoryUtils /** * 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 class InventoryUtils /** * @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 @@ public class InventoryUtils /** * 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 class InventoryUtils /** * 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 class InventoryUtils /** * 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 class InventoryUtils /** * 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 class InventoryUtils /** * 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 class InventoryUtils /** * 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 @@ import static codechicken.lib.inventory.InventoryUtils.*; */ 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(int id, int damage) - { - this(new ItemStack(id, 1, damage)); + public ItemKey(Item item, int damage) { + this(new ItemStack(item, 1, damage)); } - - public ItemKey(int id, int damage, NBTTagCompound compound) - { - this(id, damage); - item.setTagCompound(compound); + + public ItemKey(Item item, NBTTagCompound tag) { + this(item, OreDictionary.WILDCARD_VALUE, tag); + } + + 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)); - } - - 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() - { + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); return true; } + + @Override + 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 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 @@ 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.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 class LightModel implements IVertexModifier * @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)); - } - - @Override - public boolean needsNormals() - { + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; } - - public PlanarLightModel reducePlanar() - { + + @Override + public void operate() { + CCRenderState.setColour(apply(CCRenderState.colour, CCRenderState.normal)); + } + + @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) ; - } - - @Override - public boolean needsNormals() - { + public boolean load() { + CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); return true; } + + @Override + 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 void handlePacket(PacketCustom packetCustom, EntityPlayerMP sender, INetHandlerPlayServer handler); } - - public static class PacketAssembler + + public static AttributeKey cclHandler = new AttributeKey("ccl:handler"); + + @ChannelHandler.Sharable + public static class CustomInboundHandler extends SimpleChannelInboundHandler { - 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()); + public EnumMap handlers = Maps.newEnumMap(Side.class); + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + super.handlerAdded(ctx); + ctx.channel().attr(cclHandler).set(this); } @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); + 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())); } - - 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 + + private static interface CustomHandler { - public ClientPacketHandler(String channel) - { - super(channel); - NetClientHandlerHelper.register(); - } - - @Override - public Side getSide() - { - return Side.CLIENT; - } - - @Override - public void handle(ICustomPacketHandler handler, PacketCustom packet, Player player) - { - ((IClientPacketHandler)handler).handlePacket(packet, NetClientHandlerHelper.handler, Minecraft.getMinecraft()); - } + public void handle(INetHandler handler, String channel, PacketCustom packet) throws Exception; } - - private static class ServerPacketHandler extends CustomPacketHandler + + public static class ClientInboundHandler implements CustomHandler { - public ServerPacketHandler(String channel) - { - super(channel); + private IClientPacketHandler handler; + + public ClientInboundHandler(ICustomPacketHandler handler) { + this.handler = (IClientPacketHandler) handler; } @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); + public void handle(INetHandler netHandler, String channel, PacketCustom packet) throws Exception { + if (netHandler instanceof INetHandlerPlayClient) + handler.handlePacket(packet, Minecraft.getMinecraft(), (INetHandlerPlayClient) netHandler); else - clientDelegate.handle(packetCustom, handler); + System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); + } + } + + public static class ServerInboundHandler implements CustomHandler + { + private IServerPacketHandler 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"); - } - } - } - - 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); - 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; + System.err.println("Invalid INetHandler for PacketCustom on channel: " + channel); } } - public static PacketAssembler assembler = new PacketAssembler(); - public static IPacketCarrier carrier250 = new Packet250Carrier(); - public static IPacketCarrier carrier131 = new Packet131Carrier(); - - public static IPacketCarrier carrierForChannel(Object channel) + public static interface IHandshakeHandler { - if(channel instanceof String) - return carrier250; - if(FMLNetworkHandler.instance().findNetworkModHandler(channel) != null) - return carrier131; - - return null; + public void handshakeRecieved(NetHandlerPlayServer netHandler); } - - private static int assemblyID = 0; - - public static void writeInt(byte[] b, int pos, int i) + + public static class HandshakeInboundHandler extends ChannelInboundHandlerAdapter { - b[pos++] = (byte) (i>>>24); - b[pos++] = (byte) (i>>16); - b[pos++] = (byte) (i>>8); - b[pos++] = (byte) (i); + public IHandshakeHandler handler; + + public HandshakeInboundHandler(IHandshakeHandler handler) { + this.handler = 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(); + if (netHandler instanceof NetHandlerPlayServer) + handler.handshakeRecieved((NetHandlerPlayServer) netHandler); + } else + ctx.fireUserEventTriggered(evt); + } } - - public static int readInt(byte[] b, int pos) - { - return (b[pos++]&0xFF)<<24| - (b[pos++]&0xFF)<<16| - (b[pos++]&0xFF)<<8| - b[pos++]&0xFF; + + public static String channelName(Object channelKey) { + if (channelKey instanceof String) + return (String) channelKey; + if (channelKey instanceof ModContainer) + return ((ModContainer) channelKey).getModId(); + + ModContainer mc = FMLCommonHandler.instance().findContainerFor(channelKey); + if (mc != null) + return mc.getModId(); + + throw new IllegalArgumentException("Invalid channel: " + channelKey); } - - private PacketCustom(Object channel, int type, byte[] data) - { - this.channel = channel; + + 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 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 static void assignHandshakeHandler(Object channelKey, IHandshakeHandler handler) { + FMLEmbeddedChannel channel = getOrCreateChannel(channelName(channelKey), Side.SERVER); + channel.pipeline().addLast(new HandshakeInboundHandler(handler)); + } + + 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(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; - if(type > 0x80) - data = decompress(data); - datain = new DataInputStream(new ByteArrayInputStream(data)); + byteBuf = Unpooled.buffer(); + byteBuf.writeByte(type); } - 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; - + /** + * 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 final class PacketCustom implements MCDataInput, MCDataOutput } 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 int readUByte() - { - return readByte() & 0xFF; - } - - public int readUShort() - { - 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 boolean readBoolean() { + return byteBuf.readBoolean(); } - public ItemStack readItemStack() - { + public short readUByte() { + return byteBuf.readUnsignedByte(); + } + + public int readUShort() { + return byteBuf.readUnsignedShort(); + } + + public byte readByte() { + return byteBuf.readByte(); + } + + public short readShort() { + return byteBuf.readShort(); + } + + public int readInt() { + return byteBuf.readInt(); + } + + public float readFloat() { + return byteBuf.readFloat(); + } + + public double readDouble() { + return byteBuf.readDouble(); + } + + public long readLong() { + return byteBuf.readLong(); + } + + public char readChar() { + return byteBuf.readChar(); + } + + @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) { + byte[] barray = new byte[length]; + byteBuf.readBytes(barray, 0, length); + return barray; + } + + public String readString() { + return ByteBufUtils.readUTF8String(byteBuf); + } + + 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 final class PacketCustom implements MCDataInput, MCDataOutput 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.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.MovingObjectType; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; @@ -112,7 +112,7 @@ public class RayTracer 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 class RayTracer 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 class RayTracer MovingObjectPosition mop = rayTraceCuboids(start, end, cuboids); if(mop != null) { - mop.typeOfHit = EnumMovingObjectType.TILE; + mop.typeOfHit = MovingObjectType.BLOCK; mop.blockX = pos.x; mop.blockY = pos.y; mop.blockZ = pos.z; @@ -174,7 +174,7 @@ public class RayTracer 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 class RayTracer 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 class RayTracer 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel { 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel { 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 class CCModel 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. + * 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 CCRBModel withMCLighting() + public CCModel computeLighting(LightModel light) { - return new CCRBModel(this); + 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) + { + 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); + 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 class CCModel 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 class CCModel 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 class CCModel { 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) + + public void render(CCRenderState.IVertexOperation... ops) { - render(t, u, ColourModifier.instance); - } - - public void render(Transformation t, IUVTransformation u, IVertexModifier m) - { - 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 class CCModel { if(!b) throw new IllegalArgumentException(err); } - + public static void assertMatch(Matcher m, String s) { m.reset(s); @@ -497,7 +495,7 @@ public class CCModel 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 class CCModel 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 class CCModel line = line.replaceAll("\\s+", " ").trim(); if(line.startsWith("#") || line.length() == 0) continue; - + if(line.startsWith("v ")) { assertMatch(vertMatcher, line); @@ -584,13 +582,13 @@ public class CCModel 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 class CCModel polys.add(polyVerts[i-1]); } } - + public static void quadulate(List polys, int[][] polyVerts) { if(polyVerts.length == 4) @@ -624,7 +622,7 @@ public class CCModel /** * 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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()]; - + model.getOrAllocate(CCRenderState.normalAttrib); + for(int i = 0; i < polys.size(); i++) { int[] ai = polys.get(i); @@ -690,12 +688,12 @@ public class CCModel 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(); + model.normals()[i] = normals.get(ai[2]-1).copy(); } - + return model; } @@ -726,7 +724,7 @@ public class CCModel 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 class CCModel 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 class CCModel { 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 class CCModel } return this; } - + /** * @param side1 The side of this model * @param side2 The side of the new model @@ -811,30 +809,18 @@ public class CCModel 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 class CCModel { 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel 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 class CCModel generateSidedPart(side, s, point, length*(side-2), length*(s-2), length); } - + return this; } @@ -962,13 +950,14 @@ public class CCModel 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 class CCModel { if(models.isEmpty()) return null; - + int numVerts = 0; int vertexMode = -1; for(CCModel model : models) @@ -985,10 +974,10 @@ public class CCModel 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 class CCModel copy(model, 0, c_model, i, model.verts.length); i+=model.verts.length; } - + return c_model; } @@ -1013,7 +1002,7 @@ public class CCModel copy(this, 0, model, 0, verts.length); return model; } - + /** * @return The average of all vertices, for bones. */ @@ -1025,13 +1014,13 @@ public class CCModel 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 class CCModel } 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; - } - - public static boolean useNormals() - { - return useNormals; - } - - public static void useModelColours(boolean b) - { - useModelColours = b; +{ + private static int nextOperationIndex; + + public static int registerOperation() { + return nextOperationIndex++; } - 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 int operationCount() { + return nextOperationIndex; } - public static void vertexColour(int r, int g, int b, int a) + /** + * Represents an operation to be run for each vertex that operates on and modifies the current state + */ + public static interface IVertexOperation { - 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); + /** + * 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 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.bindTexture(texture); + private static ArrayList> vertexAttributes = new ArrayList>(); + private static int registerVertexAttribute(VertexAttribute attr) { + vertexAttributes.add(attr); + return vertexAttributes.size()-1; } - public static void apply() + public static VertexAttribute getAttribute(int index) { + return vertexAttributes.get(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 static abstract 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 + */ + 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 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 T copyOf(VertexAttribute attr, T src, int length) { + T dst = attr.newArray(length); + arrayCopy(src, 0, dst, 0, length); + return dst; + } + + 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 + * @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 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 setPipeline(IVertexOperation... ops) { + pipeline.setPipeline(ops); + } + + public static 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; + pipeline.rebuild(); + } + } + + public static void setModel(IVertexSource source) { + setModel(source, 0, source.getVertices().length); + } + + 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 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 boolean load() { + if(colour == -1) + return false; + + CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); + return true; } @Override - public boolean needsNormals() - { - return false; + public void operate() { + CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colour)); + } + + @Override + 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 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.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 class EntityDigIconFX extends EntityFX 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 class EntityDigIconFX extends EntityFX .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 @@ public class PlaceholderTexture extends TextureAtlasSprite } @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 class QBImporter 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 @@ 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; @@ -10,7 +12,7 @@ import codechicken.lib.vec.Rectangle4i; 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 class RenderUtils 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 class RenderUtils * @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 class RenderUtils 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 class RenderUtils * @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 class RenderUtils 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 class RenderUtils 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 class RenderUtils 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 @@ public class RenderUtils 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 @@ package codechicken.lib.render; 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 class SpriteSheetManager setupSprite(i); } - public void registerIcons(IconRegister register) + public void registerIcons(IIconRegister register) { TextureMap textureMap = (TextureMap)register; @@ -79,9 +79,9 @@ public class SpriteSheetManager 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 load(ResourceManager manager, ResourceLocation location) - { - if(baseTextures != null) - { - for(TextureDataHolder tex : baseTextures) - { - framesTextureData.add(tex.data); + 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(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 java.util.ArrayList; 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 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.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 class TextureUtils } } - 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.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; -public class Vertex5 +public class Vertex5 implements Copyable { public Vector3 vec; public UV uv; @@ -32,7 +35,7 @@ public class Vertex5 { 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 class Vertex5 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 class Vertex5 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.BigDecimal; 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 class Cuboid6 { 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 @@ package codechicken.lib.vec; @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.ByteBuffer; 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.BigDecimal; 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 class Rotation extends Transformation { 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 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) - { +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 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) - { +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) - { - } @Override - public void apply(Matrix4 mat) - { + public void applyN(Vector3 normal) { + } + + @Override + 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.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; @@ -17,7 +18,7 @@ import net.minecraft.entity.Entity; 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 @@ 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.Packet; public abstract class ChunkExtension { @@ -42,7 +42,7 @@ public abstract class ChunkExtension 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.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.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 class WorldExtensionManager 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 class WorldExtensionManager removeChunk(event.world, event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { if(!worldMap.containsKey(event.world)) @@ -60,7 +59,7 @@ public class WorldExtensionManager extension.loadChunk(event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onChunkUnLoad(ChunkEvent.Unload event) { if(event.getChunk() instanceof EmptyChunk) @@ -73,7 +72,7 @@ public class WorldExtensionManager removeChunk(event.world, event.getChunk()); } - @ForgeSubscribe + @SubscribeEvent public void onWorldSave(WorldEvent.Save event) { if(worldMap.containsKey(event.world)) @@ -81,14 +80,14 @@ public class WorldExtensionManager 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 class WorldExtensionManager 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 class WorldExtensionManager 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) + + @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); - } - } - - @Override - public void tickEnd(EnumSet type, Object... tickData) - { - if(type.contains(TickType.CLIENT)) - { - World world = Minecraft.getMinecraft().theWorld; - if(worldMap.containsKey(world)) + else postTick(world); - } } - @Override - public EnumSet ticks() + @SubscribeEvent + public void clientTick(TickEvent.WorldTickEvent event) { - 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"; + if(event.phase == TickEvent.Phase.START) + preTick(event.world); + else + postTick(event.world); } } @@ -199,11 +150,7 @@ public class WorldExtensionManager { 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/153] 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/153] 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 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%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/153] 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/153] 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 com.google.common.base.Objects; 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 class ObfMapping 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 class ObfMapping } } + 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 class ObfMapping 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 class ObfMapping } 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/153] 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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/153] 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/153] 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.Packet; 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 final class PacketCustom implements MCDataInput, MCDataOutput } 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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/153] 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 | 37 +++++++------------ 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 | 17 ++++----- codechicken/lib/vec/Scale.java | 9 ++--- codechicken/lib/vec/TransformationList.java | 6 +-- codechicken/lib/vec/Translation.java | 9 ++--- codechicken/lib/vec/Vector3.java | 21 +++++------ 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, 174 insertions(+), 300 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,27 +1,18 @@ package codechicken.lib.asm; +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.*; + 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 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.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.*; 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 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; -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; /** * 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 class ClassHeirachyManager implements IClassTransformer } /** - * 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,31 +1,14 @@ 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; -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; 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,5 +1,19 @@ 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; +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.*; + +import javax.swing.*; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; @@ -7,29 +21,6 @@ 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; -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 javax.swing.*; - public class ObfMapping { public static class ObfRemapper extends Remapper 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 @@ 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.*; 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 @@ package codechicken.lib.lighting; 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 @@ 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; @@ -13,14 +12,12 @@ 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.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.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; 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.client.Minecraft; 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.resources.IResourceManager; 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.ByteBuffer; 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,19 +1,16 @@ package codechicken.lib.vec; +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; - -import codechicken.lib.math.MathHelper; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - 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.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 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; +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/153] 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/153] 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 @@ public final class PacketCustom implements MCDataInput, MCDataOutput } 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/153] 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/153] Upgraded ASM lib --- src/codechicken/lib/asm/ASMBlock.java | 173 +++++++++++ src/codechicken/lib/asm/ASMHelper.java | 248 +++++---------- 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, 1142 insertions(+), 747 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"); + + 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 class ForBlock extends CodeBlock + public static interface Acceptor { - 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.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 class ASMHelper 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 Map cloneLabels(InsnList list) { + return new InsnListSection(list).cloneLabels(); } - 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 InsnList cloneInsnList(InsnList list) { + return new InsnListSection(list).copy().list; } - 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 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 class ASMHelper } public static List 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 class ASMHelper 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 class ASMHelper 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 class ASMHelper 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 class ASMReader 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 class ASMReader 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 @@ public class ASMReader 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 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 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 class ObfMapping 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 class ObfMapping try { mappings = parseConfDir(dir); } catch (Exception e) { - if (i >= 3) + if (i >= DIR_GUESSES) e.printStackTrace(); continue; } @@ -102,6 +99,8 @@ public class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 @@ import java.io.*; 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 class ConfigFile extends ConfigTagParent 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 class ConfigFile extends ConfigTagParent 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 class ConfigFile extends ConfigTagParent 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 abstract class ConfigTagParent 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/153] 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 @@ package codechicken.lib.asm; 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 class ClassHeirachyManager implements IClassTransformer 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 class ClassHeirachyManager implements IClassTransformer 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/153] 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 @@ import java.util.HashSet; */ 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 class ObfMapping 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 class ObfMapping } 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/153] 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 class InventoryUtils 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 class InventoryUtils 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/153] 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/153] 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/153] 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 class LightMatrix implements CCRenderState.IVertexOperation 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 class BlockRenderer } } + 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 @@ package codechicken.lib.render; 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 class CCRenderState 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 class Rectangle4i 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/153] 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 @@ package codechicken.lib.render; 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/153] 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 class CCRenderState 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/153] 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 class ColourMultiplier implements CCRenderState.IVertexOperation @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/153] 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 class BlockCoord implements Comparable, Copyable { this(ia[0], ia[1], ia[2]); } - + public BlockCoord() { } @@ -49,7 +49,7 @@ public class BlockCoord implements Comparable, Copyable BlockCoord o2 = (BlockCoord)obj; return x == o2.x && y == o2.y && z == o2.z; } - + @Override public int hashCode() { @@ -81,7 +81,7 @@ public class BlockCoord implements Comparable, Copyable { return Math.sqrt(x*x+y*y+z*z); } - + public int mag2() { return x*x+y*y+z*z; @@ -96,7 +96,7 @@ public class BlockCoord implements Comparable, Copyable { return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); } - + public BlockCoord add(BlockCoord coord2) { x+=coord2.x; @@ -112,7 +112,7 @@ public class BlockCoord implements Comparable, Copyable z+=k; return this; } - + public BlockCoord sub(BlockCoord coord2) { x-=coord2.x; @@ -128,7 +128,7 @@ public class BlockCoord implements Comparable, Copyable z-=k; return this; } - + public BlockCoord offset(int side) { return offset(side, 1); @@ -142,7 +142,7 @@ public class BlockCoord implements Comparable, Copyable z+=offset.z*amount; return this; } - + public BlockCoord inset(int side) { return inset(side, 1); @@ -182,7 +182,7 @@ public class BlockCoord implements Comparable, Copyable } return this; } - + public static final BlockCoord[] sideOffsets = new BlockCoord[]{ new BlockCoord( 0,-1, 0), new BlockCoord( 0, 1, 0), @@ -218,7 +218,7 @@ public class BlockCoord implements Comparable, Copyable { return set(ia[0], ia[1], ia[2]); } - + public int toSide() { if(!isAxial()) return -1; @@ -228,14 +228,19 @@ public class BlockCoord implements Comparable, Copyable 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/153] 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/153] 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 class MCDataOutputWrapper implements MCDataOutput 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 final class PacketCustom implements MCDataInput, MCDataOutput 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/153] 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCRenderState 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/153] 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 class CCRenderState 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/153] 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 class CCRenderPipeline 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 class CCRenderState 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/153] 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 class CCRenderState 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/153] 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 class LightMatrix implements CCRenderState.IVertexOperation @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 class LightModel implements CCRenderState.IVertexOperation @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 class PlanarLightModel implements CCRenderState.IVertexOperation @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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCRenderPipeline 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 class CCRenderState 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 class CCRenderState 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 class CCRenderState 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 class CCRenderState 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 class Vertex5 implements Copyable { 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/153] 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 class CCRenderState @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/153] 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 class GuiDraw 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 final class PacketCustom implements MCDataInput, MCDataOutput 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 class CCModel implements CCRenderState.IVertexSource, Copyable */ 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/153] 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 final class PacketCustom implements MCDataInput, MCDataOutput 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/153] 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 class GuiDraw } 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/153] 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 @@ package codechicken.lib.asm; 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/153] 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/153] 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 class ObfMapping 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/153] 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 @@ import net.minecraft.util.ResourceLocation; public class PlaceholderTexture extends TextureAtlasSprite { - protected PlaceholderTexture(String par1) - { + protected PlaceholderTexture(String par1) { super(par1); } - + @Override - public boolean load(IResourceManager manager, ResourceLocation location) - { - return false; + public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) { + return true; + } + + @Override + 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/153] 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/153] 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 class GuiDraw 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/153] 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/153] 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 | 339 +++++++----------- .../lib/config/ConfigTagParent.java | 195 ++++------ 3 files changed, 244 insertions(+), 320 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 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 getIntValue(int defaultValue) { + try { + if (value != null) + return getIntValue(); + } catch (NumberFormatException ignored) {} + + setIntValue(defaultValue); + return defaultValue; } - public int getHexValue() - { + 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) { + try { + if (value != null) + return getBooleanValue(); + } catch (NumberFormatException ignored) {} + + setBooleanValue(defaultValue); + return defaultValue; + } + + 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); - } - - 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) { + try { + return type.valueOf(getValue()); + } catch (Exception e) { + throw new RuntimeException(e); } } - public void save(PrintWriter writer, int tabs, String bracequalifier, boolean first) - { + 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) { 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) - ConfigFile.writeLine(writer, "", tabs); - - writeComment(writer, tabs); - if(value != null) - ConfigFile.writeLine(writer, vname+"="+value, tabs); - if(!hasChildTags()) + 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) + + 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 class ConfigTag extends ConfigTagParent 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 abstract class ConfigTagParent } } - 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 @@ public abstract class ConfigTagParent * 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/153] 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 class CCRenderState 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/153] 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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/153] 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 class SpriteSheetManager 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.TextureAtlasSprite; 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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/153] 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.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) @@ -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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis } + /** + * 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/153] 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 class BlockRenderer } public static FullBlock fullBlock = new FullBlock(); + public static void renderFullBlock(int sideMask) { + CCRenderState.setModel(fullBlock); + renderFaces(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< { 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 class Vertex5 implements Copyable 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/153] 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 class InventoryUtils 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/153] 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.ClassReader; 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 class ASMHelper 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 class ASMHelper 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 class ASMHelper } } + 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 @@ 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", + "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 class BlockCoord implements Comparable, Copyable 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/153] 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 class WorldExtensionManager } @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/153] 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/153] 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.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; @@ -17,7 +20,8 @@ public class TileChunkLoadHook @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/153] 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 | 103 ++++++++---------- 4 files changed, 50 insertions(+), 100 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 class InventoryRange 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 class RayTracer 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 class RayTracer return mop; } - public void 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 class CuboidCoord implements Iterable, Copyable 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 class CuboidCoord implements Iterable, Copyable } } - 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 class CuboidCoord implements Iterable, Copyable 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 class CuboidCoord implements Iterable, Copyable 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) - { - this.min.set(min); - this.max.set(max); + public CuboidCoord set(CuboidCoord c) { + return set(c.min, c.max); } - public CuboidCoord set(int x1, int y1, int z1, int x2, int y2, int z2) - { + 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) { 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/153] 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 class TextureUtils 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/153] 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 class MCDataOutputWrapper implements MCDataOutput 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.MinecraftServer; 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 final class PacketCustom implements MCDataInput, MCDataOutput if (fluid == null) { writeShort(-1); } else { - writeShort(fluid.fluidID); + writeShort(fluid.getFluidID()); writeVarInt(fluid.amount); writeNBTTagCompound(fluid.tag); } @@ -465,13 +467,11 @@ public final class PacketCustom implements MCDataInput, MCDataOutput } 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/153] 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 class GuiDraw 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/153] 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 class GuiDraw } 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 class GuiDraw 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 @@ public class GuiDraw 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/153] 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 final class PacketCustom implements MCDataInput, MCDataOutput 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/153] 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/153] 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 class ObfMapping 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 class ObfMapping 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/153] 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 | 130 +++-- 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, 814 insertions(+), 681 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 zD6ehCWxkntKAc=>I3D4u%G}7e=qxAA?Sf`7*}AmHFeW@~qH!)52qnK%eE1Y#m6@67 zO3V-|xB*e9&pCv-V1+5(CZj28OXi|x%O;Z1nrRvV`va^-K+)hKm%358ZVl@hdM9FC z`qetqkt}(vC?B4YCb`J1(B|W2FUG9=weI5{@{Eh?>TQW{wfaYPWn!Jhvi4SDn*L$O z+ba3AEvl-&kMm{7T5kJbXBWyP97&!1W`(U0yLFAp9aCM&B={x zw*WRe*|v*CO#xJU;A^drAdD7ha@q#PMDU?H^H2WEu}hJ9kuKa2l$b+q&aPcCIBJZP zAZo7C9ZN3co+jwrzGvV{^s{n)Kc3W#5G$jqL7K|khz zHk9sIccAw2J>9kHTcA3D%3k#TKTv!LRIIO0y^=2-AV?H36JTji*0YMLNu)niMyk&E z>H$==7YOv~!yZRv+ZW0%4RLQvHEY1XN`DS6f_RM3L{@V~P819bgI?8PXV0;)N|M z_OCId;-W+3Nup|vCg}PkK!^wI7siD<`aYadbQJhMK)T2jHdK{cU2vw5dL!&%Od|^+ zWYfAf+WceYJw%7cLdinWYmJUeHjx+QXFw*q9snlQ7#m$U!&XcYZz3&bP|{nHH){)o z2oR$Xj=5F|89VqOZ{-3c&YDC#40G;G2J!EA1>VOXL_hTle3ZoE-^LmYnG|`3MDIzg zpD0HilUchX^S142{rYLEPrp_g1{{gWkr|HPP?SRBwD(v9W_))vD!Q&)ME8 zSqn$@K-gXj!KjW zE?pbiw!2Ea+NTTTYAi+aM_$J>(+K8|w5P|^h~B-Yz!OGn2=d8X+!g;So?07|^!WaL zG~pYy3zW9Cn_v8aRS1-}C#_q$CO(3MwoL5FsS7kld0qI)VlS6;X1*mdSP1 zf$sx2Bhc6b9k@Kibq*xVKTah~}u(zWjRCNOE`wS;aKjJk4K*^DTK@F45G5 zs1PuH;tY6CoP*^A`6iUj4WbjmhEkBPXCYx$O5^JFa7J0@i5stv( z5CV!l5pY>sFbST5=Lb{?BZh-*AO!6q1xfHspjn?W3ABKmv>}p?1@WK+)kX+3@s1F! z@a6z0$q3v-2$yQJ6@76nkN;wH%)hk}hW`wJ z{$~O#VQBZa)bMZg6RURVjI4_CW1D3%A$T89ap1KRfRJL-Fj+UN95AVdizybLu+xp5r`swfpn= zjvny!ra43xQ|=)wj4Z~IJzO5e&iY3B_zMix_<@1W9hr(uHCydIHB2oA#8IpkQgT+x zNiI09f?(F#1AA%lN(g#qU<6HPuq&yXoSvJ!4CO6uvq@+mjByDGIrJ*VVHS%S(`jS$syH!&2}e11N+vIh?Gegr%!V9Q znsd}fZ1@D1I1O2jrXk&3^rhMOaW9j|f3cpz?Es3cEJT}HwVs*DZN1%WScaR;$V{ZW z%Y~-hjEv3h$O4_ECgc)=xQalfgxl&E%1%;*H8ik=eoCA?96gEXG_zGy^AWXy!uh@! zb4Y5$!c2=YYPou!Y-v!_?PmKb;+MwWSFXgU0Y`<9nuc9V+C;__(Yex&NpHS^bZD@m zI!Bnb^yYKNv5V=liHdo3eo1x1c!(*Y72>=TYJhDGLLC4l^8_ZHeG8VUQzuE3^kZcZ z-AOK*YyQVZfmi(nr}(*p?x2ijn6|^2vB$Gf?Rr^iJ+z$Cue}Q|G3jS%W!x^oGxnM- z=f&|d&$K9NE+&H|8_STipg8m9q$i8>`otwi)sLO6{4x}mS`fcdgAOw_6$oytCN4Dw z=BCC8H+b&2>yXo>K`3(@BmZLljT$4t zF(STsM_l~MH;J*a_JRXs+`J%7pRhSsoPKnw-epH+r{2L;s@{cr+TNvmUOxp#>9P1X zNkNxu_>92imp-5#BxyMGrmb@vI&_WfjoJiYak4st&8YGRR%uv&Cgal*X3RLz?OqAr zCYRNQNr^G*rzv_@)~|f)G!2^!i5?=>LRg~my=+!y-(aZk6@p2N$#x2J5AD( zuz2=<&QyfjkY=S=8Yt~53@5u(a|C?f6t58*tEy9`-sZ$S1ZbE2rtT7~xZ?u%dZv#< z%OS~#Do{gG(O?`kF-u&!LwWFe``KTvFJ(Ag{hVufn6?_Bu`N6YNr-Bbvfi-lQkhBb zw_kZ5^rwn|+3W#X>k&|J>cj=oA z@hbF`1VMJSmk6TpEf&>00q}wk-x@+oPr@wmqS1F>K>l-Iq;C@tG4z5trKfu$_WFpI zZ*|+jd}qm73AYoxA>^s~^7I8M8<(4GC=H2pY^V#rUlFqMnr%HpULtphTKUAng9P=* zUokdOwgwK~D5NGY9(eSkM;c_*;HZAQDU$;y#BfZAZpN7$v(1kJzGYr~o8sF+6Gy)`+S(Q) zr+s}~x+LSp%Qp?^1+(DoM=ExNqF;)Z50aCwbAUZy-@!9a6naAy<`_KCIe7i8*e&H> zmjbP^=#|rDtd|(?>^`^&`vd+@muYuNFoXpT0N@A*06_MiU8aJei-n-Gv#G7oe>=() zwLiw2YN+48)>5m=Z7)jWO(Y$Y-CVCoN_D5Cx=@hDta%SeqLX8q>t!NU#dBy)y_z9o z*h2xaZMvaBNB_WL+PGP+L4A(ngJu&`x?NG){25Sx)ywmqb?<%LCjR=v|GEq0fc2B) zfKtNC5v>Y|WhcSnof^&rkBZ1;kKL_-e4h;hNxH-6X(np;xRgk6KxV&tV5mDB783jx z5+eWLZ+`ECl81C}37I!wUi6k7GIt2w{YErr7yX9B-$%2Lp|`hBP1H+uV6E6qVF*Ak zdhg2i4F*r&G^g(IGDFcjGG{M-pF`10z3=_Tci4_R0$=z>nAc5wP#XZ8JQ}5xJ5RH@ zoQkW>>;mW{x2npltVSc<0)o@Q!_CH+p_@r>VxCqjbJ`>w+OfX1Yzo*gfjucps;l;- z)F}Y>v?vPb%^YU89%V;QVJePVZ*S)I5ou#q>u04up%P{4x}!8hEfz}4!=9Pwr$b$J zMD&neYW+eAcpW(a3Rn=MNYeC`oLMW!nPR$a9!7SvuH?4!+BH z5!r?~n_YADL_{zzYajr)U^=2yhC;@qMbfs@Jj4PcHT0xL^dm^^@20Aa%#h>Z{k$Wb z3z&kA+vFqKpav>2Y}o5DtIdOhKymlE6J@0-C7ClXRcQ)+_83FsI>N~6O`Nm)&b}U= z#%_aVvDxAX2vp)}5x#o$5!HF3jMA`$prWl@gTcOX)md|qI^`na4v7?jKq%h)KJsdD z`I>lHnUkA0bDhM>%w?Z?$+go;c51ES86WFNm82c;y}fRs6M(S#3l0rtOh?f(d3cAU z2$7G_7$wa_XV{p?kAyfHf9j1RH?<*x+|&m|*(J^0EA<|^o5~oI+NDZcF@{^Kqdb$z zZ<39FXf86bIY$4^3Z?JYJ$3FERvi?_aiUT;C| z8j&CQ;p-dl_SfeyC!+tad-6}sQ8K;cd-P9Lfi&-8q5Z`}Ey}V@t4PJZS+F9HU_^CL z92kY5fZWlW>Y`08(d~P4`%#CJW~cE#lxM0n$G;OG`8KP0w|OmxGNUXC+S+#gMyj?w+Y zyOBnKWjn{Fq%M&IYL<95=T3*Ud!0yuNcOC`j;6T#3SNr+cU_%(y}j+m>tX|a3Ba_l z9Q_MH?t$gzo)}-D;f6Hztn6*?`4HULz1_)~WRiA8F*@urNZA4KU?yI+jjBTfz6S+A zOViz>$v_8zXEIt#DCUM%CEfAqY zuwgnoo?pw*W{uVU>~w{^%BKef(pOn6t81D9xEj91o6_95845@4*lQ;u-LI1NomHGv zi|(@xs$*NV9BN#N5s*n_$qH& z7B^ zxqxkE?Y<(`5XkPv8N++(%7yd(-AkU!NCTEgs-HXeqePOJ+m>8GwP6i$oGi>5QkFDS zfklKaq>X_7US|R8-AX|FdtQ*bBdVvtm&GOAqTI+IHV1uhvlTqk##pxX#-`knqA@f$ zdg8{xy*R9P#*2$LVm>`z1*`#I5{EFA8Do&EVX8v+USL(ZD|V_`Tx;NQT#&_E7jFI!`b;fCnS=q)qzzWb z#AOZ^R&Aj@^cb3O$gwZ$F!!M<&hE6mp#h^?kd@0r;N?39YFA%mi?}6EJe-m-`FUer z6rVr_Q*YBReUP4X(LgyD1ZL-SavES3{eERTHe%N&;mzvnT$Xxe6rDZ;L_v^oT5&)%0=b)jbKt9Va7oY zkdc)rnbq(^XVo+8vG^aL9AhyuB}O3z7x0CnON&jJk+5x5@+n?6C-`%$oxTavdscjI z*$26X-*YyXpNZhK66TT>pix}ntm$Kr2fdDln2GF}k~m=VpUMt~eYW9BjxfExh)cWiPl&?6%1`T1~X?7fM~1 znq`;Bc#~S?u*rG-Y`u0Zg@5eLhFNhM;R>IAi9f5;wx@bZ5WzWGr<>IiDe*n?GM ze`sfZBp!h^|L7+k`~W=(XLM9DP)-BVLDqvKU%@V#y+|IyHx33W(H-XxnhIVNvjbNb zo}xB3=!j7VcSlj9)T*>gwW@<#vaf*PxkU5D%F<3j>g59 z*$o!9ep;Wxr*uyT2ak>9vs! z&*<(kQ!&@#v>QgR|5?`IC{XbyaVM`H++Qv{4pAvb0f{J<`~KAp#?()oFI= zE4FCX*;1Y^zJ+&_&Qz+LYKCoQB%gfAG<1b9GP0BWekmh+n~uT~71U!YQ+(vT6~&m+ zb%flx&FJR;(6*#qA1B6&@W= ztBRMsjJ!c0c)An}jMP}nd5BpVjc*5IY7#w>j;>PMAM@vlU$h@F7iwD)WFsd414>rm zp`>URjgPz)6_neHMc}Tq7hz_Laha5FC1ml>eoIl-f9H2MieQ@0%pBO9a9XW6^^4$E z5|c3vX|DfxihVpPmlPfmOstV(J=rzf*@yrzRn2PjchS3c5SkeS50F zx3c44b67t_2iPcUl6VZrB60Hz3ma}|keQQ4a&n0xZ>e;MwkS<#tQ6C6G3|IXJzGHV zgtEfyB4Bf+@rY6rIn}UF#V{xEq&-E{m5=$`Q;6-1>DT@mmN++p&{rc7BdGawu}%Ga zOM5?uunCF1o(4BfkD~5F3Xuyeb(*uhusI~OgJ33M%VF4Y z!jQ4qWahGNe#N=(b)#%aUVfg+IrLMvRG-LP<&)w^x)fNB+WC-+AZhX~Ko@qW=6Hc! z%E2#%bG|6bts*D-SIRB=FTa%ABVeirIy*J%x*Ad5070P(UaGz{a6-3UH7NKB9+^3U z_u~XNhLrl)_FP#dnb)23dAL*c%Da=WqZ5ba<>dVk%Wy~fdRAh@-$>4DX6MPRl#H8r zH+eY&;dro{W*$%z)YWrV$!<1u-K1UiwYZ{mWBw)wETyV=`-+I4bSdx;7)$roP>Clw zAkfS>{_aTSJ`rPykk0+rtu(fB^HmRqUSh|@K5dhTn7GHrR9`_Fv>b*ci(%-Bw}KB{ ze_1Al1z5A<=?P^=WY3)@>oK^L_(#YBC#7R=O=S^Tf;_+oV-ndkHp@;pA8IR@7996x#LH@9QcOW#_t#C{f&e(z+t5o3KqLpmFo(9>y^HySTwX!D%EcHX+fC3}3O=OC4D)MzTj*rHat|TP1cfwHq{0DGQPWZ=gCN_OFJXJpW8&466THTA( z#Gp>iH2k4=>4QZ0=->n=y`oiAKb7P7J6tIK(uc#(kV*XGc*5UxIdl%76Vnpe1t)er z_uj6ft8v1Q-4WE$I>=byV8y$iaQbi*Thg@~5GA9fCGz2S&qpR)p2YBZ?$6ofIz$!D zxKmJB)Ek0VQ@u1`JFbG%&4CyzbtU$m+oE;WaAyg0m|O}dB7S{T zLoX?Lu0)j1N*7qJbC*m@yqG5OMp!MJA$?;CI&QZgf5dZ0bU+0?TR}1#0)PX-mR^h& zdez#|IQ6*+0n)YNTtCbm=c1ubk&!}MhQ;z|YsjA@wc^e7WyS?b-dJ6r%S;3p)}&9Q z$sXtOB6)2iOERZ6x~h)_*qT+Ut0I~qIEeKcMJzhu(6!sIo`?$VZ+Fzb$?C+Yq-aa^ zU7D~3JfG!1dTe?NBj~(<{L+~2{o5h|s7wq1dYrYB*z#hcvo97^4C<*A7jNqSFsY3| zv2l{`iG~R-N;O98FRzFPRTgt?N;p_g-Rvxnur$3#yzUvWo(cZNO?VbvH z5h;3AI_2*gDkrEgq&o>xuHVFNk2x(c4begN6|yeOq7`uw-6%vkr4g1``lK#VRL64h zjwL!1Ie4$mPt*-##hA^nhtzU>5Balr6`HaNQi5gkqD$1c?C^pq0ioa1{%a9rZIz@bjrJ^_3H9aV&1;OB;CEnxomgX7|-xI;|5K{+1S zC9*G~N(|C0TU(6+JNvC^}^FTG8uvP2>(Rp(8b-JBb zo{_&(6tsxrix#lNFA$rH9DeJn$Qv)qg_oznaci-5Z8d4ZayvCKd!Zmu3`_t&A$q|) z;gNePIeMKyPX8sl=&u8J#q08K^@^VpK{pscz(eR4*j(7*+j=^eF4xbi?pHkW3LUg# z?XA=JkMhc5(y+S!dbSH%%o~=_+00RG=B}{-SQhC?s`k2>Moxcc z1jpcy`|&vLggdkklBPV_1sc7iPkfyuQWe*t!bY=LLV%}VJc;;0wTkhe${HownLKHT zsB_KL8bvE_nZkaURn|_UKgue5A-6nqUT%=csb5K*ta)sP{nJ{MRfhZ6{K#~zU#y!b zx`CT`-A1Rd3Uqz`K) z8JxZqhB6;IJRe+~KcHh?|A#RBlM&;~9HB~nDL9`^e2&0~FZ|v)BI^{9nSSZdx$4y? zTHz_TLo|n5*rY=*?!X<1%r^q-eA!u9|2Id)WnNfxSN{+5Q!(MI$T0m-8D+S?s6%$_SkWg%;!_3BBM~gO=yiI@ z8(fW2SBZRsO9{D%SOy3} z98{3vD2sA292NqkOhnL{w;d=D@|@=5p>Cl*nLeO~DMai%VH*zzGi2Y~S`MPy$xLf> zou_)@2Xq4k^7(f=ha`yhc8MZHlbS9a9o%0>tYi~Y{d)++@UdMQ{63LZqRDFS96-7! z=XM59m(eJI{qbT@ztPUtfVP*8?cqF4FFeNk1js?I$my4$&|k=fC#}=!{FKsnsFMNB zQJ}irK(TPaQHJr*ToU*o&U6I)0p&UpT7LVPzyQSr1iuDb$x@Rz9!3$fkJK zRw3LTBb{hrEr7uiN zEksU#u#1_)pI=v|t6`CsL@f&0)8h-m{66{v_GQRO*uima4H3D{@AUG+m_Qp@4I=sO zEirmE4F3Ja|IciByI&@9_%D5z^0$fk|H3p2+1tA~yZoh_WeqLulwAy+T>d}qPE&hR z4S{#C5wsGi--Z#y0SF~)L{3=>JD&wIv>qeLAeE~)x}IK4B(k7fS_w_1~6_Jt4Lp3q# z6O*l>?if&-2Sdp)a7N52js2l7FP^=m@Mnz_gfxb~wMT2D-=;PO%7fs~5)SO~Z}lVL zW6y62qvCHGgXGT&?@roc=t)RQKt9Tu1?x*dJOy`Q0FI+FjDWF>GX~Th(`-$@mu+)M zzSA>Qo?%xO-+Bp9u61dt32>NeTv%)?D04*fv@X8+nhM=zmu5GbHPu*&?W$5|swDw; zX!N1Z;B7}PRlRaBixJR3mMxnT4$Wqz8aYo@^40ceJIXd20L$o@g)mEB;%Rjk6qx@YTg-0dNQJ1t1uM&-^a_i6ljzX;K5XByp z)LDD2B~xPVPMOivUUbmgLQ_qByw^0HTXFx%EnEk&n!nU}_YE$zGE)|15UABax>f6F zR&^osrW$)VDavKFk?Cl_SHSI4#S-JaJ2i+RvTv0b&>O|36kMDP(V43=hiyoqvm#AG z)KmBXrjz^KM7FI$S;UOFQW`FRw`o=Kf{3`qNXt}7pg|nZ3Xv;Xd+r0gdiL`h{`*m2 zk2ZGnvN?K@X8sD7E9@=^&GoEk;S_>rG_!lD<*)Z}rAY=S0P@(?B;bI8;-m^a0hFT+-?WdV}VSIodxM@#xDL^v)P{t#HU6MbD zL03b?Nr)tO$mpNs6~?z2MV}VB zU7~&u*Y{mxTzk6E#CK=E#6;T~z0RHCS|Zy!ReI{&gFl>oLiPr{uAUa&P4)Tb6jJZ^ zX_5E@-55W8I;sV_K|w;mBb+lhC%% zptY4mp9jS~x3h?ZZ5NQNL4BQ#)bdg^M}%@@QTaz9F8H-@XYygy5Uwr7B0A7z9H z_dD@nhN)XLtZnj+ZNFDKtSj{B8nIjW#C>wM>*!Jee zC%xu^B(rV0+ipEfPoaLerOpC-eRhA5&$gOg*_N%5rE#Z(Wm--%8r_?PT0A@~%B|NT zO@y=7Zu0b5M-1B?;I=x&(EAO1`+vy)Ktd2}3oca|Q-id)fZzY2aYF-7XfY3uH#d zdc7vobbMnIWsS!gg{H_gw|}21`^28XDXd3vfHbgGjo23lzLiRWqI$x8tBbwnl-EV* zrFh`1hL2M`?TD7QPSY!1(EutAU3466O2I+u5=&iBu8q4b=1H<1%4|U@?NFC5G8Kj* z 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%0DvTus6fLI&f~`9YxjD=W5pR41LBYQt z9A{#TtXEX_DN=hSuafzWTeYt2aLNU0avuS|`tnpT*Eb*MH-U}=;4E4e=WGW^5|lnx zncb6PwPV8KFsD$UcRd(S`$NRb>hOk`lo=g`nZE#EHV(8_T&_ru)Rq zS;8Q*^r+~UH-%@EM7I!)9&vOH3V=Oq2ioLX{)x_nouWf@6+8Pmje=2%`uapkI|S=c zRE9bDjM*s|iNz9rAEojXvWq`RqcBez+;XF8xmByi5u;bfm)gYO;r0iET#jJ(G?mlj z&FTmZf9K-d2Rmyz4-!br3=`V9kq;k%SK_|2HUF?NgR20aP+hy3C*M9rs>-U%M>OcHQY5(a* zO8Xy1tM*^M0(AEO*NRkWYEq7JQc^`iQg(b|oMv=ldS4NqQdY%YT2_&PMVW!6o{6o6 zi9yNU6;6SHiGgL8iehY9N|uhYS(aW(W>j)fc53v1ifWR2bV9c2U#w`ozdUk3g*^C1 zza9kn3l(C1T@76>Xfab{Zpu}g&!SX*g>7}* z*|J8{<~Uqy7`f6EDKo|G#;}8d+QXi*4>-w})Qc=^uZ2 zKE-}PC&vGJyP)A;8eAi1VLKa}FaI1F3tN*f?1#k+M7;Tg( znLv~>i^eS6RMjy{Elo}C-nLkB?kHcvHcl&VWNC6JTqE1|5*vLrZpOMxO143T)v98D z@Lytp;cjX+sz`5Gw`5bPm`b>8u2kA|b?z8p@Znru9o_cEVV6`cSB)?kLtoT}5$4k2 zRFzv45^jp@$8Wo-1jyvv>RhTX<3h(PuYW%Z%LTF=3$tu-$uMw;l_!V;*%jUrEG^<& z&ojzMCTtz6={A20Git7MMb&~W2q`uw`!QU+cQ1TADt`!@aVqHOuh11^Xn)zA|KR{j zJz$K%(+tva1p$A6>~QkkIb>R`cR3bF9jBe~;L5SxpqZ<=xQFdkn_ioBxB{0vnqvr4aXCs0m%bKH9I1%oiU>^{8>_m@ zcw}qmia`cmb-0#A#KSk0uLf`ZgvDk26pj;)LuV?cm=N51m0j`A`rvkMZL1Hg)@R$4 zu*`J^VX<2&R1*40SE3+_=(SZU2_8z-e&agfXsb#a(7TuvBub-LpaXP5~AdMtJU(4U2;0{W9j0&LpkTf80bTbcnl#(JTfbdlj!nw2B#px zv(RuiE*xV5WL7aw-h1jz5Ihj=6n1Dm-1Q`-ND_33pOSd&M6%h5+@Llu2XR$6<+3E8 z(8F=ojp81-`kKVm$r>?VZ?gkInOmGjb>-r9<+MMC5BNu1MdM$ph$A}GPL3@#4gx1W zzx}^rSFL6L%gIZlgynm1{}xE{8L zS_x0fqk@X|p$xi~(pmsZKHAgq{0u=>(r&lsyXPk`-8%p64m^Sw0x2vKcw%kaykk?9 zT00`UE~Rs2HA!xPx9&oG9nY|RB7~)Oe%8CWm`G?ESX7r(T1kTzA+)%6?2&{d5bCDc zFqz~WjYoJICnTv8wqLZHPh9vZA$i6L;%#;UwhbKV4UXxR^A`01_eh)O{cj0ndrwrn z=qp1!fAP0G|20GW*LRh*aB{M+HIuXdtGX6+H2V_oJDdDdC6J^eH?NO6{5j3mUUhDq z`@Ne9YHZ6G771}iTO65qg_eZgYo*%P%c>#1?0^J~v}LAcbPQIc0`2L($-mc0oc#=87cuYf3}ol|*`UCMbAsze+zzQNjo zV|)7L#J6DPAvoQs8m97v!34BhG+m_sS&5Bc@|`eMeG(pEP`qm{6$D_xNvF=#Msj1* z?bZjQ$%qM70{Wgp^X${nnJ03(zuX*uulF%H`R~3&MPp6%!Iy3Iw#e!Pr;TTN8YtJG zRTa}|2Rrkd6`q2ihiDfmaKgo-1|9^S7zZ|z7Y3cAjnw%BI=<>bUdLk-ImLRU^60?U zp({5BG&r+eW$fch-jIZuIA;xu0O>&GO40R%j6Ac+{n9>@!^16_RIvYs!3%FA+3O*8 zO9?{a#E-N!Am3dJaX5^$VTO?M1h?L5{4*h5N-^|+Iu*9pEdX>MS%y`xUc0O z00soa`@dQK|5*1*U;L7-*;jDb8+^GW{-@b`ma^d2W{LX8wB5vDQ>aWHttwZU0#ySV zG9H=8!cfS15L7t7#Ud?{bewK=6ZsQ5v(uv%gFe>WkmtQ1(yrMGO;c$23}IySkY$^R&@5)3PZB;O0Z>hUCrZ z+i=i1Rl`LBjkm{9nYL4h)5GPME9Y(&T`}6lFEyd2#Y7sW;EY*~(y9Rci8z&L6KY1nGU0K)rI(>_BwGyw#PwpTtNAhcNZW7N_ z!cz21`lis#q+qvn9ODCm?N2`_ZN~?`Xy_)Z|3s zLG4z(!A#P$gkf&CLK-hBgwV(pbv^F~*&1e$EfkGl6daS=E3UAIRe4hvI%C;kAtT|@ zV$V&~7R7zwK-A(7wL$91dEgMkL)#@g=)`!7kti7}JBiUFsF%A92Cl{1<691Q!6Jlgsz59!`G@*5wAL2AJ7X8erHL>xpINn0wcdR5reKtmMx*uD z*f_}Ec;7_1`*ZsSz5_dn486i+ur9hO8qmvm>|es`|CZ+`M^J{LfaLjG*#XHlCKxnG zn$r|iB?rbe13+91?u=?tbTs}`Ot`#t^w^Lv>n3n#Foo(tNOTzK-aphUg(Kht@T!kxj1_Zl=|vnAMmo%}6-;KECs-a`9hXzLsBJm5yqk@71`rMPU=vvb z6J_CWRu1#7%Y6R^HZWh&Vh6wAdC1o!jQ>>zlD7RCbn%Zg^bh#)w;gy>-O3%;1kJa{ zIAQfiG3h3o%{&!sEX(Lob}?WMTUIzPj-{%YB#??@6EB`JBhAH>&Ei(7D6= zYFqQ1H8v4@kQ5Ab=!sv>@bT>}KR?=ZTH2;{eTHqn+^4rw_kGs7o9*^$*UdJD9{5aj z&-jY}y6Q}P>}(h#RBOYDJv=?#de#!?g;l7%CtOY@N??9_`KXK)e0#uBoyS6}G ze6>LuNVQEWF>?0ziEdn28!uU<7BA%V{gY?`s~nS<#^@DIp1hVJWHGB4R<`1_TfTvX zXRGFdb=I~IZqP9wIAAsHz{O+2v+xz%dZ36BqU-?)8k6XXw)Vh;!OIMWUdUg`d(B5P z4Q2b9M1Ypc3+~D&t18N6iN+_auY)^k@JJ*jCnYwhY7P6&`E7C*r$W|NH;f1;ak!G= z%RTmITK%)EV2f5A;N!E11bSv@0I%N0?6{NZK(0XPaCkxsok9Gcg%!e0zFa&hM6x+E zK;vMpDNZLsEa6jfZ~M8dRsTa(I>zKB0FGipsym6cVI5yG>a>`;wt|me8*W@SsWv$Y zWAy7hC)}rI)waiXkaQ8)=5c(f&Qiqf*?cPVu;>wv-6Mr?%2>#(CeeeETHbI0vT|~C zTvx4yb$M^1ymmuja|^*oqCL1UaxrK#n#-&1fCELv$3z}A#P5Rg z@7Xp#5*B>V_c6=$vCT*)DBO`6pnXG*NjnR7Ogi&-RN%#yx0L%?OH~`@@LYsi9!baj z;CfPSAi!!G5Vm^TJi4F9#rp_WFYWd^{bAgt^?wV6>rfISE!&*cL5R7i^sT?3(EFjU z#44C^SZd3yc}998t7U|p;AN)VRQo@xzv$g`2lhah0;p8_AYL+hRR|i?V4P{{TqcY( zb%2&TEAdHY8Z*I#>^yJhFiNSnr~|}=tFo3H$ATH7xPCtY+b#5U2dRiptNtn}DW7>C z>PKnk+>7>X_dIn;;~zlOj2OnSH(QvgK*<{}<&LW*tG`C#U5ekmI3nsXH+*?U`Q{0Z_U$C73XPqx`^v7ZINAkz7@|fT(5G5gy{-TpPd7fkY zik~&KwqtXYaqHc^ZClHTw5p*r5jFS=SBuqB?$a9TMu)tphrQmBgX0Av4VtdVv94k# zpZEK;q{&43@lSt4?&cv=Rj`#ZyA!NDuM>&HAcWj+Kjfe2#PMpg7CNsO4 z7<&Dm)+ii5ae#3`Mm(`w6r?r#EtF;R(;p}GvwBHXrwo5HaJvnZy_T!pJ_2AwT)@jE zyv|Vd4cl~n^jsa^T&!4PQPC`>#hn2e2?gAq&Fym)v-!9}Enz`! zSB{;KGafnr8~Lw0ZN%zg27%6S);-p-wPngDyB%}~c$7U^T#REzO1hmucNn?QmfK(M z5Cq|Fw*3@bMQ2l#qH4OdkZwlzh>d1fazcL%sC7 zrlC^uyq1EYHu0nmhy_uylZ$z0^%kM?F#X;=B`z^?DU(uQA*J0x5CDH@B}4=&nP2$I zss37B&_?E<1-kqUJa8eml=P!xb#TM>XvW^b-8pc#+xo*4=hF5tJ_=Yvo^QSoA9CxA zA6z7VCt&|7Q1-DNh338h+xl01&i=nIQ2xC%`HRP!mq+!zTAEeh!n9Mm0TY>E+ZqEB zq#)t|(9r2K3GWRvrEAPJ6<&t&4-oWY^!$t)yjj&VUcj8T$>3Zme97xN&c4q)-tf|0 zv+L>c29xh?4n#F2eYjIYI1-tVMy&mAfFwVhPP)xHEb ze#3^j*Y<%QAm51K9Nb-RaLOI^)_v8v_#`_An|N7ndSwya_nfDAvxP$^?D;&xY+Yf# z9K#}hZyh2?r;&VxDm&@oB1DsHQ&PNud)d2?RBk~LSY@^J4dGtQNqaM`b1aW3RK-vH zm+oOTAtcYDxk$H2W-~noCRsjS`VCmS)#i>a$f5A1x{}OfIVIXOV`Vz_3S|6b6Q$Wb&uWLa7`iG4Ekh`1vBwUyDg#1=__V`7&%xp_P1Fr zA4sQ`Tx-$8$r1SAfepHk&)WWUg|1>zlaR?Gd9 z-HQ`R&$RRSguieGx?RAAO`o*?Y-OG=)qBASTfjqZ%e>2K_r+Ci^ENgPH^ zA`(vX5uu)woTGRk#wj95^hb;Q^KU2`Vs~I*_bW_nzmPQl|0YaSY_0wW9NncduJ~2S z^YV_87%&MyBHjjtQj8)(?&cAN5)~DxplSxy>o1ci?VlJ2r^_Vj-RNmcpv6#O`2OVI z8Cvd-!eMW3?&M8_MiL@**ge|1T7S;$_PLro_5v zOZ2yx5OH7)w}N$C-Ot7c;0k{rxsA7XkO9MJ z=GnSL!Fhc$>o^6y0A@>A{o_C4!q3quE0X4lulSBKlIe60P+Oa(bd)Xv^jEwr<0U}k zE{>b;=X_fa)1rT;WYQ+uBd2C>o1AR<=;}H~NlCWwDzay-=GGc11)o=)t#8H0dNE~L zw8(`U5zK8_ZbW$sC*x_f43b9{t+Zi%#!YHR$Pg)KJs6#X4$65rTgBH}&9H zRJc49#m1561=2etiF_ZHy5Eh|vve}udPWejjdi?%jTiX+YcKc*cwDiuL>c}v%zu!W z-a&(W#Ms~c`JT{9PGl;O^?}TQ{7C7H|43<5zEUg5gyx$$(6w?&>l#b$E;o4*5%qV! zc3M8N?3i%G^Z}*8#MU>*jARh+T)XJEfp-gxDfc-Y6eaZXd)t?%%X`H|M*N9L#k~G$ z8s|8O24$17uqJ9wpx}5%SU{w{A~(2N(;knkqIxDlPY0omQ~3QfB9$!}j~{5AQ*jZ3 zfM02{Oa*NqN#Gb$3?$1);+-o(W#~FGkTHig;>Xwg^c4ER+<^6|GYdSB}%xIGTI!`VG_hP<2>@(5Td3IN|&@C~Wpd{wBQUE3Rt1 zS}$Fk5H^*)n7wJ|*28;8;P?54^E2hv2A7+G)QBsZO~yr^d+VeZ)->p$*nNW39^@Ws zW03aNU3zF8Y9pA+NKlL~dg`pqKbD2Ci?}e~on|O^*j}7sJE{+{oYY|n6+v1|a>xtW zxZ>a>StEId)mOZ$;)p8R_Mn)>OkHR=QI|!f#Lx=)X{iUV%oc8u=BOA~i#=k1+(Ss= z($GYbIqMXH6n_n|7Mpd!F^wz(+l3g*fk|Oz%tOnqPeLMiQ%Pe+sySILXtdHYV?iqP z+_bx1AZtZ}9kShAD`~FsibjfK19GiCqAkA)9hNqQ{b8fDsj)CU$YFDVY;(jGc^2tQ z-J5`{cnTEBDBiFLCX9oh8i$D01f5QSCHF%)8J)#TvlFGas?&0!w3+THo5|9{qUrRv z?>BAvYNg?NEY>}mvy1+045P}LFNRb|&d0vF7i5Me1|4srdR29SP9(Vxaa4tgg8Pf&*Xcx0)KH1U;5!FG)9- zfu>-;DSOM!AmxHy>Ew!h>wr~yy>a_58h<(Q`OkqA=|Rd0!{es=_FONyk+ayF@}2M2 zbB*Y``I@@Ms9@Z6(qbCF0=l4|LdC_*si3d+vLoN2@%3f;-d_ZS+>GRmy-Rn9y(i$8 zv}4Xqnz>X%KSlu-e7YgE-@Y$^{j-p^$F;kw4moO^>>f0-0)oV43+!T zUNrmIiCniMs8m9{9e1OX-Lw@aD)(IVCe*pS2-31UJfnG`^}vt~+ubbcW?Z@uv`t5A zlXI}|yo5TYOOfVv&O(Zy!$Ovq6@Fqa`sW&PSyMyesYsJf7WV1STUhYgDhM-2`1e)z zr3PM}&VJTMbE>M45}`xm62d#hRuv>0ASUD%!i+B^S9V~#-rsiwY`;;&`)U0WRjgA4MdJHLt_t~iCy)v`@j_Q{LUw|cHW(yl0$P&$#W9-O zA_z~WgU+M!q<3ZgavHX3-sy8)w&OtOR0*V0B(}kP+-m5cWp1-Tt}stFjQ-UPuq4Ok z!swgn5BQFkbWY9yh3U~8-TpOZ=lWBf{Yu?uCkl-^I->!awnxOSsOGNfQKsevpzQCYeX2t%gLGG(t06ixGrq2du~_&9*)>Q< z8h><#IJL<=j_l)lgy_M>YCNC-_7Sef+Q6B^VDwE&eY&n8<;;D$KblX9QmJ+?h+Z{a zT>GhA*_|RCe{_f7dIU-&rCXnu4uUELE5OsP09kCrDVV16GlGT~XWuXyKUUjlS)BC(W^{wf~|2 zSH5?CnFO}vi|;M|uj1MN{uuNBLnii|1x&SaL}&#n+gM}u1@weM-9<`}kr|O1Z#!6^F{9~| zU*D_buYlD=W1r7o2&l(mpf4|wt&MCng{`4-lynB1fc!}e8YdGPU!jvoz-kX5g1BFT zCrY(0Ik~Fj1I`j*%;dz{VCpfBoCeXCOvK>nZ@u1s)s4g~!SYmJV7L|WzunURgE=<- z8|D8`hF|TUs@e6>FTgcaFKSrHp&v+7z#*#%fu#90MT>EVq;P1(X6{=QKt7MK0Ey8e zp;|JfP&(fB$8!>$ZN@{{WxH>?w^h!cVBhnUKjH1yUChYH*p_d<+K#t4*Wa_9rbGQc zj${15?O}TsV+ZTQV=N&J+CVfCRVvLxJu||gwS+g;D_!?III>Fn(PGlWS<&dtPloD) z>9kJ=xp2|wUH6P$+;Qp4+%*bT$yqM?$W^?hgrUbByfrIx!uA^seMHSWsc86@!=?w2 z*6AT3^ptNkacitFdsDdnYPvr0R^i!_zb*E+^;&GYka`?^t2|dvLY6B|j$$R&bE!EcS1xvK#KSSuIVx%MR#IyiB|!9i~X0{4iV{gy@)nKFo zd~Iae2}m&e4;xKqsVWV7p5lv3I}OFsN$*;6z`#=CM`+88WSNRKL02c{ZV9W2Drni@ z&A2xERBWayG;Z2`-7*RNSj*0lLG>D#d^O)4=jhUjH1gBRs%TQDnD?^$2NS!@6Q^;a zNuT~0gorZ=Lk2acLJKYZ^xrDJFlJbGefgo6^xy$XIdYMxvsderA*^NN-$;BFuL3t? zb1$c}Se;VA9!dx{s*1g&cCL(zFhkJc<(W?tlxul0qN+@Dwf6YuY7!O#P0+8~wBtym z=q1nwDnB5Cz!b+pVocg3F9hplyy4&d441BhSQeuluS;Iz+@Zu6}V$&7aB7(IElhHJ`D zYB=V`$oEHc8ffNcTVr(2P6;lkFxS)$6dpluh|32o4wY~9egH?!KE?~_u+x0kaS#R8 zp(l7rHBCC-(Qo|XhZ%hr3Z1%5=h;q~LI9FNDi~VNoC6#Vmv0mdmu~>frATvK;rC3W zL%GIjyeZZ3PwhHl%`35aGn!f7v2P=U%)>#oN+N`YgsKhpr(i&*4)(KK0L_w-1NWg$TRd{j9eBgQQ42R&O6usI3ejZ zQdb*5J$QjIKmvOOfRp`70mb{8g6OaB+Vq2c&50pwFai+fnC3KwgO}();Acwq3c?W? z*t-6m>PiT6H(RZ}j(>>v+QH}(k);}8zbkPYg5vi>?%l!Rg)GJDI^^WG$O{({Y5}Uz za-L$O(nTx$*!)FA>E$>>Y!QMdgV^ckeSDccU3HG1 z7&9>#4v6%GQR1b%lA!2*Ju&$|F-;i*8F|M1fXKqUGn0}2pt;wPV-kmy9IVIoMxt;) zNt`lf5{Z{ko@;j{4C7SFD(*S&BxE{7NoF}4+C9igOocQI7H$o8ufB#NvJ(FJ_P!n0 z44hQL|GnYyqvZDrA!A9W=FYaZk#;p{?NRWrX$Lh0IPHW1zx*?tvHK=&)`` zm|@bEc}+x_E_Co!3s ztXRPu?P+!?pgMc)B*&s%nh!If^YmsxM5K%uLJM28lt|4f7MB3u4e@!}4h1nBc%Vk1 zdnuIME3sVLQ{9_(5}V4u_bL6g+eQeoT6=#%EtoH;#r0ncXn99FOA{mKuZ#Vcw$j4H z>2DkFzX>k0;-%&K1yF;g!9Yd4`Q-=lFM2_-QC#+k6(XtgNid&pVE}(n&>f-61iWQILXFDjMh~2Xf8=TcUr#<+El&! z#l0qxLrwdVOBwJp$hOf+DVW&E(M3l6@x{#Cdwy9cI55hx>akaB;z{FV6|YL z=7e-v=4FF45oHNH8u>OlC>ob4L@%uLu#5k3DU^$XD1_(NTA-ny)MC^V6b4>()k?VY zo$0wQmGpD#A|CX1Q!$*n%GM3GY8PH)!G;9`KBM1=61Z>Vub?U>yM%`*pZS|8zg zy%QEAx#KUILj z22LhlQ(#PNoh+QcCUgJy8lfU39XsSNFwN|39T6eAwnrY0Myuy4{Rj{Ul`<3}u@str z{sx|Dx@zN^GSsu@w*yE?f6@1T634ox!I6OhM-fi-I-Y7fp5k?TIB3XBV z=;uSqo_nXjMBt;!*%j1!so#H@yH&}ZGNHdoWVY={VBQVuef+YH-Iu7bf!R(;ylFr8 zG_tw~%cHIORYlYPBanGPg&%S{Mb`n&B%lv7kh^`zx6F%bD#!%J%z82|>QJIhnDa^_ zSG%P8T?3dVI;ONC4?7A|{TTZF{ZAP#Xw+e->2VG`J&L&5TcK^Qp@2k7^Q))ubp8vy zK=5QXHaAhKC26`}#~F)!^P_n8k>fLMzSQGJ8GEc|tnIN@6G!M*#Pz7HD?Dvct z7T3TGt3J#~?wBu!&0vZv#q6U=Vh92I3?59zRTIp_s+X5U7^-7?WFCovthT#shG}Zb z_dk^HX$>Dh=9113NGuNkBDghHc>1 zewRVq73PXDpdaKHVr-0YAifAlxKJ@Zxq2QYYPiMu*IG|AxKh;;2?%K7ORxGrGkE`4 ztp8;2G`;k-O_KP{blr}Qnq`IOU7>A+30Ptz=h3m(9@3J5gUE`&HHADL$l4@JvL*uC z5{dXwam=ioU;`{g= zd%SwCy^no-w_l5WZb#;)k!KBkiA1^{`0rj4c(#&| zqqdeMQ*J@BVADRRf6FGvm^&*QQ5l)W{76`>P~v=Nc{*1f{l&Dzp*}>obf{2VmpAX5 zjd&2oHMt{+opR0+K@QO-)E$#BjG9-vaLSa8ePF@Ftb=cmmWFh&pGTU5c#wuYJx3{Y z9d@vat#-N~a1Hh<63HWu?_@H}<1v8&P7bvVc2^plJ=LAgRDHSE(incus#`jb zZ9C&0Hx%KbIV|mLd6W=zf*O@_=FHXE8^x7HNnP=x9F=nF+{~ao(dLs4BO$ zYXJc%>F#bMMY_AYrMtT&rMtVNySuwPq)U*H?vj6d^<0nWJ>MDsJH{Rx#@K7lRqu*t zJ!?MRN>1;Ki=k!Hg;j{dXIRVDYffj2Pa5eL2KRm3l6o;eUD&}p3r36~wJ?L-P~C8< zZA!2n!1YpNbz{~MAnDA$Oe;Fs#!Dx3FrO$$<|45)=iyZP)Oq)Lw>h@X*o_mB4jpsT znzDh@V4+r@L1K9+K8R$)yg-j}rHXT6(U4?Bo}j>*ZR*QKuDN;0qT*6mZkB5?FF~%2 zq2pmIR6=e#>MFJrba!fx?Qpg^@uIB3;G`29QJQ;54OAjYlelKL{5(R9d4Pjrax{kt zL@lFZUU4>qsi_;?6cUrI3!`z~!Yx~dQW^RYu#df>BY`pUu&JBKEYJvu!Q^0c6G&hR zGaw>RXRoA5-rFY0oM(KLM{k*=1*m%cAUBf&3PT# zUX!H@8J}h-PM|vTEnytJd1u2aVX1R7XCQl+F)+ zQcK^d>{ia7Sy)}vCLTlP4OocTVboO{(UWhTif)}AC7Vt-!>?s|hjKEb(lSXA*nHY4 zLgJBbrp;R8;#z@f3MoMTRf7e%BeU4{3!=BiN7`M?O9$1&^F1w9#Z*G@~KC#y- z&l!W1Ki=%j8swC(f4WbM%~_9MAx*GNGrzh&beE4j-`itm!9ubfR z6F=yN{4SGRLqMT&N?Ib=NH=>I!?OcX{zz@gBHPO{scs#`yr6nD(I(GW+&>M4&C5XR5sFo}VsJAc%i+EQGtuz~?ZMsAq)q@av+mD<|EwKFMOSPHn%A`PW z!nRU4EHIPNGj>ez?N`<)i(enI;7p2czri6FQ1HbB# zveI{)6bMkEK!W&KWU9e5CR)(%M4yxUSY#(B80a}!9!gzYlx-vgqPcwa$v)PQOB%@Nj{h$!wb zAdteWUZ7GJ3m|W280I!CMTnDVjgbmW821QZgxZTd(3{;Lt!f?T-3aZHD>IV+yU;Zrac}MG_*E$hDv`j=5HzzfAk6TVkui6KVLjp?8{v5 zA@7Ea2sfwR@xgshNUAY(_)%?RWrLGR;4qY>7T9Ws<96a?ig=Qb4X=?KY81XKpwcF} z(B10Z9E-VycW7?2F}2QRDBW=S9KHIO#=!{9Nu{!#Y&jPGnK&6_0Lqwi>S1m?`ct*uvpF0Fzm?iHR72a^Bf+Argts+Xtt}Z8 zCQ6BPNN#gl3aF#^^)ofn)z^*nH}F2Vv5-cpmc5&S^0D(X3bFn3raG4F3{$(~AITXK z3o!z69TchaHOr6rs`>(bd&AN1-w+aRhhQ=?E}QldV_ZeGxT&M`HCo0;DIeBZ=Mv*S zypx3-#oi=ot7a^wX#5zj`sV$dYi_?#gKrFQ?hO~rGvVQ}Sm<_c`{6almd0)67Nu*n)bt(3k%z&M z*kxingw55S-ZpU>#Yu{wn)XCwiB)GHMd$6UrT3IUhF*4T5=}D;$+B$$87HSbGkr08 z7K!wxm1oaLTczbu}p0z%`zeL^vGyj0? zz-muf#N2pUiAdCBD_-B;K1h@U|O= z@;#@Hxcl-hk4{{>BA!8yt1O#BQYVmpppz*<8iZCu)^I`v&-vM!n`OFx6 z5Xp-ZwNzYkU?=;@zMDktFF~ovz?e$nc?D3W(EFhZrlRtNGxucEc5P92-abVxYxGu6m*NU7$ zqUvKvSYMK}S)g)~zIQBq7GI~f14s0w>)|3;**4~qtWer~S&q><01%H-A5(hId{7&C zuo7|t+m3YhsIy7go%yR3IY}Aq1&-&dq4r*8(XE3Ij14W95T{|%pi{Ki%;IvYf(4Z= zuRFUKYicZfb2BNg-n$brrtadk5m{>IT26$Jc({M$;_t)# z-eF(66=X_*&u)V!323k!x7*gw$U+Ve3oXkTuO9398FEKwd7Ik|TCjsDz=GT74C-xK6!{eR%zU5J8F6gVc( z?k`qaz9=qm^97xh5pns|AJTK2nT>;F#pDi)aC5+DRpl$30^(krMB%fl^fpLzSXl)C z)XkCCwR+X_d71mqClx((^XZ9bOq>1VIw;%%HK3Bt-Qrx5a?{1lp=-DOf!SN=MK&oS&eob%D?mWh5In&d2j@r zjdXS3NR|e76pt~p*vjOBaqPQ}yxzQ>B|)x9zSp#*BrVFhcirLz|#%X~!b{hCFkJJnuC?Mwo!y}ODlSP|pj8*X3lZeeTyAjIxf=c#Nyl|8zA7C19(Ph4EyyYBR{b91e$?I?Vuc}QuKYFmrnsiA7d&X{V4&=ODr z2_e?!i+FhU#sjM7jVH=y&|93zGl?Ydde)Gcx`+iXX|_?Xcd)!=&zK@XWZw0^M!Gg; z7mMxb^6bUoz7IY}*sk^bkQALg8UwoWHWwFvi|?Mj1z7k34^L`bD#I&2?)czbuG)Z8 z`4T!?I8kIG#d~7n%ut2H~Hy0_D(+-Ha^~`J!%`BAmkyRxhbj0OI2iw6YP`+k36uybqquaNA* zEiErsA=Qh!w8>C**3Q6GC$Ywr&f9u+xF3$5Rl-iT*e7m|QKp+GBTRcn)#dmF6Q{V`dINqntM zf(|u2C{@Ep_99NTTu$OC)B*V`O9EXX|IMB{W5@?|tB04=AKKav9VdjFL&@601=m2T z4?I8*RwG1&Dy=v`SspT2Svjsz>Mz$?G&*WfTNex07W`Wf+{uM z58c&(3L0pBK{GS|6TCcSnICM`KJT>=BD7(Usr_ zs=$zJ%OfcaGw2mseCQA;(Sr)suKwg=Uv+qrq?@SF_Zru_%y>re(mf7Mw$4oZt`5DI zbaOdx5PAT)PVhK|vDlKCBJL_d39Ax1Zi&KiaH%Q>2P68cSkpj6%UNe#v%jU=BC@Oo zV&|zM){2>Gb`m(DkPeuLlkUVtjD2gzs!}mby6d~4ep*Hqm!4Idsr4)ii|aJ%Jux{o zXo$lZeH-j(X!p_pJb86(G^2r%e8ycl7&VQ44V@m;iH^9tBflF%^@_tFt{J_rgIW!0 z<|ijvk@D*L&$<@i!&uVPp;dY26Qj!rx<1Op(HdbM)+*H;&Q~(|vAG%ON2=&W#Fm+= zob$?6w3nlac@VsXx=P)#aUt}V7(km-SnAh-XGS*&oAH63>YIP(ceCjTzPxs=p`Wnx zW}<7f2<~&=ai&_?qrYEZ?M7SfB7D3BZQ0D>;Wf@HTf;@xPlVEfUabkn{g=2g90Ibi zNb`nzyMzav#*m@tsRuk0p|6C$L=|SFuRI8k59aM?k7ZPR?vFID-wI=weC9<|5t0^- z2AK)PDEf-{q+&#r=WVB`Z)P<*q>3bH2z&|*I;;_>fY2dZRI=Y!bcjUlu{@A=muFPf z>Wl5_FJdNHqL8A-Hgy8tzBHXBnz;^&X_cD!1Z^8(5Gq`#np|Ad@2qld)UQU2i_VpU z>8jNPPQMhQmtbNmTaRRx9MemSqi4sW%)&zox??9v0Sz57XN)mMv;{lf4vGQANRXcE zk>Q1I)b_;5F!TPDEDF%+Qvmk#f7R)~_xJB+^dIgCatD&%+;XSNG~#NCx5SVnIw%g} zDv?eQ`E^1ABRwI&d>;KAsKsiVMhx}2X<0b?F916wEdBoS~OXvHf;vz5|*@<*42dy zpE|d`8UfO_(Pe6!Hw0nP1x9la=;tu=<#K+VN@<4RO!5Ai5>2y7xQrzR?U<$JGa7w` zHzg=n7+F1-IKB?jZ$e3d=5w)ItU7ClxXR8@F3`#2ZXpy1+cqhkx}W*Yp-wt;rWd9N zY)m!NDrlpiL85lhL7%!TzwF|*w@zED*&v<)gc&uzz2jMaw;PZdej%TL2#2ktz0$H8xs#=j&)Q#qFgQ$wQbk=wjkL;E}6)FgmXx?3McyF;EG1a!&Iz^0tyB$Cv{wV_p%$l25b9a+|tJKPCVGknn3kbGF|()=TgtSUX5d{F(jmT(e6Tqx6VvJ3Nfp6(+R3JE|{9q zxzb3&SVf}(yL;;5tm>^xa}vubLGF+|!_qnb0r!}EW^w_@I_TCIW{g=}M%S@4hq{st zsC`8Ov%-)KFD%nwk`!iEh+>1N^ak?cT6UoRWHDH=^8}sn&7koHcr}iO;{g!IFfQ)o z0AeL6HOiC;dS-xz-_hHoE|NM{V;9p`gL{{0Nwp#^(~P5g_AnYZLGjMEIjQR>2>>O-$*y^!cdyX0q&iR@|( z(dPWnmEn2=eH5j0fM5XcZ1E8ILe39Vji09%2q%zi@J)9fJttp^ML!IB`X&@u|20Cm zzT5jU=d;idG8(#+LVVs{eYlQjQi{y(KC$d}Qw@D&=BoGZ3U!ouY1(T7vEitBt}E4{ zujQVnZ{A-MM>rzyqoFL{WD3iLEgCCG+@uHHOTlqm1!&izucq0@Vhbi!WrKUYeUrC= z0GpWvj$fd1Pg6T*g65s1W?aBHOO;>Pj$alxNPkk7g<}3WdX0wTw2=XhiQ@x`k|SDY zsE*|ERVKH?9Knk0gkFPj4dnfK6jvBaq|r4tTo~gd6za~0ZRqPV)Ks&u~$B}cicV3iTSDX-zPWI!zjInA| zdI9bWPVBo};PEcd#_k=s1{XhRt@ehsH-THKPKcacGSa;Jq}8;ouaUQ%lJRTqILmR5 zsH~$-b8+p3b>pJWDU{N63DQw&^*(5UH)???rWO$fVYk4>D>f`nO}1Y3A+BLU5X%?* zuixOLS`!@SCI=9EcL9m$ZcgOwkgw15;tcM_Qj`-9HI(lQXtNH5+ zH#)T$xfw9o;{hgns^3S#-`o$s&-LGD`A|8v|Hx?6)=?i2tmX-nd1@Xe((xzu^`2{75P-RDWru9-&kyxv}JIb%8Y`gkYnZ3~(1P+Pd zI&5aG#FJY&beXVn>RX`XyH8EIQvlhe^LA(*(xCBOym!?A6bFG;ac1+5`9xW(yW`ijM>1!c zJFZFJw{@Y=G@+%aA#2Xap{*uQV{Bz9hapXy@G2#qA4d|7KZV1~E-8frwYgn2X=a}? zY{JB9NRBp!D?BPJx)^5QtC*CHe?z8@$pj{7LE*BE$$divHd<5rp10m4t*?8a^yyrkG;-*`ns<1bNT-9 zqhWrB0hBACEoynOew0ELD=fEov35enS{go(j{~hmof@W$E$-rz$phm)SzZG)la8K} z@X!R3t|lxc@#M0CF%I0hPA_ttLi%U%vozuFzI-Sfr&z@&BNSvItOkVFE!CO+jN4Tc zQG{+ojogO+&T~bVsJ3zsKZ+|@6ON4+7Tq1!PmXkb2YwR%-utpZ!#aV{+oVALL;7`J z0WS_B_DuZ3OdmPUNzuMt)Z<3fMGVzCcph8Srnb#^1Xd3T9kQyEAiS|sG|`#RPUxDw zBjt7k2@7GXG%n`pz%rwO8@in#U#~0~CFc2Bls8Cz1+3n^ZhY^}%h37S4i?YBgmEV5Z+~asPG1>(B5s_VG6!!SBu8P_dq*1>Uq+_=SjxND;j?O z^IA^jZl!~8^L7~1X0l)o3nfYTX~#(dk&%^hpA}=F55-jQqbGhs$hP9j|L1~t3 zScji3)S6@JOl_2!!dbAC4-IRP+?Exfc&IV-Bd*~4X;Z1KY?e87Y&cX&pZFRxE7?k+ zcd9e$ce#sT1nM5WxdixVC|6y9Pk=hQHA~cNR0}MBq~AKpz8gQ2<>5mhhcT?k*G4mB zT4n#&+oo1CCA$pS}OtK?SXhjRU_RL2gVov@lpopGr`RcOsQjvx`kfNxPk?#nLJ5` z&lipBjfp*=jrDS*^+7fwn)mUPu9H>shjMHjb9%Hi^gNcrp)0BQA%n=^vg8ftNDzd) zu8h3V971ms;j}Bs-5qen4K?8>&+cA$oSO2~#28LV&qGI11=9uPkP9*Cy#h`pEr2H& z6+^p9RO*k<&*!`YjfB-`CHthhsBU_O`lbUS!Y%*spz_s9yG-9pDP50&s;R|9#~Do7>bA&$rMh4Y4j- zBtI#Gy2cx(wiDHE#fiO8)P1ymX(UKU>J>wCXmoQ571n$6x7Q%|GCFa*WpIJfmy~g@z70@1L%Sp;hV3nd3^!cM0UEWF+5wMi(MpMnkke;Z{F5wP` zTkj{n%9Js)H@xF8=v&Gt-gx!&Jg^vWm_o~9^% zj>j_tG`P$hUl~N~V8O(&zy;i_#-yWBu@NjMFBZn9vLKe)r?MmlduQKXW&S z5+f1J>K>r_-Jt%ZrW>!mfu)VUps|guot(YSk0$y)8TTlf%K;*FytAk*uUBEr_7hbz z%jUs*<(u)|mkd&78X*uP2j1&wyzIT&y3k4tPm1)r}c<^BjF>X@z%V3iPfRC(Bt{l zx1*8ai?AF7ynTxZX8o)ry6qvDkKg-h7YCCGztHC6m+7YV7BC(_sQc-ra#}%v>CTp37}nw&CH8S~Cn{wTdqrx@ycY@Q!GLOBI;GDCVa%Od3x4_xaf-K{67t zW@5~R4HiQo%ojAP-5q7h3N#w=T(=InKBSRLUQOIn8?DBLtL^4}gxIpkYIHA$NKm5@ zWpti(eYlDeT`8WDY`jSuJs}xMcJ?#kxJ?XTtbdY8@bz0iZ^-a`dMXzj z;|EU=KwQSPcLkhO&1xJw{t=iqTY);pcM#asv>xYBl2?Ol8n6KMh3@hdCHTE7S&^VZ zlTblM2BG+Ub=)iG-q4xq3)Q{c(*)EpcQ6V)g%N`{iy~7aG0d)P60XpdDII!T(6#&# zX|ByVslN?TYay|8OPOTUU4fs(r>QxmSG~Z5^n=qz-G3@3%SK#1E`n zdr|1x>0gvnapEtMmB8a{e!?6LD5Rc8 z0sPltJo*`1;x~`xd%*IA<@aG+&e_&Z-~8VgGE$?4M7y|={Kh^Onb*|Ln#>3+G4Ueu zcfUuCKtYv#CB6GD31=#j2$5upcSTgm8w#*kK_E4TE8yu?Nntn}dmKq=X!dAs1!@N} zi^qcvB``zERPh}FHbc%3!1EYnCmDm#Teywjt{v(V&R8(SSrK1`4{~L-iIF|B4QAz| zP-c|uE>0=;Y?n!gTC4`eW;0TK$pEg6H_?K)B!rI+rg7LfjVToD(7-H55QGTKgsHCs zY3V*tFO)GcdlzmeDBwh{JEGS70k7~veQ6T&_!E} z0Y9jG#xnunY@rOSZs|THB(F^%QS(xxcaH5279B~!LtMwi1dhSP~z z7I1Iw`_z9X03(RTf);5#XC9OBJ$^)AWn#XWde z@ctgdmIkjeRVy?{n7rFP-Ae+Ik4BecJ*4ZtytkuxieBeUC33u+3F^6ezNbt>4eXt& zM26#3U*HD|JVF7EEF@41H1Q1nBUpgzjzOP@=jVdYi`^t6Q$(Bzg-{lr!(ohUN&9PX zm~Wmj@IH7{LR{iCN|#=}9`{*I8QL}C5m4?wqk73|4s|Dhm0_02_fb;-gYwStO<$Mo zSSZAp5|@4FsEzhqQcg6UvMzj+;qB>c9DV}R*D8QyJ1F1KXP~8xe(j+tZigfA5X&!U zL?SBXxmmi=S8(%PsJdSoE&CA>a@d{ z5w~BJ!?@EOYF3z%(zP)s&KM-fK&nhez~;Sw^$|l(#kOY#opYX&Q-z(En%p(z)6v@N zMRPr;JTIoH?I5tjO80h@ockx+eDHUyb!>o@#vsHW4W7Suss9{g{f~vlz9gay+*e68 z<&QMdaBxQfvD~lBpa`_!sTE4!dm|&<*TvM(#AsA%bSnX*1!2V*^ND&rNH~LFwNt9p zGL&7sBCbCVrzEnhCMKpPavNp?-h)F|3cDUK3 zx8Fs5ipkVlyRoeCrVXXm=|exwY}??P2pT2@9~3Ipp+#BIwwOMLP*iPpq>N2bP{D~i z&(8WGeRZFvS|LkLqBCVn(_2ry2m^Z!CPWtEbfp24?85M`RaRt@mfPK@A=5E}o#T2t z#$t3O(_uO2jh@f>in`d8A}0xomD~p;wn_*-BXLmXQ3EWW6|y28_G4n@1K@Q!2F@Fz z$2&vlwHzz}agsv3qVogn3a=7gfvl=X!k1R$rX*!rP^{S0q1;62ptVY?%^*bE>bgnM%}mk7%0Z{KN#!pU zDarH@ScT+|#)u1!e17-4MAY1sM^TL(_WYgPHaDmi z@Px5Ga13jU`fIlj&dZWb=nGAOqF!r;^}rqDKufsBN4(%ABkFzIGJR3Um7sP}#nE

8hQE~u^&T}zB=}8%^H1=o39D|$iIm1TZ3ne0sQ4z=$${@ zT>UbBvuOuhVD@ojrSap(*w-)n<0b~*X87c+8&cM?0e#NWb=;^A#d$Qr*E=?F_q?N%Ryt!f~!T1Qjo=IWqJhWaRDOA`>0I#V7>=V{7MN)9q| zzOhFzV4mg3PT&&QImb85 zfalwv5(4r()FP6CfD7xtCi87_T;~M*KmqVU`u58oPqx>$t>k}`N$^OD2nxu_(?|$D zMfjEgFvtDp0nBqh9=K-@Jc)q6zscqQQwqR_>2E1oex&$bga4QiAl~`6ggd_`{1GkT zHvl7VJ%bN`pUwb2gg=sh`>OWB1gyONChh+hz+WMb{t_I2T9k0L^Dq=Z>8$`I|4$SA z0Il|V{67GnuIB(NJ11uzdpje53aqj2Pl@BFjGwu%)@axTU43z15$g7lj2V zKmmq0X+R@?JAeM`srCZ&**`%8)Njq~Z2>pA1dYw~d31I4ZEYpAEwl~)ijD9z@497P zjaq=b!vRQs&HLMzeafJpIwK>sD?+MjcLy}TKC z48Tjp0~`YUf|-Q>zcrW^KxO|A8UEgne_(&h^q(u@X{gn|psT&=0b~9jaDPsfKMxX5gVOwji&p&aeD`C_{NtSW_xydk>iION z%uhffrT-mb<|)dzRDjq2KhL+=EZ?7RQxBo?FQxpZzVbBj(?~6UC9n39{XOwtjs$;O zUq3OXK81f8(&8t4fZA_)`y1?!ogm%sz42SUJq;f56V*=rU!eX&D2b=}f2z~}lgU=| zUoidMl?YHetG}!EKc#vqlm3%RQ|F(k{)cG#Q~0NP-#_6mbpHwdM@#&Z`u9_+r`n-E zsgTV61=aUT`@gE|sq*4a5;n_!LGsT!j89ASRH*JJnX}D5k^TL6`6=d8nWUeXQcnMb z`J+L;Lx2D0Z>M!nS)S_g{A3Y#`Hkg2XuqrTJjHyfI`9*-(d&22f3HFCl;`P9_@6vs zKELt&K6w1Ad+|>>pI&JG$;syTe{=qMxO(b#`xA3F{{O}#`rQflX{MjLIQ}G9N%|KA ze;=j(T!N<#Wp#72PtU}EB2VP}hWvYH z`VRf)6Y{5pczP81ld32GpQ!$ix%BDr+D};F!heGOF<|_|VcXLJJT=1qWC|($jp^x< z|8I5oe-!AcVfZJFX8CV4e}nx|pzmM*F!nvQ68^-mto#@F|J!Exw7#C2K7JAj*8X>4 c_`eJx(qi9shu`*Bw9mQ#s%Zm&B+s7xKi|i_5dZ)H 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 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 +cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" -cd "$SAVED" >&- +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 () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# 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 + ;; +esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -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 "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# 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" "$@" 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/153] 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 94630e0b2b282ebe8f6a109a12031851c6447e53 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Sun, 21 Nov 2021 13:04:32 +0100 Subject: [PATCH 124/153] 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 125/153] 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 19dc5075993adc55921df66b0bc133a46f875ef3 Mon Sep 17 00:00:00 2001 From: Johann Bernhardt Date: Tue, 30 Nov 2021 10:01:34 +0100 Subject: [PATCH 126/153] 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 | 235 +++++++++--------- 5 files changed, 182 insertions(+), 165 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 { } } +task relocateShadowJar(type: ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" +} + 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) + 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,87 +334,105 @@ runServer { args(arguments) } +tasks.withType(JavaExec).configureEach { + javaLauncher.set( + javaToolchains.launcherFor { + languageVersion = projectJavaVersion + } + ) +} + processResources -{ - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version + { + // 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 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 + // 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 && (usesMixins.toBoolean() || coreModClass)) { + manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' + 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() == false + ] + } + return manifestAttributes } task sourcesJar(type: Jar) { from (sourceSets.main.allJava) from (file("$projectDir/LICENSE")) getArchiveClassifier().set('sources') +} - def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false) { - manifestAttributes += ["FMLCorePluginContainsFMLMod": true] - } +task shadowDevJar(type: ShadowJar) { + from sourceSets.main.output + getArchiveClassifier().set("dev") - 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()) } + + minimize() // This will only allow shading for actually used classes + configurations = [project.configurations.shadowImplementation] +} + +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") - 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()) { + 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 127/153] 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 128/153] 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 2e1fc1ece0ef93cf6e3e00a122946e349f8e4e45 Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 21 Dec 2021 08:23:33 -0600 Subject: [PATCH 129/153] update buildscript --- build.gradle | 169 ++++++++++++++++++++++++++++++++++++--------------- gradlew | 0 2 files changed, 120 insertions(+), 49 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 +{ + // 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 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 - } + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } - if(usesMixins.toBoolean()) { - from refMap - } + if(usesMixins.toBoolean()) { + from refMap + } - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } - } + // 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 0d678abc10672f77ce36743a7d9165dc7ccabcb2 Mon Sep 17 00:00:00 2001 From: bombcar Date: Wed, 22 Dec 2021 07:46:39 -0600 Subject: [PATCH 130/153] 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 cfd00f33c8daabfaebebac4f78c717a693eec48d Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Mon, 17 Jan 2022 19:20:12 -0800 Subject: [PATCH 131/153] 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 5423d96eb787fee3b139b364d46b06bde0c49647 Mon Sep 17 00:00:00 2001 From: bombcar Date: Tue, 1 Feb 2022 13:47:00 -0600 Subject: [PATCH 132/153] 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 1908388ce750998b87b2b9c959bf34724aa5eae3 Mon Sep 17 00:00:00 2001 From: MuXiu1997 Date: Sat, 16 Apr 2022 14:39:07 +0800 Subject: [PATCH 133/153] 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 class ModularASMTransformer } 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 fcd42c8496018f1f0aa62225dd3f2a99614a079f Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sat, 16 Jul 2022 10:47:29 -0700 Subject: [PATCH 134/153] [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: [ '*' ] + +permissions: + contents: write 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 - - - name: Publish to Maven - run: ./gradlew publish - env: - MAVEN_USER: ${{ secrets.MAVEN_USER }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + 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 135/153] 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 @@ public abstract class WorldExtension 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 8d95baccb517470e728845547094f2c91acfdb75 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Thu, 5 Jan 2023 11:49:10 +0000 Subject: [PATCH 136/153] 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,51 +1,89 @@ -//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' @@ -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!") + } + 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) } - 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) - } - - 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 137/153] 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 | 58 +- .../codechicken/lib/asm/InsnListSection.java | 93 +-- .../lib/asm/LocalVariablesSorterVisitor.java | 52 +- .../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 | 127 ++-- .../lib/inventory/ContainerSynchronised.java | 13 +- .../lib/inventory/IContainerSyncVar.java | 9 +- .../lib/inventory/IntegerSync.java | 21 +- .../lib/inventory/InventoryCopy.java | 80 +- .../lib/inventory/InventoryNBT.java | 74 +- .../lib/inventory/InventoryRange.java | 52 +- .../lib/inventory/InventorySimple.java | 95 +-- .../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 | 711 ++++++++---------- .../lib/render/CCModelLibrary.java | 94 +-- .../lib/render/CCRenderPipeline.java | 63 +- .../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 | 440 +++++------ .../codechicken/lib/render/RenderUtils.java | 273 ++++--- .../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 | 64 +- .../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 | 213 +++--- .../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 | 223 +++--- 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 | 187 ++--- 111 files changed, 3418 insertions(+), 4352 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 class 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 class ASMBlock 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 class ASMBlock 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 class ASMBlock 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 class ASMBlock * @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 class ASMBlock 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 class ASMBlock 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 class ASMBlock 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 class ASMBlock 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 @@ 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; +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.ASMifier; 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 class ASMHelper 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 class ASMHelper 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 class ASMHelper 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 class ASMHelper 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 class ASMHelper } 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 @@ import net.minecraft.launchwrapper.Launch; /** * 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 class ASMReader 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 @@ public class ASMReader 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 @@ public class ASMReader 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 @@ public class ASMReader } } - 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 @@ package codechicken.lib.asm; 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 class ClassHeirachyManager implements IClassTransformer } public void flatten() { - if (flattened) - return; + if (flattened) return; for (String s : new ArrayList(parents)) { SuperCache c = declareClass(s); @@ -55,7 +51,9 @@ public class ClassHeirachyManager implements IClassTransformer 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 class ClassHeirachyManager implements IClassTransformer 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 @@ public class ClassHeirachyManager implements IClassTransformer 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 @@ public class ClassHeirachyManager implements IClassTransformer 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 @@ public class ClassHeirachyManager implements IClassTransformer 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.MethodVisitor; 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 class ImportantInsnVisitor extends ClassVisitor @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 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 -{ +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import java.util.*; +import org.objectweb.asm.tree.*; + +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 class InsnComparator } 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 class InsnComparator } 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 class InsnComparator 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 class InsnComparator } 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 class InsnComparator }); 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 class InsnComparator 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 class InsnComparator 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 class InsnComparator 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.Iterator; 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 class InsnListSection implements Iterable } 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 class InsnListSection implements Iterable } 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 class InsnListSection implements Iterable 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 class InsnListSection implements Iterable } 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 class InsnListSection implements Iterable * @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 class InsnListSection implements Iterable 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 class InsnListSection implements Iterable 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 class InsnListSection implements Iterable 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 class InsnListSection implements Iterable 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 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; - } + public LocalVariablesSorterVisitor(Set methods, ClassVisitor cv) { + super(Opcodes.ASM4, cv); + this.methods = methods; } - \ No newline at end of file + 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; + } +} 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 class ModularASMTransformer 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 class ModularASMTransformer } 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 class ModularASMTransformer @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 class ModularASMTransformer } 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 class ModularASMTransformer @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 class ModularASMTransformer @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 class ModularASMTransformer @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 class ModularASMTransformer 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.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; @@ -15,18 +22,8 @@ import org.objectweb.asm.MethodVisitor; 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 class ObfMapping 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 class ObfMapping } } - 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping 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 class ObfMapping } 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 class ObfMapping @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 class ObfMapping @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 class ObfMapping } 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 class ObfMapping } 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.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; +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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable } @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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 abstract class Colour implements Copyable 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 class ColourRGBA extends 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 @@ 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 java.awt.image.BufferedImage; - -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 @@ package codechicken.lib.config; 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 @@ public class ConfigFile extends ConfigTagParent 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 @@ public class ConfigFile extends ConfigTagParent 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 class ConfigFile extends ConfigTagParent } 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 @@ package codechicken.lib.config; 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 class ConfigTag extends ConfigTagParent 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 class ConfigTag extends ConfigTagParent 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 class ConfigTag extends ConfigTagParent 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 class ConfigTag extends ConfigTagParent 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 class ConfigTag extends ConfigTagParent 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 class ConfigTag extends ConfigTagParent 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.io.PrintWriter; 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 abstract class ConfigTagParent } 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 abstract class ConfigTagParent 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 abstract class ConfigTagParent 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 abstract class ConfigTagParent 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 abstract class ConfigTagParent 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 abstract class ConfigTagParent 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 abstract class ConfigTagParent 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 @@ package codechicken.lib.config; 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.nio.charset.Charset; 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.item.ItemStack; 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 @@ package codechicken.lib.data; 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.item.ItemStack; 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 @@ package codechicken.lib.data; 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 @@ 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; @@ -10,11 +12,7 @@ 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 -{ +public class MCDataOutputWrapper implements MCDataOutput { /** * Mimics ByteBufUtils * Write an integer using variable length encoding. @@ -41,11 +39,9 @@ public class MCDataOutputWrapper implements MCDataOutput 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 class MCDataOutputWrapper implements MCDataOutput */ 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 class MCDataOutputWrapper implements MCDataOutput 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 codechicken.lib.render.TextureUtils; 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 @@ public class Canvas9Seg 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 @@ public class Canvas9Seg 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 @@ public class Canvas9Seg 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 class Canvas9Seg 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 @@ 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; 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 class GuiDraw } 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 class GuiDraw * 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 class GuiDraw 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 class GuiDraw } 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 class GuiDraw 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(font.getStringWidth(s), list.get(i).endsWith(TOOLTIP_LINESPACE) && i + 1 < list.size() ? 12 : 10); + Dimension d = line != null + ? line.getSize() + : 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; } if (x < 8) x = 8; else if (x > 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 @@ public class GuiDraw 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 class GuiDraw 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 @@ import org.apache.logging.log4j.LogManager; * 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; + 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); + 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 abstract class ContainerExtended extends Container implements ICrafting 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 abstract class ContainerExtended extends Container implements 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 abstract class ContainerExtended extends Container implements ICrafting 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 abstract class ContainerExtended extends Container implements ICrafting 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 abstract class ContainerExtended extends Container implements ICrafting 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 abstract class ContainerExtended extends Container implements ICrafting } } - if (stack.stackSize > 0)//normal transfer :) + if (stack.stackSize > 0) // normal transfer :) { slotIndex = reverse ? endIndex - 1 : startIndex; @@ -253,8 +228,7 @@ public abstract class ContainerExtended extends Container implements ICrafting 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 abstract class ContainerExtended extends Container implements ICrafting } public void sendContainerPacket(PacketCustom packet) { - for (EntityPlayerMP player : playerCrafters) - packet.sendToPlayer(player); + for (EntityPlayerMP player : playerCrafters) packet.sendToPlayer(player); } /** @@ -272,10 +245,11 @@ public abstract class ContainerExtended extends Container implements ICrafting * @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 abstract class ContainerExtended extends Container implements ICrafting 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 abstract class ContainerSynchronised extends ContainerExtended } @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 abstract class ContainerSynchronised extends ContainerExtended packet.writeByte(i); var.writeChange(packet); var.reset(); - for (EntityPlayerMP player : playerCrafters) - packet.sendToPlayer(player); + for (EntityPlayerMP player : playerCrafters) packet.sendToPlayer(player); } } diff --git a/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java b/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java index dc3b01f..f1fd61d 100644 --- a/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java +++ b/src/main/java/codechicken/lib/inventory/IContainerSyncVar.java @@ -2,13 +2,12 @@ package codechicken.lib.inventory; import codechicken.lib.packet.PacketCustom; -public interface IContainerSyncVar -{ +public interface IContainerSyncVar { public boolean changed(); - + public void reset(); - + public void writeChange(PacketCustom packet); - + public void readChange(PacketCustom packet); } diff --git a/src/main/java/codechicken/lib/inventory/IntegerSync.java b/src/main/java/codechicken/lib/inventory/IntegerSync.java index 841e564..56d62fc 100644 --- a/src/main/java/codechicken/lib/inventory/IntegerSync.java +++ b/src/main/java/codechicken/lib/inventory/IntegerSync.java @@ -2,33 +2,28 @@ package codechicken.lib.inventory; import codechicken.lib.packet.PacketCustom; -public abstract class IntegerSync implements IContainerSyncVar -{ +public abstract class IntegerSync implements IContainerSyncVar { public int c_value; - + @Override - public boolean changed() - { + public boolean changed() { return getValue() != c_value; } - + @Override - public void reset() - { + public void reset() { c_value = getValue(); } @Override - public void writeChange(PacketCustom packet) - { + public void writeChange(PacketCustom packet) { packet.writeInt(getValue()); } @Override - public void readChange(PacketCustom packet) - { + public void readChange(PacketCustom packet) { c_value = packet.readInt(); } - + public abstract int getValue(); } diff --git a/src/main/java/codechicken/lib/inventory/InventoryCopy.java b/src/main/java/codechicken/lib/inventory/InventoryCopy.java index 5843404..237e9db 100644 --- a/src/main/java/codechicken/lib/inventory/InventoryCopy.java +++ b/src/main/java/codechicken/lib/inventory/InventoryCopy.java @@ -7,35 +7,28 @@ import net.minecraft.item.ItemStack; /** * Creates a copy of an IInventory for extended simulation */ -public class InventoryCopy implements IInventory -{ +public class InventoryCopy implements IInventory { public boolean[] accessible; public ItemStack[] items; public IInventory inv; - - public InventoryCopy(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++) - { + + public void update() { + for (int i = 0; i < items.length; i++) { ItemStack stack = inv.getStackInSlot(i); - if(stack != null) - items[i] = stack.copy(); + if (stack != null) items[i] = stack.copy(); } } - - public InventoryCopy open(InventoryRange access) - { + + public InventoryCopy open(InventoryRange access) { int lslot = access.lastSlot(); - if(lslot > 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 class InventoryCopy implements IInventory 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 @@ import net.minecraft.nbt.NBTTagCompound; /** * 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() {} + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) { + return true; } @Override - public void closeInventory() - { - } - - @Override - 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 @@ import net.minecraft.item.ItemStack; /** * 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 @@ import net.minecraft.item.ItemStack; /** * 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() {} + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) { + return true; } @Override - public void closeInventory() - { - } - - @Override - public boolean isItemValidForSlot(int i, ItemStack itemstack) - { + public boolean hasCustomInventoryName() { return true; } - + @Override - 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.tileentity.TileEntityChest; 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 class InventoryUtils 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 class InventoryUtils * @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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils * 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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils 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 class InventoryUtils */ 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 class InventoryUtils } 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 class InventoryUtils */ 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 class InventoryUtils 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 class InventoryUtils 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 class ItemKey implements Comparable @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 class ItemKey implements Comparable 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.entity.player.EntityPlayer; 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.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) - { +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.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) - { +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.util.Copyable; 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 class LC implements Copyable 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 class LC implements Copyable offset = vec.x >= 1; break; } - if (!offset) - side += 6; + if (!offset) side += 6; return computeO(vec, side); } @@ -86,4 +83,4 @@ public class LC implements Copyable 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 @@ 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 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 class LightMatrix implements CCRenderState.IVertexOperation 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 class LightMatrix implements CCRenderState.IVertexOperation } 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 class LightMatrix implements CCRenderState.IVertexOperation 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.render.CCRenderState; 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 class LightModel implements CCRenderState.IVertexOperation 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 class LightModel implements CCRenderState.IVertexOperation 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 class LightModel implements CCRenderState.IVertexOperation 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 codechicken.lib.vec.BlockCoord; 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 class PlanarLightMatrix extends PlanarLightModel } 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 @@ import codechicken.lib.render.CCRenderState; /** * 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 class PlanarLightModel implements CCRenderState.IVertexOperation @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 @@ import net.minecraft.world.IBlockAccess; /** * 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 class SimpleBrightnessModel implements CCRenderState.IVertexOperation 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 class MathHelper * @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 class MathHelper * @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 class MathHelper * @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 class MathHelper * @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.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; @@ -38,32 +41,21 @@ import net.minecraftforge.fluids.Fluid; 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 final class PacketCustom implements MCDataInput, MCDataOutput @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 final class PacketCustom implements MCDataInput, MCDataOutput 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 final class PacketCustom implements MCDataInput, MCDataOutput @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 final class PacketCustom implements MCDataInput, MCDataOutput @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 final class PacketCustom implements MCDataInput, MCDataOutput 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 final class PacketCustom implements MCDataInput, MCDataOutput byteBuf = payload; type = byteBuf.readUnsignedByte(); - if (type > 0x80) - decompress(); + if (type > 0x80) decompress(); type &= 0x7F; } @@ -233,8 +224,8 @@ public final class PacketCustom implements MCDataInput, MCDataOutput 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 final class PacketCustom implements MCDataInput, MCDataOutput } 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 final class PacketCustom implements MCDataInput, MCDataOutput 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 final class PacketCustom implements MCDataInput, MCDataOutput 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 final class PacketCustom implements MCDataInput, MCDataOutput } 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 final class PacketCustom implements MCDataInput, MCDataOutput } 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 final class PacketCustom implements MCDataInput, MCDataOutput } 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.entity.Entity; 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 class ExtendedMOP extends MovingObjectPosition implements Comparable 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 @@ package codechicken.lib.raytracer; 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.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.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.MovingObjectPosition.MovingObjectType; 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 @@ public class RayTracer 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 class RayTracer 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.lighting.LC; 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 class BlockRenderer @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 class BlockRenderer } 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 class BlockRenderer 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 class BlockRenderer } } - 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 class BlockRenderer @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 class BlockRenderer * @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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable @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 class CCModel implements CCRenderState.IVertexSource, Copyable } @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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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; + 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; + // 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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable return this; } - public CCModel computeNormals() - { + public CCModel computeNormals() { return computeNormals(0, verts.length); } @@ -272,20 +298,17 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable * 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable } } - 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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable } 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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 class CCModel implements CCRenderState.IVertexSource, Copyable * 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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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(); + 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); } /** @@ -812,12 +776,9 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * @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 class CCModel implements CCRenderState.IVertexSource, Copyable * 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 class CCModel implements CCRenderState.IVertexSource, Copyable * 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 class CCModel implements CCRenderState.IVertexSource, Copyable * 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 class CCModel implements CCRenderState.IVertexSource, Copyable /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable /** * @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 class CCModel implements CCRenderState.IVertexSource, Copyable 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 @@ package codechicken.lib.render; 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 class CCRenderPipeline } } - 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 class CCRenderPipeline 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 class CCRenderPipeline } 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 (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(); + for (int i = 0; i < nodes.size(); i++) nodes.get(i).add(); } public void addRequirement(int opRef) { @@ -117,15 +99,14 @@ public class CCRenderPipeline } 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.util.Copyable; 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 class CCRenderState /** * 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 class CCRenderState } 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 class CCRenderState * 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 class CCRenderState 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 class CCRenderState @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 class CCRenderState @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 class CCRenderState @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 class CCRenderState @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 class CCRenderState @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 class CCRenderState */ 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 class CCRenderState @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 class CCRenderState @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 class CCRenderState 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 class CCRenderState 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 class CCRenderState } public static void bindModel(IVertexSource model) { - if(CCRenderState.model != model) { + if (CCRenderState.model != model) { CCRenderState.model = model; pipeline.rebuild(); } @@ -340,7 +323,7 @@ public class CCRenderState 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 class CCRenderState } 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 class CCRenderState } 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 class CCRenderState 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 @@ package codechicken.lib.render; 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 class ColourMultiplier implements CCRenderState.IVertexOperation @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.client.renderer.Tessellator; 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 class EntityDigIconFX extends EntityFX 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.client.gui.FontRenderer; 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.renderer.texture.TextureAtlasSprite; 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.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 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 class QBImporter } 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 class QBImporter 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 class QBImporter } 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 class QBImporter } 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 class QBImporter } 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 class QBImporter } 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 class QBImporter 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 class QBImporter 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 class QBImporter 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)) { + 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)) { + 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 @@ public class QBImporter 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 class QBImporter 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 @@ public class QBImporter 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 @@ public class QBImporter 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 @@ public class QBImporter 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 class QBImporter 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 class QBImporter } } - public static class RasterisedModel - { + public static class RasterisedModel { private class Holder { CCModel m; int img; @@ -633,7 +585,7 @@ public class QBImporter } 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 class QBImporter 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 class QBImporter } 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 @@ public class QBImporter 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 class QBImporter 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 class QBImporter 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 class QBImporter 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 class QBImporter } 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.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 -{ +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 class RenderUtils * @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; + 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); + 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; + 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 class RenderUtils 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 class RenderUtils * @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 class RenderUtils * 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 @@ 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 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 class SpriteSheetManager 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 @@ package codechicken.lib.render; 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 cpw.mods.fml.relauncher.SideOnly; 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 class TextureFX 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.resources.data.AnimationMetadataSection; 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 @@ public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis } 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis @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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis } } - /** * 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis } @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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis @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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis @Override public int getFrameCount() { - if (textureFX != null) - return 1; + if (textureFX != null) return 1; return super.getFrameCount(); } @@ -181,8 +167,7 @@ public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis @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 @@ 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; @@ -14,16 +19,8 @@ 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 -{ - public static interface IIconSelfRegister - { +public class TextureUtils { + public static interface IIconSelfRegister { public void registerIcons(IIconRegister register); public int atlasIndex(); @@ -42,8 +39,7 @@ public class TextureUtils @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 class TextureUtils 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 class TextureUtils 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 class TextureUtils 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 class TextureUtils 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 class TextureUtils } 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.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 class Vertex5 implements Copyable { public Vector3 vec; public UV uv; @@ -64,8 +62,9 @@ public class Vertex5 implements Copyable 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 class UV implements Copyable { @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 class UVRotation extends UVTransformation 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 class UVRotation extends UVTransformation @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 class UVRotation extends UVTransformation } @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 @@ import codechicken.lib.vec.ITransformation; /** * 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 abstract class UVTransformation extends ITransformation 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 @@ public class UVTransformationList extends UVTransformation 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 class UVTransformationList extends UVTransformation } @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 class UVTranslation extends UVTransformation { @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.nio.ByteBuffer; 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 @@ public class LibDownloader 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 @@ public class LibDownloader 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.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") || !typeName.contains("/")) - found = true; + if (typeName.startsWith("net/minecraft") || !typeName.contains("/")) found = true; return typeName; } } @@ -28,17 +26,16 @@ public class MCStripTransformer { 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.io.InputStream; 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 class StripClassLoader extends URLClassLoader 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 @@ package codechicken.lib.tool; 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 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 -{ +import codechicken.lib.render.QBImporter; +import java.io.File; +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +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 class ModuleQBConverter extends JOptModule 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 @@ package codechicken.lib.util; 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.math.MathHelper; 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 class BlockCoord implements Comparable, Copyable 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 class BlockCoord implements Comparable, Copyable 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 class Cuboid6 implements Copyable 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)+")"; + 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; + 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 java.util.Iterator; import net.minecraft.util.AxisAlignedBB; -import java.util.Iterator; - -public class CuboidCoord implements Iterable, Copyable -{ +public class CuboidCoord implements Iterable, Copyable { public BlockCoord min; public BlockCoord max; @@ -43,10 +41,9 @@ public class CuboidCoord implements Iterable, Copyable } 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 class CuboidCoord implements Iterable, Copyable 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 class CuboidCoord implements Iterable, Copyable } 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 class CuboidCoord implements Iterable, Copyable } 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 class CuboidCoord implements Iterable, Copyable } 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 @@ package codechicken.lib.vec; * @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 class Line3 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 @@ 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; 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 class Matrix4 extends Transformation implements Copyable 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 class Matrix4 extends Transformation implements Copyable 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 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 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 class Matrix4 extends Transformation implements Copyable 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 class Matrix4 extends Transformation implements Copyable 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 class Matrix4 extends Transformation implements Copyable 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 class Matrix4 extends Transformation implements Copyable 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 class Matrix4 extends Transformation implements Copyable 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 @@ 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; -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 class Quat implements Copyable 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 class Quat implements Copyable 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 class Quat implements Copyable 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 class Rectangle4i } 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 class Rectangle4i 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 class Rectangle4i } 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 @@ package codechicken.lib.vec; 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 @@ 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 java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; - -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 class Rotation extends Transformation * @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 @@ 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; public class Scale extends Transformation { public Vector3 factor; @@ -29,8 +28,7 @@ public class Scale extends Transformation { } @Override - public void applyN(Vector3 normal) { - } + public void applyN(Vector3 normal) {} @Override public void apply(Matrix4 mat) { @@ -50,8 +48,7 @@ public class Scale extends Transformation { @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 class Scale extends Transformation { @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 @@ import cpw.mods.fml.relauncher.SideOnly; /** * 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 abstract class Transformation extends ITransformation 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 class TransformationList extends Transformation @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 @@ 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; public class Translation extends Transformation { public Vector3 vec; @@ -25,8 +24,7 @@ public class Translation extends Transformation { } @Override - public void applyN(Vector3 normal) { - } + public void applyN(Vector3 normal) {} @Override public void apply(Matrix4 mat) { @@ -51,8 +49,7 @@ public class Translation extends Transformation { @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 class Translation extends Transformation { @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 @@ package codechicken.lib.vec; 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.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; @@ -11,97 +14,77 @@ 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 -{ +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 class Vector3 implements Copyable } public double getSide(int side) { - switch(side) { + switch (side) { case 0: case 1: return y; @@ -123,39 +106,39 @@ public class Vector3 implements Copyable 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 class Vector3 implements Copyable 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 class Vector3 implements Copyable z = d1; return this; } - - public Vector3 zCrossProduct() - { + + public Vector3 zCrossProduct() { double d = y; double d1 = -x; x = d; @@ -283,9 +249,8 @@ public class Vector3 implements Copyable z = 0; return this; } - - public Vector3 yCrossProduct() - { + + public Vector3 yCrossProduct() { double d = -z; double d1 = x; x = d; @@ -293,217 +258,180 @@ public class Vector3 implements Copyable 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 @@ package codechicken.lib.world; * 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 class 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(); + 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 @@ package codechicken.lib.world; 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.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; @@ -16,186 +18,143 @@ 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 - { +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); + 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); + 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 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 removeChunk(World world, Chunk chunk) { + for (WorldExtension extension : worldMap.get(world)) extension.remChunk(chunk); } - public static WorldExtension getWorldExtension(World world, int instantiatorID) - { + 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 f6102d56ec78e69efcbf434b83a6b904a31e46ea Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Wed, 11 Jan 2023 21:05:45 +0000 Subject: [PATCH 138/153] 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 class ObfMapping { 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 class ObfMapping { 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 139/153] [ci skip] Update buildscript to RetroFuturaGradle --- build.gradle | 859 +++++++++++++---------- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 286 +++++--- gradlew.bat | 38 +- settings.gradle | 24 +- 6 files changed, 715 insertions(+), 495 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 { + 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) + } + + // 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" + ]) + } + } + + // 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") + } + } } } -minecraft { - version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion - runDir = 'run' - - if (replaceGradleTokenInFile) { - for (f in replaceGradleTokenInFile.split(',')) { - replaceIn f +// 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 (gradleTokenModId) { - replace gradleTokenModId, modId - } - if (gradleTokenModName) { - replace gradleTokenModName, modName - } - if (gradleTokenVersion) { - replace gradleTokenVersion, modVersion - } - if (gradleTokenGroupName) { - replace gradleTokenGroupName, modGroup - } - } - - clientIntellijRun { - args(arguments) - jvmArgs(jvmArguments) - - if (developmentEnvironmentUserName) { - args("--username", developmentEnvironmentUserName) - } - } - - serverIntellijRun { - args(arguments) - jvmArgs(jvmArguments) } } @@ -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" +def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' +def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap +def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" -task generateAssets { - if (usesMixins.toBoolean()) { +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" -} +if (usesMixins.toBoolean()) { + tasks.named("reobfJar", ReobfuscatedJar).configure { + extraSrgFiles.from(mixinSrg) + } -shadowJar { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' + tasks.named("processResources").configure { + dependsOn("generateAssets") + } + + tasks.named("compileJava", JavaCompile).configure { + doFirst { + new File(mixinTmpDir).mkdirs() } - } - - manifest { - attributes(getManifestAttributes()) - } - - 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/**' - } - } - - 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" - ] - } - } -} - -runClient { - if (developmentEnvironmentUserName) { - arguments += [ - "--username", - developmentEnvironmentUserName + 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" ] } - args(arguments) - jvmArgs(jvmArguments) -} - -runServer { - args(arguments) - jvmArgs(jvmArguments) -} - -tasks.withType(JavaExec).configureEach { - javaLauncher.set( - javaToolchains.launcherFor { - languageVersion = projectJavaVersion + 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() + } + } + } + } + } -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" -} +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 circularResolverJar(type: Jar) { - dependsOn(relocateShadowDevJar) - dependsOn(shadowDevJar) - enabled = false -} - -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()) - } - - if (usesShadowedDependencies.toBoolean()) { - dependsOn(circularResolverJar) + 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 + +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 -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# 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##*/} +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 -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 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 - # 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" ;; +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 -# 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, 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. -# 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" +# 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" ) -# 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")" + 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 +# 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 + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat 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 140/153] [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 | 74 ++--- .../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 | 269 +++++++++--------- 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 | 32 ++- .../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, 1261 insertions(+), 1062 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 @@ 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 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 class ASMBlock { } 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 class ASMBlock { /** * Pulls all common labels from other into this + * * @return this */ public ASMBlock mergeLabels(ASMBlock other) { @@ -99,6 +102,7 @@ public class ASMBlock { /** * 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 class ASMBlock { 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.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; @@ -19,16 +18,18 @@ import org.objectweb.asm.util.ASMifier; 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 @@ public class ASMHelper { } public static interface Acceptor { + public void accept(ClassVisitor cv) throws IOException; } @@ -80,27 +82,30 @@ public class ASMHelper { 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 class ASMHelper { 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 class ASMHelper { 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 class ASMHelper { } 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 @@ 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() { 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.IOException; 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 class ASMReader { 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 @@ package codechicken.lib.asm; 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 class ClassHeirachyManager implements IClassTransformer { 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 class ClassHeirachyManager implements IClassTransformer { 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 @@ public class ClassHeirachyManager implements IClassTransformer { 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.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) { 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 @@ package codechicken.lib.asm; 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 class InsnComparator { Set controlFlowLabels = getControlFlowLabels(list); Map labelMap = Maps.asMap(controlFlowLabels, new Function() { + @Override public LabelNode apply(LabelNode input) { return input; @@ -138,8 +142,8 @@ public class InsnComparator { 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 class InsnComparator { 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.Iterator; 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 @@ 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 { + int i = 0; @Override @@ -143,6 +146,7 @@ public class InsnListSection implements Iterable { /** * 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 class InsnListSection implements Iterable { 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 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; public class ModularASMTransformer { + public static class ClassNodeTransformerList { + List transformers = new LinkedList(); HashSet methodsToSort = new HashSet(); @@ -45,6 +48,7 @@ public class ModularASMTransformer { } public abstract static class ClassNodeTransformer { + public int writeFlags; public ClassNodeTransformer(int writeFlags) { @@ -63,6 +67,7 @@ public class ModularASMTransformer { } public abstract static class MethodTransformer extends ClassNodeTransformer { + public final ObfMapping method; public MethodTransformer(ObfMapping method) { @@ -90,6 +95,7 @@ public class ModularASMTransformer { } public static class MethodWriter extends ClassNodeTransformer { + public final int access; public final ObfMapping method; public final String[] exceptions; @@ -148,6 +154,7 @@ public class ModularASMTransformer { } public static class MethodInjector extends MethodTransformer { + public ASMBlock needle; public ASMBlock injection; public boolean before; @@ -184,8 +191,14 @@ public class ModularASMTransformer { 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 class ModularASMTransformer { } public static class MethodReplacer extends MethodTransformer { + public ASMBlock needle; public ASMBlock replacement; @@ -225,6 +239,7 @@ public class ModularASMTransformer { } 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 class ObfMapping { 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 class ObfMapping { } 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 class ObfMapping { 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 class ObfMapping { 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 class ObfMapping { 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 abstract class Colour implements Copyable { @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 java.awt.image.BufferedImage; + +import net.minecraft.util.ResourceLocation; + import codechicken.lib.math.MathHelper; import codechicken.lib.render.TextureUtils; -import java.awt.image.BufferedImage; -import net.minecraft.util.ResourceLocation; 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 @@ package codechicken.lib.config; 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 @@ package codechicken.lib.config; 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 class ConfigTag extends ConfigTagParent { 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 class ConfigTag extends ConfigTagParent { 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 class ConfigTag extends ConfigTagParent { 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 class ConfigTag extends ConfigTagParent { 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.*; 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 @@ public abstract class ConfigTagParent { */ 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 abstract class ConfigTagParent { 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 @@ package codechicken.lib.config; 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.HashMap; 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 class SimpleProperties { 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 @@ package codechicken.lib.data; 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 @@ package codechicken.lib.data; 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 class MCDataOutputWrapper implements MCDataOutput { } /** - * 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 class MCDataOutputWrapper implements MCDataOutput { } /** - * 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 class Canvas9Seg { 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.gui.ScaledResolution; 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 class GuiDraw { 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 class GuiDraw { for (int i = 0; i < list.size(); i++) { String s = list.get(i); ITooltipLineHandler line = getTipLine(s); - Dimension d = line != null - ? line.getSize() + Dimension d = line != null ? line.getSize() : new Dimension( font.getStringWidth(s), list.get(i).endsWith(TOOLTIP_LINESPACE) && i + 1 < list.size() ? 12 : 10); diff --git a/src/main/java/codechicken/lib/inventory/ContainerExtended.java b/src/main/java/codechicken/lib/inventory/ContainerExtended.java index c365c4c..d8448a1 100644 --- a/src/main/java/codechicken/lib/inventory/ContainerExtended.java +++ b/src/main/java/codechicken/lib/inventory/ContainerExtended.java @@ -1,13 +1,9 @@ package codechicken.lib.inventory; -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.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -18,19 +14,27 @@ 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; +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; + /** - * Clean container implementation with a few extra features. - * Easy shift-click handling. - * Hooks for slot clicks, large stack sizes and some networking. + * 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; @@ -42,6 +46,7 @@ public abstract class ContainerExtended extends Container implements ICrafting { } }); PacketCustom.assignHandler(netChannel, new IServerPacketHandler() { + @Override public void handlePacket(PacketCustom packet, EntityPlayerMP sender, INetHandlerPlayServer handler) { Container cont = sender.openContainer; @@ -87,8 +92,8 @@ public abstract class ContainerExtended extends Container implements ICrafting { 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); @@ -159,8 +164,7 @@ public abstract class ContainerExtended extends Container implements ICrafting { 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 abstract class ContainerExtended extends Container implements ICrafting { } /** - * 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 @@ public abstract class ContainerExtended extends Container implements ICrafting { } 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 abstract class ContainerExtended extends Container implements ICrafting { } /** - * @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 abstract class ContainerSynchronised extends ContainerExtended { } @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 @@ package codechicken.lib.inventory; 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 @@ package codechicken.lib.inventory; 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 @@ import net.minecraft.item.ItemStack; * 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 @@ import net.minecraft.nbt.NBTTagCompound; * 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 @@ import net.minecraft.item.ItemStack; * 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 @@ 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; 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.tileentity.TileEntityChest; 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 class InventoryUtils { 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 class InventoryUtils { 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 class InventoryUtils { 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 @@ 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 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 class ItemKey implements Comparable { 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.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) { 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.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); } 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.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); } 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.Rotation; 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 - }; + { 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)); - }*/ + /* + * 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.Rotation; 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 class LightModel implements CCRenderState.IVertexOperation { 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 class LightModel implements CCRenderState.IVertexOperation { 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 class PlanarLightMatrix extends PlanarLightModel { 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 @@ import codechicken.lib.render.CCRenderState; * 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 net.minecraft.block.Block; +import net.minecraft.world.IBlockAccess; + 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(); @@ -29,8 +31,8 @@ public class SimpleBrightnessModel implements CCRenderState.IVertexOperation { 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 class MathHelper { } /** - * @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 class MathHelper { } /** - * @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 class MathHelper { } /** - * @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 class MathHelper { } /** - * @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 class MathHelper { } /** - * @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 class MathHelper { /** * * @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.Fluid; 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 final class PacketCustom implements MCDataInput, MCDataOutput { @ChannelHandler.Sharable public static class CustomInboundHandler extends SimpleChannelInboundHandler { + public EnumMap handlers = Maps.newEnumMap(Side.class); @Override @@ -66,19 +75,20 @@ public final class PacketCustom implements MCDataInput, MCDataOutput { @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 final class PacketCustom implements MCDataInput, MCDataOutput { } public static class ServerInboundHandler implements CustomHandler { + private IServerPacketHandler handler; public ServerInboundHandler(ICustomPacketHandler handler) { @@ -102,18 +113,21 @@ public final class PacketCustom implements MCDataInput, MCDataOutput { @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 final class PacketCustom implements MCDataInput, MCDataOutput { 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 final class PacketCustom implements MCDataInput, MCDataOutput { 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 final class PacketCustom implements MCDataInput, MCDataOutput { 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 @@ public final class PacketCustom implements MCDataInput, MCDataOutput { 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 final class PacketCustom implements MCDataInput, MCDataOutput { 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 final class PacketCustom implements MCDataInput, MCDataOutput { 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 final class PacketCustom implements MCDataInput, MCDataOutput { } 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.MovingObjectPosition; 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 @@ package codechicken.lib.raytracer; 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.MovingObjectPosition.MovingObjectType; 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 @@ public class RayTracer { 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 class RayTracer { 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) { mop.typeOfHit = MovingObjectType.BLOCK; @@ -160,8 +166,8 @@ public class RayTracer { 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 class RayTracer { } 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.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 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 class BlockRenderer { } 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 class BlockRenderer { /** * 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 @@ package codechicken.lib.render; 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.UVTransformation; 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } /** - * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } /** - * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * Computes the minecraft lighting coordinates for use with a LightMatrix + * * @return The model */ public CCModel computeLightCoords() { @@ -349,19 +355,18 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } } - 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } /** - * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { /** * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } /** - * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } /** - * 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } 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 static codechicken.lib.math.MathHelper.phi; import codechicken.lib.vec.*; public class CCModelLibrary { + public static CCModel icosahedron4; public static CCModel icosahedron7; @@ -68,20 +69,12 @@ public class CCModelLibrary { 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 class CCRenderPipeline { } private class PipelineNode { + public ArrayList deps = new ArrayList(); public IVertexOperation op; @@ -81,9 +85,8 @@ public class CCRenderPipeline { 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.util.Copyable; 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 class CCRenderState { * 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 class CCRenderState { 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 class CCRenderState { } /** - * 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 class CCRenderState { } 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 class CCRenderState { } public static VertexAttribute normalAttrib = new VertexAttribute() { + private Vector3[] normalRef; @Override @@ -151,6 +163,7 @@ public class CCRenderState { } }; public static VertexAttribute colourAttrib = new VertexAttribute() { + private int[] colourRef; @Override @@ -171,6 +184,7 @@ public class CCRenderState { } }; public static VertexAttribute lightingAttrib = new VertexAttribute() { + private int[] colourRef; @Override @@ -196,6 +210,7 @@ public class CCRenderState { } }; public static VertexAttribute sideAttrib = new VertexAttribute() { + private int[] sideRef; @Override @@ -222,6 +237,7 @@ public class CCRenderState { * 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 class CCRenderState { 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 class CCRenderState { 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 @@ package codechicken.lib.render; 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 class EntityDigIconFX extends EntityFX { * 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 class EntityDigIconFX extends EntityFX { 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 class EntityDigIconFX extends EntityFX { 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 class EntityDigIconFX extends EntityFX { 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 class EntityDigIconFX extends EntityFX { 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 @@ package codechicken.lib.render; 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 class FontUtils { 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.client.resources.IResourceManager; 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 class QBImporter { 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 @@ public class QBImporter { 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 class QBImporter { } public static class QBImage implements Comparable { + int[][] data; ImageTransform packT; Rectangle4i packSlot; @@ -190,16 +196,14 @@ public class QBImporter { } 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 class QBImporter { } 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 class QBImporter { 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 class QBImporter { } public static class QBCuboid { + public QBMatrix mat; public CuboidCoord c; public int sides; @@ -281,8 +282,7 @@ public class QBImporter { 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 class QBImporter { 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 @@ public class QBImporter { 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 class QBImporter { } 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 class QBImporter { 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 @@ public class QBImporter { 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 @@ public class QBImporter { public static final int SCALEMC = 8; public static class QBModel { + public QBMatrix[] matrices; public boolean rightHanded; @@ -551,8 +546,7 @@ public class QBImporter { } } - 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 class QBImporter { } public static class RasterisedModel { + private class Holder { + CCModel m; int img; @@ -594,9 +590,10 @@ public class QBImporter { 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 class QBImporter { 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 class QBImporter { 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 @@ 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; 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.IItemRenderer; 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 class RenderUtils { 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 class RenderUtils { /** * 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 class RenderUtils { 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 class RenderUtils { 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 class RenderUtils { } /** - * 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 class RenderUtils { /** * 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 class RenderUtils { 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.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() { 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 @@ public class SpriteSheetManager { 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 @@ package codechicken.lib.render; 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.resources.data.AnimationMetadataSection; 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 class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegis } @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.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 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 class TextureUtils { } 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 class TextureUtils { 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 class TextureUtils { } /** - * 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 class Vertex5 implements Copyable { 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.MathContext; 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 @@ import codechicken.lib.vec.ITransformation; */ 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.ArrayList; import java.util.Iterator; public class UVTransformationList extends UVTransformation { + private ArrayList transformations = new ArrayList(); public UVTransformationList(UVTransformation... transforms) { @@ -69,8 +70,7 @@ public class UVTransformationList extends UVTransformation { @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.LinkedList; 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 class LibDownloader { 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.commons.RemappingMethodAdapter; 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.URL; 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 @@ 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(); @@ -11,7 +13,7 @@ public class ToolMain { 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 @@ public class ToolMain { 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 @@ 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 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 @@ package codechicken.lib.util; 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 class BlockCoord implements Comparable, Copyable 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 class Cuboid6 implements Copyable { } 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 class Cuboid6 implements Copyable { 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 class CuboidCoord implements Iterable, Copyable 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 class CuboidCoord implements Iterable, Copyable 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 class CuboidCoord implements Iterable, Copyable } 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 class CuboidCoord implements Iterable, Copyable 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 @@ package codechicken.lib.vec; /** * 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 class Matrix4 extends Transformation implements Copyable { 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 class Matrix4 extends Transformation implements Copyable { @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 class Matrix4 extends Transformation implements Copyable { @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 class Quat implements Copyable { 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.Side; 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 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; -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 { + /** * 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; - } + 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 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 void apply(Vector3 vec) { + double d1 = vec.x; + double d2 = vec.z; + vec.x = -d2; + vec.z = d1; + } - @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[3]; + } + }, new VariableTransformation(new Matrix4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)) { - @Override - public Transformation inverse() { - return quarterRotations[1]; - } - } - }; + @Override + public void apply(Vector3 vec) { + vec.x = -vec.x; + vec.z = -vec.z; + } - 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(0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1)) { - @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 void apply(Vector3 vec) { + double d1 = vec.x; + double d2 = vec.z; + vec.x = 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 quarterRotations[1]; + } + } }; - @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; - } + 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 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 void apply(Vector3 vec) { + vec.y = -vec.y; + vec.z = -vec.z; + } - @Override - public Transformation inverse() { - return sideRotations[4]; - } - } - }; + @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)) { - 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) - }; + @Override + public void apply(Vector3 vec) { + double d1 = vec.y; + double d2 = vec.z; + vec.y = -d2; + vec.z = d1; + } - 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 - }; + @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)) { - 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 - }; + @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 class Rotation extends Transformation { /** * @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 class Rotation extends Transformation { @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 class Scale extends Transformation { @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 @@ import cpw.mods.fml.relauncher.SideOnly; */ 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 class TransformationList extends Transformation { 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 class TransformationList extends Transformation { @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 class TransformationList extends Transformation { @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 class Translation extends Transformation { @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.Side; 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 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; -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; 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 class Vector3 implements Copyable { 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 class Vector3 implements Copyable { /** * 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.ChunkCoordIntPair; 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 class TileChunkLoadHook { @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.World; 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.UnWatch; 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 class WorldExtensionManager { @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 class WorldExtensionManager { @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 class WorldExtensionManager { } 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 @@ public class WorldExtensionManager { 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 141/153] [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 142/153] Release with RFG From f1034f699e94e1f90428e918184e4f7f9c1b4d59 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Tue, 31 Jan 2023 09:51:54 +0000 Subject: [PATCH 143/153] [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 144/153] 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 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 145/153] 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 @@ public abstract class WorldExtension { } 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 146/153] 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" } } + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } maven { name = "ic2" - url = "https://maven.ic2.player.to/" - metadataSources { - mavenPom() - artifact() + url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + content { + includeGroup "net.industrial-craft" } - } - maven { - name = "ic2-mirror" - url = "https://maven2.ic2.player.to/" 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) + return dependencies.rfg.deobf(files(obfFile)) } - -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) { @@ -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 147/153] Fix wildcard import & spotlessApply --- .../java/codechicken/lib/asm/ASMBlock.java | 12 +- .../java/codechicken/lib/asm/ASMHelper.java | 8 +- .../java/codechicken/lib/asm/ASMReader.java | 187 +++++++++++++++++- .../codechicken/lib/asm/InsnComparator.java | 34 +++- .../codechicken/lib/asm/InsnListSection.java | 14 +- .../lib/asm/ModularASMTransformer.java | 16 +- .../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, 357 insertions(+), 44 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 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.*; +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.apache.logging.log4j.Logger; 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 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.*; +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.*; +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.Map.Entry; 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 java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; -import org.objectweb.asm.*; +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.HashMap; 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.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 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 @@ package codechicken.lib.config; 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 net.minecraftforge.fluids.FluidStack; 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.tileentity.TileEntityChest; 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.Fluid; 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 @@ package codechicken.lib.render; 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.UV; 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 @@ package codechicken.lib.render; 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.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; +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 @@ package codechicken.lib.tool.module; 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 static java.util.Arrays.asList; 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 148/153] 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 final class PacketCustom implements MCDataInput, MCDataOutput { 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 final class PacketCustom implements MCDataInput, MCDataOutput { public ItemStack readItemStack(boolean large) { ItemStack item = null; - short itemID = readShort(); + int itemID = readInt(); if (itemID >= 0) { int stackSize = large ? readInt() : readByte(); From e8dab5710171baa9c9d99d0be1eb96fd0e191c02 Mon Sep 17 00:00:00 2001 From: miozune Date: Fri, 1 Dec 2023 17:56:58 +0900 Subject: [PATCH 149/153] 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 class MCDataOutputWrapper implements MCDataOutput { 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 150/153] 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 class ObfMapping { 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 @@ public class Canvas9Seg { 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 class LightMatrix implements CCRenderState.IVertexOperation { } @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 class LightModel implements CCRenderState.IVertexOperation { } @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 class PlanarLightMatrix extends PlanarLightModel { } @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 class PlanarLightModel implements CCRenderState.IVertexOperation { } @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 class SimpleBrightnessModel implements CCRenderState.IVertexOperation { } @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 class BlockRenderer { } @Override - public void prepareVertex() { - CCRenderState.side = side; + public void prepareVertex(CCRenderState state) { + state.side = side; } public BlockFace computeLightCoords() { @@ -145,16 +145,21 @@ public class BlockRenderer { } @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 class BlockRenderer { * * @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 class BlockRenderer { * @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.Transformation; 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 class CCModel implements CCRenderState.IVertexSource, Copyable { } @Override - public void prepareVertex() {} + public void prepareVertex(CCRenderState state) {} public T getOrAllocate(CCRenderState.VertexAttribute attrib) { T array = getAttributes(attrib); @@ -426,20 +427,36 @@ public class CCModel implements CCRenderState.IVertexSource, Copyable { 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 class CCModel implements CCRenderState.IVertexSource, Copyable { * @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 class CCRenderPipeline { 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 class CCRenderPipeline { } } - 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 @@ public class CCRenderPipeline { } 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 class CCRenderPipeline { } 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.Transformation; 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 class CCRenderState { /** * 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 class CCRenderState { 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 class CCRenderState { * @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 class CCRenderState { } @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 class CCRenderState { } @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 class CCRenderState { } @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 class CCRenderState { } @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 class CCRenderState { } @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 class CCRenderState { } @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 class CCRenderState { 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 class CCRenderState { 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 class CCRenderState { 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 class CCRenderState { 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 @@ import codechicken.lib.colour.ColourRGBA; 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 class ColourMultiplier implements CCRenderState.IVertexOperation { } @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 class RenderUtils { 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 class RenderUtils { 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 class RenderUtils { * @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 class RenderUtils { * 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 class RenderUtils { 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 abstract class UVTransformation extends ITransformation, Copyable 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 abstract class Transformation extends ITransformation Date: Mon, 8 Jan 2024 21:24:44 +0000 Subject: [PATCH 151/153] [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 4e743ba64b5abfce87fb44dab0c92879c1b812ac Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Thu, 11 Jan 2024 23:15:32 +0100 Subject: [PATCH 152/153] 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 ce1830d7b5d497e6161620dc0451680491576229 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sun, 4 Feb 2024 19:57:39 +0000 Subject: [PATCH 153/153] [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 +# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. +includeWellKnownRepositories = 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 = +# 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. - +# 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 -} +