diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..4ffbd90
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# This is the universal Text Editor Configuration
+# for all GTNewHorizons projects
+# See: https://editorconfig.org/
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{bat,ini}]
+end_of_line = crlf
+
+[*.{dtd,json,info,mcmeta,md,sh,svg,xml,xsd,xsl,yaml,yml}]
+indent_size = 2
+
+[*.lang]
+trim_trailing_whitespace = false
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/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 0000000..3ee2f68
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,13 @@
+
+name: Build and test
+
+on:
+ pull_request:
+ branches: [ master, main ]
+ push:
+ branches: [ master, main ]
+
+jobs:
+ build-and-test:
+ uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master
+ secrets: inherit
diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml
new file mode 100644
index 0000000..e4c0be6
--- /dev/null
+++ b/.github/workflows/release-tags.yml
@@ -0,0 +1,14 @@
+
+name: Release tagged build
+
+on:
+ push:
+ tags: [ '*' ]
+
+permissions:
+ contents: write
+
+jobs:
+ release-tags:
+ uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master
+ secrets: inherit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5e80e0a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+.gradle
+.settings
+/.idea/
+/.vscode/
+/run/
+/build/
+/eclipse/
+.classpath
+.project
+/bin/
+/config/
+/crash-reports/
+/logs/
+options.txt
+/saves/
+usernamecache.json
+banned-ips.json
+banned-players.json
+eula.txt
+ops.json
+server.properties
+servers.dat
+usercache.json
+whitelist.json
+/out/
+*.iml
+*.ipr
+*.iws
+src/main/resources/mixins.*([!.]).json
+*.bat
+*.DS_Store
+!gradlew.bat
+.factorypath
+addon.local.gradle
+addon.local.gradle.kts
+addon.late.local.gradle
+addon.late.local.gradle.kts
+layout.json
diff --git a/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/LICENSE b/LICENSE
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/build.gradle b/build.gradle
index 556fe16..d3a4bc1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,76 +1,1605 @@
+//version: 1704650211
/*
+ 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.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 {
- mavenCentral()
maven {
- name = "forge"
- url = "http://files.minecraftforge.net/maven"
+ // GTNH RetroFuturaGradle and ASM Fork
+ name "GTNH Maven"
+ url "https://nexus.gtnewhorizons.com/repository/public/"
}
- maven {
- name = "sonatype"
- url = "https://oss.sonatype.org/content/repositories/snapshots/"
+ 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 {
- classpath 'net.minecraftforge.gradle:ForgeGradle:2.0-SNAPSHOT'
+ 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)
+ })
}
}
-apply plugin: 'forge'
-*/
+eclipse {
+ classpath {
+ downloadSources = true
+ downloadJavadoc = true
+ }
+}
-plugins {
- id "net.minecraftforge.gradle.forge" version "2.0.2"
+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
+ }
}
-version = "v6-1.8"
-group= "com.yyon.grapplemod" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
-archivesBaseName = "grapplemod"
minecraft {
- version = "1.8-11.14.4.1563" // "1.8.8-11.15.0.1623"
- runDir = "eclipse"
-
- // the mappings can be changed at any time, and must be in the following format.
- // snapshot_YYYYMMDD snapshot are built nightly.
- // stable_# stables are built at the discretion of the MCP team.
- // Use non-default mappings at your own risk. they may not allways work.
- // simply re-run your setup task after changing the mappings to update your workspace.
- mappings = "snapshot_20141130"
+ 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 {
- // you may put jars on which you depend on in ./libs
- // or you may define them like so..
- //compile "some.group:artifact:version:classifier"
- //compile "some.group:artifact:version"
-
- // real examples
- //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
- //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
+ 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)
+ }
+ }
+}
- // for more info...
- // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
- // http://www.gradle.org/docs/current/userguide/dependency_management.html
+// 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]")
}
-processResources
-{
+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.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 version and mcversion
- expand 'version':project.version, 'mcversion':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
+ }
+
+ 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]
}
-
- // copy everything else, thats not the 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()
+ ]
+ }
+ 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) {
- exclude 'mcmod.info'
+ 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'
}
diff --git a/dependencies.gradle b/dependencies.gradle
new file mode 100644
index 0000000..624c487
--- /dev/null
+++ b/dependencies.gradle
@@ -0,0 +1,37 @@
+/*
+ * Add your dependencies here. Supported configurations:
+ * - api("group:name:version:classifier"): if you use the types from this dependency in the public API of this mod
+ * Available at runtime and compiletime for mods depending on this mod
+ * - implementation("g:n:v:c"): if you need this for internal implementation details of the mod, but none of it is visible via the public API
+ * Available at runtime but not compiletime for mods depending on this mod
+ * - compileOnly("g:n:v:c"): if the mod you're building doesn't need this dependency during runtime at all, e.g. for optional mods
+ * Not available at all for mods depending on this mod, only visible at compiletime for this mod
+ * - compileOnlyApi("g:n:v:c"): like compileOnly, but also visible at compiletime for mods depending on this mod
+ * Available at compiletime but not runtime for mods depending on this mod
+ * - runtimeOnlyNonPublishable("g:n:v:c"): if you want to include a mod in this mod's runClient/runServer runs, but not publish it as a dependency
+ * Not available at all for mods depending on this mod, only visible at runtime for this mod
+ * - devOnlyNonPublishable("g:n:v:c"): a combination of runtimeOnlyNonPublishable and compileOnly for dependencies present at both compiletime and runtime,
+ * but not published as Maven dependencies - useful for RFG-deobfuscated dependencies or local testing
+ * - runtimeOnly("g:n:v:c"): if you don't need this at compile time, but want it to be present at runtime
+ * Available at runtime for mods depending on this mod
+ * - annotationProcessor("g:n:v:c"): mostly for java compiler plugins, if you know you need this, use it, otherwise don't worry
+ * - testCONFIG("g:n:v:c") - replace CONFIG by one of the above (except api), same as above but for the test sources instead of main
+ *
+ * - shadowImplementation("g:n:v:c"): effectively the same as API, but the dependency is included in your jar under a renamed package name
+ * Requires you to enable usesShadowedDependencies in gradle.properties
+ *
+ * - compile("g:n:v:c"): deprecated, replace with "api" (works like the old "compile") or "implementation" (can be more efficient)
+ *
+ * You can exclude transitive dependencies (dependencies of the chosen dependency) by appending { transitive = false } if needed,
+ * but use this sparingly as it can break using your mod as another mod's dependency if you're not careful.
+ *
+ * To depend on obfuscated jars you can use `devOnlyNonPublishable(rfg.deobf("dep:spec:1.2.3"))` to fetch an obfuscated jar from maven,
+ * or `devOnlyNonPublishable(rfg.deobf(project.files("libs/my-mod-jar.jar")))` to use a file.
+ *
+ * Gradle names for some of the configuration can be misleading, compileOnlyApi and runtimeOnly both get published as dependencies in Maven, but compileOnly does not.
+ * The buildscript adds runtimeOnlyNonPublishable to also have a runtime dependency that's not published.
+ *
+ * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph
+ */
+dependencies {
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..b6af6d4
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,152 @@
+modName = Grappling Hook Mod
+
+# This is a case-sensitive string to identify your mod. Convention is to use lower case.
+modId = grapplemod
+
+modGroup = com.yyon.grapplinghook
+
+# 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
+
+# Specify a MCP channel and mappings version for dependency deobfuscation and the deobfParams task.
+channel = stable
+mappingsVersion = 12
+
+# Define other MCP mappings for dependency deobfuscation
+remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/
+
+# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you
+# restart Minecraft in development. Choose this dependent on your mod:
+# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
+# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
+developmentEnvironmentUserName = Developer
+
+# Enables using modern java syntax (up to version 17) via Jabel, while still targeting JVM 8.
+# See https://github.com/bsideup/jabel for details on how this works.
+enableModernJavaSyntax = true
+
+# Enables injecting missing generics into the decompiled source code for a better coding experience
+# Turns most publicly visible List, Map, etc. into proper List, Map types
+enableGenericInjection = true
+
+# Generate a class with String fields for the mod id, name, version and group name named with the fields below
+generateGradleTokenClass = com.yyon.grapplemod.Tags
+gradleTokenModId = MODID
+gradleTokenModName = MODNAME
+gradleTokenVersion = VERSION
+gradleTokenGroupName = GROUPNAME
+# [DEPRECATED]
+# Multiple source files can be defined here by providing a comma-seperated list: Class1.java,Class2.java,Class3.java
+# public static final String VERSION = "GRADLETOKEN_VERSION";
+# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
+# version in @Mod([...], version = VERSION, [...])
+# Leave these properties empty to skip individual token replacements
+replaceGradleTokenInFile =
+
+# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
+# leave this property empty.
+# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api
+apiPackage =
+
+# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
+# There can be multiple files in a space-separated list.
+# Example value: mymodid_at.cfg nei_at.cfg
+accessTransformersFile =
+
+# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
+usesMixins = false
+# Adds some debug arguments like verbose output and export
+usesMixinDebug = false
+# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
+mixinPlugin =
+# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
+mixinsPackage =
+# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
+# This parameter is for legacy compatibility only
+# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
+coreModClass =
+# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
+# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
+containsMixinsAndOrCoreModOnly = false
+
+# 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 in your jar. It is your
+# responsibility check the licence and request permission for distribution, if required.
+usesShadowedDependencies = false
+# If disabled, won't remove unused classes from shaded dependencies. Some libraries use reflection to access
+# their own classes, making the minimization unreliable.
+minimizeShadowedDependencies = true
+# If disabled, won't rename the shadowed classes.
+relocateShadowedDependencies = true
+
+# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories
+includeWellKnownRepositories = true
+
+# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
+# Authenticate with the MAVEN_USERNAME 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
+# mavenPublishUrl = https://nexus.gtnewhorizons.com/repository/releases/
+
+# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token.
+
+# The project's ID on Modrinth. Can be either the slug or the ID.
+# Leave this empty if you don't want to publish on Modrinth.
+modrinthProjectId =
+
+# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth.
+# Syntax: scope1-type1:name1;scope2-type2:name2;...
+# Where scope can be one of [required, optional, incompatible, embedded],
+# type can be one of [project, version],
+# and the name is the Modrinth project or version slug/id of the other mod.
+# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
+# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true
+modrinthRelations =
+
+
+# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
+
+# The project's numeric ID on CurseForge. You can find this in the About Project box.
+# Leave this empty if you don't want to publish on CurseForge.
+curseForgeProjectId =
+
+# 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: GTNH Mixins is automatically set as a required dependency if usesMixins = true
+curseForgeRelations =
+
+
+# Optional parameter to customize the produced artifacts. Use this to preserver artifact naming when migrating older
+# projects. New projects should not use this parameter.
+# customArchiveBaseName =
+
+# Optional parameter to prevent the source code from being published
+# noPublishedSources =
+
+# 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 value is "" (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 always 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
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..d64cd49
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..1af9e09
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+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
new file mode 100755
index 0000000..1aa94a4
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+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 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.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/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/main/java/com/yyon/grapplinghook/ClientProxyClass.java.orig b/main/java/com/yyon/grapplinghook/ClientProxyClass.java.orig
deleted file mode 100644
index cc503f3..0000000
--- a/main/java/com/yyon/grapplinghook/ClientProxyClass.java.orig
+++ /dev/null
@@ -1,335 +0,0 @@
-package com.yyon.grapplinghook;
-
-import java.util.Collection;
-import java.util.ConcurrentModificationException;
-import java.util.HashMap;
-
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.input.Mouse;
-
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.entity.EntityPlayerSP;
-import net.minecraft.client.renderer.entity.Render;
-import net.minecraft.client.renderer.entity.RenderManager;
-import net.minecraft.client.settings.GameSettings;
-import net.minecraft.client.settings.KeyBinding;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.init.Items;
-import net.minecraft.item.Item;
-import net.minecraft.item.ItemStack;
-import net.minecraftforge.event.world.BlockEvent.BreakEvent;
-
-import com.yyon.grapplinghook.controllers.grappleController;
-import com.yyon.grapplinghook.entities.RenderGrappleArrow;
-import com.yyon.grapplinghook.entities.grappleArrow;
-import com.yyon.grapplinghook.items.clickitem;
-import com.yyon.grapplinghook.items.enderBow;
-import com.yyon.grapplinghook.items.grappleBow;
-import com.yyon.grapplinghook.items.hookBow;
-import com.yyon.grapplinghook.items.launcherItem;
-import com.yyon.grapplinghook.items.magnetBow;
-import com.yyon.grapplinghook.items.multiBow;
-import com.yyon.grapplinghook.items.repeller;
-import com.yyon.grapplinghook.items.smartHookBow;
-
-import cpw.mods.fml.client.registry.RenderingRegistry;
-import cpw.mods.fml.common.event.FMLInitializationEvent;
-import cpw.mods.fml.common.event.FMLPostInitializationEvent;
-import cpw.mods.fml.common.event.FMLPreInitializationEvent;
-import cpw.mods.fml.common.eventhandler.SubscribeEvent;
-import cpw.mods.fml.common.gameevent.TickEvent;
-
-public class ClientProxyClass extends CommonProxyClass {
- public boolean leftclick = false;
- public boolean prevleftclick = false;
- public HashMap enderlaunchtimer = new HashMap();
- public final int reusetime = 50;
-
- @Override
- public void preInit(FMLPreInitializationEvent event) {
- super.preInit(event);
- }
-
- /*
- public ModelResourceLocation grapplinghookloc = new ModelResourceLocation("grapplemod:grapplinghook", "inventory");
- public ModelResourceLocation hookshotloc = new ModelResourceLocation("grapplemod:hookshot", "inventory");
- public ModelResourceLocation smarthookloc = new ModelResourceLocation("grapplemod:smarthook", "inventory");
- public ModelResourceLocation smarthookropeloc = new ModelResourceLocation("grapplemod:smarthookrope", "inventory");
- public ModelResourceLocation enderhookloc = new ModelResourceLocation("grapplemod:enderhook", "inventory");
- public ModelResourceLocation magnetbowloc = new ModelResourceLocation("grapplemod:magnetbow", "inventory");
- public ModelResourceLocation ropeloc = new ModelResourceLocation("grapplemod:rope", "inventory");
- public ModelResourceLocation hookshotropeloc = new ModelResourceLocation("grapplemod:hookshotrope", "inventory");
- public ModelResourceLocation repellerloc = new ModelResourceLocation("grapplemod:repeller", "inventory");
- public ModelResourceLocation repelleronloc = new ModelResourceLocation("grapplemod:repelleron", "inventory");
- public ModelResourceLocation multihookloc = new ModelResourceLocation("grapplemod:multihook", "inventory");
- public ModelResourceLocation multihookropeloc = new ModelResourceLocation("grapplemod:multihookrope", "inventory");
-
- private void setgrapplebowtextures(Item item, final ModelResourceLocation notinusetexture, final ModelResourceLocation inusetexture) {
- ModelLoader.setCustomMeshDefinition(item, new ItemMeshDefinition() {
- @Override
- public ModelResourceLocation getModelLocation(ItemStack stack) {
- if (ClientProxyClass.isactive(stack)) {
- return inusetexture;
- }
- return notinusetexture;
- }
- });
- ModelBakery.registerItemVariants(item, notinusetexture);
- ModelBakery.registerItemVariants(item, inusetexture);
- }
-
- private void registerItemModels() {
- setgrapplebowtextures(grapplemod.grapplebowitem, grapplinghookloc, ropeloc);
- setgrapplebowtextures(grapplemod.hookshotitem, hookshotloc, hookshotropeloc);
- registerItemModel(grapplemod.launcheritem);
- registerItemModel(grapplemod.longfallboots);
- setgrapplebowtextures(grapplemod.enderhookitem, enderhookloc, ropeloc);
- setgrapplebowtextures(grapplemod.magnetbowitem, magnetbowloc, ropeloc);
- setgrapplebowtextures(grapplemod.repelleritem, repellerloc, repelleronloc);
- setgrapplebowtextures(grapplemod.multihookitem, multihookloc, multihookropeloc);
- setgrapplebowtextures(grapplemod.smarthookitem, smarthookloc, smarthookropeloc);
- }
-
- private void registerItemModel(Item item) {
- registerItemModel(item, Item.REGISTRY.getNameForObject(item).toString());
- }
-
- private void registerItemModel(Item item, String modelLocation) {
- final ModelResourceLocation fullModelLocation = new ModelResourceLocation(modelLocation, "inventory");
-// ModelBakery.registerItemVariants(item, fullModelLocation); // Ensure the custom model is loaded and prevent the default model from being loaded
- ModelLoader.setCustomModelResourceLocation(item, 0, fullModelLocation);
- }
- */
-
- @Override
- public void init(FMLInitializationEvent event, grapplemod grappleModInst) {
- super.init(event, grappleModInst);
- RenderGrappleArrow rga = new RenderGrappleArrow(grapplemod.grapplebowitem);
- RenderingRegistry.registerEntityRenderingHandler(grappleArrow.class, rga);
-// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.grapplebowitem, 0, new ModelResourceLocation("grapplemod:grapplinghook", "inventory"));
-// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.hookshotitem, 0, new ModelResourceLocation("grapplemod:hookshot", "inventory"));
-// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.launcheritem, 0, new ModelResourceLocation("grapplemod:launcheritem", "inventory"));
-// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.longfallboots, 0, new ModelResourceLocation("grapplemod:longfallboots", "inventory"));
-// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.enderhookitem, 0, new ModelResourceLocation("grapplemod:enderhook", "inventory"));
- }
-
- public crosshairRenderer crosshairrenderer;
-
- @Override
- public void postInit(FMLPostInitializationEvent event) {
- super.postInit(event);
-
- crosshairrenderer = new crosshairRenderer();
- }
-
- @Override
- public void getplayermovement(grappleController control, int playerid) {
- Entity entity = control.entity;
- if (entity instanceof EntityPlayerSP) {
- EntityPlayerSP player = (EntityPlayerSP) entity;
- control.receivePlayerMovementMessage(player.moveStrafing, player.moveForward, player.movementInput.jump);
- }
- }
-
- @SubscribeEvent
- public void onClientTick(TickEvent.ClientTickEvent event) {
- EntityPlayer player = Minecraft.getMinecraft().thePlayer;
- if (player != null) {
- if (!Minecraft.getMinecraft().isGamePaused() || !Minecraft.getMinecraft().isSingleplayer()) {
- try {
- Collection controllers = grapplemod.controllers.values();
- for (grappleController controller : controllers) {
- controller.doClientTick();
- }
- } catch (ConcurrentModificationException e) {
- System.out.println("ConcurrentModificationException caught");
- }
-
- leftclick = (GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindAttack) && Minecraft.getMinecraft().currentScreen == null);
- if (prevleftclick != leftclick) {
- if (player != null) {
- ItemStack stack = player.getHeldItem();
- if (stack != null) {
- Item item = stack.getItem();
- if (item instanceof clickitem) {
- if (leftclick) {
- ((clickitem)item).onLeftClick(stack, player);
- } else {
- ((clickitem)item).onLeftClickRelease(stack, player);
- }
- }
- }
- }
- }
-
- prevleftclick = leftclick;
-
- if (player.onGround) {
- if (enderlaunchtimer.containsKey(player.getEntityId())) {
- long timer = player.worldObj.getTotalWorldTime() - enderlaunchtimer.get(player.getEntityId());
- if (timer > 10) {
- this.resetlaunchertime(player.getEntityId());
- }
- }
- }
- }
- }
- }
-
- @Override
- public void launchplayer(EntityPlayer player) {
- long prevtime;
- if (enderlaunchtimer.containsKey(player.getEntityId())) {
- prevtime = enderlaunchtimer.get(player.getEntityId());
- } else {
- prevtime = 0;
- }
- long timer = player.worldObj.getTotalWorldTime() - prevtime;
- if (timer > reusetime) {
-<<<<<<< HEAD
- if (player.getHeldItem().getItem() instanceof enderBow || player.getHeldItem().getItem() instanceof launcherItem) {
-=======
- if ((player.getHeldItemMainhand()!=null && (player.getHeldItemMainhand().getItem() instanceof enderBow || player.getHeldItemMainhand().getItem() instanceof launcherItem)) || (player.getHeldItemOffhand()!=null && (player.getHeldItemOffhand().getItem() instanceof enderBow || player.getHeldItemOffhand().getItem() instanceof launcherItem))) {
->>>>>>> 6c8b29cf1a9f87c1801402122aee8a079fcdc67a
- enderlaunchtimer.put(player.getEntityId(), player.worldObj.getTotalWorldTime());
-
- vec facing = new vec(player.getLookVec());
-// vec playermotion = vec.motionvec(player);
-// vec newvec = playermotion.add(facing.mult(3));
-
- /*
- if (!grapplemod.controllers.containsKey(player.getEntityId())) {
- player.motionX = newvec.x;
- player.motionY = newvec.y;
- player.motionZ = newvec.z;
-
- if (player instanceof EntityPlayerMP) {
- ((EntityPlayerMP) player).connection.sendPacket(new SPacketEntityVelocity(player));
- } else {
- grapplemod.network.sendToServer(new PlayerMovementMessage(player.getEntityId(), player.posX, player.posY, player.posZ, player.motionX, player.motionY, player.motionZ));
- }
- } else {
- facing.mult_ip(3);
- grapplemod.receiveEnderLaunch(player.getEntityId(), facing.x, facing.y, facing.z);
- }
- */
- if (!grapplemod.controllers.containsKey(player.getEntityId())) {
- player.onGround = false;
- grapplemod.createControl(grapplemod.AIRID, -1, player.getEntityId(), player.worldObj, new vec(0,0,0), 0, null);
- }
- facing.mult_ip(3);
- grapplemod.receiveEnderLaunch(player.getEntityId(), facing.x, facing.y, facing.z);
- }
- }
- }
-
- @Override
- public void resetlaunchertime(int playerid) {
- if (enderlaunchtimer.containsKey(playerid)) {
- enderlaunchtimer.put(playerid, (long) 0);
- }
- }
-
- @Override
- public boolean isSneaking(Entity entity) {
- if (entity == Minecraft.getMinecraft().thePlayer) {
- return (GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindSneak));
- } else {
- return entity.isSneaking();
- }
- }
-
- @Override
- public void blockbreak(BreakEvent event) {
- BlockPos pos = new BlockPos(event.x, event.y, event.z);
- if (pos != null) {
- if (grapplemod.controllerpos.containsKey(pos)) {
- grappleController control = grapplemod.controllerpos.get(pos);
-
- control.unattach();
-
- grapplemod.controllerpos.remove(pos);
- }
- }
- }
-
- @Override
- public void handleDeath(Entity entity) {
- int id = entity.getEntityId();
- if (grapplemod.controllers.containsKey(id)) {
- grappleController controller = grapplemod.controllers.get(id);
- controller.unattach();
- }
- }
-
- @Override
- public String getkeyname(CommonProxyClass.keys keyenum) {
- KeyBinding binding = null;
-
- GameSettings gs = Minecraft.getMinecraft().gameSettings;
-
- if (keyenum == keys.keyBindAttack) {
- binding = gs.keyBindAttack;
- } else if (keyenum == keys.keyBindBack) {
- binding = gs.keyBindBack;
- } else if (keyenum == keys.keyBindForward) {
- binding = gs.keyBindForward;
- } else if (keyenum == keys.keyBindJump) {
- binding = gs.keyBindJump;
- } else if (keyenum == keys.keyBindLeft) {
- binding = gs.keyBindLeft;
- } else if (keyenum == keys.keyBindRight) {
- binding = gs.keyBindRight;
- } else if (keyenum == keys.keyBindSneak) {
- binding = gs.keyBindSneak;
- } else if (keyenum == keys.keyBindUseItem) {
- binding = gs.keyBindUseItem;
- }
-
- if (binding == null) {
- return "";
- }
-
- String displayname;
- int keycode = binding.getKeyCode();
- if (keycode == -99) {
- return "Right Click";
- } else if (keycode == -100) {
- return "Left Click";
- }
- try {
- displayname = Keyboard.getKeyName(keycode);
- } catch (ArrayIndexOutOfBoundsException e) {
- displayname = "???";
- }
- return displayname;
- }
-
- public static boolean isactive(ItemStack stack) {
- EntityPlayer p = Minecraft.getMinecraft().thePlayer;
-// if (p.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND) == stack || p.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND) == stack) {
- int entityid = p.getEntityId();
- if (grapplemod.controllers.containsKey(entityid)) {
- Item item = stack.getItem();
- grappleController controller = grapplemod.controllers.get(entityid);
- if (item.getClass() == grappleBow.class && controller.controllerid == grapplemod.GRAPPLEID) {
- return true;
- } else if (item.getClass() == enderBow.class && controller.controllerid == grapplemod.ENDERID) {
- return true;
- } else if (item.getClass() == hookBow.class && controller.controllerid == grapplemod.HOOKID) {
- return true;
- } else if (item.getClass() == magnetBow.class && controller.controllerid == grapplemod.MAGNETID) {
- return true;
- } else if (item.getClass() == repeller.class && controller.controllerid == grapplemod.REPELID) {
- return true;
- } else if (item.getClass() == multiBow.class && controller.controllerid == grapplemod.MULTIID) {
- return true;
- } else if (item.getClass() == smartHookBow.class && controller.controllerid == grapplemod.SMARTHOOKID) {
- return true;
- }
- }
-// }
- return false;
- }
-}
diff --git a/main/java/com/yyon/grapplinghook/grapplemod.java.orig b/main/java/com/yyon/grapplinghook/grapplemod.java.orig
deleted file mode 100644
index 953671f..0000000
--- a/main/java/com/yyon/grapplinghook/grapplemod.java.orig
+++ /dev/null
@@ -1,562 +0,0 @@
-package com.yyon.grapplinghook;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Random;
-
-import net.minecraft.block.Block;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.EntityLivingBase;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.entity.player.EntityPlayerMP;
-import net.minecraft.init.Blocks;
-import net.minecraft.init.Items;
-import net.minecraft.item.Item;
-import net.minecraft.item.ItemArmor;
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.server.MinecraftServer;
-import net.minecraft.util.ChatComponentText;
-import net.minecraft.world.World;
-
-import com.yyon.grapplinghook.controllers.airfrictionController;
-import com.yyon.grapplinghook.controllers.enderController;
-import com.yyon.grapplinghook.controllers.grappleController;
-import com.yyon.grapplinghook.controllers.hookControl;
-import com.yyon.grapplinghook.controllers.magnetController;
-import com.yyon.grapplinghook.controllers.multihookController;
-import com.yyon.grapplinghook.controllers.repelController;
-import com.yyon.grapplinghook.controllers.smartHookControl;
-import com.yyon.grapplinghook.entities.enderArrow;
-import com.yyon.grapplinghook.entities.grappleArrow;
-import com.yyon.grapplinghook.entities.hookArrow;
-import com.yyon.grapplinghook.entities.magnetArrow;
-import com.yyon.grapplinghook.entities.multihookArrow;
-import com.yyon.grapplinghook.entities.smartHookArrow;
-import com.yyon.grapplinghook.items.LongFallBoots;
-import com.yyon.grapplinghook.items.enderBow;
-import com.yyon.grapplinghook.items.grappleBow;
-import com.yyon.grapplinghook.items.hookBow;
-import com.yyon.grapplinghook.items.launcherItem;
-import com.yyon.grapplinghook.items.magnetBow;
-import com.yyon.grapplinghook.items.multiBow;
-import com.yyon.grapplinghook.items.repeller;
-import com.yyon.grapplinghook.items.smartHookBow;
-import com.yyon.grapplinghook.network.GrappleAttachMessage;
-import com.yyon.grapplinghook.network.GrappleAttachPosMessage;
-import com.yyon.grapplinghook.network.GrappleClickMessage;
-import com.yyon.grapplinghook.network.GrappleEndMessage;
-import com.yyon.grapplinghook.network.MultiHookMessage;
-import com.yyon.grapplinghook.network.PlayerMovementMessage;
-import com.yyon.grapplinghook.network.ToolConfigMessage;
-
-import cpw.mods.fml.common.Mod;
-import cpw.mods.fml.common.Mod.EventHandler;
-import cpw.mods.fml.common.SidedProxy;
-import cpw.mods.fml.common.event.FMLInitializationEvent;
-import cpw.mods.fml.common.event.FMLPostInitializationEvent;
-import cpw.mods.fml.common.event.FMLPreInitializationEvent;
-import cpw.mods.fml.common.event.FMLServerStartingEvent;
-import cpw.mods.fml.common.network.NetworkRegistry;
-import cpw.mods.fml.common.network.simpleimpl.IMessage;
-import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
-import cpw.mods.fml.common.registry.EntityRegistry;
-import cpw.mods.fml.common.registry.GameRegistry;
-import cpw.mods.fml.relauncher.Side;
-
-/*
- * This file is part of GrappleMod.
-
- GrappleMod is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- GrappleMod is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GrappleMod. If not, see .
- */
-
-//TODO
-// Pull mobs
-// Attach 2 things together
-
-@Mod(modid = grapplemod.MODID, version = grapplemod.VERSION)
-public class grapplemod {
-
- public grapplemod(){}
-
- public static final String MODID = "grapplemod";
-
-<<<<<<< HEAD
- public static final String VERSION = "1.7.10-v7";
-=======
- public static final String VERSION = "1.10.2-v10";
->>>>>>> 6c8b29cf1a9f87c1801402122aee8a079fcdc67a
-
- public static Item grapplebowitem;
- public static Item hookshotitem;
- public static Item smarthookitem;
- public static Item enderhookitem;
- public static Item launcheritem;
- public static Item longfallboots;
- public static Item magnetbowitem;
- public static Item repelleritem;
- public static Item multihookitem;
-
- public static Object instance;
-
- public static SimpleNetworkWrapper network;
-
- public static HashMap controllers = new HashMap(); // client side
- public static HashMap controllerpos = new HashMap();
- public static HashSet attached = new HashSet(); // server side
-
- private static int controllerid = 0;
- public static int GRAPPLEID = controllerid++;
- public static int ENDERID = controllerid++;
- public static int HOOKID = controllerid++;
- public static int MAGNETID = controllerid++;
- public static int REPELID = controllerid++;
- public static int MULTIID = controllerid++;
- public static int MULTISUBID = controllerid++;
- public static int AIRID = controllerid++;
- public static int SMARTHOOKID = controllerid++;
-
- public static int REPELCONFIGS = 0;
-// public static int REPELSPEED = REPELCONFIGS++;
- public static int REPELSTRONG = REPELCONFIGS++;
- public static int REPELWEAK = REPELCONFIGS++;
- public static int REPELNONE = REPELCONFIGS++;
-
- public static int grapplingLength = 0;
- public static boolean anyblocks = true;
- public static ArrayList grapplingblocks;
- public static boolean removeblocks = false;
-
- @SidedProxy(clientSide="com.yyon.grapplinghook.ClientProxyClass", serverSide="com.yyon.grapplinghook.ServerProxyClass")
- public static CommonProxyClass proxy;
-
- @EventHandler
- public void load(FMLInitializationEvent event){
- GameRegistry.addRecipe(new ItemStack(grapplebowitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(Items.iron_pickaxe, 1), Character.valueOf('4'), new ItemStack(Items.lead, 1),
- });
- GameRegistry.addRecipe(new ItemStack(hookshotitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(Blocks.piston, 1),
- });
- GameRegistry.addRecipe(new ItemStack(smarthookitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(hookshotitem, 1), Character.valueOf('4'), new ItemStack(Items.REDSTONE, 1),
- });
- GameRegistry.addRecipe(new ItemStack(launcheritem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(Items.ender_pearl, 1), Character.valueOf('4'), new ItemStack(Blocks.piston, 1),
- });
- GameRegistry.addRecipe(new ItemStack(enderhookitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(launcheritem, 1),
- });
- GameRegistry.addRecipe(new ItemStack(repelleritem, 1), new Object[]{
- "X2X",
- "242",
- "X2X", Character.valueOf('2'), new ItemStack(Items.iron_ingot, 1), Character.valueOf('4'), new ItemStack(Items.compass, 1),
- });
- GameRegistry.addRecipe(new ItemStack(magnetbowitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(repelleritem, 1),
- });
- GameRegistry.addRecipe(new ItemStack(longfallboots, 1), new Object[]{
- "2",
- "4", Character.valueOf('2'), new ItemStack(Items.diamond_boots, 1), Character.valueOf('4'), new ItemStack(Blocks.wool, 1),
- });
- GameRegistry.addRecipe(new ItemStack(multihookitem, 1), new Object[]{
- "X2",
- "2X", Character.valueOf('2'), new ItemStack(hookshotitem, 1),
- });
- }
-
- public void registerRenderers(){
- }
- public void generateNether(World world, Random random, int chunkX, int chunkZ){}
- public void generateSurface(World world, Random random, int chunkX, int chunkZ){}
- public int addFuel(ItemStack fuel){
- return 0;
- }
-
- @EventHandler
- public void serverLoad(FMLServerStartingEvent event){
- event.getServer().worldServerForDimension(0).getGameRules().addGameRule("grapplingLength", "0");
- event.getServer().worldServerForDimension(0).getGameRules().addGameRule("grapplingBlocks", "any");
- event.getServer().worldServerForDimension(0).getGameRules().addGameRule("grapplingNonBlocks", "none");
- }
-
- public static void updateMaxLen(World world) {
- String s = MinecraftServer.getServer().worldServerForDimension(0).getGameRules().getGameRuleStringValue("grapplingLength");
- if (!s.equals("")) {
- grapplemod.grapplingLength = Integer.parseInt(s);
- }
- }
-
- public static void updateGrapplingBlocks(World world) {
- String s = MinecraftServer.getServer().worldServerForDimension(0).getGameRules().getGameRuleStringValue("grapplingBlocks");
- if (s.equals("any") || s.equals("")) {
- s = MinecraftServer.getServer().worldServerForDimension(0).getGameRules().getGameRuleStringValue("grapplingNonBlocks");
- if (s.equals("none") || s.equals("")) {
- anyblocks = true;
- } else {
- anyblocks = false;
- removeblocks = true;
- }
- } else {
- anyblocks = false;
- removeblocks = false;
- }
-
- if (!anyblocks) {
- String[] blockstr = s.split(",");
-
- grapplingblocks = new ArrayList();
-
- for(String str:blockstr){
- str = str.trim();
- String modid;
- String name;
- if (str.contains(":")) {
- String[] splitstr = str.split(":");
- modid = splitstr[0];
- name = splitstr[1];
- } else {
- modid = "minecraft";
- name = str;
- }
-
- Block b = GameRegistry.findBlock(modid, name);
-
- grapplingblocks.add(b);
- }
- }
- }
-
- @EventHandler
- public void preInit(FMLPreInitializationEvent event){
- grapplebowitem = new grappleBow();
- GameRegistry.registerItem(grapplebowitem, "grapplinghook");
- hookshotitem = new hookBow();
-<<<<<<< HEAD
- GameRegistry.registerItem(hookshotitem, "hookshot");
-=======
- hookshotitem.setRegistryName("hookshot");
- GameRegistry.register(hookshotitem);
- smarthookitem = new smartHookBow();
- smarthookitem.setRegistryName("smarthook");
- GameRegistry.register(smarthookitem);
->>>>>>> 6c8b29cf1a9f87c1801402122aee8a079fcdc67a
- launcheritem = new launcherItem();
- GameRegistry.registerItem(launcheritem, "launcheritem");
- longfallboots = new LongFallBoots(ItemArmor.ArmorMaterial.DIAMOND, 3);
- GameRegistry.registerItem(longfallboots, "longfallboots");
- enderhookitem = new enderBow();
- GameRegistry.registerItem(enderhookitem, "enderhook");
- magnetbowitem = new magnetBow();
- GameRegistry.registerItem(magnetbowitem, "magnetbow");
- repelleritem = new repeller();
- GameRegistry.registerItem(repelleritem, "repeller");
- multihookitem = new multiBow();
- GameRegistry.registerItem(multihookitem, "multihook");
-
- registerEntity(grappleArrow.class, "grappleArrow");
- registerEntity(enderArrow.class, "enderArrow");
- registerEntity(hookArrow.class, "hookArrow");
- registerEntity(magnetArrow.class, "magnetArrow");
- registerEntity(multihookArrow.class, "multihookArrow");
- registerEntity(smartHookArrow.class, "smartHookArrow");
-
- proxy.preInit(event);
- network = NetworkRegistry.INSTANCE.newSimpleChannel("grapplemodchannel");
- byte id = 0;
- network.registerMessage(PlayerMovementMessage.Handler.class, PlayerMovementMessage.class, id++, Side.SERVER);
- network.registerMessage(GrappleAttachMessage.Handler.class, GrappleAttachMessage.class, id++, Side.CLIENT);
- network.registerMessage(GrappleEndMessage.Handler.class, GrappleEndMessage.class, id++, Side.SERVER);
- network.registerMessage(GrappleClickMessage.Handler.class, GrappleClickMessage.class, id++, Side.CLIENT);
- network.registerMessage(GrappleAttachPosMessage.Handler.class, GrappleAttachPosMessage.class, id++, Side.CLIENT);
- network.registerMessage(MultiHookMessage.Handler.class, MultiHookMessage.class, id++, Side.SERVER);
- network.registerMessage(ToolConfigMessage.Handler.class, ToolConfigMessage.class, id++, Side.SERVER);
- }
-
- @EventHandler
- public void Init(FMLInitializationEvent event) {
- proxy.init(event, this);
- }
-
- @EventHandler
- public void postInit(FMLPostInitializationEvent event) {
- proxy.postInit(event);
- }
-
- int entityID = 0;
- public void registerEntity(Class extends Entity> entityClass, String name)
- {
- EntityRegistry.registerModEntity(entityClass, name, entityID++, this, 900, 1, true);
- }
-
- public static void registerController(int entityId, grappleController controller) {
- if (controllers.containsKey(entityId)) {
- controllers.get(entityId).unattach();
- }
-
- controllers.put(entityId, controller);
- }
-
- public static void unregisterController(int entityId) {
- controllers.remove(entityId);
- }
-
- public static void receiveGrappleClick(int id,
- boolean leftclick) {
- grappleController controller = controllers.get(id);
- if (controller != null) {
- controller.receiveGrappleClick(leftclick);
- } else {
- System.out.println("Couldn't find controller");
- }
- }
-
- public static void receiveEnderLaunch(int id, double x, double y, double z) {
- grappleController controller = controllers.get(id);
- if (controller != null) {
- controller.receiveEnderLaunch(x, y, z);
- } else {
- System.out.println("Couldn't find controller");
- }
- }
-
- public static void sendtocorrectclient(IMessage message, int playerid, World w) {
- Entity entity = w.getEntityByID(playerid);
- if (entity instanceof EntityPlayerMP) {
- grapplemod.network.sendTo(message, (EntityPlayerMP) entity);
- } else {
- System.out.println("ERROR! couldn't find player");
- }
- }
-
- public static grappleController createControl(int id, int arrowid, int entityid, World world, vec pos, int maxlen, BlockPos blockpos) {
-
- grappleArrow arrow = null;
- Entity arrowentity = world.getEntityByID(arrowid);
- if (arrowentity != null && arrowentity instanceof grappleArrow) {
- arrow = (grappleArrow) arrowentity;
- }
-
- if (id != MULTISUBID) {
- grappleController currentcontroller = controllers.get(entityid);
- if (currentcontroller != null) {
- currentcontroller.unattach();
- }
- }
-
- System.out.println(blockpos);
-
- grappleController control = null;
- if (id == GRAPPLEID) {
- control = new grappleController(arrowid, entityid, world, pos, maxlen, id);
- } else if (id == ENDERID) {
- control = new enderController(arrowid, entityid, world, pos, maxlen, id);
- } else if (id == HOOKID) {
- control = new hookControl(arrowid, entityid, world, pos, maxlen, id);
- } else if (id == SMARTHOOKID) {
- boolean slow = false;
- if (arrow != null && arrow instanceof smartHookArrow) {
- slow = ((smartHookArrow) arrow).slow;
- }
- control = new smartHookControl(arrowid, entityid, world, pos, maxlen, id, slow);
- } else if (id == MAGNETID) {
- int repelconf = 0;
- if (arrow != null && arrow instanceof magnetArrow) {
- repelconf = ((magnetArrow) arrow).repelconf;
- }
- control = new magnetController(arrowid, entityid, world, pos, maxlen, id, repelconf);
- } else if (id == REPELID) {
- control = new repelController(arrowid, entityid, world, pos, maxlen, id);
- } else if (id == MULTIID) {
- control = new multihookController(arrowid, entityid, world, pos, maxlen, id);
- } else if (id == MULTISUBID) {
- control = grapplemod.controllers.get(entityid);
- boolean created = false;
- if (control instanceof multihookController) {
- multihookController c = (multihookController) control;
- if (arrow != null && arrow instanceof multihookArrow) {
- multihookArrow multiarrow = (multihookArrow) arrowentity;
- created = true;
- c.addArrow(multiarrow, pos);
- }
- }
- if (!created) {
- System.out.println("Couldn't create");
- grapplemod.removesubarrow(arrowid);
- }
- } else if (id == AIRID) {
- System.out.println("AIR FRICTION CONTROLLER");
- control = new airfrictionController(arrowid, entityid, world, pos, maxlen, id);
- }
- if (blockpos != null && control != null) {
- grapplemod.controllerpos.put(blockpos, control);
- }
-
- return control;
- }
-
- public static void removesubarrow(int id) {
- grapplemod.network.sendToServer(new GrappleEndMessage(-1, id));
- }
-
- public static void receiveGrappleEnd(int id, World world, int arrowid) {
- if (grapplemod.attached.contains(id)) {
- grapplemod.attached.remove(new Integer
- (id));
- } else {
- }
-
- if (arrowid != -1) {
- Entity grapple = world.getEntityByID(arrowid);
- if (grapple instanceof grappleArrow) {
- ((grappleArrow) grapple).removeServer();
- } else {
-
- }
- }
-
- Entity entity = world.getEntityByID(id);
- if (entity != null) {
- entity.fallDistance = 0;
- }
-
- grapplemod.removeallmultihookarrows();
- }
-
- public static HashSet multihookarrows = new HashSet();
- public static void receiveMultihookMessage(int id, World w, boolean sneaking) {
- Entity e = w.getEntityByID(id);
- if (e != null && e instanceof EntityLivingBase) {
- EntityLivingBase player = (EntityLivingBase) e;
-
- float angle = multiBow.getAngle(player);
-
- //vec look = new vec(player.getLookVec());
-
- //System.out.println(player.rotationPitch);
- //System.out.println(player.rotationYaw);
-
- /*
- grappleArrow arrow = new grappleArrow(w, player, false);
- arrow.setHeadingFromThrower(player, (float)look.getPitch(), (float)look.getYaw(), 0.0F, arrow.getVelocity(), 0.0F);
- w.spawnEntityInWorld(arrow);
- */
-
- vec anglevec = new vec(0,0,1).rotate_yaw(Math.toRadians(-angle));
- anglevec = anglevec.rotate_pitch(Math.toRadians(-player.rotationPitch));
- anglevec = anglevec.rotate_yaw(Math.toRadians(player.rotationYaw));
- multihookArrow entityarrow = new multihookArrow(w, player, false);
- entityarrow.setHeadingFromThrower(player, (float) anglevec.getPitch(), (float)anglevec.getYaw(), 0.0F, entityarrow.func_70182_d(), 0.0F);
-
- /*
- vec pos = vec.positionvec(entityarrow);
- pos.add_ip(new vec(0.36, -0.175, 0.45).rotate_yaw(Math.toRadians(player.rotationYaw)));
- entityarrow.setPosition(pos.x, pos.y, pos.z);
- */
-
- w.spawnEntityInWorld(entityarrow);
- multihookarrows.add(entityarrow);
-
-
- anglevec = new vec(0,0,1).rotate_yaw(Math.toRadians(angle));
- anglevec = anglevec.rotate_pitch(Math.toRadians(-player.rotationPitch));
- anglevec = anglevec.rotate_yaw(Math.toRadians(player.rotationYaw));
- entityarrow = new multihookArrow(w, player, true);
- entityarrow.setHeadingFromThrower(player, (float) anglevec.getPitch(), (float)anglevec.getYaw(), 0.0F, entityarrow.func_70182_d(), 0.0F);
-
- /*
- pos = vec.positionvec(entityarrow);
- pos.add_ip(new vec(-0.36, -0.175, 0.45).rotate_yaw(Math.toRadians(player.rotationYaw)));
- entityarrow.setPosition(pos.x, pos.y, pos.z);
- */
-
- w.spawnEntityInWorld(entityarrow);
- multihookarrows.add(entityarrow);
- }
- }
-
- public static void removeallmultihookarrows() {
- for (multihookArrow arrow : multihookarrows) {
- if (arrow != null && !arrow.isDead) {
- arrow.removeServer();
- }
- }
- }
-
- public static void receiveToolConfigMessage(int id, World w) {
- Entity e = w.getEntityByID(id);
- if (e != null && e instanceof EntityPlayer) {
- EntityPlayer player = (EntityPlayer) e;
-
- ItemStack stack = player.getHeldItem();
- Item item = stack.getItem();
- if (item instanceof multiBow) {
- NBTTagCompound compound = stack.getTagCompound();
- if (compound == null) {
- compound = new NBTTagCompound();
- stack.setTagCompound(compound);
- }
- boolean slow = compound.getBoolean("slow");
- slow = !slow;
- compound.setBoolean("slow", slow);
-
- if (slow) {
- player.addChatMessage(new ChatComponentText("Set to slow mode"));
- } else {
- player.addChatMessage(new ChatComponentText("Set to fast mode"));
- }
- } else if (item instanceof magnetBow) {
- NBTTagCompound compound = stack.getTagCompound();
- if (compound == null) {
- compound = new NBTTagCompound();
- stack.setTagCompound(compound);
- }
- int repelconf = compound.getInteger("repelconf");
- repelconf++;
- if (repelconf >= REPELCONFIGS) {
- repelconf = 0;
- }
- compound.setInteger("repelconf", repelconf);
-
-// if (repelconf == REPELSPEED) {
-// player.addChatMessage(new TextComponentString("Repel force set to speed based"));
- if (repelconf == REPELSTRONG) {
- player.addChatMessage(new ChatComponentText("Repel force set to strong"));
- } else if (repelconf == REPELWEAK) {
- player.addChatMessage(new ChatComponentText("Repel force set to weak"));
- } else if (repelconf == REPELNONE) {
- player.addChatMessage(new ChatComponentText("Repel force set to off"));
- }
- } else if (item instanceof smartHookBow) {
- NBTTagCompound compound = stack.getSubCompound("grapplemod", true);
- boolean slow = compound.getBoolean("slow");
- slow = !slow;
- compound.setBoolean("slow", slow);
-
- if (slow) {
- player.addChatMessage(new TextComponentString("Set to slow mode"));
- } else {
- player.addChatMessage(new TextComponentString("Set to fast mode"));
- }
- }
- }
- }
-}
diff --git a/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java b/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java
deleted file mode 100644
index 2685403..0000000
--- a/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.yyon.grapplinghook.network;
-
-import io.netty.buffer.ByteBuf;
-import net.minecraft.entity.Entity;
-import net.minecraft.world.World;
-import cpw.mods.fml.common.network.simpleimpl.IMessage;
-import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
-import cpw.mods.fml.common.network.simpleimpl.MessageContext;
-//* // 1.8 Compatability
-
-
-/*
- * This file is part of GrappleMod.
-
- GrappleMod is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- GrappleMod is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GrappleMod. If not, see .
- */
-
-public class PlayerMovementMessage implements IMessage {
-
- public int entityId;
- public double x;
- public double y;
- public double z;
- public double mx;
- public double my;
- public double mz;
-
- public PlayerMovementMessage() {
- }
-
- public PlayerMovementMessage(int entityId, double x, double y, double z, double mx, double my, double mz) {
- this.entityId = entityId;
- this.x = x;
- this.y = y;
- this.z = z;
- this.mx = mx;
- this.my = my;
- this.mz = mz;
- }
-
- @Override
- public void fromBytes(ByteBuf buf) {
- try {
- this.entityId = buf.readInt();
- this.x = buf.readDouble();
- this.y = buf.readDouble();
- this.z = buf.readDouble();
- this.mx = buf.readDouble();
- this.my = buf.readDouble();
- this.mz = buf.readDouble();
- } catch (Exception e) {
- System.out.println(buf);
- }
- }
-
- @Override
- public void toBytes(ByteBuf buf) {
- buf.writeInt(entityId);
- buf.writeDouble(x);
- buf.writeDouble(y);
- buf.writeDouble(z);
- buf.writeDouble(mx);
- buf.writeDouble(my);
- buf.writeDouble(mz);
-
- }
-
- public static class Handler implements IMessageHandler {
-
- public class runner implements Runnable {
- PlayerMovementMessage message;
- MessageContext ctx;
- public runner(PlayerMovementMessage message, MessageContext ctx) {
- super();
- this.message = message;
- this.ctx = ctx;
- }
-
- @Override
- public void run() {
- World world = ctx.getServerHandler().playerEntity.worldObj;
- Entity entity = world.getEntityByID(message.entityId);
- entity.posX = message.x;
- entity.posY = message.y;
- entity.posZ = message.z;
- entity.motionX = message.mx;
- entity.motionY = message.my;
- entity.motionZ = message.mz;
- }
- }
-
- @Override
- public IMessage onMessage(PlayerMovementMessage message, MessageContext ctx) {
- new runner(message, ctx).run();
-
- return null; // no response in this case
- }
- }
-}
diff --git a/main/resources/mcmod.info b/main/resources/mcmod.info
deleted file mode 100644
index c50dd9e..0000000
--- a/main/resources/mcmod.info
+++ /dev/null
@@ -1,16 +0,0 @@
-[
-{
- "modid": "grapplemod",
- "name": "Grappling hook mod",
- "description": "A mod which adds grappling hooks",
- "version": "${version}",
- "mcversion": "${mcversion}",
- "url": "",
- "updateUrl": "",
- "authorList": ["yyon"],
- "credits": "The Forge and FML guys, for making this example",
- "logoFile": "",
- "screenshots": [],
- "dependencies": []
-}
-]
diff --git a/repositories.gradle b/repositories.gradle
new file mode 100644
index 0000000..c884390
--- /dev/null
+++ b/repositories.gradle
@@ -0,0 +1,5 @@
+// Add any additional repositories for your dependencies here
+
+repositories {
+
+}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..d5cde6d
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,27 @@
+
+pluginManagement {
+ repositories {
+ maven {
+ // RetroFuturaGradle
+ name "GTNH Maven"
+ url "https://nexus.gtnewhorizons.com/repository/public/"
+ mavenContent {
+ includeGroupByRegex("com\\.gtnewhorizons\\..+")
+ }
+ }
+ gradlePluginPortal()
+ mavenCentral()
+ mavenLocal()
+ }
+}
+
+plugins {
+ id 'com.diffplug.blowdryerSetup' version '1.7.1'
+ id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains
+}
+
+blowdryerSetup {
+ repoSubfolder 'gtnhShared'
+ github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.2')
+ //devLocal '.' // Use this when testing config updates locally
+}
diff --git a/main/java/com/yyon/grapplinghook/BlockPos.java b/src/main/java/com/yyon/grapplinghook/BlockPos.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/BlockPos.java
rename to src/main/java/com/yyon/grapplinghook/BlockPos.java
diff --git a/main/java/com/yyon/grapplinghook/ClientProxyClass.java b/src/main/java/com/yyon/grapplinghook/ClientProxyClass.java
similarity index 98%
rename from main/java/com/yyon/grapplinghook/ClientProxyClass.java
rename to src/main/java/com/yyon/grapplinghook/ClientProxyClass.java
index 21484a7..120040e 100644
--- a/main/java/com/yyon/grapplinghook/ClientProxyClass.java
+++ b/src/main/java/com/yyon/grapplinghook/ClientProxyClass.java
@@ -45,12 +45,12 @@ public class ClientProxyClass extends CommonProxyClass {
public boolean prevleftclick = false;
public HashMap enderlaunchtimer = new HashMap();
public final int reusetime = 50;
-
+
@Override
public void preInit(FMLPreInitializationEvent event) {
super.preInit(event);
}
-
+
/*
public ModelResourceLocation grapplinghookloc = new ModelResourceLocation("grapplemod:grapplinghook", "inventory");
public ModelResourceLocation hookshotloc = new ModelResourceLocation("grapplemod:hookshot", "inventory");
@@ -64,7 +64,7 @@ public void preInit(FMLPreInitializationEvent event) {
public ModelResourceLocation repelleronloc = new ModelResourceLocation("grapplemod:repelleron", "inventory");
public ModelResourceLocation multihookloc = new ModelResourceLocation("grapplemod:multihook", "inventory");
public ModelResourceLocation multihookropeloc = new ModelResourceLocation("grapplemod:multihookrope", "inventory");
-
+
private void setgrapplebowtextures(Item item, final ModelResourceLocation notinusetexture, final ModelResourceLocation inusetexture) {
ModelLoader.setCustomMeshDefinition(item, new ItemMeshDefinition() {
@Override
@@ -78,7 +78,7 @@ public ModelResourceLocation getModelLocation(ItemStack stack) {
ModelBakery.registerItemVariants(item, notinusetexture);
ModelBakery.registerItemVariants(item, inusetexture);
}
-
+
private void registerItemModels() {
setgrapplebowtextures(grapplemod.grapplebowitem, grapplinghookloc, ropeloc);
setgrapplebowtextures(grapplemod.hookshotitem, hookshotloc, hookshotropeloc);
@@ -101,7 +101,7 @@ private void registerItemModel(Item item, String modelLocation) {
ModelLoader.setCustomModelResourceLocation(item, 0, fullModelLocation);
}
*/
-
+
@Override
public void init(FMLInitializationEvent event, grapplemod grappleModInst) {
super.init(event, grappleModInst);
@@ -113,16 +113,16 @@ public void init(FMLInitializationEvent event, grapplemod grappleModInst) {
// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.longfallboots, 0, new ModelResourceLocation("grapplemod:longfallboots", "inventory"));
// Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(grapplemod.enderhookitem, 0, new ModelResourceLocation("grapplemod:enderhook", "inventory"));
}
-
+
public crosshairRenderer crosshairrenderer;
-
+
@Override
public void postInit(FMLPostInitializationEvent event) {
super.postInit(event);
-
+
crosshairrenderer = new crosshairRenderer();
}
-
+
@Override
public void getplayermovement(grappleController control, int playerid) {
Entity entity = control.entity;
@@ -131,7 +131,7 @@ public void getplayermovement(grappleController control, int playerid) {
control.receivePlayerMovementMessage(player.moveStrafing, player.moveForward, player.movementInput.jump);
}
}
-
+
@SubscribeEvent
public void onClientTick(TickEvent.ClientTickEvent event) {
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
@@ -143,9 +143,9 @@ public void onClientTick(TickEvent.ClientTickEvent event) {
controller.doClientTick();
}
} catch (ConcurrentModificationException e) {
- System.out.println("ConcurrentModificationException caught");
+ grapplemod.LOGGER.error("ConcurrentModificationException caught");
}
-
+
leftclick = (GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindAttack) && Minecraft.getMinecraft().currentScreen == null);
if (prevleftclick != leftclick) {
if (player != null) {
@@ -162,9 +162,9 @@ public void onClientTick(TickEvent.ClientTickEvent event) {
}
}
}
-
+
prevleftclick = leftclick;
-
+
if (player.onGround) {
if (enderlaunchtimer.containsKey(player.getEntityId())) {
long timer = player.worldObj.getTotalWorldTime() - enderlaunchtimer.get(player.getEntityId());
@@ -176,7 +176,7 @@ public void onClientTick(TickEvent.ClientTickEvent event) {
}
}
}
-
+
@Override
public void launchplayer(EntityPlayer player) {
long prevtime;
@@ -189,17 +189,17 @@ public void launchplayer(EntityPlayer player) {
if (timer > reusetime) {
if (player.getHeldItem() != null && (player.getHeldItem().getItem() instanceof enderBow || player.getHeldItem().getItem() instanceof launcherItem)) {
enderlaunchtimer.put(player.getEntityId(), player.worldObj.getTotalWorldTime());
-
+
vec facing = new vec(player.getLookVec());
// vec playermotion = vec.motionvec(player);
// vec newvec = playermotion.add(facing.mult(3));
-
+
/*
if (!grapplemod.controllers.containsKey(player.getEntityId())) {
player.motionX = newvec.x;
player.motionY = newvec.y;
player.motionZ = newvec.z;
-
+
if (player instanceof EntityPlayerMP) {
((EntityPlayerMP) player).connection.sendPacket(new SPacketEntityVelocity(player));
} else {
@@ -219,14 +219,14 @@ public void launchplayer(EntityPlayer player) {
}
}
}
-
+
@Override
public void resetlaunchertime(int playerid) {
if (enderlaunchtimer.containsKey(playerid)) {
enderlaunchtimer.put(playerid, (long) 0);
}
}
-
+
@Override
public boolean isSneaking(Entity entity) {
if (entity == Minecraft.getMinecraft().thePlayer) {
@@ -235,7 +235,7 @@ public boolean isSneaking(Entity entity) {
return entity.isSneaking();
}
}
-
+
@Override
public void blockbreak(BreakEvent event) {
BlockPos pos = new BlockPos(event.x, event.y, event.z);
@@ -244,12 +244,12 @@ public void blockbreak(BreakEvent event) {
grappleController control = grapplemod.controllerpos.get(pos);
control.unattach();
-
+
grapplemod.controllerpos.remove(pos);
}
}
}
-
+
@Override
public void handleDeath(Entity entity) {
int id = entity.getEntityId();
@@ -258,13 +258,13 @@ public void handleDeath(Entity entity) {
controller.unattach();
}
}
-
+
@Override
public String getkeyname(CommonProxyClass.keys keyenum) {
KeyBinding binding = null;
-
+
GameSettings gs = Minecraft.getMinecraft().gameSettings;
-
+
if (keyenum == keys.keyBindAttack) {
binding = gs.keyBindAttack;
} else if (keyenum == keys.keyBindBack) {
@@ -282,11 +282,11 @@ public String getkeyname(CommonProxyClass.keys keyenum) {
} else if (keyenum == keys.keyBindUseItem) {
binding = gs.keyBindUseItem;
}
-
+
if (binding == null) {
return "";
}
-
+
String displayname;
int keycode = binding.getKeyCode();
if (keycode == -99) {
diff --git a/main/java/com/yyon/grapplinghook/CommonProxyClass.java b/src/main/java/com/yyon/grapplinghook/CommonProxyClass.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/CommonProxyClass.java
rename to src/main/java/com/yyon/grapplinghook/CommonProxyClass.java
diff --git a/main/java/com/yyon/grapplinghook/ServerProxyClass.java b/src/main/java/com/yyon/grapplinghook/ServerProxyClass.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/ServerProxyClass.java
rename to src/main/java/com/yyon/grapplinghook/ServerProxyClass.java
diff --git a/main/java/com/yyon/grapplinghook/controllers/airfrictionController.java b/src/main/java/com/yyon/grapplinghook/controllers/airfrictionController.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/controllers/airfrictionController.java
rename to src/main/java/com/yyon/grapplinghook/controllers/airfrictionController.java
diff --git a/main/java/com/yyon/grapplinghook/controllers/enderController.java b/src/main/java/com/yyon/grapplinghook/controllers/enderController.java
similarity index 96%
rename from main/java/com/yyon/grapplinghook/controllers/enderController.java
rename to src/main/java/com/yyon/grapplinghook/controllers/enderController.java
index 90e7fd6..c501a49 100644
--- a/main/java/com/yyon/grapplinghook/controllers/enderController.java
+++ b/src/main/java/com/yyon/grapplinghook/controllers/enderController.java
@@ -23,20 +23,20 @@
public class enderController extends grappleController {
public final double playermovementmult = 1;
-
+
public enderController(int arrowId, int entityId, World world, vec pos, int maxlen, int id) {
super(arrowId, entityId, world, pos, maxlen, id);
}
public void receiveGrappleClick(boolean leftclick) {
super.receiveGrappleClick(leftclick);
-
+
}
-
+
/*
@Override
public void receiveEnderLaunch(double x, double y, double z) {
-// System.out.println("now launching");
+// grapplemod.LOGGER.debug("now launching");
}
*/
}
diff --git a/main/java/com/yyon/grapplinghook/controllers/grappleController.java b/src/main/java/com/yyon/grapplinghook/controllers/grappleController.java
similarity index 97%
rename from main/java/com/yyon/grapplinghook/controllers/grappleController.java
rename to src/main/java/com/yyon/grapplinghook/controllers/grappleController.java
index bbf6969..adcb52e 100644
--- a/main/java/com/yyon/grapplinghook/controllers/grappleController.java
+++ b/src/main/java/com/yyon/grapplinghook/controllers/grappleController.java
@@ -32,50 +32,50 @@ public class grappleController {
public int entityId;
public World world;
public vec pos;
-
+
public grappleArrow arrow;
public Entity entity;
-
+
public boolean attached = true;
-
+
public double r;
public vec motion;
-
+
public double playerforward = 0;
public double playerstrafe = 0;
public boolean playerjump = false;
public boolean waitingonplayerjump = false;
public vec playermovement_unrotated = new vec(0,0,0);
public vec playermovement = new vec(0,0,0);
-
+
// public int counter = 0;
public int ongroundtimer = 0;
public int maxongroundtimer = 3;
-
+
public int maxlen;
-
+
public int controllerid;
-
+
public final double playermovementmult = 0.5;
-
+
public grappleController(int arrowId, int entityId, World world, vec pos, int maxlen, int controllerid) {
this.arrowId = arrowId;
this.entityId = entityId;
this.world = world;
this.pos = pos;
this.maxlen = maxlen;
-
+
this.controllerid = controllerid;
-
+
this.entity = world.getEntityByID(entityId);
-
+
this.r = this.pos.sub(vec.positionvec(entity)).length();
this.motion = vec.motionvec(entity);
-
+
this.ongroundtimer = 0;
-
+
grapplemod.registerController(this.entityId, this);
-
+
if (arrowId != -1) {
Entity arrowentity = world.getEntityByID(arrowId);
if (arrowentity != null && !arrowentity.isDead && arrowentity instanceof grappleArrow) {
@@ -83,24 +83,24 @@ public grappleController(int arrowId, int entityId, World world, vec pos, int ma
}
}
}
-
+
public void unattach() {
if (grapplemod.controllers.containsValue(this)) {
this.attached = false;
-
+
grapplemod.unregisterController(this.entityId);
-
+
if (this.controllerid != grapplemod.AIRID) {
grapplemod.network.sendToServer(new GrappleEndMessage(this.entityId, this.arrowId));
grapplemod.createControl(grapplemod.AIRID, -1, this.entityId, this.entity.worldObj, new vec(0,0,0), 0, null);
}
}
}
-
+
public grappleArrow getArrow() {
return (grappleArrow) world.getEntityByID(arrowId);
}
-
+
public void doClientTick() {
if (this.attached) {
if (this.entity == null || this.entity.isDead) {
@@ -111,7 +111,7 @@ public void doClientTick() {
}
}
}
-
+
public void receivePlayerMovementMessage(float strafe,
float forward, boolean jump) {
playerforward = forward;
@@ -125,7 +125,7 @@ public void receivePlayerMovementMessage(float strafe,
playermovement_unrotated = new vec(strafe, 0, forward);
playermovement = playermovement_unrotated.rotate_yaw((float) (this.entity.rotationYaw * (Math.PI / 180.0)));
}
-
+
public boolean isjumping() {
if (playerjump && waitingonplayerjump) {
waitingonplayerjump = false;
@@ -133,36 +133,36 @@ public boolean isjumping() {
}
return false;
}
-
+
public void updatePlayerPos() {
Entity entity = this.entity;
-
+
if (this.attached) {
if(entity != null) {
if (true) {
this.normalGround();
this.normalCollisions();
// this.applyAirFriction();
-
+
vec arrowpos = this.pos;//this.getPositionVector();
vec playerpos = vec.positionvec(entity);
// Vec3 playermotion = new Vec3(entity.motionX, entity.motionY, entity.motionZ);
-
+
vec oldspherevec = playerpos.sub(arrowpos);
vec spherevec = oldspherevec.changelen(r);
vec spherechange = spherevec.sub(oldspherevec);
// Vec3 spherepos = spherevec.add(arrowpos);
-
+
vec additionalmotion;
if (arrowpos.sub(playerpos).length() < this.r) {
additionalmotion = new vec(0,0,0);
} else {
additionalmotion = spherechange;//new Vec3(0,0,0);
}
-
+
double dist = oldspherevec.length();
this.calctaut(dist);
-
+
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
if (this.isjumping()) {
@@ -176,11 +176,11 @@ public void updatePlayerPos() {
if (motion.dot(motiontorwards) < 0) {
motion.add_ip(motiontorwards);
}
-
+
vec newmotion = dampenmotion(motion, motiontorwards);
motion = new vec(newmotion.x, motion.y, newmotion.z);
// motion = multvec(motion, 0.98);
-
+
if (this.playerforward != 0) {
if (dist < maxlen || this.playerforward > 0 || maxlen == 0) {
// double motionup = this.playerforward;
@@ -198,26 +198,26 @@ public void updatePlayerPos() {
applyPlayerMovement();
}
}
-
+
if (!(this.ongroundtimer > 0)) {
motion.add_ip(0, -0.05, 0);
}
-
+
vec newmotion = motion.add(additionalmotion);
-
+
if (arrowpos.sub(playerpos.add(motion)).length() > r) { // moving away
motion = motion.removealong(spherevec);
}
-
+
// entity.setVelocity(newmotion.xCoord, newmotion.yCoord, newmotion.zCoord);
entity.motionX = newmotion.x;
entity.motionY = newmotion.y;
entity.motionZ = newmotion.z;
-
+
// if (entity instanceof EntityPlayerMP) {
-
+
// ((EntityPlayerMP) entity).playerNetServerHandler.sendPacket(new S12PacketEntityVelocity(entity));
-
+
/*
counter++;
if (counter > 100) {
@@ -226,15 +226,15 @@ public void updatePlayerPos() {
}
*/
// }
-
+
// entity.fallDistance = 0;
-
+
this.updateServerPos();
}
}
}
}
-
+
public void calctaut(double dist) {
if (this.arrow != null) {
if (dist < this.r) {
@@ -299,9 +299,9 @@ public void dojump(Entity player, double jumppower) {
if (jumppower < 0) {
jumppower = 0;
}
-
+
this.unattach();
-
+
if (jumppower > 0) {
if (jumppower > player.motionY + jumppower) {
player.motionY = jumppower;
@@ -309,10 +309,10 @@ public void dojump(Entity player, double jumppower) {
player.motionY += jumppower;
}
}
-
+
this.updateServerPos();
}
-
+
public void dojump(Entity player, vec spherevec) {
double maxjump = 1;
vec jump = new vec(0, maxjump, 0);
@@ -320,14 +320,14 @@ public void dojump(Entity player, vec spherevec) {
jump = jump.proj(spherevec);
}
double jumppower = jump.y;
-
+
if (spherevec != null && spherevec.y > 0) {
jumppower = 0;
}
if ((this.arrow != null) && r < 1 && (player.posY < this.arrow.posY)) {
jumppower = maxjump;
}
-
+
this.dojump(player, jumppower);
}
@@ -336,13 +336,13 @@ public vec dampenmotion(vec motion, vec forward) {
double dampening = 0.05;
return new vec(newmotion.x*dampening + motion.x*(1-dampening), newmotion.y*dampening + motion.y*(1-dampening), newmotion.z*dampening + motion.z*(1-dampening));
}
-
+
public void updateServerPos() {
grapplemod.network.sendToServer(new PlayerMovementMessage(this.entityId, this.entity.posX, this.entity.posY, this.entity.posZ, this.entity.motionX, this.entity.motionY, this.entity.motionZ));
}
-
+
// Vector stuff:
-
+
public void receiveGrappleClick(boolean leftclick) {
if (!leftclick) {
this.unattach();
@@ -355,18 +355,18 @@ public void receiveEnderLaunch(double x, double y, double z) {
this.entity.motionY = this.motion.y;
this.entity.motionZ = this.motion.z;
}
-
+
public void applyAirFriction() {
double vel = this.motion.length();
double dragforce = vel*vel / 200;
-
+
vec airfric = new vec(this.motion.x, this.motion.y, this.motion.z);
airfric.changelen_ip(-dragforce);
this.motion.add_ip(airfric);
}
-
+
public void applyPlayerMovement() {
- System.out.println(motion.length());
+ //grapplemod.LOGGER.debug(motion.length());
motion.add_ip(this.playermovement.changelen(0.015 + motion.length() * 0.01));//0.02 * playermovementmult));
}
}
diff --git a/main/java/com/yyon/grapplinghook/controllers/hookControl.java b/src/main/java/com/yyon/grapplinghook/controllers/hookControl.java
similarity index 94%
rename from main/java/com/yyon/grapplinghook/controllers/hookControl.java
rename to src/main/java/com/yyon/grapplinghook/controllers/hookControl.java
index 6a5b0d7..08d5fc6 100644
--- a/main/java/com/yyon/grapplinghook/controllers/hookControl.java
+++ b/src/main/java/com/yyon/grapplinghook/controllers/hookControl.java
@@ -32,22 +32,22 @@ public hookControl(int arrowId, int entityId, World world, vec pos, int maxlen,
public double acceleration = 0.2;
public float oldstepheight;
public final double playermovementmult = 1;
-
+
@Override
public void updatePlayerPos() {
-
+
/*
super.updatePlayerPos(theplayer);
if (r > 1) {
r -= 1;
}
*/
-
+
Entity entity = this.entity;
-
-// System.out.println(entity == theplayer);
-// System.out.println(entity.worldObj.isRemote);
-
+
+// grapplemod.LOGGER.debug(entity == theplayer);
+// grapplemod.LOGGER.debug(entity.worldObj.isRemote);
+
if (this.attached) {
if(entity != null && entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
@@ -57,17 +57,17 @@ public void updatePlayerPos() {
// this.normalGround();
this.normalCollisions();
// this.applyAirFriction();
-
+
vec arrowpos = this.pos;
vec playerpos = vec.positionvec(player);
-
+
vec oldspherevec = playerpos.sub(arrowpos);
vec spherevec = oldspherevec.changelen(r);
// Vec3 spherechange = spherevec.subtract(oldspherevec);
// Vec3 spherepos = spherevec.add(arrowpos);
-
+
double dist = oldspherevec.length();
-
+
if (this.isjumping()) {
this.dojump(player, spherevec);
return;
@@ -82,14 +82,14 @@ public void updatePlayerPos() {
} else {
applyPlayerMovement();
}
-
+
vec newmotion;
-
+
if (dist < 4) {
if (motion.length() > 0.3) {
motion.mult_ip(0.6);
}
-
+
// if (this.playermovement.lengthVector() > 0.05) {
// this.unattach();
// }
@@ -98,19 +98,19 @@ public void updatePlayerPos() {
entity.motionY = 0;
entity.motionZ = 0;
this.updateServerPos();
-
+
// this.unattach();
}
}
-
+
motion.add_ip(arrowpos.sub(playerpos).changelen(acceleration));
-
+
double speed = motion.proj(oldspherevec).length();
-
+
if (speed > maxspeed) {
motion.changelen_ip(maxspeed);
}
-
+
/*
if (!player.onGround) {
motion = motion.addVector(0, -0.05, 0);
@@ -120,29 +120,29 @@ public void updatePlayerPos() {
}
}
*/
-
+
newmotion = motion;
-
+
vec motiontorwards = spherevec.changelen(-1);
motion = dampenmotion(motion, motiontorwards);
-
+
// entity.setVelocity(newmotion.xCoord, newmotion.yCoord, newmotion.zCoord);
entity.motionX = newmotion.x;
entity.motionY = newmotion.y;
entity.motionZ = newmotion.z;
-
+
// if (player instanceof EntityPlayerMP) {
-
+
// ((EntityPlayerMP) entity).playerNetServerHandler.sendPacket(new S12PacketEntityVelocity(entity));
// }
-
+
player.fallDistance = 0;
-
+
this.updateServerPos();
}
}
}
}
-
+
}
diff --git a/main/java/com/yyon/grapplinghook/controllers/magnetController.java b/src/main/java/com/yyon/grapplinghook/controllers/magnetController.java
similarity index 96%
rename from main/java/com/yyon/grapplinghook/controllers/magnetController.java
rename to src/main/java/com/yyon/grapplinghook/controllers/magnetController.java
index ea32641..1da1baa 100644
--- a/main/java/com/yyon/grapplinghook/controllers/magnetController.java
+++ b/src/main/java/com/yyon/grapplinghook/controllers/magnetController.java
@@ -31,7 +31,7 @@
public class magnetController extends grappleController {
public int repelconf = 0;
public final double playermovementmult = 1.5;
-
+
public magnetController(int arrowId, int entityId, World world, vec pos, int maxlen, int id, int repelconf) {
super(arrowId, entityId, world, pos, maxlen, id);
this.repelconf = repelconf;
@@ -39,41 +39,41 @@ public magnetController(int arrowId, int entityId, World world, vec pos, int max
public void receiveGrappleClick(boolean leftclick) {
super.receiveGrappleClick(leftclick);
-
+
}
-
+
HashMap blockcache = new HashMap();
-
+
public void updatePlayerPos() {
Entity entity = this.entity;
-
+
if (this.attached) {
if(entity != null) {
if (true) {
this.normalGround();
this.normalCollisions();
// this.applyAirFriction();
-
+
vec arrowpos = this.pos;
vec playerpos = vec.positionvec(entity);
-
-
+
+
vec oldspherevec = playerpos.sub(arrowpos);
vec spherevec = oldspherevec.changelen(r);
vec spherechange = spherevec.sub(oldspherevec);
-
+
vec additionalmotion;
if (arrowpos.sub(playerpos).length() < this.r) {
additionalmotion = new vec(0,0,0);
} else {
additionalmotion = spherechange;
}
-
+
double dist = oldspherevec.length();
this.calctaut(dist);
-
+
boolean domagnet = true;
-
+
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
if (this.isjumping()) {
@@ -87,10 +87,10 @@ public void updatePlayerPos() {
if (motion.dot(motiontorwards) < 0) {
motion.add_ip(motiontorwards);
}
-
+
vec newmotion = dampenmotion(motion, motiontorwards);
motion = new vec(newmotion.x, motion.y, newmotion.z);
-
+
if (this.playerforward != 0) {
if (dist < maxlen || this.playerforward > 0 || maxlen == 0) {
additionalmotion = new vec(0, this.playerforward, 0);
@@ -106,55 +106,55 @@ public void updatePlayerPos() {
applyPlayerMovement();
}
}
-
+
if (domagnet && this.repelconf != grapplemod.REPELNONE) {
vec blockpush = check(playerpos, entity.worldObj);
-
+
// if (this.repelconf == grapplemod.REPELSPEED) {
// blockpush.mult_ip(0.5 + motion.length()/2);//0.5);//0.005);
-// System.out.println();
+// grapplemod.LOGGER.debug();
if (this.repelconf == grapplemod.REPELSTRONG) {
blockpush.mult_ip(1.5);
} else if (this.repelconf == grapplemod.REPELWEAK) {
blockpush.mult_ip(0.5);
}
// blockpush.mult_ip(motion.length());
-
+
// blockpush.print();
// vec facing = new vec(entity.getLookVec());
// blockpush.removealong(facing);
this.motion.add_ip(blockpush);
}
-
+
if (!entity.onGround) {
motion.add_ip(0, -0.05, 0);
}
-
+
vec newmotion = motion.add(additionalmotion);
-
+
if (arrowpos.sub(playerpos.add(motion)).length() > r) { // moving away
motion = motion.removealong(spherevec);
}
-
+
entity.motionX = newmotion.x;
entity.motionY = newmotion.y;
entity.motionZ = newmotion.z;
-
+
this.updateServerPos();
}
}
}
}
-
+
public final int radius = 10;
public final double maxpush = 0.3;//0.25;
-
+
public vec check(vec p, World w) {
// long startTime = System.nanoTime();
-
+
p = p.add(0.0, 0.75, 0.0);
vec v = new vec(0, 0, 0);
-
+
/*
for (int x = (int)p.x - radius; x <= (int)p.x + radius; x++) {
for (int y = (int)p.y - radius; y <= (int)p.y + radius; y++) {
@@ -172,9 +172,9 @@ public vec check(vec p, World w) {
}
}
*/
-
+
double t = (1.0 + Math.sqrt(5.0)) / 2.0;
-
+
BlockPos pos = new BlockPos((int) Math.floor(p.x), (int) Math.floor(p.y), (int) Math.floor(p.z));
if (hasblock(pos, w)) {
v.add_ip(0, 1, 0);
@@ -192,19 +192,19 @@ public vec check(vec p, World w) {
v.add_ip(vecdist(p, new vec(-t, 0, -1), w));
v.add_ip(vecdist(p, new vec(-t, 0, 1), w));
}
-
+
if (v.length() > maxpush) {
v.changelen_ip(maxpush);
}
-
+
// long endTime = System.nanoTime();
// long duration = (endTime - startTime); //divide by 1000000 to get milliseconds.
-// System.out.println(duration);
-
+// grapplemod.LOGGER.debug(duration);
+
return v;
}
-
+
public vec vecdist(vec p, vec v, World w) {
for (double i = 0.5; i < 10; i += 0.5) {
vec v2 = v.changelen(i);
@@ -215,7 +215,7 @@ public vec vecdist(vec p, vec v, World w) {
return v3;
}
}
-
+
return new vec(0, 0, 0);
}
@@ -226,7 +226,7 @@ public boolean hasblock(BlockPos pos, World w) {
if (!(b.isAir(w, pos.x, pos.y, pos.z))) {
isblock = true;
}
-
+
// blockcache.put(pos, (Boolean) isblock);
return isblock;
// } else {
diff --git a/main/java/com/yyon/grapplinghook/controllers/multihookController.java b/src/main/java/com/yyon/grapplinghook/controllers/multihookController.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/controllers/multihookController.java
rename to src/main/java/com/yyon/grapplinghook/controllers/multihookController.java
diff --git a/main/java/com/yyon/grapplinghook/controllers/repelController.java b/src/main/java/com/yyon/grapplinghook/controllers/repelController.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/controllers/repelController.java
rename to src/main/java/com/yyon/grapplinghook/controllers/repelController.java
diff --git a/main/java/com/yyon/grapplinghook/controllers/smartHookControl.java b/src/main/java/com/yyon/grapplinghook/controllers/smartHookControl.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/controllers/smartHookControl.java
rename to src/main/java/com/yyon/grapplinghook/controllers/smartHookControl.java
diff --git a/main/java/com/yyon/grapplinghook/crosshairRenderer.java b/src/main/java/com/yyon/grapplinghook/crosshairRenderer.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/crosshairRenderer.java
rename to src/main/java/com/yyon/grapplinghook/crosshairRenderer.java
diff --git a/main/java/com/yyon/grapplinghook/entities/RenderGrappleArrow.java b/src/main/java/com/yyon/grapplinghook/entities/RenderGrappleArrow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/entities/RenderGrappleArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/RenderGrappleArrow.java
diff --git a/main/java/com/yyon/grapplinghook/entities/enderArrow.java b/src/main/java/com/yyon/grapplinghook/entities/enderArrow.java
similarity index 95%
rename from main/java/com/yyon/grapplinghook/entities/enderArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/enderArrow.java
index 90c0c5a..3a8afeb 100644
--- a/main/java/com/yyon/grapplinghook/entities/enderArrow.java
+++ b/src/main/java/com/yyon/grapplinghook/entities/enderArrow.java
@@ -27,19 +27,19 @@ public class enderArrow extends grappleArrow
public enderArrow(World worldIn) {
super(worldIn);
}
-
+
public enderArrow(World worldIn, EntityLivingBase shooter,
boolean righthand) {
super(worldIn, shooter, righthand);
}
-
+
@Override
protected float func_70182_d()
{
return 20F;
}
-
-
+
+
@Override
public int getControlId() {
return grapplemod.ENDERID;
@@ -47,7 +47,7 @@ public int getControlId() {
/*
@Override
public void createControl() {
- System.out.println("Creating ender controller");
+ grapplemod.LOGGER.debug("Creating ender controller");
this.control = new enderController(this.getEntityId(), this.shootingEntity.getEntityId(), this.worldObj, new Vec3(this.posX, this.posY, this.posZ));
}
*/
diff --git a/main/java/com/yyon/grapplinghook/entities/grappleArrow.java b/src/main/java/com/yyon/grapplinghook/entities/grappleArrow.java
similarity index 97%
rename from main/java/com/yyon/grapplinghook/entities/grappleArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/grappleArrow.java
index a2d26e1..7a10917 100644
--- a/main/java/com/yyon/grapplinghook/entities/grappleArrow.java
+++ b/src/main/java/com/yyon/grapplinghook/entities/grappleArrow.java
@@ -46,29 +46,29 @@ public class grappleArrow extends EntityThrowable implements IEntityAdditionalSp
{
public Entity shootingEntity = null;
public int shootingEntityID;
-
+
private boolean firstattach = false;
public vec thispos;
-
+
public boolean righthand = true;
-
+
public boolean attached = false;
-
+
public double taut = 1;
-
+
public boolean ignoreFrustumCheck = true;
-
+
public grappleArrow(World worldIn) {
super(worldIn);
}
-
+
public grappleArrow(World worldIn, EntityLivingBase shooter,
boolean righthand) {
super(worldIn, shooter);
-
+
this.shootingEntity = shooter;
this.shootingEntityID = this.shootingEntity.getEntityId();
-
+
/*
double x = 0.36;
if (righthand) {x = -0.36;}
@@ -79,18 +79,18 @@ public grappleArrow(World worldIn, EntityLivingBase shooter,
grapplemod.updateMaxLen(worldIn);
grapplemod.updateGrapplingBlocks(worldIn);
-
+
this.righthand = righthand;
}
-
+
@Override
public void onEntityUpdate(){
super.onEntityUpdate();
-
+
if (this.shootingEntityID == 0) { // removes ghost grappling hooks
this.kill();
}
-
+
if (this.firstattach) {
this.motionX = 0;
this.motionY = 0;
@@ -98,13 +98,13 @@ public void onEntityUpdate(){
this.firstattach = false;
super.setPosition(this.thispos.x, this.thispos.y, this.thispos.z);
}
-
-
+
+
if (this.toofaraway()) {
this.removeServer();
}
}
-
+
@Override
@SideOnly(Side.CLIENT)
public boolean isInRangeToRender3d(double x, double y, double z) {
@@ -122,7 +122,7 @@ public boolean isInRangeToRenderDist(double distance) {
@Override
@SideOnly(Side.CLIENT)
public AxisAlignedBB getRenderBoundingBox() {
- return new AxisAlignedBB(-RenderBoundingBoxSize, -RenderBoundingBoxSize, -RenderBoundingBoxSize,
+ return new AxisAlignedBB(-RenderBoundingBoxSize, -RenderBoundingBoxSize, -RenderBoundingBoxSize,
RenderBoundingBoxSize, RenderBoundingBoxSize, RenderBoundingBoxSize);
}
*/
@@ -150,15 +150,15 @@ public void setPosition(double x, double y, double z) {
}
super.setPosition(x, y, z);
}
-
-
+
+
@Override
public void writeSpawnData(ByteBuf data)
{
data.writeInt(this.shootingEntity != null ? this.shootingEntity.getEntityId() : 0);
data.writeBoolean(this.righthand);
}
-
+
@Override
public void readSpawnData(ByteBuf data)
{
@@ -166,11 +166,11 @@ public void readSpawnData(ByteBuf data)
this.shootingEntity = this.worldObj.getEntityByID(this.shootingEntityID);
this.righthand = data.readBoolean();
}
-
+
public void remove() {
this.kill();
}
-
+
@Override
public String toString() {
return super.toString() + String.valueOf(System.identityHashCode(this)) + "]";
@@ -186,23 +186,23 @@ protected void onImpact(MovingObjectPosition movingobjectposition) {
if (entityhit == this.shootingEntity) {
return;
}
-
+
vec playerpos = vec.positionvec(this.shootingEntity);
vec entitypos = vec.positionvec(entityhit);
vec yank = playerpos.sub(entitypos).mult(0.4);
entityhit.addVelocity(yank.x, Math.min(yank.y, 2), yank.z);
-
+
this.removeServer();
return;
}
-
+
BlockPos blockpos = null;
-
+
if (movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
blockpos = new BlockPos(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);
}
vec vec3 = null;
-
+
if (movingobjectposition != null)
{
vec3 = new vec(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord);
@@ -211,13 +211,13 @@ protected void onImpact(MovingObjectPosition movingobjectposition) {
}
}
}
-
+
public void serverAttach(BlockPos blockpos, vec pos, int sideHit) {
if (this.attached) {
return;
}
this.attached = true;
-
+
if (blockpos != null) {
if (!grapplemod.anyblocks) {
Block block = this.worldObj.getBlock(blockpos.x, blockpos.y, blockpos.z);
@@ -229,18 +229,18 @@ public void serverAttach(BlockPos blockpos, vec pos, int sideHit) {
}
}
}
-
+
vec vec3 = vec.positionvec(this);
vec3.add_ip(vec.motionvec(this));
if (pos != null) {
vec3 = pos;
-
+
this.setPosition(vec3.x, vec3.y, vec3.z);
}
-
+
//west -x
//north -z
- System.out.println(sideHit);
+ //grapplemod.LOGGER.debug(sideHit);
if (sideHit == 0) { // bottom
this.posY -= 0.3;
// } else if (sideHit == 1) { // top
@@ -257,18 +257,18 @@ public void serverAttach(BlockPos blockpos, vec pos, int sideHit) {
if (this.toofaraway()) {
- System.out.println("TOOFAR");
+ //grapplemod.LOGGER.error("TOOFAR");
return;
}
-
+
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
-
+
this.thispos = vec.positionvec(this);
this.firstattach = true;
grapplemod.attached.add(this.shootingEntityID);
-
+
grapplemod.sendtocorrectclient(new GrappleAttachMessage(this.getEntityId(), this.posX, this.posY, this.posZ, this.getControlId(), this.shootingEntityID, grapplemod.grapplingLength, blockpos), this.shootingEntityID, this.worldObj);
if (this.shootingEntity instanceof EntityPlayerMP) { // fixes strange bug in LAN
EntityPlayerMP sender = (EntityPlayerMP) this.shootingEntity;
@@ -282,22 +282,22 @@ public void serverAttach(BlockPos blockpos, vec pos, int sideHit) {
}
}
}
-
+
public void clientAttach(double x, double y, double z) {
this.setAttachPos(x, y, z);
-
+
if (this.shootingEntity instanceof EntityPlayer) {
grapplemod.proxy.resetlaunchertime(this.shootingEntityID);
}
}
-
-
+
+
@Override
protected float getGravityVelocity()
{
return 0F;
}
-
+
@Override
protected float func_70182_d()
{
@@ -309,7 +309,7 @@ public void removeServer() {
this.shootingEntityID = 0;
}
-
+
public int getControlId() {
return grapplemod.GRAPPLEID;
}
diff --git a/main/java/com/yyon/grapplinghook/entities/hookArrow.java b/src/main/java/com/yyon/grapplinghook/entities/hookArrow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/entities/hookArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/hookArrow.java
diff --git a/main/java/com/yyon/grapplinghook/entities/magnetArrow.java b/src/main/java/com/yyon/grapplinghook/entities/magnetArrow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/entities/magnetArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/magnetArrow.java
diff --git a/main/java/com/yyon/grapplinghook/entities/multihookArrow.java b/src/main/java/com/yyon/grapplinghook/entities/multihookArrow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/entities/multihookArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/multihookArrow.java
diff --git a/main/java/com/yyon/grapplinghook/entities/smartHookArrow.java b/src/main/java/com/yyon/grapplinghook/entities/smartHookArrow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/entities/smartHookArrow.java
rename to src/main/java/com/yyon/grapplinghook/entities/smartHookArrow.java
diff --git a/main/java/com/yyon/grapplinghook/grapplemod.java b/src/main/java/com/yyon/grapplinghook/grapplemod.java
similarity index 93%
rename from main/java/com/yyon/grapplinghook/grapplemod.java
rename to src/main/java/com/yyon/grapplinghook/grapplemod.java
index 6d8121a..0b809ba 100644
--- a/main/java/com/yyon/grapplinghook/grapplemod.java
+++ b/src/main/java/com/yyon/grapplinghook/grapplemod.java
@@ -5,6 +5,7 @@
import java.util.HashSet;
import java.util.Random;
+import com.yyon.grapplemod.Tags;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -64,6 +65,8 @@
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.Side;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
/*
* This file is part of GrappleMod.
@@ -86,14 +89,12 @@
// Pull mobs
// Attach 2 things together
-@Mod(modid = grapplemod.MODID, version = grapplemod.VERSION)
+@Mod(modid = Tags.MODID, version = Tags.VERSION)
public class grapplemod {
- public grapplemod(){}
+ public static final Logger LOGGER = LogManager.getLogger("grapplemod");
- public static final String MODID = "grapplemod";
-
- public static final String VERSION = "1.7.10-v10";
+ public grapplemod(){}
public static Item grapplebowitem;
public static Item hookshotitem;
@@ -104,15 +105,15 @@ public grapplemod(){}
public static Item magnetbowitem;
public static Item repelleritem;
public static Item multihookitem;
-
+
public static Object instance;
-
+
public static SimpleNetworkWrapper network;
-
+
public static HashMap controllers = new HashMap(); // client side
public static HashMap controllerpos = new HashMap();
public static HashSet attached = new HashSet(); // server side
-
+
private static int controllerid = 0;
public static int GRAPPLEID = controllerid++;
public static int ENDERID = controllerid++;
@@ -123,59 +124,59 @@ public grapplemod(){}
public static int MULTISUBID = controllerid++;
public static int AIRID = controllerid++;
public static int SMARTHOOKID = controllerid++;
-
+
public static int REPELCONFIGS = 0;
// public static int REPELSPEED = REPELCONFIGS++;
public static int REPELSTRONG = REPELCONFIGS++;
public static int REPELWEAK = REPELCONFIGS++;
public static int REPELNONE = REPELCONFIGS++;
-
+
public static int grapplingLength = 0;
public static boolean anyblocks = true;
public static ArrayList grapplingblocks;
public static boolean removeblocks = false;
-
+
@SidedProxy(clientSide="com.yyon.grapplinghook.ClientProxyClass", serverSide="com.yyon.grapplinghook.ServerProxyClass")
public static CommonProxyClass proxy;
-
+
@EventHandler
public void load(FMLInitializationEvent event){
GameRegistry.addRecipe(new ItemStack(grapplebowitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(Items.iron_pickaxe, 1), Character.valueOf('4'), new ItemStack(Items.lead, 1),
+ "X2",
+ "4X", Character.valueOf('2'), new ItemStack(Items.iron_pickaxe, 1), Character.valueOf('4'), new ItemStack(Items.lead, 1),
});
GameRegistry.addRecipe(new ItemStack(hookshotitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(Blocks.piston, 1),
+ "X2",
+ "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(Blocks.piston, 1),
});
GameRegistry.addRecipe(new ItemStack(smarthookitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(hookshotitem, 1), Character.valueOf('4'), new ItemStack(Items.redstone, 1),
+ "X2",
+ "4X", Character.valueOf('2'), new ItemStack(hookshotitem, 1), Character.valueOf('4'), new ItemStack(Items.redstone, 1),
});
GameRegistry.addRecipe(new ItemStack(launcheritem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(Items.ender_pearl, 1), Character.valueOf('4'), new ItemStack(Blocks.piston, 1),
+ "X2",
+ "4X", Character.valueOf('2'), new ItemStack(Items.ender_pearl, 1), Character.valueOf('4'), new ItemStack(Blocks.piston, 1),
});
GameRegistry.addRecipe(new ItemStack(enderhookitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(launcheritem, 1),
+ "X2",
+ "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(launcheritem, 1),
});
GameRegistry.addRecipe(new ItemStack(repelleritem, 1), new Object[]{
- "X2X",
+ "X2X",
"242",
- "X2X", Character.valueOf('2'), new ItemStack(Items.iron_ingot, 1), Character.valueOf('4'), new ItemStack(Items.compass, 1),
+ "X2X", Character.valueOf('2'), new ItemStack(Items.iron_ingot, 1), Character.valueOf('4'), new ItemStack(Items.compass, 1),
});
GameRegistry.addRecipe(new ItemStack(magnetbowitem, 1), new Object[]{
- "X2",
- "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(repelleritem, 1),
+ "X2",
+ "4X", Character.valueOf('2'), new ItemStack(grapplebowitem, 1), Character.valueOf('4'), new ItemStack(repelleritem, 1),
});
GameRegistry.addRecipe(new ItemStack(longfallboots, 1), new Object[]{
- "2",
- "4", Character.valueOf('2'), new ItemStack(Items.diamond_boots, 1), Character.valueOf('4'), new ItemStack(Blocks.wool, 1),
+ "2",
+ "4", Character.valueOf('2'), new ItemStack(Items.diamond_boots, 1), Character.valueOf('4'), new ItemStack(Blocks.wool, 1),
});
GameRegistry.addRecipe(new ItemStack(multihookitem, 1), new Object[]{
- "X2",
- "2X", Character.valueOf('2'), new ItemStack(hookshotitem, 1),
+ "X2",
+ "2X", Character.valueOf('2'), new ItemStack(hookshotitem, 1),
});
}
@@ -193,14 +194,14 @@ public void serverLoad(FMLServerStartingEvent event){
event.getServer().worldServerForDimension(0).getGameRules().addGameRule("grapplingBlocks", "any");
event.getServer().worldServerForDimension(0).getGameRules().addGameRule("grapplingNonBlocks", "none");
}
-
+
public static void updateMaxLen(World world) {
String s = MinecraftServer.getServer().worldServerForDimension(0).getGameRules().getGameRuleStringValue("grapplingLength");
if (!s.equals("")) {
grapplemod.grapplingLength = Integer.parseInt(s);
}
}
-
+
public static void updateGrapplingBlocks(World world) {
String s = MinecraftServer.getServer().worldServerForDimension(0).getGameRules().getGameRuleStringValue("grapplingBlocks");
if (s.equals("any") || s.equals("")) {
@@ -215,12 +216,12 @@ public static void updateGrapplingBlocks(World world) {
anyblocks = false;
removeblocks = false;
}
-
+
if (!anyblocks) {
String[] blockstr = s.split(",");
-
+
grapplingblocks = new ArrayList();
-
+
for(String str:blockstr){
str = str.trim();
String modid;
@@ -233,14 +234,14 @@ public static void updateGrapplingBlocks(World world) {
modid = "minecraft";
name = str;
}
-
+
Block b = GameRegistry.findBlock(modid, name);
-
+
grapplingblocks.add(b);
}
}
}
-
+
@EventHandler
public void preInit(FMLPreInitializationEvent event){
grapplebowitem = new grappleBow();
@@ -261,14 +262,14 @@ public void preInit(FMLPreInitializationEvent event){
GameRegistry.registerItem(repelleritem, "repeller");
multihookitem = new multiBow();
GameRegistry.registerItem(multihookitem, "multihook");
-
+
registerEntity(grappleArrow.class, "grappleArrow");
registerEntity(enderArrow.class, "enderArrow");
registerEntity(hookArrow.class, "hookArrow");
registerEntity(magnetArrow.class, "magnetArrow");
registerEntity(multihookArrow.class, "multihookArrow");
registerEntity(smartHookArrow.class, "smartHookArrow");
-
+
proxy.preInit(event);
network = NetworkRegistry.INSTANCE.newSimpleChannel("grapplemodchannel");
byte id = 0;
@@ -280,31 +281,31 @@ public void preInit(FMLPreInitializationEvent event){
network.registerMessage(MultiHookMessage.Handler.class, MultiHookMessage.class, id++, Side.SERVER);
network.registerMessage(ToolConfigMessage.Handler.class, ToolConfigMessage.class, id++, Side.SERVER);
}
-
+
@EventHandler
public void Init(FMLInitializationEvent event) {
proxy.init(event, this);
}
-
+
@EventHandler
public void postInit(FMLPostInitializationEvent event) {
proxy.postInit(event);
}
-
+
int entityID = 0;
public void registerEntity(Class extends Entity> entityClass, String name)
{
EntityRegistry.registerModEntity(entityClass, name, entityID++, this, 900, 1, true);
}
-
+
public static void registerController(int entityId, grappleController controller) {
if (controllers.containsKey(entityId)) {
controllers.get(entityId).unattach();
}
-
+
controllers.put(entityId, controller);
}
-
+
public static void unregisterController(int entityId) {
controllers.remove(entityId);
}
@@ -315,7 +316,7 @@ public static void receiveGrappleClick(int id,
if (controller != null) {
controller.receiveGrappleClick(leftclick);
} else {
- System.out.println("Couldn't find controller");
+ grapplemod.LOGGER.error("Couldn't find controller");
}
}
@@ -324,19 +325,19 @@ public static void receiveEnderLaunch(int id, double x, double y, double z) {
if (controller != null) {
controller.receiveEnderLaunch(x, y, z);
} else {
- System.out.println("Couldn't find controller");
+ grapplemod.LOGGER.error("Couldn't find controller");
}
}
-
+
public static void sendtocorrectclient(IMessage message, int playerid, World w) {
Entity entity = w.getEntityByID(playerid);
if (entity instanceof EntityPlayerMP) {
grapplemod.network.sendTo(message, (EntityPlayerMP) entity);
} else {
- System.out.println("ERROR! couldn't find player");
+ grapplemod.LOGGER.error("ERROR! couldn't find player");
}
}
-
+
public static grappleController createControl(int id, int arrowid, int entityid, World world, vec pos, int maxlen, BlockPos blockpos) {
grappleArrow arrow = null;
@@ -344,16 +345,16 @@ public static grappleController createControl(int id, int arrowid, int entityid,
if (arrowentity != null && arrowentity instanceof grappleArrow) {
arrow = (grappleArrow) arrowentity;
}
-
+
if (id != MULTISUBID) {
grappleController currentcontroller = controllers.get(entityid);
if (currentcontroller != null) {
currentcontroller.unattach();
}
}
-
- System.out.println(blockpos);
-
+
+ //grapplemod.LOGGER.debug(blockpos);
+
grappleController control = null;
if (id == GRAPPLEID) {
control = new grappleController(arrowid, entityid, world, pos, maxlen, id);
@@ -389,20 +390,20 @@ public static grappleController createControl(int id, int arrowid, int entityid,
}
}
if (!created) {
- System.out.println("Couldn't create");
+ grapplemod.LOGGER.error("Couldn't create");
grapplemod.removesubarrow(arrowid);
}
} else if (id == AIRID) {
- System.out.println("AIR FRICTION CONTROLLER");
+ //System.out.println("AIR FRICTION CONTROLLER");
control = new airfrictionController(arrowid, entityid, world, pos, maxlen, id);
}
if (blockpos != null && control != null) {
grapplemod.controllerpos.put(blockpos, control);
}
-
+
return control;
}
-
+
public static void removesubarrow(int id) {
grapplemod.network.sendToServer(new GrappleEndMessage(-1, id));
}
@@ -413,21 +414,21 @@ public static void receiveGrappleEnd(int id, World world, int arrowid) {
(id));
} else {
}
-
+
if (arrowid != -1) {
Entity grapple = world.getEntityByID(arrowid);
if (grapple instanceof grappleArrow) {
((grappleArrow) grapple).removeServer();
} else {
-
+
}
}
-
+
Entity entity = world.getEntityByID(id);
if (entity != null) {
entity.fallDistance = 0;
}
-
+
grapplemod.removeallmultihookarrows();
}
@@ -436,53 +437,53 @@ public static void receiveMultihookMessage(int id, World w, boolean sneaking) {
Entity e = w.getEntityByID(id);
if (e != null && e instanceof EntityLivingBase) {
EntityLivingBase player = (EntityLivingBase) e;
-
+
float angle = multiBow.getAngle(player);
-
+
//vec look = new vec(player.getLookVec());
-
- //System.out.println(player.rotationPitch);
- //System.out.println(player.rotationYaw);
-
+
+ //grapplemod.LOGGER.debug(player.rotationPitch);
+ //grapplemod.LOGGER.debug(player.rotationYaw);
+
/*
grappleArrow arrow = new grappleArrow(w, player, false);
arrow.setHeadingFromThrower(player, (float)look.getPitch(), (float)look.getYaw(), 0.0F, arrow.getVelocity(), 0.0F);
w.spawnEntityInWorld(arrow);
*/
-
+
vec anglevec = new vec(0,0,1).rotate_yaw(Math.toRadians(-angle));
anglevec = anglevec.rotate_pitch(Math.toRadians(-player.rotationPitch));
anglevec = anglevec.rotate_yaw(Math.toRadians(player.rotationYaw));
multihookArrow entityarrow = new multihookArrow(w, player, false);
entityarrow.setHeadingFromThrower(player, (float) anglevec.getPitch(), (float)anglevec.getYaw(), 0.0F, entityarrow.func_70182_d(), 0.0F);
-
+
/*
vec pos = vec.positionvec(entityarrow);
pos.add_ip(new vec(0.36, -0.175, 0.45).rotate_yaw(Math.toRadians(player.rotationYaw)));
entityarrow.setPosition(pos.x, pos.y, pos.z);
*/
-
+
w.spawnEntityInWorld(entityarrow);
multihookarrows.add(entityarrow);
-
-
+
+
anglevec = new vec(0,0,1).rotate_yaw(Math.toRadians(angle));
anglevec = anglevec.rotate_pitch(Math.toRadians(-player.rotationPitch));
anglevec = anglevec.rotate_yaw(Math.toRadians(player.rotationYaw));
entityarrow = new multihookArrow(w, player, true);
entityarrow.setHeadingFromThrower(player, (float) anglevec.getPitch(), (float)anglevec.getYaw(), 0.0F, entityarrow.func_70182_d(), 0.0F);
-
+
/*
pos = vec.positionvec(entityarrow);
pos.add_ip(new vec(-0.36, -0.175, 0.45).rotate_yaw(Math.toRadians(player.rotationYaw)));
entityarrow.setPosition(pos.x, pos.y, pos.z);
*/
-
+
w.spawnEntityInWorld(entityarrow);
multihookarrows.add(entityarrow);
}
}
-
+
public static void removeallmultihookarrows() {
for (multihookArrow arrow : multihookarrows) {
if (arrow != null && !arrow.isDead) {
@@ -495,7 +496,7 @@ public static void receiveToolConfigMessage(int id, World w) {
Entity e = w.getEntityByID(id);
if (e != null && e instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) e;
-
+
ItemStack stack = player.getHeldItem();
Item item = stack.getItem();
if (item instanceof multiBow) {
@@ -507,7 +508,7 @@ public static void receiveToolConfigMessage(int id, World w) {
boolean slow = compound.getBoolean("slow");
slow = !slow;
compound.setBoolean("slow", slow);
-
+
if (slow) {
player.addChatMessage(new ChatComponentText("Set to slow mode"));
} else {
@@ -525,7 +526,7 @@ public static void receiveToolConfigMessage(int id, World w) {
repelconf = 0;
}
compound.setInteger("repelconf", repelconf);
-
+
// if (repelconf == REPELSPEED) {
// player.addChatMessage(new TextComponentString("Repel force set to speed based"));
if (repelconf == REPELSTRONG) {
@@ -544,7 +545,7 @@ public static void receiveToolConfigMessage(int id, World w) {
boolean slow = compound.getBoolean("slow");
slow = !slow;
compound.setBoolean("slow", slow);
-
+
if (slow) {
player.addChatMessage(new ChatComponentText("Set to slow mode"));
} else {
diff --git a/main/java/com/yyon/grapplinghook/items/LongFallBoots.java b/src/main/java/com/yyon/grapplinghook/items/LongFallBoots.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/LongFallBoots.java
rename to src/main/java/com/yyon/grapplinghook/items/LongFallBoots.java
diff --git a/main/java/com/yyon/grapplinghook/items/clickitem.java b/src/main/java/com/yyon/grapplinghook/items/clickitem.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/clickitem.java
rename to src/main/java/com/yyon/grapplinghook/items/clickitem.java
diff --git a/main/java/com/yyon/grapplinghook/items/enderBow.java b/src/main/java/com/yyon/grapplinghook/items/enderBow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/enderBow.java
rename to src/main/java/com/yyon/grapplinghook/items/enderBow.java
diff --git a/main/java/com/yyon/grapplinghook/items/grappleBow.java b/src/main/java/com/yyon/grapplinghook/items/grappleBow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/grappleBow.java
rename to src/main/java/com/yyon/grapplinghook/items/grappleBow.java
diff --git a/main/java/com/yyon/grapplinghook/items/hookBow.java b/src/main/java/com/yyon/grapplinghook/items/hookBow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/hookBow.java
rename to src/main/java/com/yyon/grapplinghook/items/hookBow.java
diff --git a/main/java/com/yyon/grapplinghook/items/launcherItem.java b/src/main/java/com/yyon/grapplinghook/items/launcherItem.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/launcherItem.java
rename to src/main/java/com/yyon/grapplinghook/items/launcherItem.java
diff --git a/main/java/com/yyon/grapplinghook/items/magnetBow.java b/src/main/java/com/yyon/grapplinghook/items/magnetBow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/magnetBow.java
rename to src/main/java/com/yyon/grapplinghook/items/magnetBow.java
diff --git a/main/java/com/yyon/grapplinghook/items/multiBow.java b/src/main/java/com/yyon/grapplinghook/items/multiBow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/multiBow.java
rename to src/main/java/com/yyon/grapplinghook/items/multiBow.java
diff --git a/main/java/com/yyon/grapplinghook/items/repeller.java b/src/main/java/com/yyon/grapplinghook/items/repeller.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/repeller.java
rename to src/main/java/com/yyon/grapplinghook/items/repeller.java
diff --git a/main/java/com/yyon/grapplinghook/items/smartHookBow.java b/src/main/java/com/yyon/grapplinghook/items/smartHookBow.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/items/smartHookBow.java
rename to src/main/java/com/yyon/grapplinghook/items/smartHookBow.java
diff --git a/main/java/com/yyon/grapplinghook/network/GrappleAttachMessage.java b/src/main/java/com/yyon/grapplinghook/network/GrappleAttachMessage.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/network/GrappleAttachMessage.java
rename to src/main/java/com/yyon/grapplinghook/network/GrappleAttachMessage.java
diff --git a/main/java/com/yyon/grapplinghook/network/GrappleAttachPosMessage.java b/src/main/java/com/yyon/grapplinghook/network/GrappleAttachPosMessage.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/network/GrappleAttachPosMessage.java
rename to src/main/java/com/yyon/grapplinghook/network/GrappleAttachPosMessage.java
diff --git a/main/java/com/yyon/grapplinghook/network/GrappleClickMessage.java b/src/main/java/com/yyon/grapplinghook/network/GrappleClickMessage.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/network/GrappleClickMessage.java
rename to src/main/java/com/yyon/grapplinghook/network/GrappleClickMessage.java
diff --git a/main/java/com/yyon/grapplinghook/network/GrappleEndMessage.java b/src/main/java/com/yyon/grapplinghook/network/GrappleEndMessage.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/network/GrappleEndMessage.java
rename to src/main/java/com/yyon/grapplinghook/network/GrappleEndMessage.java
diff --git a/main/java/com/yyon/grapplinghook/network/MultiHookMessage.java b/src/main/java/com/yyon/grapplinghook/network/MultiHookMessage.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/network/MultiHookMessage.java
rename to src/main/java/com/yyon/grapplinghook/network/MultiHookMessage.java
diff --git a/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java.orig b/src/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java
similarity index 61%
rename from main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java.orig
rename to src/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java
index 708cee8..85f8997 100644
--- a/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java.orig
+++ b/src/main/java/com/yyon/grapplinghook/network/PlayerMovementMessage.java
@@ -1,28 +1,15 @@
package com.yyon.grapplinghook.network;
+import com.yyon.grapplinghook.grapplemod;
import io.netty.buffer.ByteBuf;
-
-import java.lang.reflect.Field;
-
import net.minecraft.entity.Entity;
-<<<<<<< HEAD
+import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
//* // 1.8 Compatability
-=======
-import net.minecraft.entity.player.EntityPlayerMP;
-import net.minecraft.network.NetHandlerPlayServer;
-import net.minecraft.util.IThreadListener;
-import net.minecraft.world.World;
-import net.minecraft.world.WorldServer;
-import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
-import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
->>>>>>> 6c8b29cf1a9f87c1801402122aee8a079fcdc67a
/*
* This file is part of GrappleMod.
@@ -42,41 +29,41 @@
*/
public class PlayerMovementMessage implements IMessage {
-
- public int entityId;
- public double x;
- public double y;
- public double z;
- public double mx;
- public double my;
- public double mz;
-
- public PlayerMovementMessage() {
- }
-
+
+ public int entityId;
+ public double x;
+ public double y;
+ public double z;
+ public double mx;
+ public double my;
+ public double mz;
+
+ public PlayerMovementMessage() {
+ }
+
public PlayerMovementMessage(int entityId, double x, double y, double z, double mx, double my, double mz) {
- this.entityId = entityId;
- this.x = x;
- this.y = y;
- this.z = z;
- this.mx = mx;
- this.my = my;
- this.mz = mz;
+ this.entityId = entityId;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.mx = mx;
+ this.my = my;
+ this.mz = mz;
}
@Override
public void fromBytes(ByteBuf buf) {
- try {
- this.entityId = buf.readInt();
- this.x = buf.readDouble();
- this.y = buf.readDouble();
- this.z = buf.readDouble();
- this.mx = buf.readDouble();
- this.my = buf.readDouble();
- this.mz = buf.readDouble();
- } catch (Exception e) {
- System.out.println(buf);
- }
+ try {
+ this.entityId = buf.readInt();
+ this.x = buf.readDouble();
+ this.y = buf.readDouble();
+ this.z = buf.readDouble();
+ this.mx = buf.readDouble();
+ this.my = buf.readDouble();
+ this.mz = buf.readDouble();
+ } catch (Exception e) {
+ grapplemod.LOGGER.error(buf);
+ }
}
@Override
@@ -88,21 +75,21 @@ public void toBytes(ByteBuf buf) {
buf.writeDouble(mx);
buf.writeDouble(my);
buf.writeDouble(mz);
-
+
}
public static class Handler implements IMessageHandler {
-
- public class runner implements Runnable {
- PlayerMovementMessage message;
- MessageContext ctx;
-
- public runner(PlayerMovementMessage message, MessageContext ctx) {
- super();
- this.message = message;
- this.ctx = ctx;
- }
-
+
+ public class runner implements Runnable {
+ PlayerMovementMessage message;
+ MessageContext ctx;
+
+ public runner(PlayerMovementMessage message, MessageContext ctx) {
+ super();
+ this.message = message;
+ this.ctx = ctx;
+ }
+
@Override
public void run() {
World world = ctx.getServerHandler().playerEntity.worldObj;
@@ -115,12 +102,14 @@ public void run() {
entity.motionY = message.my;
entity.motionZ = message.mz;
if (entity instanceof EntityPlayerMP) {
- EntityPlayerMP player = ((EntityPlayerMP) entity);
- player.connection.update();
+ EntityPlayerMP player = ((EntityPlayerMP) entity);
+ player.onUpdateEntity();
+ player.setPositionAndRotation(message.x, message.y, message.z, player.rotationYaw, player.rotationPitch);
+ world.updateEntity(player);
}
}
- }
-
+ }
+
@Override
public IMessage onMessage(PlayerMovementMessage message, MessageContext ctx) {
new runner(message, ctx).run();
diff --git a/main/java/com/yyon/grapplinghook/network/ToolConfigMessage.java b/src/main/java/com/yyon/grapplinghook/network/ToolConfigMessage.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/network/ToolConfigMessage.java
rename to src/main/java/com/yyon/grapplinghook/network/ToolConfigMessage.java
diff --git a/main/java/com/yyon/grapplinghook/vec.java b/src/main/java/com/yyon/grapplinghook/vec.java
similarity index 100%
rename from main/java/com/yyon/grapplinghook/vec.java
rename to src/main/java/com/yyon/grapplinghook/vec.java
diff --git a/src/main/resources/LICENSE b/src/main/resources/LICENSE
new file mode 100644
index 0000000..20d40b6
--- /dev/null
+++ b/src/main/resources/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
\ No newline at end of file
diff --git a/main/resources/assets/grapplemod/lang/en_US.lang b/src/main/resources/assets/grapplemod/lang/en_US.lang
similarity index 100%
rename from main/resources/assets/grapplemod/lang/en_US.lang
rename to src/main/resources/assets/grapplemod/lang/en_US.lang
diff --git a/main/resources/assets/grapplemod/models/item/enderhook.json b/src/main/resources/assets/grapplemod/models/item/enderhook.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/enderhook.json
rename to src/main/resources/assets/grapplemod/models/item/enderhook.json
diff --git a/main/resources/assets/grapplemod/models/item/grapplinghook.json b/src/main/resources/assets/grapplemod/models/item/grapplinghook.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/grapplinghook.json
rename to src/main/resources/assets/grapplemod/models/item/grapplinghook.json
diff --git a/main/resources/assets/grapplemod/models/item/hookshot.json b/src/main/resources/assets/grapplemod/models/item/hookshot.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/hookshot.json
rename to src/main/resources/assets/grapplemod/models/item/hookshot.json
diff --git a/main/resources/assets/grapplemod/models/item/hookshotrope.json b/src/main/resources/assets/grapplemod/models/item/hookshotrope.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/hookshotrope.json
rename to src/main/resources/assets/grapplemod/models/item/hookshotrope.json
diff --git a/main/resources/assets/grapplemod/models/item/launcheritem.json b/src/main/resources/assets/grapplemod/models/item/launcheritem.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/launcheritem.json
rename to src/main/resources/assets/grapplemod/models/item/launcheritem.json
diff --git a/main/resources/assets/grapplemod/models/item/longfallboots.json b/src/main/resources/assets/grapplemod/models/item/longfallboots.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/longfallboots.json
rename to src/main/resources/assets/grapplemod/models/item/longfallboots.json
diff --git a/main/resources/assets/grapplemod/models/item/magnetbow.json b/src/main/resources/assets/grapplemod/models/item/magnetbow.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/magnetbow.json
rename to src/main/resources/assets/grapplemod/models/item/magnetbow.json
diff --git a/main/resources/assets/grapplemod/models/item/multihook.json b/src/main/resources/assets/grapplemod/models/item/multihook.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/multihook.json
rename to src/main/resources/assets/grapplemod/models/item/multihook.json
diff --git a/main/resources/assets/grapplemod/models/item/multihookrope.json b/src/main/resources/assets/grapplemod/models/item/multihookrope.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/multihookrope.json
rename to src/main/resources/assets/grapplemod/models/item/multihookrope.json
diff --git a/main/resources/assets/grapplemod/models/item/repeller.json b/src/main/resources/assets/grapplemod/models/item/repeller.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/repeller.json
rename to src/main/resources/assets/grapplemod/models/item/repeller.json
diff --git a/main/resources/assets/grapplemod/models/item/repelleron.json b/src/main/resources/assets/grapplemod/models/item/repelleron.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/repelleron.json
rename to src/main/resources/assets/grapplemod/models/item/repelleron.json
diff --git a/main/resources/assets/grapplemod/models/item/rope.json b/src/main/resources/assets/grapplemod/models/item/rope.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/rope.json
rename to src/main/resources/assets/grapplemod/models/item/rope.json
diff --git a/main/resources/assets/grapplemod/models/item/smarthook.json b/src/main/resources/assets/grapplemod/models/item/smarthook.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/smarthook.json
rename to src/main/resources/assets/grapplemod/models/item/smarthook.json
diff --git a/main/resources/assets/grapplemod/models/item/smarthookrope.json b/src/main/resources/assets/grapplemod/models/item/smarthookrope.json
similarity index 100%
rename from main/resources/assets/grapplemod/models/item/smarthookrope.json
rename to src/main/resources/assets/grapplemod/models/item/smarthookrope.json
diff --git a/main/resources/assets/grapplemod/textures/items/enderhook.png b/src/main/resources/assets/grapplemod/textures/items/enderhook.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/enderhook.png
rename to src/main/resources/assets/grapplemod/textures/items/enderhook.png
diff --git a/main/resources/assets/grapplemod/textures/items/grapplinghook.png b/src/main/resources/assets/grapplemod/textures/items/grapplinghook.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/grapplinghook.png
rename to src/main/resources/assets/grapplemod/textures/items/grapplinghook.png
diff --git a/main/resources/assets/grapplemod/textures/items/hookshot.png b/src/main/resources/assets/grapplemod/textures/items/hookshot.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/hookshot.png
rename to src/main/resources/assets/grapplemod/textures/items/hookshot.png
diff --git a/main/resources/assets/grapplemod/textures/items/hookshotrope.png b/src/main/resources/assets/grapplemod/textures/items/hookshotrope.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/hookshotrope.png
rename to src/main/resources/assets/grapplemod/textures/items/hookshotrope.png
diff --git a/main/resources/assets/grapplemod/textures/items/launcheritem.png b/src/main/resources/assets/grapplemod/textures/items/launcheritem.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/launcheritem.png
rename to src/main/resources/assets/grapplemod/textures/items/launcheritem.png
diff --git a/main/resources/assets/grapplemod/textures/items/longfallboots.png b/src/main/resources/assets/grapplemod/textures/items/longfallboots.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/longfallboots.png
rename to src/main/resources/assets/grapplemod/textures/items/longfallboots.png
diff --git a/main/resources/assets/grapplemod/textures/items/magnetbow.png b/src/main/resources/assets/grapplemod/textures/items/magnetbow.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/magnetbow.png
rename to src/main/resources/assets/grapplemod/textures/items/magnetbow.png
diff --git a/main/resources/assets/grapplemod/textures/items/multihook.png b/src/main/resources/assets/grapplemod/textures/items/multihook.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/multihook.png
rename to src/main/resources/assets/grapplemod/textures/items/multihook.png
diff --git a/main/resources/assets/grapplemod/textures/items/multihookrope.png b/src/main/resources/assets/grapplemod/textures/items/multihookrope.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/multihookrope.png
rename to src/main/resources/assets/grapplemod/textures/items/multihookrope.png
diff --git a/main/resources/assets/grapplemod/textures/items/repeller.png b/src/main/resources/assets/grapplemod/textures/items/repeller.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/repeller.png
rename to src/main/resources/assets/grapplemod/textures/items/repeller.png
diff --git a/main/resources/assets/grapplemod/textures/items/repelleron.png b/src/main/resources/assets/grapplemod/textures/items/repelleron.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/repelleron.png
rename to src/main/resources/assets/grapplemod/textures/items/repelleron.png
diff --git a/main/resources/assets/grapplemod/textures/items/rope.png b/src/main/resources/assets/grapplemod/textures/items/rope.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/rope.png
rename to src/main/resources/assets/grapplemod/textures/items/rope.png
diff --git a/main/resources/assets/grapplemod/textures/items/smarthook.png b/src/main/resources/assets/grapplemod/textures/items/smarthook.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/smarthook.png
rename to src/main/resources/assets/grapplemod/textures/items/smarthook.png
diff --git a/main/resources/assets/grapplemod/textures/items/smarthookrope.png b/src/main/resources/assets/grapplemod/textures/items/smarthookrope.png
similarity index 100%
rename from main/resources/assets/grapplemod/textures/items/smarthookrope.png
rename to src/main/resources/assets/grapplemod/textures/items/smarthookrope.png
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
new file mode 100644
index 0000000..97e6de0
--- /dev/null
+++ b/src/main/resources/mcmod.info
@@ -0,0 +1,21 @@
+{
+ "modListVersion": 2,
+ "modList": [{
+ "modid": "${modId}",
+ "name": "${modName}",
+ "description": "A mod which adds grappling hooks",
+ "version": "${modVersion}",
+ "mcversion": "${minecraftVersion}",
+ "url": "",
+ "updateUrl": "",
+ "authorList": ["yyon"],
+ "credits": "",
+ "logoFile": "",
+ "screenshots": [],
+ "parent": "",
+ "requiredMods": [],
+ "dependencies": [],
+ "dependants": [],
+ "useDependencyInformation": true
+ }]
+}