mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-15 09:44:44 +00:00
Compare commits
67
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae21012ea2 | ||
|
|
2b31129ef9 | ||
|
|
ba77a63545 | ||
|
|
8f7d698e7d | ||
|
|
72d44fd711 | ||
|
|
d735cc2a38 | ||
|
|
91e9b2a5ae | ||
|
|
96e4fe55e8 | ||
|
|
8717df0cbb | ||
|
|
d6a6551561 | ||
|
|
995ed24056 | ||
|
|
2917f2a4c9 | ||
|
|
5b2ff42d4f | ||
|
|
6f2782b06e | ||
|
|
f17bf6e8e2 | ||
|
|
10ee4d17ef | ||
|
|
f6acd768f3 | ||
|
|
8a5146b672 | ||
|
|
1632a90d15 | ||
|
|
269b16a8de | ||
|
|
1e93f719fe | ||
|
|
db6e3d33ca | ||
|
|
991a6dc772 | ||
|
|
5f1ed67a8b | ||
|
|
49b22e0683 | ||
|
|
00dacef241 | ||
|
|
c4da6706a5 | ||
|
|
f588543b64 | ||
|
|
f006a93dd5 | ||
|
|
6609911d96 | ||
|
|
3291dab52d | ||
|
|
b31de63fe6 | ||
|
|
0cfc3301f6 | ||
|
|
837411aa41 | ||
|
|
ee3d685a14 | ||
|
|
47951372cb | ||
|
|
7834d72ecf | ||
|
|
3ced04b4d3 | ||
|
|
75c02f0357 | ||
|
|
51ea8bba34 | ||
|
|
b0c6f358f7 | ||
|
|
c73edaa72e | ||
|
|
caebccc1fd | ||
|
|
a0c5ea42b9 | ||
|
|
23d4be06e8 | ||
|
|
1e36822fa4 | ||
|
|
3ce702343d | ||
|
|
a3387f0290 | ||
|
|
116b96f67b | ||
|
|
60fe49d18c | ||
|
|
cab0aff563 | ||
|
|
144a37cebb | ||
|
|
2d18dcf42b | ||
|
|
5bbcc570f9 | ||
|
|
98c9f03e74 | ||
|
|
5dde7cad8b | ||
|
|
ce17ec8026 | ||
|
|
63f49a5e4a | ||
|
|
e2a9d02c4c | ||
|
|
6695185c54 | ||
|
|
e5b8a4c9c9 | ||
|
|
60d033e879 | ||
|
|
0310b4177f | ||
|
|
304cc12750 | ||
|
|
a7ca6c8527 | ||
|
|
43b71b1de6 | ||
|
|
b6070dd508 |
No files matched your search
@@ -0,0 +1,9 @@
|
||||
directory="run/crash-reports"
|
||||
if [ -d $directory ]; then
|
||||
echo "Crash reports detected:"
|
||||
cat $directory/*
|
||||
exit 1
|
||||
else
|
||||
echo "No crash reports detected"
|
||||
exit 0
|
||||
fi
|
||||
@@ -1,14 +1,16 @@
|
||||
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
||||
|
||||
name: Build pull request
|
||||
name: Build and test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master, main ]
|
||||
push:
|
||||
branches: [ master, main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -30,3 +32,14 @@ jobs:
|
||||
|
||||
- name: Build the mod
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Run server for 1 minute
|
||||
run: |
|
||||
mkdir run
|
||||
echo "eula=true" > run/eula.txt
|
||||
timeout 10 ./gradlew runServer || true
|
||||
|
||||
- name: Test no crashes happend
|
||||
run: |
|
||||
chmod +x .github/scripts/test-no-crash-reports.sh
|
||||
.github/scripts/test-no-crash-reports.sh
|
||||
@@ -0,0 +1,51 @@
|
||||
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
||||
|
||||
name: Release tagged build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set release version
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up JDK 8
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Setup the workspace
|
||||
run: ./gradlew setupCIWorkspace
|
||||
|
||||
- name: Build the mod
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Release under current tag
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "${{ env.RELEASE_VERSION }}"
|
||||
prerelease: false
|
||||
title: "${{ env.RELEASE_VERSION }}"
|
||||
files: build/libs/*.jar
|
||||
|
||||
- name: Publish to Maven
|
||||
run: ./gradlew publish
|
||||
env:
|
||||
MAVEN_USER: ${{ secrets.MAVEN_USER }}
|
||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
@@ -1,41 +0,0 @@
|
||||
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
||||
|
||||
name: Build and release main branch
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master, main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 8
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Setup the workspace
|
||||
run: ./gradlew setupCIWorkspace
|
||||
|
||||
- name: Build the mod
|
||||
run: ./gradlew build
|
||||
|
||||
- uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: "latest"
|
||||
prerelease: true
|
||||
title: "Latest Development Build"
|
||||
files: build/libs/*.jar
|
||||
|
||||
@@ -26,3 +26,4 @@ whitelist.json
|
||||
*.ipr
|
||||
*.iws
|
||||
src/main/resources/mixins.*.json
|
||||
*.bat
|
||||
@@ -0,0 +1,3 @@
|
||||
# Any Github changes require admin approval
|
||||
/.github/** @GTNewHorizons/admin
|
||||
|
||||
@@ -1,674 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
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
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.1996
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
+149
-44
@@ -1,60 +1,165 @@
|
||||
GTNH Modifications:
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (c) 2019 mitchej123
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE - See COPYING & COPYING.LESSER
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
Parts inspired/borrowed/backported from JEI under the MIT License:
|
||||
0. Additional Definitions.
|
||||
|
||||
https://github.com/mezz/JustEnoughItems/tree/1.12
|
||||
|
||||
The MIT License (MIT)
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
Copyright (c) 2014-2015 mezz
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
Base NEI License:
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
The MIT License (MIT)
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
Copyright (c) 2014 ChickenBones
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
A continuation of NotEnoughItems for 1.7.10 by the developers of Gregtech: New Horizons modpack, with features either inspired and/or backported from JustEnoughItems
|
||||
|
||||
|
||||
We've tested this against all of the mods included in GTNH, as well as a limited set of other mods (like Reika's mods). Every effort has been made to maintain backwards compatibility, however the focus is on the mods contained in the GTNH modpack.
|
||||
|
||||
We've tested this against all of the mods included in GTNH, as well as a limited set of other mods (like Reika's mods). Every effort has been made to maintain backwards compatibility, however the focus is on the mods contained in the GTNH modpack.
|
||||
|
||||
|
||||
If you have issues with NEI outside of the GTNH modpack you may report them in the [GTNH NEI GitHub](https://github.com/GTNewHorizons/NotEnoughItems).
|
||||
|
||||
## New Features:
|
||||
|
||||
@@ -26,6 +24,15 @@ We've tested this against all of the mods included in GTNH, as well as a limited
|
||||
|
||||
## Other items of note:
|
||||
|
||||
* Licensed under LGPL - Use this however you want, but please give back any modifications
|
||||
* Remove TMI style
|
||||
* Removed inventory Load/Save state
|
||||
|
||||
## License
|
||||
|
||||
GTNH Modifications Copyright (c) 2019-2022 mitchej123 and the GTNH Team
|
||||
|
||||
Licensed under LGPL-3.0 or later - use this however you want, but please give back any modifications
|
||||
|
||||
Parts inspired/borrowed/backported from [JEI](https://github.com/mezz/JustEnoughItems/tree/1.12) under the MIT License.
|
||||
|
||||
Originial code Copyright (c) 2014-2015 mezz and was licensed under the MIT License.
|
||||
@@ -0,0 +1,3 @@
|
||||
compileJava {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
+369
-127
@@ -1,49 +1,65 @@
|
||||
//version: 1fc864ac9e3945981c864c3492bdd57330f9fe70
|
||||
//version: 1652851397
|
||||
/*
|
||||
DO NOT CHANGE THIS FILE!
|
||||
|
||||
Also, you may replace this file at any time if there is an update available.
|
||||
Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates.
|
||||
*/
|
||||
Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates.
|
||||
*/
|
||||
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.internal.logging.text.StyledTextOutput.Style
|
||||
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
name = "jitpack"
|
||||
url = "https://jitpack.io"
|
||||
name 'forge'
|
||||
url 'https://maven.minecraftforge.net'
|
||||
}
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://maven.minecraftforge.net"
|
||||
name 'sonatype'
|
||||
url 'https://oss.sonatype.org/content/repositories/snapshots/'
|
||||
}
|
||||
maven {
|
||||
name = "sonatype"
|
||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
name 'Scala CI dependencies'
|
||||
url 'https://repo1.maven.org/maven2/'
|
||||
}
|
||||
maven {
|
||||
name = "Scala CI dependencies"
|
||||
url = "https://repo1.maven.org/maven2/"
|
||||
name 'jitpack'
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4'
|
||||
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'idea'
|
||||
id 'eclipse'
|
||||
id 'scala'
|
||||
id("org.ajoberstar.grgit") version("3.1.1")
|
||||
id("com.github.johnrengelman.shadow") version("4.0.4")
|
||||
id("com.palantir.git-version") version("0.12.3")
|
||||
id 'maven-publish'
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false
|
||||
id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false
|
||||
id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false
|
||||
id 'org.ajoberstar.grgit' version '4.1.1'
|
||||
id 'com.github.johnrengelman.shadow' version '4.0.4'
|
||||
id 'com.palantir.git-version' version '0.13.0' apply false
|
||||
id 'de.undercouch.download' version '5.0.1'
|
||||
id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false
|
||||
}
|
||||
|
||||
if (project.file('.git/HEAD').isFile()) {
|
||||
apply plugin: 'com.palantir.git-version'
|
||||
}
|
||||
|
||||
def out = services.get(StyledTextOutputFactory).create('an-output')
|
||||
|
||||
apply plugin: 'forge'
|
||||
|
||||
def projectJavaVersion = JavaLanguageVersion.of(8)
|
||||
@@ -62,6 +78,10 @@ idea {
|
||||
}
|
||||
}
|
||||
|
||||
if(JavaVersion.current() != JavaVersion.VERSION_1_8) {
|
||||
throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current())
|
||||
}
|
||||
|
||||
checkPropertyExists("modName")
|
||||
checkPropertyExists("modId")
|
||||
checkPropertyExists("modGroup")
|
||||
@@ -83,33 +103,32 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly")
|
||||
checkPropertyExists("usesShadowedDependencies")
|
||||
checkPropertyExists("developmentEnvironmentUserName")
|
||||
|
||||
def checkPropertyExists(String propertyName) {
|
||||
if (project.hasProperty(propertyName) == false) {
|
||||
throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties")
|
||||
}
|
||||
}
|
||||
|
||||
boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false
|
||||
boolean usesMixinDebug = project.findProperty('usesMixinDebug') ?: project.usesMixins.toBoolean()
|
||||
|
||||
String javaSourceDir = "src/main/java/"
|
||||
String scalaSourceDir = "src/main/scala/"
|
||||
String kotlinSourceDir = "src/main/kotlin/"
|
||||
|
||||
String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
|
||||
String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
||||
}
|
||||
|
||||
if(apiPackage) {
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
|
||||
targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
||||
}
|
||||
}
|
||||
|
||||
if(accessTransformersFile) {
|
||||
String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
|
||||
if(new File(targetFile).exists() == false) {
|
||||
if(!getFile(targetFile).exists()) {
|
||||
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
|
||||
}
|
||||
}
|
||||
@@ -121,15 +140,17 @@ if(usesMixins.toBoolean()) {
|
||||
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
|
||||
targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
||||
}
|
||||
|
||||
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala"
|
||||
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
|
||||
if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava)
|
||||
String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt"
|
||||
if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +158,9 @@ if(coreModClass) {
|
||||
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala"
|
||||
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
|
||||
if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava)
|
||||
String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt"
|
||||
if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,15 +173,64 @@ configurations.all {
|
||||
}
|
||||
|
||||
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
|
||||
'git config core.fileMode false'.execute()
|
||||
// Pulls version from git tag
|
||||
version = minecraftVersion + "-" + gitVersion()
|
||||
try {
|
||||
'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 {
|
||||
identifiedVersion = versionOverride == null ? gitVersion() : 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 = minecraftVersion + '-' + identifiedVersion
|
||||
ext {
|
||||
modVersion = identifiedVersion
|
||||
}
|
||||
|
||||
if(identifiedVersion == versionOverride) {
|
||||
out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7')
|
||||
}
|
||||
|
||||
group = modGroup
|
||||
archivesBaseName = modId
|
||||
if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
|
||||
archivesBaseName = customArchiveBaseName
|
||||
}
|
||||
else {
|
||||
archivesBaseName = modId
|
||||
}
|
||||
|
||||
def arguments = []
|
||||
def jvmArguments = []
|
||||
|
||||
if (usesMixins.toBoolean()) {
|
||||
arguments += [
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
if (usesMixinDebug.toBoolean()) {
|
||||
jvmArguments += [
|
||||
"-Dmixin.debug.countInjections=true",
|
||||
"-Dmixin.debug.verbose=true",
|
||||
"-Dmixin.debug.export=true"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion
|
||||
runDir = "run"
|
||||
version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion
|
||||
runDir = 'run'
|
||||
|
||||
if (replaceGradleTokenInFile) {
|
||||
replaceIn replaceGradleTokenInFile
|
||||
@@ -170,79 +241,99 @@ minecraft {
|
||||
replace gradleTokenModName, modName
|
||||
}
|
||||
if(gradleTokenVersion) {
|
||||
replace gradleTokenVersion, versionDetails().lastTag
|
||||
replace gradleTokenVersion, modVersion
|
||||
}
|
||||
if(gradleTokenGroupName) {
|
||||
replace gradleTokenGroupName, modGroup
|
||||
}
|
||||
}
|
||||
|
||||
clientIntellijRun {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
|
||||
if(developmentEnvironmentUserName) {
|
||||
args("--username", developmentEnvironmentUserName)
|
||||
}
|
||||
}
|
||||
|
||||
serverIntellijRun {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
}
|
||||
|
||||
if(file("addon.gradle").exists()) {
|
||||
apply from: "addon.gradle"
|
||||
if(file('addon.gradle').exists()) {
|
||||
apply from: 'addon.gradle'
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
|
||||
configurations {
|
||||
implementation.extendsFrom(shadowImplementation)
|
||||
implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored
|
||||
implementation.extendsFrom(shadowCompile)
|
||||
implementation.extendsFrom(shadeCompile)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "Overmind forge repo mirror"
|
||||
url = "https://gregtech.overminddl1.com/"
|
||||
name 'Overmind forge repo mirror'
|
||||
url 'https://gregtech.overminddl1.com/'
|
||||
}
|
||||
if(usesMixins.toBoolean()) {
|
||||
maven {
|
||||
name = "sponge"
|
||||
url = "https://repo.spongepowered.org/repository/maven-public"
|
||||
name 'sponge'
|
||||
url 'https://repo.spongepowered.org/repository/maven-public'
|
||||
}
|
||||
maven {
|
||||
url = "https://jitpack.io"
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
if(usesMixins.toBoolean()) {
|
||||
annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3")
|
||||
annotationProcessor("com.google.guava:guava:24.1.1-jre")
|
||||
annotationProcessor("com.google.code.gson:gson:2.8.6")
|
||||
annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT")
|
||||
annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3')
|
||||
annotationProcessor('com.google.guava:guava:24.1.1-jre')
|
||||
annotationProcessor('com.google.code.gson:gson:2.8.6')
|
||||
annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT')
|
||||
// using 0.8 to workaround a issue in 0.7 which fails mixin application
|
||||
compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
|
||||
compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') {
|
||||
// Mixin includes a lot of dependencies that are too up-to-date
|
||||
exclude module: "launchwrapper"
|
||||
exclude module: "guava"
|
||||
exclude module: "gson"
|
||||
exclude module: "commons-io"
|
||||
exclude module: "log4j-core"
|
||||
exclude module: 'launchwrapper'
|
||||
exclude module: 'guava'
|
||||
exclude module: 'gson'
|
||||
exclude module: 'commons-io'
|
||||
exclude module: 'log4j-core'
|
||||
}
|
||||
compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev")
|
||||
compile('com.github.GTNewHorizons:SpongeMixins:1.5.0')
|
||||
}
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
def mixinConfigJson = "mixins." + modId + ".json"
|
||||
def mixingConfigRefMap = "mixins." + modId + ".refmap.json"
|
||||
def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
|
||||
def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap
|
||||
def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg"
|
||||
|
||||
task generateAssets {
|
||||
if(usesMixins.toBoolean()) {
|
||||
new File(projectDir.toString() + "/src/main/resources/", mixinConfigJson).text = """{
|
||||
if (usesMixins.toBoolean()) {
|
||||
def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json");
|
||||
if (!mixinConfigFile.exists()) {
|
||||
mixinConfigFile.text = """{
|
||||
"required": true,
|
||||
"minVersion": "0.7.11",
|
||||
"package": "${modGroup}.${mixinsPackage}",
|
||||
"plugin": "${modGroup}.${mixinPlugin}",
|
||||
"refmap": "${mixingConfigRefMap}",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8"
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [],
|
||||
"client": [],
|
||||
"server": []
|
||||
}
|
||||
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,16 +343,28 @@ task relocateShadowJar(type: ConfigureShadowRelocation) {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [project.configurations.shadowImplementation]
|
||||
configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile]
|
||||
dependsOn(relocateShadowJar)
|
||||
}
|
||||
|
||||
jar {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
@@ -294,15 +397,6 @@ afterEvaluate {
|
||||
}
|
||||
|
||||
runClient {
|
||||
def arguments = []
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
arguments += [
|
||||
"--mods=../build/libs/$modId-${version}.jar",
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
}
|
||||
|
||||
if(developmentEnvironmentUserName) {
|
||||
arguments += [
|
||||
"--username",
|
||||
@@ -311,19 +405,12 @@ runClient {
|
||||
}
|
||||
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
|
||||
runServer {
|
||||
def arguments = []
|
||||
|
||||
if (usesMixins.toBoolean()) {
|
||||
arguments += [
|
||||
"--mods=../build/libs/$modId-${version}.jar",
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
}
|
||||
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
|
||||
tasks.withType(JavaExec).configureEach {
|
||||
@@ -334,32 +421,35 @@ tasks.withType(JavaExec).configureEach {
|
||||
)
|
||||
}
|
||||
|
||||
processResources
|
||||
{
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
processResources {
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
|
||||
// replace stuff in mcmod.info, nothing else
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
// replace stuff in mcmod.info, nothing else
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
|
||||
// replace version and mcversion
|
||||
expand "minecraftVersion": project.minecraft.version,
|
||||
"modVersion": versionDetails().lastTag,
|
||||
"modId": modId,
|
||||
"modName": modName
|
||||
}
|
||||
// replace modVersion and minecraftVersion
|
||||
expand "minecraftVersion": project.minecraft.version,
|
||||
"modVersion": modVersion,
|
||||
"modId": modId,
|
||||
"modName": modName
|
||||
}
|
||||
|
||||
// copy everything else, thats not the mcmod.info
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
if(usesMixins.toBoolean()) {
|
||||
from refMap
|
||||
}
|
||||
|
||||
// copy everything else that's not the mcmod.info
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
def getManifestAttributes() {
|
||||
def manifestAttributes = [:]
|
||||
if(containsMixinsAndOrCoreModOnly.toBoolean() == false) {
|
||||
if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) {
|
||||
manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
|
||||
}
|
||||
|
||||
@@ -374,20 +464,26 @@ def getManifestAttributes() {
|
||||
if(usesMixins.toBoolean()) {
|
||||
manifestAttributes += [
|
||||
"TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
|
||||
"MixinConfigs" : mixinConfigJson,
|
||||
"ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false
|
||||
"MixinConfigs" : "mixins." + modId + ".json",
|
||||
"ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean()
|
||||
]
|
||||
}
|
||||
return manifestAttributes
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from (sourceSets.main.allJava)
|
||||
from (sourceSets.main.allSource)
|
||||
from (file("$projectDir/LICENSE"))
|
||||
getArchiveClassifier().set('sources')
|
||||
}
|
||||
|
||||
task shadowDevJar(type: ShadowJar) {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
@@ -396,22 +492,27 @@ task shadowDevJar(type: ShadowJar) {
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [project.configurations.shadowImplementation]
|
||||
//dependsOn(relocateShadowDevJar)
|
||||
configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile]
|
||||
}
|
||||
|
||||
task relocateShadowDevJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowDevJar //gradle.taskGraph.getAllTasks().find {it.name.equals("shadowDevJar") } //
|
||||
target = tasks.shadowDevJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
task feongweosn(type: Jar) {
|
||||
task circularResolverJar(type: Jar) {
|
||||
dependsOn(relocateShadowDevJar)
|
||||
dependsOn(shadowDevJar)
|
||||
enabled = false
|
||||
}
|
||||
|
||||
task devJar(type: Jar) {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
@@ -420,18 +521,18 @@ task devJar(type: Jar) {
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(shadowDevJar)
|
||||
dependsOn(circularResolverJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
task apiJar(type: Jar) {
|
||||
from (sourceSets.main.allJava) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**'
|
||||
from (sourceSets.main.allSource) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.output) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**'
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.resources.srcDirs) {
|
||||
@@ -442,48 +543,111 @@ task apiJar(type: Jar) {
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourcesJar
|
||||
archives feongweosn
|
||||
if(!noPublishedSources) {
|
||||
archives sourcesJar
|
||||
}
|
||||
archives devJar
|
||||
if(apiPackage) {
|
||||
archives apiJar
|
||||
}
|
||||
}
|
||||
|
||||
// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID),
|
||||
// and isn't strictly needed with the POM so just disable it.
|
||||
tasks.withType(GenerateModuleMetadata) {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
// workaround variable hiding in pom processing
|
||||
def projectConfigs = project.configurations
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
from components.java
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
artifact source: shadowJar, classifier: ""
|
||||
}
|
||||
if(!noPublishedSources) {
|
||||
artifact source: sourcesJar, classifier: "sources"
|
||||
}
|
||||
artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev"
|
||||
if (apiPackage) {
|
||||
artifact source: apiJar, classifier: "api"
|
||||
}
|
||||
|
||||
groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons"
|
||||
artifactId = System.getenv("ARTIFACT_ID") ?: project.name
|
||||
// Using the identified version, not project.version as it has the prepended 1.7.10
|
||||
version = System.getenv("RELEASE_VERSION") ?: identifiedVersion
|
||||
|
||||
// remove extra garbage from minecraft and minecraftDeps configuration
|
||||
pom.withXml {
|
||||
def badArtifacts = [:].withDefault {[] as Set<String>}
|
||||
for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) {
|
||||
for (dependency in configuration.allDependencies) {
|
||||
badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name
|
||||
}
|
||||
}
|
||||
// example for specifying extra stuff to ignore
|
||||
// badArtifacts["org.example.group"] += "artifactName"
|
||||
|
||||
Node pomNode = asNode()
|
||||
pomNode.dependencies.'*'.findAll() {
|
||||
badArtifacts[it.groupId.text()].contains(it.artifactId.text())
|
||||
}.each() {
|
||||
it.parent().remove(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases"
|
||||
credentials {
|
||||
username = System.getenv("MAVEN_USER") ?: "NONE"
|
||||
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updating
|
||||
task updateBuildScript {
|
||||
doLast {
|
||||
if (updateBuildScript()) return
|
||||
if (performBuildScriptUpdate(projectDir.toString())) return
|
||||
|
||||
print("Build script already up-to-date!")
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewBuildScriptVersionAvailable()) {
|
||||
if (isNewBuildScriptVersionAvailable(projectDir.toString())) {
|
||||
if (autoUpdateBuildScript.toBoolean()) {
|
||||
updateBuildScript()
|
||||
performBuildScriptUpdate(projectDir.toString())
|
||||
} else {
|
||||
println("Build script update available! Run 'gradle updateBuildScript'")
|
||||
out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'")
|
||||
}
|
||||
}
|
||||
|
||||
static URL availableBuildScriptUrl() {
|
||||
new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle")
|
||||
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle")
|
||||
}
|
||||
|
||||
static boolean updateBuildScript() {
|
||||
if (isNewBuildScriptVersionAvailable()) {
|
||||
def buildscriptFile = new File("build.gradle")
|
||||
boolean performBuildScriptUpdate(String projectDir) {
|
||||
if (isNewBuildScriptVersionAvailable(projectDir)) {
|
||||
def buildscriptFile = getFile("build.gradle")
|
||||
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
|
||||
print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
|
||||
out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static boolean isNewBuildScriptVersionAvailable() {
|
||||
boolean isNewBuildScriptVersionAvailable(String projectDir) {
|
||||
Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
|
||||
|
||||
String currentBuildScript = new File("build.gradle").getText()
|
||||
String currentBuildScript = getFile("build.gradle").getText()
|
||||
String currentBuildScriptHash = getVersionHash(currentBuildScript)
|
||||
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
|
||||
String availableBuildScriptHash = getVersionHash(availableBuildScript)
|
||||
@@ -504,3 +668,81 @@ configure(updateBuildScript) {
|
||||
group = 'forgegradle'
|
||||
description = 'Updates the build script to the latest version'
|
||||
}
|
||||
|
||||
// Deobfuscation
|
||||
|
||||
def deobf(String sourceURL) {
|
||||
try {
|
||||
URL url = new URL(sourceURL)
|
||||
String fileName = url.getFile()
|
||||
|
||||
//get rid of directories:
|
||||
int lastSlash = fileName.lastIndexOf("/")
|
||||
if(lastSlash > 0) {
|
||||
fileName = fileName.substring(lastSlash + 1)
|
||||
}
|
||||
//get rid of extension:
|
||||
if(fileName.endsWith(".jar")) {
|
||||
fileName = fileName.substring(0, fileName.lastIndexOf("."))
|
||||
}
|
||||
|
||||
String hostName = url.getHost()
|
||||
if(hostName.startsWith("www.")) {
|
||||
hostName = hostName.substring(4)
|
||||
}
|
||||
List parts = Arrays.asList(hostName.split("\\."))
|
||||
Collections.reverse(parts)
|
||||
hostName = String.join(".", parts)
|
||||
|
||||
return deobf(sourceURL, hostName + "/" + fileName)
|
||||
} catch(Exception e) {
|
||||
return deobf(sourceURL, "deobf/" + String.valueOf(sourceURL.hashCode()))
|
||||
}
|
||||
}
|
||||
|
||||
// The method above is to be preferred. Use this method if the filename is not at the end of the URL.
|
||||
def deobf(String sourceURL, String fileName) {
|
||||
String cacheDir = System.getProperty("user.home") + "/.gradle/caches/"
|
||||
String bon2Dir = cacheDir + "forge_gradle/deobf"
|
||||
String bon2File = bon2Dir + "/BON2-2.5.0.jar"
|
||||
String obfFile = cacheDir + "modules-2/files-2.1/" + fileName + ".jar"
|
||||
String deobfFile = cacheDir + "modules-2/files-2.1/" + fileName + "-deobf.jar"
|
||||
|
||||
if(file(deobfFile).exists()) {
|
||||
return files(deobfFile)
|
||||
}
|
||||
|
||||
download.run {
|
||||
src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar'
|
||||
dest bon2File
|
||||
quiet true
|
||||
overwrite false
|
||||
}
|
||||
|
||||
download.run {
|
||||
src sourceURL
|
||||
dest obfFile
|
||||
quiet true
|
||||
overwrite false
|
||||
}
|
||||
|
||||
exec {
|
||||
commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch'
|
||||
workingDir bon2Dir
|
||||
standardOutput = new ByteArrayOutputStream()
|
||||
}
|
||||
|
||||
return files(deobfFile)
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
def checkPropertyExists(String propertyName) {
|
||||
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 getFile(String relativePath) {
|
||||
return new File(projectDir, relativePath)
|
||||
}
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
compile("com.github.GTNewHorizons:CodeChickenLib:master-SNAPSHOT:dev")
|
||||
compile("com.github.GTNewHorizons:CodeChickenCore:master-SNAPSHOT:dev")
|
||||
shadowImplementation("org.apache.commons:commons-csv:1.5")
|
||||
compile('com.github.GTNewHorizons:CodeChickenLib:1.1.5.3:dev')
|
||||
compile('com.github.GTNewHorizons:CodeChickenCore:1.1.3:dev')
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.8')
|
||||
}
|
||||
+6
-6
@@ -15,15 +15,15 @@ autoUpdateBuildScript = false
|
||||
minecraftVersion = 1.7.10
|
||||
forgeVersion = 10.13.4.1614
|
||||
|
||||
# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name each time you
|
||||
# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you
|
||||
# restart Minecraft in development. Choose this dependent on your mod:
|
||||
# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
|
||||
# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
|
||||
developmentEnvironmentUserName = "Developer"
|
||||
developmentEnvironmentUserName = Developer
|
||||
|
||||
# Define a source file of your project with:
|
||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's
|
||||
# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
|
||||
# version in @Mod([...], version = VERSION, [...])
|
||||
# Leave these properties empty to skip individual token replacements
|
||||
replaceGradleTokenInFile = NEIModContainer.java
|
||||
@@ -32,12 +32,12 @@ gradleTokenModName = GRADLETOKEN_MODNAME
|
||||
gradleTokenVersion = GRADLETOKEN_VERSION
|
||||
gradleTokenGroupName =
|
||||
|
||||
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can
|
||||
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
|
||||
# leave this property empty.
|
||||
# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api
|
||||
apiPackage =
|
||||
|
||||
# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/
|
||||
# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
|
||||
# Example value: mymodid_at.cfg
|
||||
accessTransformersFile = nei_at.cfg
|
||||
|
||||
@@ -48,7 +48,7 @@ mixinPlugin =
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
mixinsPackage =
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
# This parameter is for legacy compatability only
|
||||
# This parameter is for legacy compatibility only
|
||||
# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
|
||||
coreModClass = asm.NEICorePlugin
|
||||
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
||||
|
||||
+11
-1
@@ -3,6 +3,16 @@
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = "https://jitpack.io"
|
||||
name 'GTNH Maven'
|
||||
url 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/'
|
||||
}
|
||||
maven {
|
||||
url 'https://cursemaven.com'
|
||||
content {
|
||||
includeGroup 'curse.maven'
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -6,6 +6,8 @@ import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
@@ -46,18 +48,24 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ClientHandler
|
||||
{
|
||||
private static String[] defaultSerialHandlers = {
|
||||
"WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler"
|
||||
};
|
||||
private static String[] defaultHeightHackHandlers = {
|
||||
"ic2.neiIntegration.core.recipehandler.FluidCannerRecipeHandler",
|
||||
"tconstruct.plugins.nei.RecipeHandlerAlloying",
|
||||
"tconstruct.plugins.nei.RecipeHandlerCastingBasin",
|
||||
"tconstruct.plugins.nei.RecipeHandlerCastingTable",
|
||||
"tconstruct.plugins.nei.RecipeHandlerMelting",
|
||||
private static String[] defaultHeightHackHandlerRegex = {
|
||||
"buildcraft.compat.nei.*",
|
||||
"cofh.thermalexpansion.plugins.nei.handlers.*",
|
||||
"crazypants.enderio.nei.*",
|
||||
"forestry.factory.recipes.nei.*",
|
||||
"ic2.neiIntegration.core.recipehandler.*",
|
||||
"mariculture.plugins.nei.*",
|
||||
"redgear.brewcraft.plugins.nei.*",
|
||||
"tconstruct.plugins.nei.*",
|
||||
"WayofTime.alchemicalWizardry.client.nei.*",
|
||||
};
|
||||
private static String[] defaultHandlerOrdering = {
|
||||
"# Each line in this file should either be a comment (starts with '#') or an ordering.",
|
||||
@@ -154,6 +162,7 @@ public class ClientHandler
|
||||
loadSerialHandlers();
|
||||
loadHeightHackHandlers();
|
||||
ItemInfo.preInit();
|
||||
StackInfo.loadGuidFilters();
|
||||
}
|
||||
|
||||
public static void loadSerialHandlers() {
|
||||
@@ -180,7 +189,7 @@ public class ClientHandler
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default height hack handlers list {}", file);
|
||||
Collection<String> toSave = Loader.isModLoaded("dreamcraft") ? Collections.singletonList("") : Arrays.asList(defaultHeightHackHandlers);
|
||||
Collection<String> toSave = Arrays.asList(defaultHeightHackHandlerRegex);
|
||||
IOUtils.writeLines(toSave, "\n", writer);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default height hack handlers list to file {}", file, e);
|
||||
@@ -189,7 +198,10 @@ public class ClientHandler
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
NEIClientConfig.logger.info("Loading height hack handlers from file {}", file);
|
||||
NEIClientConfig.heightHackHandlers = new HashSet<>(IOUtils.readLines(reader));
|
||||
NEIClientConfig.heightHackHandlerRegex =
|
||||
IOUtils.readLines(reader).stream()
|
||||
.map(Pattern::compile)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load height hack handlers from file {}", file, e);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@@ -50,7 +52,21 @@ public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
||||
return false;
|
||||
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h)
|
||||
{
|
||||
return (new Rectangle4i(guiLeft - 15, guiTop + 18, 18, 18 * 4 + 4)).intersects(new Rectangle4i(x, y, w, h));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMouseClick(Slot p_146984_1_, int p_146984_2_, int p_146984_3_, int p_146984_4_)
|
||||
{
|
||||
|
||||
//Hack for armor slots, because they are outside the container
|
||||
if (p_146984_1_ != null && p_146984_4_ == 4 && p_146984_1_.xDisplayPosition < 0) {
|
||||
p_146984_4_ = 0;
|
||||
}
|
||||
|
||||
super.handleMouseClick(p_146984_1_, p_146984_2_, p_146984_3_, p_146984_4_);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -185,13 +185,13 @@ public class ItemList
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute() {
|
||||
// System.out.println("Executing NEI Item Loading");
|
||||
ThreadOperationTimer timer = getTimer(500);
|
||||
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
|
||||
LinkedList<ItemStack> items = new LinkedList<>();
|
||||
LinkedList<ItemStack> permutations = new LinkedList<>();
|
||||
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
||||
|
||||
timer.setLimit(500);
|
||||
timer.setLimit(NEIClientConfig.getItemLoadingTimeout());
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
if (interrupted()) return;
|
||||
|
||||
@@ -252,6 +252,7 @@ public class ItemList
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(() -> items.parallelStream()
|
||||
.filter(PresetsWidget::matches)
|
||||
.filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
|
||||
@@ -1,489 +1,229 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
import static codechicken.nei.NEIClientConfig.canPerformAction;
|
||||
|
||||
public class ItemPanel extends Widget {
|
||||
public class ItemPanel extends PanelWidget
|
||||
{
|
||||
|
||||
/**
|
||||
* Backwards compat :-/
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
private int itemsPerPage = 0;
|
||||
|
||||
@Deprecated
|
||||
public static ArrayList<ItemStack> items = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Should not be externally modified, use updateItemList
|
||||
*/
|
||||
@Deprecated
|
||||
public ArrayList<ItemStack> realItems = new ArrayList<>();
|
||||
/**
|
||||
* Swapped into visible items on update
|
||||
*/
|
||||
protected ArrayList<ItemStack> _items = realItems;
|
||||
|
||||
public ItemStack getStackMouseOver(int mousex, int mousey) {
|
||||
// *looks angrily at AppleCore*
|
||||
return super.getStackMouseOver(mousex, mousey);
|
||||
};
|
||||
|
||||
public ArrayList<ItemStack> getItems() {
|
||||
return realItems;
|
||||
}
|
||||
public Button more;
|
||||
public Button less;
|
||||
public ItemQuantityField quantity;
|
||||
|
||||
public static void updateItemList(ArrayList<ItemStack> newItems) {
|
||||
ItemPanels.itemPanel._items = newItems;
|
||||
}
|
||||
|
||||
public class ItemPanelSlot
|
||||
public static class ItemPanelSlot
|
||||
{
|
||||
public ItemStack item;
|
||||
public int slotIndex;
|
||||
|
||||
public ItemPanelSlot(int index) {
|
||||
item = realItems.get(index);
|
||||
slotIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack draggedStack;
|
||||
public int mouseDownSlot = -1;
|
||||
|
||||
public Button prev;
|
||||
public Button next;
|
||||
public Label pageLabel;
|
||||
|
||||
|
||||
private int marginLeft;
|
||||
private int marginTop;
|
||||
private int rows;
|
||||
private int columns;
|
||||
|
||||
private boolean[] validSlotMap;
|
||||
private int firstIndex;
|
||||
private int itemsPerPage;
|
||||
|
||||
private int page;
|
||||
private int numPages;
|
||||
|
||||
|
||||
|
||||
public void init() {
|
||||
pageLabel = new Label("(0/0)", true);
|
||||
|
||||
prev = new Button("Prev")
|
||||
public ItemPanelSlot(int idx, ItemStack stack)
|
||||
{
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
scroll(-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
slotIndex = idx;
|
||||
item = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return "<";
|
||||
}
|
||||
};
|
||||
next = new Button("Next")
|
||||
@Deprecated
|
||||
public ItemPanelSlot(int idx)
|
||||
{
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
scroll(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return ">";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int getX(GuiContainer gui) {
|
||||
return (gui.xSize + gui.width) / 2 + 3;
|
||||
}
|
||||
|
||||
public int getMarginLeft() {
|
||||
return x + (w % 18) / 2;
|
||||
}
|
||||
|
||||
public int getMarginTop() {
|
||||
return y + (h % 18) / 2;
|
||||
}
|
||||
|
||||
public int getButtonTop() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int getNextX(GuiContainer gui) {
|
||||
return gui.width - prev.w - 2;
|
||||
}
|
||||
|
||||
public int getPrevX(GuiContainer gui) {
|
||||
return (gui.xSize + gui.width) / 2 + 2;
|
||||
}
|
||||
|
||||
public int getPageX(GuiContainer gui) {
|
||||
return gui.guiLeft * 3 / 2 + gui.xSize + 1;
|
||||
}
|
||||
|
||||
public int getHeight(GuiContainer gui) {
|
||||
return gui.height - 15 - y;
|
||||
}
|
||||
|
||||
public int getWidth(GuiContainer gui) {
|
||||
return LayoutManager.getSideWidth(gui) - x;
|
||||
}
|
||||
|
||||
public String getLabelText() {
|
||||
return pageLabel.text = "(" + getPage() + "/" + getNumPages() + ")";
|
||||
}
|
||||
|
||||
protected void setItems() {
|
||||
realItems = _items;
|
||||
|
||||
// Backwards compat
|
||||
ItemPanels.itemPanel._items = _items;
|
||||
}
|
||||
|
||||
public void resize(GuiContainer gui) {
|
||||
setItems();
|
||||
final int buttonHeight = 16;
|
||||
final int buttonWidth = 16;
|
||||
|
||||
prev.x = getPrevX(gui);
|
||||
prev.y = getButtonTop();
|
||||
prev.h = buttonHeight;
|
||||
prev.w = buttonWidth;
|
||||
|
||||
next.x = getNextX(gui);
|
||||
next.y = getButtonTop();
|
||||
next.h = buttonHeight;
|
||||
next.w = buttonWidth;
|
||||
|
||||
pageLabel.x = getPageX(gui);
|
||||
pageLabel.y = prev.y + 5;
|
||||
pageLabel.text = getLabelText();
|
||||
|
||||
y = prev.h + prev.y;
|
||||
x = getX(gui);
|
||||
w = getWidth(gui);
|
||||
h = getHeight(gui);
|
||||
|
||||
marginLeft = getMarginLeft();
|
||||
marginTop = getMarginTop();
|
||||
columns = w / 18;
|
||||
rows = h / 18;
|
||||
//sometimes width and height can be negative with certain resizing
|
||||
if(rows < 0) rows = 0;
|
||||
if(columns < 0) columns = 0;
|
||||
|
||||
calculatePage();
|
||||
updateValidSlots();
|
||||
}
|
||||
|
||||
private void calculatePage() {
|
||||
if (itemsPerPage == 0)
|
||||
numPages = 0;
|
||||
else
|
||||
numPages = (int) Math.ceil((float) realItems.size() / (float) itemsPerPage);
|
||||
|
||||
if (firstIndex >= realItems.size())
|
||||
firstIndex = 0;
|
||||
|
||||
if (numPages == 0)
|
||||
page = 0;
|
||||
else
|
||||
page = firstIndex / itemsPerPage + 1;
|
||||
}
|
||||
|
||||
public void setVisible() {
|
||||
LayoutManager.addWidget(prev);
|
||||
LayoutManager.addWidget(next);
|
||||
LayoutManager.addWidget(pageLabel);
|
||||
|
||||
}
|
||||
private void updateValidSlots() {
|
||||
GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
validSlotMap = new boolean[rows * columns];
|
||||
itemsPerPage = 0;
|
||||
for (int i = 0; i < validSlotMap.length; i++)
|
||||
if (slotValid(gui, i)) {
|
||||
validSlotMap[i] = true;
|
||||
itemsPerPage++;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean slotValid(GuiContainer gui, int i) {
|
||||
Rectangle4i rect = getSlotRect(i);
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
if(GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)))
|
||||
return false;
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Rectangle4i getSlotRect(int i) {
|
||||
return getSlotRect(i / columns, i % columns);
|
||||
}
|
||||
|
||||
public Rectangle4i getSlotRect(int row, int column) {
|
||||
return new Rectangle4i(marginLeft + column * 18, marginTop + row * 18, 18, 18);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
if (itemsPerPage == 0)
|
||||
return;
|
||||
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
int index = firstIndex;
|
||||
for (int i = 0; i < rows * columns && index < realItems.size(); i++) {
|
||||
if (validSlotMap[i]) {
|
||||
Rectangle4i rect = getSlotRect(i);
|
||||
if (rect.contains(mousex, mousey))
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight
|
||||
|
||||
GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, realItems.get(index));
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDraw(int mousex, int mousey) {
|
||||
if (draggedStack != null) {
|
||||
GuiContainerManager.drawItems.zLevel += 100;
|
||||
GuiContainerManager.drawItem(mousex - 8, mousey - 8, draggedStack);
|
||||
GuiContainerManager.drawItems.zLevel -= 100;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
|
||||
if (mouseDownSlot >= 0 && draggedStack == null && NEIClientUtils.getHeldItem() == null &&
|
||||
NEIClientConfig.hasSMPCounterPart() && !GuiInfo.hasCustomSlots(NEIClientUtils.getGuiContainer())) {
|
||||
ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey);
|
||||
ItemStack stack = new ItemPanelSlot(mouseDownSlot).item;
|
||||
if (stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500)) {
|
||||
int amount = NEIClientConfig.getItemQuantity();
|
||||
if (amount == 0)
|
||||
amount = stack.getMaxStackSize();
|
||||
|
||||
draggedStack = NEIServerUtils.copyStack(stack, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
if (handleDraggedClick(mousex, mousey, button))
|
||||
return true;
|
||||
|
||||
if (NEIClientUtils.getHeldItem() != null) {
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
if (GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(NEIClientUtils.getGuiContainer(), mousex, mousey, 1, 1)))
|
||||
return false;
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item"))
|
||||
if (button == 1)
|
||||
NEIClientUtils.decreaseSlotStack(-999);
|
||||
else
|
||||
NEIClientUtils.deleteHeldItem();
|
||||
else
|
||||
NEIClientUtils.dropHeldItem();
|
||||
|
||||
return true;
|
||||
this(idx, ItemPanels.itemPanel.getGrid().getItem(idx));
|
||||
}
|
||||
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null) {
|
||||
if (button == 2) {
|
||||
ItemStack stack = hoverSlot.item;
|
||||
if (stack != null) {
|
||||
int amount = NEIClientConfig.getItemQuantity();
|
||||
if (amount == 0)
|
||||
amount = stack.getMaxStackSize();
|
||||
}
|
||||
|
||||
draggedStack = NEIServerUtils.copyStack(stack, amount);
|
||||
}
|
||||
protected static class ItemPanelGrid extends ItemsGrid
|
||||
{
|
||||
public ArrayList<ItemStack> newItems;
|
||||
|
||||
public void setItems(ArrayList<ItemStack> items)
|
||||
{
|
||||
newItems = items;
|
||||
}
|
||||
|
||||
public void refresh(GuiContainer gui)
|
||||
{
|
||||
|
||||
if (newItems != null) {
|
||||
realItems = newItems;
|
||||
newItems = null;
|
||||
refreshBuffer = true;
|
||||
}
|
||||
|
||||
super.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
if(!PresetsWidget.isHidden(getItem(slotIdx)))
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);
|
||||
} else {
|
||||
mouseDownSlot = hoverSlot.slotIndex;
|
||||
super.drawSlotOutline(focused, slotIdx, rect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean handleDraggedClick(int mousex, int mousey, int button) {
|
||||
if (draggedStack == null)
|
||||
return false;
|
||||
public ItemPanel()
|
||||
{
|
||||
grid = new ItemPanelGrid();
|
||||
}
|
||||
|
||||
GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
boolean handled = false;
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
for (INEIGuiHandler handler : GuiInfo.guiHandlers) {
|
||||
if (handler.handleDragNDrop(gui, mousex, mousey, draggedStack, button)) {
|
||||
handled = true;
|
||||
if (draggedStack.stackSize == 0) {
|
||||
draggedStack = null;
|
||||
return true;
|
||||
}
|
||||
public static void updateItemList(ArrayList<ItemStack> newItems)
|
||||
{
|
||||
((ItemPanelGrid) ItemPanels.itemPanel.getGrid()).setItems(newItems);
|
||||
ItemPanels.itemPanel.realItems = newItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
more = new Button("+")
|
||||
{
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick)
|
||||
return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? 64 : NEIClientUtils.shiftKey() ? 10 : 1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
};
|
||||
less = new Button("-")
|
||||
{
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick)
|
||||
return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? -64 : NEIClientUtils.shiftKey() ? -10 : -1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
quantity = new ItemQuantityField("quantity");
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void scroll(int i)
|
||||
{
|
||||
grid.shiftPage(i);
|
||||
}
|
||||
|
||||
public String getLabelText()
|
||||
{
|
||||
return String.format("(%d/%d)", getPage(), Math.max(1, getNumPages()));
|
||||
}
|
||||
|
||||
protected String getPositioningSettingName()
|
||||
{
|
||||
return "world.panels.items";
|
||||
}
|
||||
|
||||
public int getMarginLeft(GuiContainer gui)
|
||||
{
|
||||
return (gui.width + gui.xSize) / 2 + PADDING;
|
||||
}
|
||||
|
||||
public int getMarginTop(GuiContainer gui)
|
||||
{
|
||||
return PADDING;
|
||||
}
|
||||
|
||||
public int getWidth(GuiContainer gui)
|
||||
{
|
||||
return gui.width - (gui.xSize + gui.width) / 2 - PADDING * 2;
|
||||
}
|
||||
|
||||
public int getHeight(GuiContainer gui)
|
||||
{
|
||||
return gui.height - getMarginTop(gui) - PADDING;
|
||||
}
|
||||
|
||||
protected int resizeFooter(GuiContainer gui)
|
||||
{
|
||||
final int BUTTON_SIZE = 16;
|
||||
|
||||
more.w = less.w = BUTTON_SIZE;
|
||||
more.h = less.h = quantity.h = BUTTON_SIZE;
|
||||
|
||||
less.x = x;
|
||||
more.x = x + w - BUTTON_SIZE;
|
||||
more.y = less.y = quantity.y = y + h - BUTTON_SIZE;
|
||||
|
||||
quantity.x = x + BUTTON_SIZE + 2;
|
||||
quantity.w = more.x - quantity.x - 2;
|
||||
|
||||
return BUTTON_SIZE + 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible()
|
||||
{
|
||||
super.setVisible();
|
||||
|
||||
if (grid.getPerPage() > 0) {
|
||||
LayoutManager.addWidget(more);
|
||||
LayoutManager.addWidget(less);
|
||||
LayoutManager.addWidget(quantity);
|
||||
}
|
||||
|
||||
if (handled)
|
||||
return true;
|
||||
|
||||
Slot overSlot = gui.getSlotAtPosition(mousex, mousey);
|
||||
if (overSlot != null && overSlot.isItemValid(draggedStack)) {
|
||||
if (NEIClientConfig.canCheatItem(draggedStack)) {
|
||||
int contents = overSlot.getHasStack() ? overSlot.getStack().stackSize : 0;
|
||||
int add = button == 0 ? draggedStack.stackSize : 1;
|
||||
if (overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack()))
|
||||
contents = 0;
|
||||
int total = Math.min(contents + add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize()));
|
||||
|
||||
if (total > contents) {
|
||||
NEIClientUtils.setSlotContents(overSlot.slotNumber, NEIServerUtils.copyStack(draggedStack, total), true);
|
||||
NEICPH.sendGiveItem(NEIServerUtils.copyStack(draggedStack, total), false, false);
|
||||
draggedStack.stackSize -= total - contents;
|
||||
}
|
||||
if (draggedStack.stackSize == 0)
|
||||
draggedStack = null;
|
||||
} else {
|
||||
draggedStack = null;
|
||||
}
|
||||
} else if (mousex < gui.guiLeft || mousey < gui.guiTop || mousex >= gui.guiLeft + gui.xSize || mousey >= gui.guiTop + gui.ySize) {
|
||||
draggedStack = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClickExt(int mousex, int mousey, int button) {
|
||||
return handleDraggedClick(mousex, mousey, button);
|
||||
}
|
||||
protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot)
|
||||
{
|
||||
ItemStack stack = grid.getItem(mouseDownSlot);
|
||||
|
||||
@Override
|
||||
public void mouseUp(int mousex, int mousey, int button) {
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item;
|
||||
if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) {
|
||||
if (button == 0)
|
||||
GuiCraftingRecipe.openRecipeGui("item", item);
|
||||
else if (button == 1)
|
||||
GuiUsageRecipe.openRecipeGui("item", item);
|
||||
if (stack != null) {
|
||||
int amount = NEIClientConfig.getItemQuantity();
|
||||
|
||||
draggedStack = null;
|
||||
mouseDownSlot = -1;
|
||||
return;
|
||||
if (amount == 0) {
|
||||
amount = stack.getMaxStackSize();
|
||||
}
|
||||
|
||||
NEIClientUtils.cheatItem(item, button, -1);
|
||||
return NEIServerUtils.copyStack(stack, amount);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMouseWheel(int i, int mousex, int mousey) {
|
||||
if (!contains(mousex, mousey))
|
||||
return false;
|
||||
|
||||
scroll(-i);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyPress(int keyID, char keyChar) {
|
||||
if (keyID == NEIClientConfig.getKeyBinding("gui.next")) {
|
||||
scroll(1);
|
||||
return true;
|
||||
}
|
||||
if (keyID == NEIClientConfig.getKeyBinding("gui.prev")) {
|
||||
scroll(-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackMouseOver(int mousex, int mousey) {
|
||||
ItemPanelSlot slot = getSlotMouseOver(mousex, mousey);
|
||||
return slot == null ? null : slot.item;
|
||||
}
|
||||
|
||||
public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) {
|
||||
int index = firstIndex;
|
||||
for (int i = 0; i < rows * columns && index < realItems.size(); i++)
|
||||
if (validSlotMap[i]) {
|
||||
if (getSlotRect(i).contains(mousex, mousey))
|
||||
return new ItemPanelSlot(index);
|
||||
index++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void scroll(int i) {
|
||||
if (itemsPerPage != 0) {
|
||||
int oldIndex = firstIndex;
|
||||
firstIndex += i * itemsPerPage;
|
||||
if (firstIndex >= realItems.size())
|
||||
firstIndex = 0;
|
||||
if (firstIndex < 0)
|
||||
if (oldIndex > 0)
|
||||
firstIndex = 0;
|
||||
else
|
||||
firstIndex = (realItems.size() - 1) / itemsPerPage * itemsPerPage;
|
||||
|
||||
calculatePage();
|
||||
}
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public int getNumPages() {
|
||||
return numPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int px, int py) {
|
||||
GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
Rectangle4i rect = new Rectangle4i(px, py, 1, 1);
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
if(GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)))
|
||||
return false;
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
}
|
||||
return super.contains(px, py);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
public class ItemsGrid
|
||||
{
|
||||
public static final int SLOT_SIZE = 18;
|
||||
|
||||
protected int width;
|
||||
protected int height;
|
||||
|
||||
protected int marginLeft;
|
||||
protected int marginTop;
|
||||
|
||||
protected int paddingLeft;
|
||||
|
||||
protected ArrayList<ItemStack> realItems = new ArrayList<>();
|
||||
|
||||
protected int page;
|
||||
protected int perPage;
|
||||
|
||||
protected int firstIndex;
|
||||
protected int numPages;
|
||||
|
||||
protected int rows;
|
||||
protected int columns;
|
||||
|
||||
protected boolean[] validSlotMap;
|
||||
protected boolean[] invalidSlotMap;
|
||||
|
||||
@Nullable
|
||||
private Framebuffer framebuffer = null;
|
||||
protected boolean refreshBuffer = true;
|
||||
|
||||
public ArrayList<ItemStack> getItems()
|
||||
{
|
||||
return realItems;
|
||||
}
|
||||
|
||||
public ItemStack getItem(int idx)
|
||||
{
|
||||
return realItems.get(idx);
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return realItems.size();
|
||||
}
|
||||
|
||||
public int indexOf(ItemStack stackA, boolean useNBT)
|
||||
{
|
||||
|
||||
for (int idx = 0; idx < realItems.size(); idx++) {
|
||||
if (StackInfo.equalItemAndNBT(stackA, realItems.get(idx), useNBT)) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getPage()
|
||||
{
|
||||
return page + 1;
|
||||
}
|
||||
|
||||
public int getPerPage()
|
||||
{
|
||||
return perPage;
|
||||
}
|
||||
|
||||
public int getNumPages()
|
||||
{
|
||||
return numPages;
|
||||
}
|
||||
|
||||
public int getRows()
|
||||
{
|
||||
return rows;
|
||||
}
|
||||
|
||||
public int getColumns()
|
||||
{
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void setGridSize(int mleft, int mtop, int w, int h)
|
||||
{
|
||||
if(width != w || height != h || mleft != marginLeft || mtop != marginTop)
|
||||
refreshBuffer = true;
|
||||
|
||||
marginLeft = mleft;
|
||||
marginTop = mtop;
|
||||
|
||||
width = Math.max(0, w);
|
||||
height = Math.max(0, h);
|
||||
|
||||
columns = width / SLOT_SIZE;
|
||||
rows = height / SLOT_SIZE;
|
||||
|
||||
paddingLeft = (width % SLOT_SIZE) / 2;
|
||||
}
|
||||
|
||||
public void shiftPage(int shift)
|
||||
{
|
||||
if (perPage == 0) {
|
||||
numPages = 0;
|
||||
page = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
numPages = (int) Math.ceil((float) realItems.size() / (float) perPage);
|
||||
|
||||
page += shift;
|
||||
|
||||
if (page >= numPages) {
|
||||
page = page - numPages;
|
||||
}
|
||||
|
||||
if (page < 0) {
|
||||
page = numPages + page;
|
||||
}
|
||||
|
||||
page = Math.max(0, Math.min(page, numPages - 1));
|
||||
if(shift != 0)
|
||||
refreshBuffer = true;
|
||||
}
|
||||
|
||||
public void refresh(GuiContainer gui)
|
||||
{
|
||||
updateGuiOverlapSlots(gui);
|
||||
shiftPage(0);
|
||||
}
|
||||
|
||||
private void updateGuiOverlapSlots(GuiContainer gui)
|
||||
{
|
||||
boolean[] oldSlotMap = invalidSlotMap;
|
||||
invalidSlotMap = new boolean[rows * columns];
|
||||
perPage = columns * rows;
|
||||
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
if(NEIClientConfig.shouldCacheItemRendering() && !Arrays.equals(oldSlotMap, invalidSlotMap)) {
|
||||
refreshBuffer = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkGuiOverlap(GuiContainer gui, int start, int end, int dir)
|
||||
{
|
||||
boolean validColumn = false;
|
||||
|
||||
for (int c = start; c != end && !validColumn; c += dir) {
|
||||
validColumn = true;
|
||||
|
||||
for (int r = 0; r < rows; r++) {
|
||||
final int idx = columns * r + c;
|
||||
if (GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c)) && idx >= 0 && idx < invalidSlotMap.length && !invalidSlotMap[idx]) {
|
||||
invalidSlotMap[idx] = true;
|
||||
validColumn = false;
|
||||
perPage--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Rectangle4i getSlotRect(int i)
|
||||
{
|
||||
return getSlotRect(i / columns, i % columns);
|
||||
}
|
||||
|
||||
public Rectangle4i getSlotRect(int row, int column)
|
||||
{
|
||||
return new Rectangle4i(marginLeft + paddingLeft + column * SLOT_SIZE, marginTop + row * SLOT_SIZE, SLOT_SIZE, SLOT_SIZE);
|
||||
}
|
||||
|
||||
public boolean isInvalidSlot(int idx)
|
||||
{
|
||||
return invalidSlotMap[idx];
|
||||
}
|
||||
|
||||
private void drawSlotOutlines(int mousex, int mousey)
|
||||
{
|
||||
ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
int idx = page * perPage;
|
||||
for (int i = 0; i < rows * columns && idx < size(); i++) {
|
||||
if(!invalidSlotMap[i]) {
|
||||
drawSlotOutline(focused, idx, getSlotRect(i));
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if(focused != null && focused.slotIndex == slotIdx)
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight
|
||||
}
|
||||
|
||||
private void blitExistingBuffer() {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
framebuffer.bindFramebufferTexture();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
ScaledResolution res = new ScaledResolution(minecraft, minecraft.displayWidth, minecraft.displayHeight);
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertexWithUV(0, res.getScaledHeight_double(), 0.0, 0, 0);
|
||||
tessellator.addVertexWithUV(res.getScaledWidth_double(), res.getScaledHeight_double(), 0.0, 1, 0);
|
||||
tessellator.addVertexWithUV(res.getScaledWidth_double(), 0, 0.0, 1, 1);
|
||||
tessellator.addVertexWithUV(0, 0, 0, 0, 1);
|
||||
tessellator.draw();
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey)
|
||||
{
|
||||
if (getPerPage() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean shouldCache = NEIClientConfig.shouldCacheItemRendering() && !PresetsWidget.inEditMode();
|
||||
if(shouldCache) {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
if (framebuffer == null) {
|
||||
framebuffer = new Framebuffer(minecraft.displayWidth, minecraft.displayHeight, true);
|
||||
framebuffer.framebufferColor[0] = 0.0F;
|
||||
framebuffer.framebufferColor[1] = 0.0F;
|
||||
framebuffer.framebufferColor[2] = 0.0F;
|
||||
}
|
||||
drawSlotOutlines(mousex, mousey);
|
||||
if (refreshBuffer) {
|
||||
framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight);
|
||||
framebuffer.framebufferClear();
|
||||
framebuffer.bindFramebuffer(false);
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glDepthMask(true);
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
} else {
|
||||
blitExistingBuffer();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
drawSlotOutlines(mousex, mousey);
|
||||
}
|
||||
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
|
||||
int idx = page * perPage;
|
||||
for (int i = 0; i < rows * columns && idx < size(); i++) {
|
||||
if (!invalidSlotMap[i]) {
|
||||
drawItem(getSlotRect(i), idx);
|
||||
idx ++;
|
||||
}
|
||||
}
|
||||
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
|
||||
if (refreshBuffer && shouldCache) {
|
||||
refreshBuffer = false;
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
blitExistingBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawItem(Rectangle4i rect, int idx)
|
||||
{
|
||||
GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, getItem(idx));
|
||||
}
|
||||
|
||||
public ItemPanelSlot getSlotMouseOver(int mousex, int mousey)
|
||||
{
|
||||
if (!contains(mousex, mousey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int overRow = (int) ((mousey - marginTop) / SLOT_SIZE);
|
||||
final int overColumn = (int) ((mousex - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int slt = columns * overRow + overColumn;
|
||||
int idx = page * perPage + slt;
|
||||
|
||||
if (overRow >= rows || overColumn >= columns) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < slt; i++) {
|
||||
if (invalidSlotMap[i]) {
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
|
||||
return idx < size()? new ItemPanelSlot(idx, realItems.get(idx)): null;
|
||||
}
|
||||
|
||||
public boolean contains(int px, int py)
|
||||
{
|
||||
|
||||
if (!(new Rectangle4i(marginLeft + paddingLeft, marginTop, columns * SLOT_SIZE, height)).contains(px, py)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int r = (int) ((py - marginTop) / SLOT_SIZE);
|
||||
final int c = (int) ((px - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int slt = columns * r + c;
|
||||
|
||||
return r >= rows || c >= columns || !invalidSlotMap[slt];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.api.LayoutStyle;
|
||||
@@ -16,7 +15,7 @@ import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerObjectHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
@@ -38,7 +37,6 @@ import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
import static codechicken.lib.gui.GuiDraw.drawTexturedModalRect;
|
||||
import static codechicken.nei.NEIClientConfig.canPerformAction;
|
||||
import static codechicken.nei.NEIClientConfig.disabledActions;
|
||||
import static codechicken.nei.NEIClientConfig.getItemQuantity;
|
||||
import static codechicken.nei.NEIClientConfig.getKeyBinding;
|
||||
import static codechicken.nei.NEIClientConfig.getOptionList;
|
||||
import static codechicken.nei.NEIClientConfig.getSearchExpression;
|
||||
@@ -50,7 +48,6 @@ import static codechicken.nei.NEIClientConfig.isHidden;
|
||||
import static codechicken.nei.NEIClientConfig.showIDs;
|
||||
import static codechicken.nei.NEIClientConfig.toggleBooleanSetting;
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
import static codechicken.nei.NEIClientUtils.controlKey;
|
||||
import static codechicken.nei.NEIClientUtils.cycleGamemode;
|
||||
import static codechicken.nei.NEIClientUtils.decreaseSlotStack;
|
||||
import static codechicken.nei.NEIClientUtils.deleteEverything;
|
||||
@@ -63,7 +60,6 @@ import static codechicken.nei.NEIClientUtils.getNextGamemode;
|
||||
import static codechicken.nei.NEIClientUtils.healPlayer;
|
||||
import static codechicken.nei.NEIClientUtils.isValidGamemode;
|
||||
import static codechicken.nei.NEIClientUtils.setHourForward;
|
||||
import static codechicken.nei.NEIClientUtils.setItemQuantity;
|
||||
import static codechicken.nei.NEIClientUtils.shiftKey;
|
||||
import static codechicken.nei.NEIClientUtils.toggleMagnetMode;
|
||||
import static codechicken.nei.NEIClientUtils.toggleRaining;
|
||||
@@ -79,22 +75,26 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
/**
|
||||
* Sorted bottom first
|
||||
*/
|
||||
private static TreeSet<Widget> drawWidgets;
|
||||
private static TreeSet<Widget> drawWidgets = new TreeSet<>(new WidgetZOrder(false));
|
||||
/**
|
||||
* Sorted top first
|
||||
*/
|
||||
private static TreeSet<Widget> controlWidgets;
|
||||
private static TreeSet<Widget> controlWidgets = new TreeSet<>(new WidgetZOrder(true));
|
||||
|
||||
public static ItemPanel itemPanel;
|
||||
public static BookmarkPanel bookmarkPanel;
|
||||
public static SubsetWidget dropDown;
|
||||
public static PresetsWidget presetsPanel;
|
||||
public static TextField searchField;
|
||||
|
||||
public static ButtonCycled options;
|
||||
public static ButtonCycled bookmarksButton;
|
||||
|
||||
@Deprecated
|
||||
public static Button more;
|
||||
@Deprecated
|
||||
public static Button less;
|
||||
@Deprecated
|
||||
public static ItemQuantityField quantity;
|
||||
|
||||
public static Button delete;
|
||||
@@ -143,9 +143,12 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int getSideWidth(GuiContainer gui) {
|
||||
return gui.width - 3;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int getLeftSize(GuiContainer gui) {
|
||||
return getSideWidth(gui);
|
||||
}
|
||||
@@ -179,7 +182,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public boolean objectUnderMouse(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled())
|
||||
for (Widget widget : controlWidgets)
|
||||
for (Widget widget : drawWidgets)
|
||||
if (widget.contains(mousex, mousey))
|
||||
return true;
|
||||
|
||||
@@ -240,7 +243,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public ItemStack getStackUnderMouse(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled()) {
|
||||
for (Widget widget : controlWidgets) {
|
||||
for (Widget widget : drawWidgets) {
|
||||
ItemStack stack = widget.getStackMouseOver(mousex, mousey);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
@@ -265,7 +268,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void postRenderObjects(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled()) {
|
||||
@@ -277,7 +280,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
for (Widget widget : controlWidgets)
|
||||
for (Widget widget : drawWidgets)
|
||||
currenttip = widget.handleTooltip(mousex, mousey, currenttip);
|
||||
}
|
||||
return currenttip;
|
||||
@@ -308,24 +311,32 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
public static void layout(GuiContainer gui) {
|
||||
VisiblityData visiblity = new VisiblityData();
|
||||
|
||||
if (isHidden())
|
||||
visiblity.showNEI = false;
|
||||
|
||||
|
||||
if (isBookmarkPanelHidden())
|
||||
visiblity.showBookmarkPanel = false;
|
||||
|
||||
|
||||
if (gui.height - gui.ySize <= 40)
|
||||
visiblity.showSearchSection = false;
|
||||
|
||||
|
||||
if (visiblity.showBookmarkPanel || gui.guiTop <= 20)
|
||||
visiblity.showSubsetDropdown = false;
|
||||
|
||||
if (!visiblity.showBookmarkPanel || gui.guiTop <= 20)
|
||||
visiblity.showPresetsDropdown = false;
|
||||
|
||||
if (gui.guiLeft - 4 < 76)
|
||||
visiblity.showWidgets = false;
|
||||
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
GuiInfo.guiHandlers.forEach(handler -> handler.modifyVisiblity(gui, visiblity));
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
visiblity.translateDependancies();
|
||||
|
||||
getLayoutStyle().layout(gui, visiblity);
|
||||
@@ -341,6 +352,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
bookmarkPanel.init();
|
||||
|
||||
dropDown = new SubsetWidget();
|
||||
presetsPanel = new PresetsWidget();
|
||||
searchField = new SearchField("search");
|
||||
|
||||
options = new ButtonCycled(3)
|
||||
@@ -351,7 +363,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
this.icons[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 48, 0, 16, 16).build();
|
||||
this.icons[2] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 64, 0, 16, 16).build();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
@@ -360,6 +372,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
} else {
|
||||
if (Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT || Keyboard.getEventKey() == Keyboard.KEY_RSHIFT)) {
|
||||
GuiRecipeTab.loadHandlerInfo();
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
}
|
||||
getOptionList().openGui(getGuiContainer(), false);
|
||||
}
|
||||
@@ -367,7 +380,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addTooltips(List<String> tooltip) {
|
||||
tooltip.add(translate("inventory.options.tip"));
|
||||
@@ -380,9 +393,9 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
String controlKeyLocalization = translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl");
|
||||
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode." + cheatMode));
|
||||
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode.disable", controlKeyLocalization));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return translate("inventory.options");
|
||||
@@ -396,7 +409,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
this.icons[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 0, 16, 16).build();
|
||||
this.icons[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 16, 0, 16, 16).build();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
NEIClientConfig.toggleBooleanSetting("inventory.bookmarksEnabled");
|
||||
@@ -412,43 +425,10 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
return translate("bookmark.toggle");
|
||||
}
|
||||
};
|
||||
more = new Button("+")
|
||||
{
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick)
|
||||
return false;
|
||||
|
||||
int modifier = controlKey() ? 64 : shiftKey() ? 10 : 1;
|
||||
|
||||
int quantity = getItemQuantity() + modifier;
|
||||
if (quantity < 0)
|
||||
quantity = 0;
|
||||
|
||||
LayoutManager.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
less = new Button("-")
|
||||
{
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick)
|
||||
return false;
|
||||
|
||||
int modifier = controlKey() ? -64 : shiftKey() ? -10 : -1;
|
||||
|
||||
int quantity = getItemQuantity() + modifier;
|
||||
if (quantity < 0)
|
||||
quantity = 0;
|
||||
|
||||
LayoutManager.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
quantity = new ItemQuantityField("quantity");
|
||||
|
||||
|
||||
more = ItemPanels.itemPanel.more;
|
||||
less = ItemPanels.itemPanel.less;
|
||||
quantity = ItemPanels.itemPanel.quantity;
|
||||
delete = new Button()
|
||||
{
|
||||
@Override
|
||||
@@ -619,7 +599,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static void markItemsDirty() {
|
||||
// If anything has modified data this depends on, we'll need to reload the item list
|
||||
itemsLoaded = false;
|
||||
@@ -672,18 +652,24 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
addWidget(options);
|
||||
addWidget(bookmarksButton);
|
||||
if (visiblity.showItemPanel) {
|
||||
addWidget(itemPanel);
|
||||
itemPanel.setVisible();
|
||||
|
||||
addWidget(more);
|
||||
addWidget(less);
|
||||
addWidget(quantity);
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
drawWidgets.add(itemPanel);
|
||||
} else {
|
||||
addWidget(itemPanel);
|
||||
}
|
||||
|
||||
itemPanel.setVisible();
|
||||
}
|
||||
|
||||
if (visiblity.showBookmarkPanel) {
|
||||
addWidget(bookmarkPanel);
|
||||
bookmarkPanel.setVisible();
|
||||
}
|
||||
}
|
||||
|
||||
if (visiblity.showPresetsDropdown) {
|
||||
addWidget(presetsPanel);
|
||||
}
|
||||
|
||||
if (visiblity.showSearchSection) {
|
||||
addWidget(searchField);
|
||||
@@ -707,8 +693,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
if (canPerformAction("delete"))
|
||||
addWidget(delete);
|
||||
}
|
||||
|
||||
if (!visiblity.showBookmarkPanel) {
|
||||
|
||||
if (visiblity.showSubsetDropdown) {
|
||||
// Bookmarks or Subset/dropdown
|
||||
addWidget(dropDown);
|
||||
}
|
||||
@@ -739,7 +725,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
for (Widget widget : controlWidgets)
|
||||
for (Widget widget : drawWidgets)
|
||||
widget.update();
|
||||
}
|
||||
|
||||
@@ -748,7 +734,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
if (isHidden() || !isEnabled())
|
||||
return false;
|
||||
|
||||
for (Widget widget : controlWidgets)
|
||||
for (Widget widget : drawWidgets)
|
||||
if (widget.onMouseWheel(scrolled, mousex, mousey))
|
||||
return true;
|
||||
|
||||
@@ -761,7 +747,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public boolean shouldShowTooltip(GuiContainer gui) {
|
||||
return itemPanel.draggedStack == null;
|
||||
return itemPanel.draggedStack == null && bookmarkPanel.sortedStackIndex == -1;
|
||||
}
|
||||
|
||||
/** Note: this method isn't actually used by this mod, but NEI add-ons might need it. */
|
||||
@@ -788,7 +774,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public void renderSlotOverlay(GuiContainer window, Slot slot) {
|
||||
ItemStack item = slot.getStack();
|
||||
if (world.nbt.getBoolean("searchinventories") && (item == null ? !getSearchExpression().equals("") : !ItemList.getItemListFilter().matches(item))) {
|
||||
if (world.nbt.getBoolean("searchinventories") && (item == null ? !getSearchExpression().equals("") : !((SearchField) searchField).getFilter().matches(item))) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glTranslatef(0, 0, 150);
|
||||
drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000);
|
||||
@@ -799,16 +785,16 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
public static void drawIcon(int x, int y, Image image) {
|
||||
final boolean isDrawableResource = image instanceof DrawableResource;
|
||||
|
||||
|
||||
if (!isDrawableResource)
|
||||
changeTexture("nei:textures/nei_sprites.png");
|
||||
|
||||
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
if(!isDrawableResource)
|
||||
drawTexturedModalRect(x, y, image.x, image.y, image.width, image.height);
|
||||
else
|
||||
else
|
||||
((DrawableResource)image).draw(x, y);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
@@ -884,4 +870,3 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,15 +10,13 @@ import static codechicken.nei.LayoutManager.bookmarkPanel;
|
||||
import static codechicken.nei.LayoutManager.bookmarksButton;
|
||||
import static codechicken.nei.LayoutManager.delete;
|
||||
import static codechicken.nei.LayoutManager.dropDown;
|
||||
import static codechicken.nei.LayoutManager.presetsPanel;
|
||||
import static codechicken.nei.LayoutManager.gamemode;
|
||||
import static codechicken.nei.LayoutManager.heal;
|
||||
import static codechicken.nei.LayoutManager.itemPanel;
|
||||
import static codechicken.nei.LayoutManager.itemPresenceOverlays;
|
||||
import static codechicken.nei.LayoutManager.less;
|
||||
import static codechicken.nei.LayoutManager.magnet;
|
||||
import static codechicken.nei.LayoutManager.more;
|
||||
import static codechicken.nei.LayoutManager.options;
|
||||
import static codechicken.nei.LayoutManager.quantity;
|
||||
import static codechicken.nei.LayoutManager.rain;
|
||||
import static codechicken.nei.LayoutManager.searchField;
|
||||
import static codechicken.nei.LayoutManager.timeButtons;
|
||||
@@ -118,16 +116,6 @@ public class LayoutStyleMinecraft extends LayoutStyle
|
||||
itemPanel.resize(gui);
|
||||
bookmarkPanel.resize(gui);
|
||||
|
||||
more.w = more.h = less.w = less.h = 16;
|
||||
less.x = itemPanel.prev.x;
|
||||
more.x = gui.width - less.w - 2;
|
||||
more.y = less.y = gui.height - more.h - 2;
|
||||
|
||||
quantity.x = less.x + less.w + 2;
|
||||
quantity.y = less.y;
|
||||
quantity.w = more.x - quantity.x - 2;
|
||||
quantity.h = less.h;
|
||||
|
||||
options.x = isEnabled() ? 0 : 6;
|
||||
options.y = isEnabled() ? gui.height - 22 : gui.height - 28;
|
||||
options.w = 22;
|
||||
@@ -138,15 +126,20 @@ public class LayoutStyleMinecraft extends LayoutStyle
|
||||
bookmarksButton.w = 22;
|
||||
bookmarksButton.h = 22;
|
||||
|
||||
searchField.y = gui.height - searchField.h - 2;
|
||||
dropDown.h = 18;
|
||||
dropDown.w = 150;
|
||||
dropDown.y = 0;
|
||||
dropDown.x = (gui.width - gui.xSize) / 2 + gui.xSize - dropDown.w;
|
||||
|
||||
dropDown.x = Math.min(numButtons, buttonCount) * 20 + 3;
|
||||
dropDown.h = 20;
|
||||
dropDown.w = itemPanel.x - dropDown.x - 3;
|
||||
presetsPanel.h = 16;
|
||||
presetsPanel.w = 150;
|
||||
presetsPanel.y = 2;
|
||||
presetsPanel.x = (gui.width - gui.xSize) / 2 + gui.xSize - presetsPanel.w;
|
||||
|
||||
searchField.h = 20;
|
||||
searchField.w = 150;
|
||||
searchField.x = (gui.width - searchField.w) / 2;
|
||||
searchField.y = gui.height - searchField.h - 2;
|
||||
|
||||
if (!visiblity.showItemSection) {
|
||||
searchField.setFocus(false);
|
||||
@@ -155,8 +148,8 @@ public class LayoutStyleMinecraft extends LayoutStyle
|
||||
}
|
||||
|
||||
public void layoutButton(Button button) {
|
||||
button.x = 2 + (buttonCount % numButtons) * 20;
|
||||
button.y = (buttonCount / numButtons) * 18;
|
||||
button.x = 2 + (buttonCount % numButtons) * 19;
|
||||
button.y = 2 + (buttonCount / numButtons) * 18;
|
||||
|
||||
button.h = 17;
|
||||
button.w = button.contentWidth() + 6;
|
||||
|
||||
@@ -16,6 +16,7 @@ import codechicken.nei.config.ConfigSet;
|
||||
import codechicken.nei.config.GuiHighlightTips;
|
||||
import codechicken.nei.config.GuiNEIOptionList;
|
||||
import codechicken.nei.config.GuiOptionList;
|
||||
import codechicken.nei.config.GuiPanelSettings;
|
||||
import codechicken.nei.config.OptionCycled;
|
||||
import codechicken.nei.config.OptionGamemodes;
|
||||
import codechicken.nei.config.OptionList;
|
||||
@@ -27,12 +28,13 @@ import codechicken.nei.config.OptionUtilities;
|
||||
import codechicken.nei.event.NEIConfigsLoadedEvent;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import codechicken.nei.recipe.RecipeInfo;
|
||||
import codechicken.nei.recipe.TemplateRecipeHandler;
|
||||
import codechicken.obfuscator.ObfuscationRun;
|
||||
import com.google.common.base.Objects;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.World;
|
||||
@@ -48,10 +50,12 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class NEIClientConfig {
|
||||
private static boolean configLoaded;
|
||||
private static boolean enabledOverride;
|
||||
private static String worldPath;
|
||||
|
||||
public static Logger logger = LogManager.getLogger("NotEnoughItems");
|
||||
public static File configDir = new File(CommonUtils.getMinecraftDir(), "config/NEI/");
|
||||
@@ -59,17 +63,21 @@ public class NEIClientConfig {
|
||||
new File("saves/NEI/client.dat"),
|
||||
new ConfigFile(new File(configDir, "client.cfg")));
|
||||
public static ConfigSet world;
|
||||
public static final File bookmarkFile = new File(configDir, "bookmarks.ini");
|
||||
public static final File handlerFile = new File(configDir, "handlers.csv");
|
||||
public static final File catalystFile = new File(configDir, "catalysts.csv");
|
||||
public static final File serialHandlersFile = new File(configDir, "serialhandlers.cfg");
|
||||
public static final File heightHackHandlersFile = new File(configDir, "heighthackhandlers.cfg");
|
||||
public static final File handlerOrderingFile = new File(configDir, "handlerordering.csv");
|
||||
|
||||
@Deprecated
|
||||
public static File bookmarkFile;
|
||||
|
||||
// Set of handlers that need to be run in serial
|
||||
public static HashSet<String> serialHandlers = new HashSet<>();
|
||||
|
||||
// Set of handler ID of handlers that need the hack in GuiRecipe.startHeightHack().
|
||||
public static HashSet<String> heightHackHandlers = new HashSet<>();
|
||||
// Set of regexes matching handler ID of handlers that need the hack in GuiRecipe.startHeightHack().
|
||||
// We use regex here so that we can apply the height hack to entire mods with one entry.
|
||||
public static HashSet<Pattern> heightHackHandlerRegex = new HashSet<>();
|
||||
|
||||
// Map of handler ID to sort order.
|
||||
// Handlers will be sorted in ascending order, so smaller numbers show up earlier.
|
||||
@@ -79,11 +87,9 @@ public class NEIClientConfig {
|
||||
// Function that extracts the handler ID from a handler, with special logic for
|
||||
// TemplateRecipeHandler: prefer using the overlay ID if it exists.
|
||||
public static final Function<IRecipeHandler, String> HANDLER_ID_FUNCTION =
|
||||
handler -> handler instanceof TemplateRecipeHandler
|
||||
? Objects.firstNonNull(
|
||||
((TemplateRecipeHandler) handler).getOverlayIdentifier(),
|
||||
handler.getHandlerId())
|
||||
: handler.getHandlerId();
|
||||
handler -> Objects.firstNonNull(
|
||||
handler.getOverlayIdentifier(),
|
||||
handler.getHandlerId());
|
||||
|
||||
// Comparator that compares handlers using the handlerOrdering map.
|
||||
public static final Comparator<IRecipeHandler> HANDLER_COMPARATOR =
|
||||
@@ -117,7 +123,7 @@ public class NEIClientConfig {
|
||||
|
||||
tag.getTag("inventory.widgetsenabled").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.widgetsenabled"));
|
||||
|
||||
|
||||
tag.getTag("inventory.hidden").getBooleanValue(false);
|
||||
tag.getTag("inventory.cheatmode").getIntValue(2);
|
||||
tag.getTag("inventory.lockmode").setComment("For those who can't help themselves.\nSet this to a mode and you will be unable to change it ingame").getIntValue(-1);
|
||||
@@ -150,6 +156,20 @@ public class NEIClientConfig {
|
||||
tag.getTag("world.highlight_tips.y").getIntValue(100);
|
||||
API.addOption(new OptionOpenGui("world.highlight_tips", GuiHighlightTips.class));
|
||||
|
||||
|
||||
tag.getTag("world.panels.bookmarks.left").getIntValue(0);
|
||||
tag.getTag("world.panels.bookmarks.right").getIntValue(0);
|
||||
tag.getTag("world.panels.bookmarks.top").getIntValue(0);
|
||||
tag.getTag("world.panels.bookmarks.bottom").getIntValue(0);
|
||||
|
||||
tag.getTag("world.panels.items.left").getIntValue(0);
|
||||
tag.getTag("world.panels.items.right").getIntValue(0);
|
||||
tag.getTag("world.panels.items.top").getIntValue(0);
|
||||
tag.getTag("world.panels.items.bottom").getIntValue(0);
|
||||
|
||||
API.addOption(new OptionOpenGui("world.panels", GuiPanelSettings.class));
|
||||
|
||||
|
||||
tag.getTag("inventory.profileRecipes").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.profileRecipes", true));
|
||||
|
||||
@@ -164,6 +184,11 @@ public class NEIClientConfig {
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.cacheItemRendering").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.cacheItemRendering", true));
|
||||
|
||||
tag.getTag("itemLoadingTimeout").getIntValue(500);
|
||||
|
||||
tag.getTag("command.creative").setDefaultValue("/gamemode {0} {1}");
|
||||
API.addOption(new OptionTextField("command.creative"));
|
||||
tag.getTag("command.item").setDefaultValue("/give {0} {1} {2} {3} {4}");
|
||||
@@ -174,14 +199,44 @@ public class NEIClientConfig {
|
||||
API.addOption(new OptionTextField("command.rain"));
|
||||
tag.getTag("command.heal").setDefaultValue("");
|
||||
API.addOption(new OptionTextField("command.heal"));
|
||||
|
||||
|
||||
tag.getTag("inventory.worldSpecificBookmarks").setComment("Global or world specific bookmarks").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.worldSpecificBookmarks", true) {
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
initBookmarkFile(worldPath);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.worldSpecificPresets").setComment("Global or world specific presets").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.worldSpecificPresets", true) {
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
initPresetsFile(worldPath);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.bookmarksEnabled").setComment("Enable/disable bookmarks").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarksEnabled", true));
|
||||
tag.getTag("inventory.saveCurrentRecipeInBookmarksEnabled").setComment("Save Current Recipe in Bookmarks").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.saveCurrentRecipeInBookmarksEnabled", true));
|
||||
tag.getTag("inventory.useNBTInBookmarks").setComment("Use NBT in Bookmarks").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.useNBTInBookmarks", true));
|
||||
tag.getTag("inventory.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.showRecipeMarker", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_tabs").setComment("Enable/disable JEI Style Tabs").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButtonBoubs("inventory.jei_style_tabs", true));
|
||||
tag.getTag("inventory.jei_style_item_presence_overlay").setComment("Enable/disable JEI Style item presence overlay on ?-hover").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_item_presence_overlay", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_recipe_catalyst").setComment("Enable/disable JEI Style Recipe Catalysts").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_recipe_catalyst", true));
|
||||
|
||||
|
||||
tag.getTag("inventory.creative_tab_style").setComment("Creative or JEI style tabs").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.creative_tab_style", true));
|
||||
|
||||
@@ -194,6 +249,17 @@ public class NEIClientConfig {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("tools.catalyst_load_from_config").setComment("ADVANCED: Load catalysts from config").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("tools.catalyst_load_from_config", true) {
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
setDefaultKeyBindings();
|
||||
}
|
||||
|
||||
@@ -237,6 +303,7 @@ public class NEIClientConfig {
|
||||
API.addKeyBind("gui.hide", Keyboard.KEY_O);
|
||||
API.addKeyBind("gui.search", Keyboard.KEY_F);
|
||||
API.addKeyBind("gui.bookmark", Keyboard.KEY_A);
|
||||
API.addKeyBind("gui.overlay", Keyboard.KEY_S);
|
||||
API.addKeyBind("gui.hide_bookmarks", Keyboard.KEY_B);
|
||||
API.addKeyBind("world.chunkoverlay", Keyboard.KEY_F9);
|
||||
API.addKeyBind("world.moboverlay", Keyboard.KEY_F7);
|
||||
@@ -254,17 +321,23 @@ public class NEIClientConfig {
|
||||
return OptionList.getOptionList("nei.options");
|
||||
}
|
||||
|
||||
public static void loadWorld(String saveName) {
|
||||
public static void loadWorld(String worldPath) {
|
||||
NEIClientConfig.worldPath = worldPath;
|
||||
|
||||
setInternalEnabled(true);
|
||||
logger.debug("Loading "+(Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote")+" World");
|
||||
bootNEI(ClientUtils.getWorld());
|
||||
|
||||
File saveDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + saveName);
|
||||
boolean newWorld = !saveDir.exists();
|
||||
if (newWorld)
|
||||
saveDir.mkdirs();
|
||||
final File specificDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
|
||||
final boolean newWorld = !specificDir.exists();
|
||||
|
||||
world = new ConfigSet(new File(saveDir, "NEI.dat"), new ConfigFile(new File(saveDir, "NEI.cfg")));
|
||||
if (newWorld) {
|
||||
specificDir.mkdirs();
|
||||
}
|
||||
|
||||
initBookmarkFile(worldPath);
|
||||
initPresetsFile(worldPath);
|
||||
world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg")));
|
||||
onWorldLoad(newWorld);
|
||||
}
|
||||
|
||||
@@ -274,7 +347,7 @@ public class NEIClientConfig {
|
||||
setWorldDefaults();
|
||||
creativeInv = new ItemStack[54];
|
||||
LayoutManager.searchField.setText(getSearchExpression());
|
||||
LayoutManager.quantity.setText(Integer.toString(getItemQuantity()));
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(getItemQuantity()));
|
||||
SubsetWidget.loadHidden();
|
||||
|
||||
if (newWorld && Minecraft.getMinecraft().isSingleplayer())
|
||||
@@ -308,8 +381,8 @@ public class NEIClientConfig {
|
||||
GuiInfo.load();
|
||||
RecipeInfo.load();
|
||||
LayoutManager.load();
|
||||
ItemPanels.bookmarkPanel.loadBookmarks();
|
||||
NEIController.load();
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
|
||||
configLoaded = true;
|
||||
|
||||
@@ -337,6 +410,26 @@ public class NEIClientConfig {
|
||||
ItemSorter.loadConfig();
|
||||
}
|
||||
|
||||
private static void initBookmarkFile(String worldPath)
|
||||
{
|
||||
|
||||
if (!global.config.getTag("inventory.worldSpecificBookmarks").getBooleanValue()) {
|
||||
worldPath = "global";
|
||||
}
|
||||
|
||||
ItemPanels.bookmarkPanel.setBookmarkFile(worldPath);
|
||||
}
|
||||
|
||||
private static void initPresetsFile(String worldPath)
|
||||
{
|
||||
|
||||
if (!global.config.getTag("inventory.worldSpecificPresets").getBooleanValue()) {
|
||||
worldPath = "global";
|
||||
}
|
||||
|
||||
PresetsWidget.loadPresets(worldPath);
|
||||
}
|
||||
|
||||
public static boolean isWorldSpecific(String setting) {
|
||||
if(world == null) return false;
|
||||
ConfigTag tag = world.config.getTag(setting, false);
|
||||
@@ -357,12 +450,24 @@ public class NEIClientConfig {
|
||||
public static boolean isBookmarkPanelHidden() {
|
||||
return !getBooleanSetting("inventory.bookmarksEnabled");
|
||||
}
|
||||
public static boolean saveCurrentRecipeInBookmarksEnabled() {
|
||||
return getBooleanSetting("inventory.saveCurrentRecipeInBookmarksEnabled");
|
||||
}
|
||||
public static boolean useNBTInBookmarks() {
|
||||
return getBooleanSetting("inventory.useNBTInBookmarks");
|
||||
}
|
||||
public static boolean showRecipeMarker() {
|
||||
return getBooleanSetting("inventory.showRecipeMarker");
|
||||
}
|
||||
public static boolean areJEIStyleTabsVisible() {
|
||||
return getBooleanSetting("inventory.jei_style_tabs");
|
||||
}
|
||||
public static boolean isJEIStyleItemPresenceOverlayVisible() {
|
||||
return getBooleanSetting("inventory.jei_style_item_presence_overlay");
|
||||
}
|
||||
public static boolean areJEIStyleRecipeCatalystsVisible() {
|
||||
return getBooleanSetting("inventory.jei_style_recipe_catalyst");
|
||||
}
|
||||
public static boolean useCreativeTabStyle() {
|
||||
return getBooleanSetting("inventory.creative_tab_style");
|
||||
}
|
||||
@@ -370,7 +475,10 @@ public class NEIClientConfig {
|
||||
return enabledOverride && getBooleanSetting("inventory.widgetsenabled");
|
||||
}
|
||||
public static boolean loadHandlersFromJar() {
|
||||
return !getBooleanSetting("tools.handler_load_from_config");
|
||||
return !getBooleanSetting("tools.handler_load_from_config");
|
||||
}
|
||||
public static boolean loadCatalystsFromJar() {
|
||||
return !getBooleanSetting("tools.catalyst_load_from_config");
|
||||
}
|
||||
|
||||
public static void setEnabled(boolean flag) {
|
||||
@@ -406,6 +514,10 @@ public class NEIClientConfig {
|
||||
int i = getIntSetting("inventory.itemIDs");
|
||||
return i == 2 || (i == 1 && isEnabled() && !isHidden());
|
||||
}
|
||||
|
||||
public static int getItemLoadingTimeout() {
|
||||
return getIntSetting("itemLoadingTimeout");
|
||||
}
|
||||
|
||||
public static void toggleBooleanSetting(String setting) {
|
||||
ConfigTag tag = getSetting(setting);
|
||||
@@ -441,7 +553,11 @@ public class NEIClientConfig {
|
||||
public static boolean shouldInvertMouseScrollTransfer() {
|
||||
return !getBooleanSetting("inventory.invertMouseScrollTransfer");
|
||||
}
|
||||
|
||||
|
||||
public static boolean shouldCacheItemRendering() {
|
||||
return getBooleanSetting("inventory.cacheItemRendering") && OpenGlHelper.framebufferSupported;
|
||||
}
|
||||
|
||||
public static boolean getMagnetMode() {
|
||||
return enabledActions.contains("magnet");
|
||||
}
|
||||
@@ -528,5 +644,5 @@ public class NEIClientConfig {
|
||||
if (file.isDirectory() && !saveFileNames.contains(file.getName()))
|
||||
ObfuscationRun.deleteDir(file, true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.util.LangProxy;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import com.google.common.collect.Iterables;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -136,10 +135,7 @@ public class NEIClientUtils extends NEIServerUtils
|
||||
if (mode == 1 && stack.stackSize < stack.getMaxStackSize()) {
|
||||
giveStack(stack, stack.getMaxStackSize() - stack.stackSize);
|
||||
} else {
|
||||
int amount = getItemQuantity();
|
||||
if (amount == 0)
|
||||
amount = stack.getMaxStackSize();
|
||||
giveStack(stack, amount);
|
||||
giveStack(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,7 +157,10 @@ public class NEIClientUtils extends NEIServerUtils
|
||||
final List<Iterable<Integer>> handlerSlots;
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
handlerSlots = GuiInfo.guiHandlers.stream().map(handler -> handler.getItemSpawnSlots(gui, typestack)).collect(Collectors.toCollection(LinkedList::new));
|
||||
handlerSlots = GuiInfo.guiHandlers.stream()
|
||||
.map(handler -> handler.getItemSpawnSlots(gui, typestack))
|
||||
.filter(x -> x != null)
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerSlotClickHandler;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
@@ -137,6 +138,7 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
}
|
||||
|
||||
if (NEIClientUtils.controlKey()
|
||||
&& modifier != 4//Drop key pressed: net.minecraft.client.gui.inventory.GuiContainer.keyTyped
|
||||
&& slot != null && slot.getStack() != null
|
||||
&& slot.isItemValid(slot.getStack())) {
|
||||
NEIClientUtils.cheatItem(slot.getStack(), button, 1);
|
||||
@@ -227,6 +229,11 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
if (!NEIClientConfig.isEnabled() || GuiInfo.hasCustomSlots(gui) || !NEIClientConfig.isMouseScrollTransferEnabled())
|
||||
return false;
|
||||
|
||||
// slot in GuiRecipe does not contain actual stack
|
||||
// and scroll should be handled by GuiRecipe, not here
|
||||
if (gui instanceof GuiRecipe)
|
||||
return false;
|
||||
|
||||
Point mousePos = getMousePosition();
|
||||
Slot mouseover = manager.window.getSlotAtPosition(mousePos.x, mousePos.y);
|
||||
if (mouseover != null && mouseover.getHasStack()) {
|
||||
|
||||
@@ -6,13 +6,14 @@ import codechicken.nei.api.IConfigureNEI;
|
||||
import codechicken.nei.asm.NEICorePlugin;
|
||||
import codechicken.nei.config.IMCHandler;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import cpw.mods.fml.client.FMLFileResourcePack;
|
||||
import cpw.mods.fml.client.FMLFolderResourcePack;
|
||||
import cpw.mods.fml.common.DummyModContainer;
|
||||
import cpw.mods.fml.common.LoadController;
|
||||
import cpw.mods.fml.common.MetadataCollection;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLInterModComms;
|
||||
@@ -24,15 +25,14 @@ import cpw.mods.fml.common.versioning.VersionRange;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class NEIModContainer extends DummyModContainer
|
||||
{
|
||||
public static LinkedList<IConfigureNEI> plugins = new LinkedList<>();
|
||||
|
||||
private static boolean gregTech5Loaded;
|
||||
|
||||
public NEIModContainer() {
|
||||
super(getModMetadata());
|
||||
loadMetadata();
|
||||
@@ -43,9 +43,16 @@ public class NEIModContainer extends DummyModContainer
|
||||
modMetadata.name = "GRADLETOKEN_MODNAME";
|
||||
modMetadata.modId = "GRADLETOKEN_MODID";
|
||||
modMetadata.version = "GRADLETOKEN_VERSION";
|
||||
modMetadata.authorList = Arrays.asList( "ChickenBones", "mitchej123" );
|
||||
modMetadata.url = "https://github.com/GTNewHorizons/NotEnoughItems";
|
||||
modMetadata.description = "Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more; GTNH Version includes many enhancements.";
|
||||
return modMetadata;
|
||||
}
|
||||
|
||||
public static boolean isGT5Loaded() {
|
||||
return gregTech5Loaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ArtifactVersion> getRequirements() {
|
||||
Set<ArtifactVersion> deps = new HashSet<>();
|
||||
@@ -92,6 +99,7 @@ public class NEIModContainer extends DummyModContainer
|
||||
|
||||
@Subscribe
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
gregTech5Loaded = Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi_post");
|
||||
if (CommonUtils.isClient())
|
||||
ClientHandler.preInit();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Inspired by InventoryEffectRendererGuiHandler.java in JEI
|
||||
*/
|
||||
public class NEIPotionGuiHandler extends INEIGuiAdapter {
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer guiContainer, int slotX, int slotY, int slotW, int slotH) {
|
||||
if(guiContainer instanceof InventoryEffectRenderer) {
|
||||
int x = guiContainer.guiLeft - 124;
|
||||
int y = guiContainer.guiTop;
|
||||
Minecraft minecraft = guiContainer.mc;
|
||||
if (minecraft == null) {
|
||||
return false;
|
||||
}
|
||||
EntityPlayerSP player = minecraft.thePlayer;
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Collection<PotionEffect> activePotionEffects = player.getActivePotionEffects();
|
||||
if (activePotionEffects.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
int height = 33;
|
||||
if (activePotionEffects.size() > 5) {
|
||||
height = 132 / (activePotionEffects.size() - 1);
|
||||
}
|
||||
Rectangle4i slotRect = new Rectangle4i(slotX, slotY, slotW, slotH);
|
||||
for (PotionEffect potioneffect : activePotionEffects) {
|
||||
Rectangle4i box = new Rectangle4i(x, y, 140, 32);
|
||||
if(box.intersects(slotRect))
|
||||
return true;
|
||||
y += height;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.inventory.InventoryRange;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.util.NBTHelper;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -14,6 +17,9 @@ import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.JsonToNBT;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTException;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -24,6 +30,7 @@ import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.WorldSettings.GameType;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -143,6 +150,19 @@ public class NEIServerUtils
|
||||
ItemStack.areItemStackTagsEqual(stack2, stack1));
|
||||
}
|
||||
|
||||
/**
|
||||
* NBT-friendly version of {@link #areStacksSameType(ItemStack, ItemStack)}
|
||||
* @param stack1 The {@link ItemStack} being compared.
|
||||
* @param stack2 The {@link ItemStack} to compare to.
|
||||
* @return whether the two items are the same in terms of itemID, damage and NBT.
|
||||
*/
|
||||
public static boolean areStacksSameTypeWithNBT(ItemStack stack1, ItemStack stack2) {
|
||||
return stack1 != null && stack2 != null &&
|
||||
stack1.getItem() == stack2.getItem() &&
|
||||
(!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage()) &&
|
||||
NBTHelper.matchTag(stack1.getTagCompound(), stack2.getTagCompound());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ItemStack}s with damage -1 are wildcards allowing all damages. Eg all colours of wool are allowed to create Beds.
|
||||
*
|
||||
@@ -156,6 +176,24 @@ public class NEIServerUtils
|
||||
(stack1.getItemDamage() == stack2.getItemDamage() || stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack2.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack1.getItem().isDamageable());
|
||||
}
|
||||
|
||||
/**
|
||||
* NBT-friendly version of {@link #areStacksSameTypeCrafting(ItemStack, ItemStack)}
|
||||
* @param stack1 The {@link ItemStack} being compared.
|
||||
* @param stack2 The {@link ItemStack} to compare to.
|
||||
* @return whether the two items are the same from the perspective of a crafting inventory.
|
||||
*/
|
||||
public static boolean areStacksSameTypeCraftingWithNBT(ItemStack stack1, ItemStack stack2) {
|
||||
return stack1 != null && stack2 != null &&
|
||||
stack1.getItem() == stack2.getItem() &&
|
||||
(
|
||||
stack1.getItemDamage() == stack2.getItemDamage() ||
|
||||
stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE ||
|
||||
stack2.getItemDamage() == OreDictionary.WILDCARD_VALUE ||
|
||||
stack1.getItem().isDamageable()
|
||||
) &&
|
||||
NBTHelper.matchTag(stack1.getTagCompound(), stack2.getTagCompound());
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple function for comparing ItemStacks in a compatible with comparators.
|
||||
*
|
||||
@@ -387,6 +425,50 @@ public class NEIServerUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStack getModdedItem(String itemId, String nbtString) {
|
||||
int meta = -1;
|
||||
ItemStack itemStack;
|
||||
|
||||
if (!itemId.contains(":")) {
|
||||
NEIClientConfig.logger.info(String.format("Item ID %s is missing colon", itemId));
|
||||
return null;
|
||||
}
|
||||
final String[] split = itemId.split(":");
|
||||
// ModID:ItemID
|
||||
String itemLookupId = split[0] + ":" + split[1];
|
||||
|
||||
if (split.length >= 3) {
|
||||
int mIdx = -1;
|
||||
if (split[2].matches("\\d+")) {
|
||||
mIdx = 2;
|
||||
} else {
|
||||
itemLookupId += ":" + split[2];
|
||||
if (split.length >= 4) mIdx = 3;
|
||||
}
|
||||
if (mIdx != -1) meta = Integer.parseInt(split[mIdx]);
|
||||
}
|
||||
|
||||
if (meta != -1) {
|
||||
itemStack = GameRegistry.makeItemStack(itemLookupId, meta, 1, nbtString == null ? "" : nbtString);
|
||||
} else {
|
||||
itemStack = GameRegistry.findItemStack(split[0], split[1], 1);
|
||||
if (nbtString != null && !nbtString.isEmpty()) {
|
||||
try {
|
||||
final NBTBase nbttag = JsonToNBT.func_150315_a(nbtString);
|
||||
if (!(nbttag instanceof NBTTagCompound)) {
|
||||
NEIClientConfig.logger.info("Unexpected NBT string - multiple values {}", nbtString);
|
||||
return null;
|
||||
}
|
||||
itemStack.setTagCompound((NBTTagCompound) nbttag);
|
||||
} catch (NBTException e) {
|
||||
FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public static NBTTagCompound readNBT(File file) throws IOException {
|
||||
if(!file.exists()) return null;
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
@@ -408,4 +490,8 @@ public class NEIServerUtils
|
||||
CompressedStreamTools.writeCompressed(tag, out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
public static int divideCeil(int numerator, int denominator) {
|
||||
return (int) Math.ceil((float) numerator / denominator);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class PanelWidget extends Widget
|
||||
{
|
||||
protected static final int PADDING = 2;
|
||||
|
||||
public ItemStack draggedStack;
|
||||
public int mouseDownSlot = -1;
|
||||
|
||||
public Button pagePrev;
|
||||
public Button pageNext;
|
||||
public Label pageLabel;
|
||||
|
||||
protected ItemsGrid grid;
|
||||
|
||||
public ArrayList<ItemStack> getItems()
|
||||
{
|
||||
return grid.getItems();
|
||||
}
|
||||
|
||||
public ItemsGrid getGrid()
|
||||
{
|
||||
return grid;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
pageLabel = new Label("0/0", true);
|
||||
|
||||
pagePrev = new Button("Prev")
|
||||
{
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
grid.shiftPage(-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return "<";
|
||||
}
|
||||
};
|
||||
pageNext = new Button("Next")
|
||||
{
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
grid.shiftPage(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return ">";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
public abstract String getLabelText();
|
||||
|
||||
protected abstract String getPositioningSettingName();
|
||||
|
||||
public abstract int getMarginLeft(GuiContainer gui);
|
||||
|
||||
public abstract int getMarginTop(GuiContainer gui);
|
||||
|
||||
public abstract int getWidth(GuiContainer gui);
|
||||
|
||||
public abstract int getHeight(GuiContainer gui);
|
||||
|
||||
public void resize(GuiContainer gui)
|
||||
{
|
||||
final Rectangle4i margin = new Rectangle4i(getMarginLeft(gui), getMarginTop(gui), getWidth(gui), getHeight(gui));
|
||||
|
||||
|
||||
final int minWidth = 5 * ItemsGrid.SLOT_SIZE;
|
||||
final int minHeight = 9 * ItemsGrid.SLOT_SIZE;
|
||||
|
||||
final String settingName = getPositioningSettingName();
|
||||
int paddingLeft = (int)Math.ceil(margin.w * NEIClientConfig.getSetting(settingName + ".left").getIntValue() / 100000.0);
|
||||
int paddingTop = (int)Math.ceil(margin.h * NEIClientConfig.getSetting(settingName + ".top").getIntValue() / 100000.0);
|
||||
int paddingRight = (int)Math.ceil(margin.w * NEIClientConfig.getSetting(settingName + ".right").getIntValue()/ 100000.0);
|
||||
int paddingBottom = (int)Math.ceil(margin.h * NEIClientConfig.getSetting(settingName + ".bottom").getIntValue() / 100000.0);
|
||||
|
||||
int deltaHeight = Math.min(0, margin.h - paddingTop - paddingBottom - minHeight) / 2;
|
||||
|
||||
paddingLeft = Math.min(paddingLeft, Math.max(0, margin.w - paddingRight - minWidth));
|
||||
paddingRight = Math.min(paddingRight, Math.max(0, margin.w - paddingLeft - minWidth));
|
||||
paddingTop = Math.min(margin.h - minHeight, Math.max(0, paddingTop + deltaHeight));
|
||||
paddingBottom = Math.min(margin.h - paddingTop - minHeight, Math.max(0, paddingBottom - deltaHeight));
|
||||
|
||||
x = margin.x + paddingLeft;
|
||||
y = margin.y + paddingTop;
|
||||
w = margin.w - paddingLeft - paddingRight;
|
||||
h = margin.h - paddingTop - paddingBottom;
|
||||
|
||||
final int header = resizeHeader(gui);
|
||||
final int footer = resizeFooter(gui);
|
||||
|
||||
grid.setGridSize(x, y + header, w, h - header - footer);
|
||||
grid.refresh(gui);
|
||||
}
|
||||
|
||||
protected int resizeHeader(GuiContainer gui)
|
||||
{
|
||||
final int BUTTON_SIZE = 16;
|
||||
int paddingLeft = 0;
|
||||
int paddingRight = 0;
|
||||
|
||||
while (paddingLeft < w && GuiInfo.hideItemPanelSlot(gui, new Rectangle4i(x + paddingLeft, y, ItemsGrid.SLOT_SIZE, ItemsGrid.SLOT_SIZE))) {
|
||||
paddingLeft += ItemsGrid.SLOT_SIZE;
|
||||
}
|
||||
|
||||
while (paddingRight < w && GuiInfo.hideItemPanelSlot(gui, new Rectangle4i(x + w - paddingRight - ItemsGrid.SLOT_SIZE, y, ItemsGrid.SLOT_SIZE, ItemsGrid.SLOT_SIZE))) {
|
||||
paddingRight += ItemsGrid.SLOT_SIZE;
|
||||
}
|
||||
|
||||
if (paddingLeft + paddingRight >= w) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pagePrev.w = pageNext.w = BUTTON_SIZE;
|
||||
pagePrev.h = pageNext.h = BUTTON_SIZE;
|
||||
pagePrev.y = pageNext.y = y;
|
||||
|
||||
pagePrev.x = x + paddingLeft;
|
||||
pageNext.x = x + w - pageNext.w - paddingRight;
|
||||
|
||||
pageLabel.x = x + paddingLeft + (w - paddingLeft - paddingRight) / 2;
|
||||
pageLabel.y = y + 5;
|
||||
pageLabel.text = getLabelText();
|
||||
|
||||
return BUTTON_SIZE + 2;
|
||||
}
|
||||
|
||||
protected abstract int resizeFooter(GuiContainer gui);
|
||||
|
||||
public void setVisible()
|
||||
{
|
||||
if (grid.getPerPage() > 0) {
|
||||
LayoutManager.addWidget(pagePrev);
|
||||
LayoutManager.addWidget(pageNext);
|
||||
LayoutManager.addWidget(pageLabel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey)
|
||||
{
|
||||
grid.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDraw(int mousex, int mousey)
|
||||
{
|
||||
if (draggedStack != null) {
|
||||
GuiContainerManager.drawItems.zLevel += 100;
|
||||
GuiContainerManager.drawItem(mousex - 8, mousey - 8, draggedStack);
|
||||
GuiContainerManager.drawItems.zLevel -= 100;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mousex, int mousey, int button, long heldTime)
|
||||
{
|
||||
if (mouseDownSlot >= 0 && draggedStack == null && NEIClientUtils.getHeldItem() == null &&
|
||||
NEIClientConfig.hasSMPCounterPart() && !GuiInfo.hasCustomSlots(NEIClientUtils.getGuiContainer())) {
|
||||
ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500) {
|
||||
draggedStack = getDraggedStackWithQuantity(mouseDownSlot);
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ItemStack getDraggedStackWithQuantity(int mouseDownSlot);
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button)
|
||||
{
|
||||
|
||||
if (handleClickExt(mousex, mousey, button))
|
||||
return true;
|
||||
|
||||
if (NEIClientUtils.getHeldItem() != null) {
|
||||
|
||||
if (!grid.contains(mousex, mousey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item"))
|
||||
if (button == 1)
|
||||
NEIClientUtils.decreaseSlotStack(-999);
|
||||
else
|
||||
NEIClientUtils.deleteHeldItem();
|
||||
else
|
||||
NEIClientUtils.dropHeldItem();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null) {
|
||||
|
||||
if (button == 2) {
|
||||
|
||||
if (hoverSlot.item != null) {
|
||||
draggedStack = getDraggedStackWithQuantity(hoverSlot.slotIndex);
|
||||
}
|
||||
|
||||
} else {
|
||||
mouseDownSlot = hoverSlot.slotIndex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClickExt(int mouseX, int mouseY, int button)
|
||||
{
|
||||
if (ItemPanels.itemPanel.draggedStack != null) {
|
||||
return ItemPanels.itemPanel.handleDraggedClick(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
if (ItemPanels.bookmarkPanel.draggedStack != null) {
|
||||
return ItemPanels.bookmarkPanel.handleDraggedClick(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleDraggedClick(int mouseX, int mouseY, int button)
|
||||
{
|
||||
if (draggedStack == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (handleGUIContainerClick(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
if (mouseX < gui.guiLeft || mouseY < gui.guiTop || mouseX >= gui.guiLeft + gui.xSize || mouseY >= gui.guiTop + gui.ySize) {
|
||||
draggedStack = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean handleGUIContainerClick(int mouseX, int mouseY, int button)
|
||||
{
|
||||
final GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
boolean handled = false;
|
||||
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
for (INEIGuiHandler handler : GuiInfo.guiHandlers) {
|
||||
if (handler.handleDragNDrop(gui, mouseX, mouseY, draggedStack, button)) {
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
}
|
||||
|
||||
if (draggedStack.stackSize == 0) {
|
||||
draggedStack = null;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(int mousex, int mousey, int button)
|
||||
{
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item;
|
||||
|
||||
if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) {
|
||||
|
||||
if (button == 0) {
|
||||
GuiCraftingRecipe.openRecipeGui("item", item);
|
||||
} else if (button == 1) {
|
||||
GuiUsageRecipe.openRecipeGui("item", item);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
NEIClientUtils.cheatItem(getDraggedStackWithQuantity(hoverSlot.slotIndex), button, -1);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMouseWheel(int i, int mousex, int mousey)
|
||||
{
|
||||
if (!contains(mousex, mousey))
|
||||
return false;
|
||||
|
||||
grid.shiftPage(-i);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyPress(int keyID, char keyChar)
|
||||
{
|
||||
|
||||
if (keyID == NEIClientConfig.getKeyBinding("gui.next")) {
|
||||
grid.shiftPage(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyID == NEIClientConfig.getKeyBinding("gui.prev")) {
|
||||
grid.shiftPage(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackMouseOver(int mousex, int mousey)
|
||||
{
|
||||
ItemPanelSlot slot = getSlotMouseOver(mousex, mousey);
|
||||
return slot == null ? null : slot.item;
|
||||
}
|
||||
|
||||
public ItemPanelSlot getSlotMouseOver(int mousex, int mousey)
|
||||
{
|
||||
return grid.getSlotMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return grid.page + 1;
|
||||
}
|
||||
|
||||
public int getNumPages() {
|
||||
return grid.numPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int px, int py)
|
||||
{
|
||||
return grid.contains(px, py);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -98,6 +98,17 @@ public class PositionedStack
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* NBT-friendly version of {@link #contains(ItemStack)}
|
||||
*/
|
||||
public boolean containsWithNBT(ItemStack ingredient) {
|
||||
for(ItemStack item : items)
|
||||
if(NEIServerUtils.areStacksSameTypeCraftingWithNBT(item, ingredient))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(Item ingred) {
|
||||
for(ItemStack item : items)
|
||||
if(item.getItem() == ingred)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -63,8 +63,9 @@ public class SearchField extends TextField implements ItemFilterProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if(ItemPanels.itemPanel.realItems.size() == 0) {
|
||||
public int getTextColour()
|
||||
{
|
||||
if (ItemPanels.itemPanel.getItems().isEmpty()) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
|
||||
@@ -217,6 +217,7 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
|
||||
for(SubsetTag tag : sorted)
|
||||
tag.cacheState();
|
||||
}
|
||||
|
||||
public void addFiltersWithItem(List<ItemFilter> filters, String itemSearch) {
|
||||
if(itemSearch == null) {
|
||||
addFilters(filters);
|
||||
@@ -229,6 +230,7 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void addFilters(List<ItemFilter> filters) {
|
||||
if(filter != null)
|
||||
filters.add(filter);
|
||||
|
||||
@@ -11,6 +11,14 @@ public class VisiblityData
|
||||
* Bookmark panel and associated buttons
|
||||
*/
|
||||
public boolean showBookmarkPanel = true;
|
||||
/**
|
||||
* Subset dropdown
|
||||
*/
|
||||
public boolean showSubsetDropdown = true;
|
||||
/**
|
||||
* Presets dropdown
|
||||
*/
|
||||
public boolean showPresetsDropdown = true;
|
||||
/**
|
||||
* Item and search section
|
||||
*/
|
||||
@@ -40,6 +48,6 @@ public class VisiblityData
|
||||
if(!showWidgets)
|
||||
showItemSection = showUtilityButtons = false;
|
||||
if(!showItemSection)
|
||||
showBookmarkPanel = showSearchSection = showItemPanel = false;
|
||||
showBookmarkPanel = showSubsetDropdown = showPresetsDropdown = showSearchSection = showItemPanel = false;
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,14 @@ import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
{
|
||||
public static int mobOverlay = 0;
|
||||
public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
|
||||
public static int chunkOverlay = 0;
|
||||
|
||||
public static int mobOverlay = 0;
|
||||
private static byte[] mobSpawnCache;
|
||||
private static long mobOverlayUpdateTime;
|
||||
|
||||
public static void reset() {
|
||||
mobOverlay = 0;
|
||||
chunkOverlay = 0;
|
||||
@@ -33,7 +36,7 @@ public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
if (KeyManager.keyStates.get("world.moboverlay").down)
|
||||
mobOverlay = (mobOverlay + 1) % 2;
|
||||
if (KeyManager.keyStates.get("world.chunkoverlay").down)
|
||||
chunkOverlay = (chunkOverlay + 1) % 3;
|
||||
chunkOverlay = (chunkOverlay + 1) % (NEIModContainer.isGT5Loaded() ? 4 : 3);
|
||||
}
|
||||
|
||||
public static void render(float frame) {
|
||||
@@ -46,9 +49,56 @@ public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
private static void buildMobSpawnOverlay(Entity entity) {
|
||||
if (mobSpawnCache == null) {
|
||||
mobSpawnCache = new byte[33 * 33 * 33]; // 35kB
|
||||
}
|
||||
|
||||
World world = entity.worldObj;
|
||||
int x1 = (int) entity.posX;
|
||||
int z1 = (int) entity.posZ;
|
||||
int y1 = (int) MathHelper.clip(entity.posY, 16, world.getHeight() - 16);
|
||||
|
||||
for (int i = 0; i <= 32; i++) {
|
||||
int x = x1 - 16 + i;
|
||||
for (int j = 0; j <= 32; j++) {
|
||||
int z = z1 - 16 + j;
|
||||
int bufIndex = (i * 33 + j) * 33;
|
||||
|
||||
Chunk chunk = world.getChunkFromBlockCoords(x, z);
|
||||
BiomeGenBase biome = world.getBiomeGenForCoords(x, z);
|
||||
if (biome.getSpawnableList(EnumCreatureType.monster).isEmpty() || biome.getSpawningChance() <= 0) {
|
||||
mobSpawnCache[bufIndex] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
int maxHeight = chunk.worldObj.getHeightValue(x, z);
|
||||
|
||||
for (int k = 0; k <= 32; k++) {
|
||||
int y = y1 - 16 + k;
|
||||
if (y > maxHeight) {
|
||||
mobSpawnCache[bufIndex + k] = -1;
|
||||
break;
|
||||
}
|
||||
mobSpawnCache[bufIndex + k] = getSpawnMode(chunk, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderMobSpawnOverlay(Entity entity) {
|
||||
if (mobOverlay == 0)
|
||||
if (mobOverlay == 0) {
|
||||
if (mobSpawnCache != null) {
|
||||
mobSpawnCache = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
long worldTime = entity.worldObj.getTotalWorldTime();
|
||||
if (mobSpawnCache == null || mobOverlayUpdateTime != worldTime) {
|
||||
mobOverlayUpdateTime = worldTime;
|
||||
buildMobSpawnOverlay(entity);
|
||||
}
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
@@ -65,32 +115,37 @@ public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
int z1 = (int) entity.posZ;
|
||||
int y1 = (int) MathHelper.clip(entity.posY, 16, world.getHeight() - 16);
|
||||
|
||||
for (int x = x1 - 16; x <= x1 + 16; x++)
|
||||
for (int z = z1 - 16; z <= z1 + 16; z++) {
|
||||
Chunk chunk = world.getChunkFromBlockCoords(x, z);
|
||||
BiomeGenBase biome = world.getBiomeGenForCoords(x, z);
|
||||
if (biome.getSpawnableList(EnumCreatureType.monster).isEmpty() || biome.getSpawningChance() <= 0)
|
||||
continue;
|
||||
for (int i = 0; i <= 32; i++) {
|
||||
int x = x1 - 16 + i;
|
||||
for (int j = 0; j <= 32; j++) {
|
||||
int z = z1 - 16 + j;
|
||||
int cacheIndex = (i * 33 + j) * 33;
|
||||
|
||||
for (int y = y1 - 16; y < y1 + 16; y++) {
|
||||
int spawnMode = getSpawnMode(chunk, x, y, z);
|
||||
if (spawnMode == 0)
|
||||
for (int k = 0; k <= 32; k++) {
|
||||
int y = y1 - 16 + k;
|
||||
int spawnMode = mobSpawnCache[cacheIndex + k];
|
||||
if (spawnMode == 0) {
|
||||
continue;
|
||||
} else if (spawnMode == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (spawnMode != curSpawnMode) {
|
||||
if (spawnMode == 1)
|
||||
if (spawnMode == 1) {
|
||||
GL11.glColor4f(1, 1, 0, 1);
|
||||
else
|
||||
} else {
|
||||
GL11.glColor4f(1, 0, 0, 1);
|
||||
}
|
||||
curSpawnMode = spawnMode;
|
||||
}
|
||||
|
||||
GL11.glVertex3d(x, y + 0.004, z);
|
||||
GL11.glVertex3d(x + 1, y + 0.004, z + 1);
|
||||
GL11.glVertex3d(x + 1, y + 0.004, z);
|
||||
GL11.glVertex3d(x, y + 0.004, z + 1);
|
||||
GL11.glVertex3d(x, y + 0.02, z);
|
||||
GL11.glVertex3d(x + 1, y + 0.02, z + 1);
|
||||
GL11.glVertex3d(x + 1, y + 0.02, z);
|
||||
GL11.glVertex3d(x, y + 0.02, z + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glEnd();
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
@@ -100,10 +155,12 @@ public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
|
||||
private static final Entity dummyEntity = new EntityPig(null);
|
||||
private static final AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0);
|
||||
private static int getSpawnMode(Chunk chunk, int x, int y, int z) {
|
||||
|
||||
private static byte getSpawnMode(Chunk chunk, int x, int y, int z) {
|
||||
if (!SpawnerAnimals.canCreatureTypeSpawnAtLocation(EnumCreatureType.monster, chunk.worldObj, x, y, z) ||
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15) >= 8)
|
||||
chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15) >= 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aabb.minX = x + 0.2;
|
||||
aabb.maxX = x + 0.8;
|
||||
@@ -111,14 +168,11 @@ public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
aabb.maxY = y + 1.8;
|
||||
aabb.minZ = z + 0.2;
|
||||
aabb.maxZ = z + 0.8;
|
||||
if (!chunk.worldObj.checkNoEntityCollision(aabb) ||
|
||||
!chunk.worldObj.getCollidingBoundingBoxes(dummyEntity, aabb).isEmpty() ||
|
||||
chunk.worldObj.isAnyLiquid(aabb))
|
||||
if (!chunk.worldObj.getCollidingBoundingBoxes(dummyEntity, aabb).isEmpty() || chunk.worldObj.isAnyLiquid(aabb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (chunk.getSavedLightValue(EnumSkyBlock.Sky, x & 15, y, z & 15) >= 8)
|
||||
return 1;
|
||||
return 2;
|
||||
return (byte) (chunk.getSavedLightValue(EnumSkyBlock.Sky, x & 15, y, z & 15) >= 8 ? 1 : 2);
|
||||
}
|
||||
|
||||
private static void renderChunkBounds(Entity entity) {
|
||||
@@ -172,40 +226,93 @@ public class WorldOverlayRenderer implements IKeyStateTracker
|
||||
GL11.glVertex3d(x1, y2, z1);
|
||||
}
|
||||
|
||||
if (chunkOverlay == 2 && cx == 0 && cz == 0) {
|
||||
dy = 32;
|
||||
y1 = Math.floor(entity.posY - dy / 2);
|
||||
y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
}
|
||||
if (cx == 0 && cz == 0) {
|
||||
if (chunkOverlay == 2) {
|
||||
dy = 32;
|
||||
y1 = Math.floor(entity.posY - dy / 2);
|
||||
y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
}
|
||||
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
}
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
}
|
||||
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
}
|
||||
for (double h = 1; h <= 15; h++) {
|
||||
GL11.glVertex3d(x1 + h, y1, z1);
|
||||
GL11.glVertex3d(x1 + h, y2, z1);
|
||||
GL11.glVertex3d(x1 + h, y1, z2);
|
||||
GL11.glVertex3d(x1 + h, y2, z2);
|
||||
GL11.glVertex3d(x1, y1, z1 + h);
|
||||
GL11.glVertex3d(x1, y2, z1 + h);
|
||||
GL11.glVertex3d(x2, y1, z1 + h);
|
||||
GL11.glVertex3d(x2, y2, z1 + h);
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
}
|
||||
for (double h = 1; h <= 15; h++) {
|
||||
GL11.glVertex3d(x1 + h, y1, z1);
|
||||
GL11.glVertex3d(x1 + h, y2, z1);
|
||||
GL11.glVertex3d(x1 + h, y1, z2);
|
||||
GL11.glVertex3d(x1 + h, y2, z2);
|
||||
GL11.glVertex3d(x1, y1, z1 + h);
|
||||
GL11.glVertex3d(x1, y2, z1 + h);
|
||||
GL11.glVertex3d(x2, y1, z1 + h);
|
||||
GL11.glVertex3d(x2, y2, z1 + h);
|
||||
}
|
||||
} else if (chunkOverlay == 3) {
|
||||
int gx1 = ((entity.chunkCoordX < 0 ? entity.chunkCoordX - 3 : entity.chunkCoordX) / 3 * 3) << 4;
|
||||
int gz1 = ((entity.chunkCoordZ < 0 ? entity.chunkCoordZ - 3 : entity.chunkCoordZ) / 3 * 3) << 4;
|
||||
if (entity.chunkCoordX < 0) {
|
||||
gx1 += 16;
|
||||
}
|
||||
if (entity.chunkCoordZ < 0) {
|
||||
gz1 += 16;
|
||||
}
|
||||
int gx2 = gx1 + 48;
|
||||
int gz2 = gz1 + 48;
|
||||
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(gx2, y, gz1);
|
||||
GL11.glVertex3d(gx2, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz1);
|
||||
GL11.glVertex3d(gx1, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz2);
|
||||
GL11.glVertex3d(gx2, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz1);
|
||||
GL11.glVertex3d(gx2, y, gz1);
|
||||
}
|
||||
for (double h = 4; h <= 44; h += 4) {
|
||||
if (h % 16 == 0) {
|
||||
continue;
|
||||
}
|
||||
GL11.glVertex3d(gx1 + h, y1, gz1);
|
||||
GL11.glVertex3d(gx1 + h, y2, gz1);
|
||||
GL11.glVertex3d(gx1 + h, y1, gz2);
|
||||
GL11.glVertex3d(gx1 + h, y2, gz2);
|
||||
GL11.glVertex3d(gx1, y1, gz1 + h);
|
||||
GL11.glVertex3d(gx1, y2, gz1 + h);
|
||||
GL11.glVertex3d(gx2, y1, gz1 + h);
|
||||
GL11.glVertex3d(gx2, y2, gz1 + h);
|
||||
}
|
||||
|
||||
GL11.glColor4d(0, 0, 0.9, 0.4);
|
||||
gx1 += 23;
|
||||
gz1 += 23;
|
||||
gx2 = gx1 + 1;
|
||||
gz2 = gz1 + 1;
|
||||
|
||||
GL11.glVertex3d(gx1, y1, gz1);
|
||||
GL11.glVertex3d(gx1, y2, gz1);
|
||||
GL11.glVertex3d(gx2, y1, gz1);
|
||||
GL11.glVertex3d(gx2, y2, gz1);
|
||||
GL11.glVertex3d(gx1, y1, gz2);
|
||||
GL11.glVertex3d(gx1, y2, gz2);
|
||||
GL11.glVertex3d(gx2, y1, gz2);
|
||||
GL11.glVertex3d(gx2, y2, gz2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,15 @@ import codechicken.nei.SubsetWidget.SubsetTag;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.config.Option;
|
||||
import codechicken.nei.config.OptionKeyBind;
|
||||
import codechicken.nei.recipe.CatalystInfo;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.nei.recipe.ICraftingHandler;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.IUsageHandler;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import codechicken.nei.recipe.RecipeInfo;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
@@ -29,6 +33,7 @@ import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is the main class that handles item property configuration.
|
||||
@@ -284,4 +289,78 @@ public class API
|
||||
ItemInfo.itemVariants.put(item, variant);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
|
||||
public static void registerStackStringifyHandler(IStackStringifyHandler handler)
|
||||
{
|
||||
StackInfo.stackStringifyHandlers.add(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
|
||||
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handler the recipe category handled by the ingredient
|
||||
* @param priority higher priority comes first, default to 0
|
||||
*/
|
||||
public static void addRecipeCatalyst(ItemStack stack, IRecipeHandler handler, int priority) {
|
||||
String handlerID = RecipeCatalysts.getRecipeID(handler);
|
||||
addRecipeCatalyst(stack, handlerID, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link API#addRecipeCatalyst(ItemStack, IRecipeHandler, int)}
|
||||
*/
|
||||
public static void addRecipeCatalyst(ItemStack stack, IRecipeHandler handler) {
|
||||
addRecipeCatalyst(stack, handler, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
|
||||
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handlerID recipe category identifier (see also {@link RecipeCatalysts#getRecipeID(IRecipeHandler)})
|
||||
* @param priority higher priority comes first, default to 0
|
||||
*/
|
||||
public static void addRecipeCatalyst(ItemStack stack, String handlerID, int priority) {
|
||||
RecipeCatalysts.addRecipeCatalyst(handlerID, new CatalystInfo(stack, priority));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link API#addRecipeCatalyst(ItemStack, String, int)}
|
||||
*/
|
||||
public static void addRecipeCatalyst(ItemStack stack, String handlerID) {
|
||||
addRecipeCatalyst(stack, handlerID, 0);
|
||||
}
|
||||
|
||||
public static void removeRecipeCatalyst(ItemStack stack, IRecipeHandler handler) {
|
||||
String handlerID = RecipeCatalysts.getRecipeID(handler);
|
||||
removeRecipeCatalyst(stack, handlerID);
|
||||
}
|
||||
|
||||
public static void removeRecipeCatalyst(ItemStack stack, String handlerID) {
|
||||
RecipeCatalysts.removeRecipeCatalyst(handlerID, stack);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addRecipeCatalyst(List<ItemStack> stacks, IRecipeHandler handler) {
|
||||
for (ItemStack stack : stacks) {
|
||||
addRecipeCatalyst(stack, handler);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addRecipeCatalyst(List<ItemStack> stacks, String handlerID) {
|
||||
for (ItemStack stack : stacks) {
|
||||
addRecipeCatalyst(stack, handlerID);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addRecipeCatalyst(ItemStack stack, Class<? extends IRecipeHandler> handler) {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addRecipeCatalyst(List<ItemStack> stacks, Class<? extends IRecipeHandler> handler) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.NEIChestGuiHandler;
|
||||
import codechicken.nei.NEICreativeGuiHandler;
|
||||
import codechicken.nei.NEIDummySlotHandler;
|
||||
import codechicken.nei.NEIPotionGuiHandler;
|
||||
import codechicken.nei.recipe.GuiRecipeCatalyst;
|
||||
import codechicken.nei.recipe.SearchInputDropHandler;
|
||||
import codechicken.nei.recipe.FillFluidContainerHandler;
|
||||
import codechicken.nei.recipe.CheatItemHandler;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
@@ -24,6 +30,11 @@ public class GuiInfo {
|
||||
API.registerNEIGuiHandler(new NEICreativeGuiHandler());
|
||||
API.registerNEIGuiHandler(new NEIChestGuiHandler());
|
||||
API.registerNEIGuiHandler(new NEIDummySlotHandler());
|
||||
API.registerNEIGuiHandler(new GuiRecipeCatalyst(null));
|
||||
API.registerNEIGuiHandler(new SearchInputDropHandler());
|
||||
API.registerNEIGuiHandler(new FillFluidContainerHandler());
|
||||
API.registerNEIGuiHandler(new CheatItemHandler());
|
||||
API.registerNEIGuiHandler(new NEIPotionGuiHandler());
|
||||
customSlotGuis.add(GuiContainerCreative.class);
|
||||
}
|
||||
|
||||
@@ -39,4 +50,28 @@ public class GuiInfo {
|
||||
public static boolean hasCustomSlots(GuiContainer gui) {
|
||||
return customSlotGuis.contains(gui.getClass());
|
||||
}
|
||||
|
||||
public static boolean hideItemPanelSlot(GuiContainer gui, Rectangle4i rect)
|
||||
{
|
||||
try {
|
||||
readLock.lock();
|
||||
if (guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h))) {
|
||||
return true;
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
|
||||
for (Object item : gui.buttonList) {
|
||||
GuiButton button = (GuiButton) item;
|
||||
|
||||
if ((new Rectangle4i(button.xPosition, button.yPosition, button.width, button.height)).intersects(rect)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
|
||||
public interface IGuiContainerOverlay
|
||||
{
|
||||
public GuiContainer getFirstScreen();
|
||||
GuiContainer getFirstScreen();
|
||||
|
||||
default GuiScreen getFirstScreenGeneral() {
|
||||
return getFirstScreen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public interface IStackStringifyHandler
|
||||
{
|
||||
|
||||
public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize);
|
||||
|
||||
public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag);
|
||||
|
||||
public FluidStack getFluid(ItemStack stack);
|
||||
|
||||
}
|
||||
@@ -58,6 +58,7 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* This is an internal class for storing information about items, to be accessed by the API
|
||||
@@ -82,8 +83,36 @@ public class ItemInfo
|
||||
|
||||
public static final HashMap<Item, String> itemOwners = new HashMap<>();
|
||||
|
||||
private static class ItemStackKey {
|
||||
public final ItemStack stack;
|
||||
public ItemStackKey(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(this.stack == null)
|
||||
return 1;
|
||||
int hashCode = 1;
|
||||
hashCode = 31 * hashCode + stack.stackSize;
|
||||
hashCode = 31 * hashCode + Item.getIdFromItem(stack.getItem());
|
||||
hashCode = 31 * hashCode + stack.getItemDamage();
|
||||
hashCode = 31 * hashCode + (!stack.hasTagCompound() ? 0 : stack.getTagCompound().hashCode());
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o == this)
|
||||
return true;
|
||||
if(!(o instanceof ItemStackKey))
|
||||
return false;
|
||||
return ItemStack.areItemStacksEqual(this.stack, ((ItemStackKey)o).stack);
|
||||
}
|
||||
}
|
||||
|
||||
//lookup optimisation
|
||||
public static final HashMap<ItemStack, String> itemSearchNames = new HashMap<>();
|
||||
public static final ConcurrentHashMap<ItemStackKey, String> itemSearchNames = new ConcurrentHashMap<>();
|
||||
|
||||
public static boolean isHidden(ItemStack stack) {
|
||||
return hiddenItems.contains(stack);
|
||||
@@ -129,7 +158,18 @@ public class ItemInfo
|
||||
}
|
||||
|
||||
private static void addSearchOptimisation() {
|
||||
ItemList.loadCallbacks.add(itemSearchNames::clear);
|
||||
ItemList.loadCallbacks.add(ItemInfo::populateSearchMap);
|
||||
}
|
||||
|
||||
private static void populateSearchMap() {
|
||||
/* Create a snapshot of the current keys in the cache */
|
||||
HashSet<ItemStackKey> oldItems = new HashSet<>(itemSearchNames.keySet());
|
||||
for(ItemStack stack : ItemList.items) {
|
||||
/* Populate each entry and remove it from the snapshot */
|
||||
getSearchName(stack);
|
||||
oldItems.remove(new ItemStackKey(stack));
|
||||
}
|
||||
itemSearchNames.keySet().removeAll(oldItems);
|
||||
}
|
||||
|
||||
private static void addHiddenItemFilter() {
|
||||
@@ -517,11 +557,8 @@ public class ItemInfo
|
||||
}
|
||||
|
||||
public static String getSearchName(ItemStack stack) {
|
||||
String s = itemSearchNames.get(stack);
|
||||
if(s == null) {
|
||||
s = EnumChatFormatting.getTextWithoutFormattingCodes(GuiContainerManager.concatenatedDisplayName(stack, true).toLowerCase());
|
||||
itemSearchNames.put(stack, s);
|
||||
}
|
||||
return s;
|
||||
return itemSearchNames.computeIfAbsent(new ItemStackKey(stack), key ->
|
||||
EnumChatFormatting.getTextWithoutFormattingCodes(GuiContainerManager.concatenatedDisplayName(key.stack, true).toLowerCase())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package codechicken.nei.asm;
|
||||
|
||||
import codechicken.lib.asm.ASMHelper;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.POP;
|
||||
import static org.objectweb.asm.Opcodes.PUTSTATIC;
|
||||
|
||||
public class GuiContainerManagerAPITransformer extends ClassVisitor {
|
||||
private final String tname;
|
||||
private boolean changed = false;
|
||||
|
||||
public GuiContainerManagerAPITransformer(int api, ClassVisitor cv, String tname) {
|
||||
super(api, cv);
|
||||
this.tname = tname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String mname, String mdesc, String signature, String[] exceptions) {
|
||||
return new MethodVisitor(api, super.visitMethod(access, mname, mdesc, signature, exceptions)) {
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||
if (opcode == PUTSTATIC && "codechicken/nei/guihook/GuiContainerManager".equals(owner) && name.endsWith("Handlers") && desc.equals("Ljava/util/LinkedList;")) {
|
||||
ASMHelper.logger.warn("Found suspicious PUTSTATIC {} in {}#{}{}, replacing with POP!", name, tname, mname, mdesc);
|
||||
changed = true;
|
||||
super.visitInsn(POP);
|
||||
} else {
|
||||
super.visitFieldInsn(opcode, owner, name, desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import codechicken.core.launch.CodeChickenCorePlugin;
|
||||
import codechicken.lib.asm.ASMInit;
|
||||
import cpw.mods.fml.relauncher.IFMLCallHook;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
@TransformerExclusions(value = {"codechicken.nei.asm"})
|
||||
@MCVersion( "1.7.10" )
|
||||
public class NEICorePlugin implements IFMLLoadingPlugin, IFMLCallHook
|
||||
{
|
||||
public static File location;
|
||||
|
||||
@@ -41,6 +41,7 @@ public class NEITransformer implements IClassTransformer
|
||||
ASMInit.init();
|
||||
}
|
||||
|
||||
private final boolean paranoidMode = Boolean.getBoolean("nei.paranoid");
|
||||
private final ModularASMTransformer transformer = new ModularASMTransformer();
|
||||
private final Map<String, ASMBlock> asmblocks = ASMReader.loadResource("/assets/nei/asm/blocks.asm");
|
||||
|
||||
@@ -264,6 +265,14 @@ public class NEITransformer implements IClassTransformer
|
||||
}
|
||||
bytes = transformSubclasses(name, bytes);
|
||||
}
|
||||
if (paranoidMode && !tname.startsWith("codechicken.nei")) {
|
||||
ClassReader cr = new ClassReader(bytes);
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
GuiContainerManagerAPITransformer cv = new GuiContainerManagerAPITransformer(ASM5, cw, tname);
|
||||
cr.accept(cv, ClassReader.SKIP_DEBUG);
|
||||
if (cv.isChanged())
|
||||
bytes = cw.toByteArray();
|
||||
}
|
||||
|
||||
bytes = transformer.transform(name, bytes);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.util.ArrayList;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
@@ -100,10 +101,12 @@ public class GuiItemIconDumper extends GuiScreen
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
|
||||
for(int i = 0; drawIndex < ItemPanels.itemPanel.realItems.size() && i < fit; drawIndex++, i++) {
|
||||
final ArrayList<ItemStack> items = ItemPanels.itemPanel.getItems();
|
||||
|
||||
for (int i = 0; drawIndex < items.size() && i < fit; drawIndex++, i++) {
|
||||
int x = i%cols * 18;
|
||||
int y = i/cols * 18;
|
||||
GuiContainerManager.drawItem(x+1, y+1, ItemPanels.itemPanel.realItems.get(drawIndex));
|
||||
GuiContainerManager.drawItem(x+1, y+1, items.get(drawIndex));
|
||||
}
|
||||
|
||||
GL11.glFlush();
|
||||
@@ -114,14 +117,19 @@ public class GuiItemIconDumper extends GuiScreen
|
||||
int rows = img.getHeight() / boxSize;
|
||||
int cols = img.getWidth() / boxSize;
|
||||
int fit = rows*cols;
|
||||
for(int i = 0; parseIndex < ItemPanels.itemPanel.realItems.size() && i < fit; parseIndex++, i++) {
|
||||
|
||||
final ArrayList<ItemStack> items = ItemPanels.itemPanel.getItems();
|
||||
|
||||
for(int i = 0; parseIndex < items.size() && i < fit; parseIndex++, i++) {
|
||||
int x = i%cols * boxSize;
|
||||
int y = i/cols * boxSize;
|
||||
exportImage(dir, img.getSubimage(x+borderSize, y+borderSize, iconSize, iconSize), ItemPanels.itemPanel.realItems.get(parseIndex));
|
||||
exportImage(dir, img.getSubimage(x+borderSize, y+borderSize, iconSize, iconSize), items.get(parseIndex));
|
||||
}
|
||||
|
||||
if(parseIndex >= ItemPanels.itemPanel.realItems.size())
|
||||
if (parseIndex >= items.size()) {
|
||||
returnScreen(new ChatComponentTranslation(opt.fullName()+".icon.dumped", "dumps/itempanel_icons"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String cleanFileName(String name) {
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
package codechicken.nei.config;
|
||||
|
||||
import codechicken.core.gui.GuiScreenWidget;
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
public class GuiPanelSettings extends GuiScreenWidget
|
||||
{
|
||||
private final Option opt;
|
||||
|
||||
private PanelPlaceholder bookmarksPanel;
|
||||
private PanelPlaceholder itemsPanel;
|
||||
|
||||
protected static class PanelResizeButton
|
||||
{
|
||||
private int x;
|
||||
private int y;
|
||||
private int w;
|
||||
private int h;
|
||||
|
||||
public PanelResizeButton(int w, int h)
|
||||
{
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey)
|
||||
{
|
||||
drawRect(x, y, x + w, y + h, 0xbbaaaaaa);
|
||||
drawRect(x + 2, y + 2, x + w - 2, y + h - 2, contains(mousex, mousey)? 0xFF000000: 0xbb000000);
|
||||
}
|
||||
|
||||
public boolean contains(int pointX, int pointY)
|
||||
{
|
||||
return (new Rectangle4i(x, y, w, h)).contains(pointX, pointY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class PanelPlaceholder
|
||||
{
|
||||
protected static int PANEL_SIZE = 16;
|
||||
|
||||
private final Option opt;
|
||||
private final String name;
|
||||
private Rectangle4i margin;
|
||||
private Point dragDown;
|
||||
private String dragDir;
|
||||
private int x = 0;
|
||||
private int y = 0;
|
||||
private int w = 0;
|
||||
private int h = 0;
|
||||
|
||||
private PanelResizeButton leftButton = new PanelResizeButton(PANEL_SIZE, PANEL_SIZE * 2);
|
||||
private PanelResizeButton topButton = new PanelResizeButton(PANEL_SIZE * 2, PANEL_SIZE);
|
||||
private PanelResizeButton rightButton = new PanelResizeButton(PANEL_SIZE, PANEL_SIZE * 2);
|
||||
private PanelResizeButton bottomButton = new PanelResizeButton(PANEL_SIZE * 2, PANEL_SIZE);
|
||||
|
||||
public PanelPlaceholder(Option opt, String name)
|
||||
{
|
||||
this.opt = opt;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void resize(Rectangle4i margin)
|
||||
{
|
||||
this.margin = margin;
|
||||
int[] padding = getPaddings();
|
||||
|
||||
x = margin.x + padding[0];
|
||||
y = margin.y + padding[1];
|
||||
w = margin.w - padding[2] - padding[0];
|
||||
h = margin.h - padding[3] - padding[1];
|
||||
|
||||
leftButton.x = x;
|
||||
leftButton.y = y + h / 2 - PANEL_SIZE;
|
||||
|
||||
rightButton.x = x + w - PANEL_SIZE;
|
||||
rightButton.y = y + h / 2 - PANEL_SIZE;
|
||||
|
||||
topButton.x = x + w / 2 - PANEL_SIZE;
|
||||
topButton.y = y;
|
||||
|
||||
bottomButton.x = x + w / 2 - PANEL_SIZE;
|
||||
bottomButton.y = y + h - PANEL_SIZE;
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey)
|
||||
{
|
||||
drawRect(x, y, x + w, y + PANEL_SIZE, 0xbbaaaaaa); //top-panel
|
||||
drawRect(x, y + h - PANEL_SIZE, x + w, y + h, 0xbbaaaaaa); //bottom-panel
|
||||
|
||||
drawRect(x, y, x + 2, y + h, 0xbbaaaaaa); //border left
|
||||
drawRect(x + w, y, x + w - 2, y + h, 0xbbaaaaaa); //border right
|
||||
|
||||
drawRect(x, y, x + w, y + 2, 0xbbaaaaaa); //border top
|
||||
drawRect(x, y + h, x + w, y + h - 2, 0xbbaaaaaa); //border bottom
|
||||
|
||||
drawItems();
|
||||
|
||||
leftButton.draw(mousex, mousey);
|
||||
rightButton.draw(mousex, mousey);
|
||||
topButton.draw(mousex, mousey);
|
||||
bottomButton.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
protected int[] getPaddings()
|
||||
{
|
||||
final int minWidth = 5 * ItemsGrid.SLOT_SIZE;
|
||||
final int minHeight = 9 * ItemsGrid.SLOT_SIZE;
|
||||
|
||||
int paddingLeft = (int)Math.ceil(margin.w * opt.renderTag(name + ".left").getIntValue() / 100000.0);
|
||||
int paddingTop = (int)Math.ceil(margin.h * opt.renderTag(name + ".top").getIntValue() / 100000.0);
|
||||
int paddingRight = (int)Math.ceil(margin.w * opt.renderTag(name + ".right").getIntValue() / 100000.0);
|
||||
int paddingBottom = (int)Math.ceil(margin.h * opt.renderTag(name + ".bottom").getIntValue() / 100000.0);
|
||||
|
||||
if (dragDir != null) {
|
||||
final Point mouse = getMousePosition();
|
||||
Point drag = new Point(mouse.x - dragDown.x, mouse.y - dragDown.y);
|
||||
|
||||
if (dragDir == "left") {
|
||||
paddingLeft = Math.min(Math.max(0, margin.w - paddingRight - minWidth), Math.max(0, paddingLeft + drag.x));
|
||||
} else if (dragDir == "right") {
|
||||
paddingRight = Math.min(Math.max(0, margin.w - paddingLeft - minWidth), Math.max(0, paddingRight - drag.x));
|
||||
} else if (dragDir == "top") {
|
||||
paddingTop = Math.min(Math.max(0, margin.h - paddingBottom - minHeight), Math.max(0, paddingTop + drag.y));
|
||||
} else if (dragDir == "bottom") {
|
||||
paddingBottom = Math.min(Math.max(0, margin.h - paddingTop - minHeight), Math.max(0, paddingBottom - drag.y));
|
||||
} else if (dragDir == "move") {
|
||||
int width = margin.w - paddingRight - paddingLeft;
|
||||
int height = margin.h - paddingTop - paddingBottom;
|
||||
|
||||
paddingLeft = Math.min(Math.max(0, margin.w - width), Math.max(0, paddingLeft + drag.x));
|
||||
paddingTop = Math.min(Math.max(0, margin.h - height), Math.max(0, paddingTop + drag.y));
|
||||
|
||||
paddingRight = margin.w - paddingLeft - width;
|
||||
paddingBottom = margin.h - paddingTop - height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int deltaHeight = Math.min(0, margin.h - paddingTop - paddingBottom - minHeight) / 2;
|
||||
|
||||
paddingLeft = Math.min(paddingLeft, Math.max(0, margin.w - paddingRight - minWidth));
|
||||
paddingRight = Math.min(paddingRight, Math.max(0, margin.w - paddingLeft - minWidth));
|
||||
paddingTop = Math.min(margin.h - minHeight, Math.max(0, paddingTop + deltaHeight));
|
||||
paddingBottom = Math.min(margin.h - paddingTop - minHeight, Math.max(0, paddingBottom - deltaHeight));
|
||||
|
||||
|
||||
return new int[]{ paddingLeft, paddingTop, paddingRight, paddingBottom };
|
||||
}
|
||||
|
||||
protected void drawItems()
|
||||
{
|
||||
final int columns = w / ItemsGrid.SLOT_SIZE;
|
||||
final int rows = (h - (PANEL_SIZE + 2) * 2) / ItemsGrid.SLOT_SIZE;
|
||||
final int paddingLeft = (w % ItemsGrid.SLOT_SIZE) / 2;
|
||||
final ArrayList<ItemStack> items = ItemPanels.itemPanel.getItems();
|
||||
|
||||
for (int r = 0; r < rows; r ++) {
|
||||
for (int c = 0; c < columns; c++) {
|
||||
|
||||
GuiContainerManager.drawItem(
|
||||
x + paddingLeft + ItemsGrid.SLOT_SIZE * c + 1,
|
||||
y + PANEL_SIZE + 2 + ItemsGrid.SLOT_SIZE * r + 1,
|
||||
items.get((r * columns + c) % items.size())
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean contains(int pointX, int pointY)
|
||||
{
|
||||
return (new Rectangle4i(x, y, w, h)).contains(pointX, pointY);
|
||||
}
|
||||
|
||||
protected void mouseClicked(int x, int y, int button)
|
||||
{
|
||||
|
||||
if (contains(x, y)) {
|
||||
dragDown = getMousePosition();
|
||||
|
||||
if (leftButton.contains(x, y)) {
|
||||
dragDir = "left";
|
||||
} else if (rightButton.contains(x, y)) {
|
||||
dragDir = "right";
|
||||
} else if (topButton.contains(x, y)) {
|
||||
dragDir = "top";
|
||||
} else if (bottomButton.contains(x, y)) {
|
||||
dragDir = "bottom";
|
||||
} else {
|
||||
dragDir = "move";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void mouseMovedOrUp(int x, int y, int button)
|
||||
{
|
||||
|
||||
if (button == 0 && dragDown != null) {
|
||||
int[] padding = getPaddings();
|
||||
|
||||
opt.renderTag(name + ".left").setIntValue(padding[0] * 100000 / margin.w);
|
||||
opt.renderTag(name + ".top").setIntValue(padding[1] * 100000 / margin.h);
|
||||
opt.renderTag(name + ".right").setIntValue(padding[2] * 100000 / margin.w);
|
||||
opt.renderTag(name + ".bottom").setIntValue(padding[3] * 100000 / margin.h);
|
||||
|
||||
dragDir = null;
|
||||
dragDown = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public GuiPanelSettings(Option opt) {
|
||||
super(176, 198);
|
||||
this.opt = opt;
|
||||
|
||||
bookmarksPanel = new PanelPlaceholder(opt, opt.name + ".bookmarks");
|
||||
itemsPanel = new PanelPlaceholder(opt, opt.name + ".items");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesGuiPauseGame()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int keycode)
|
||||
{
|
||||
|
||||
if (keycode == Keyboard.KEY_ESCAPE || keycode == Keyboard.KEY_BACK) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(opt.slot.getGui());
|
||||
return;
|
||||
}
|
||||
|
||||
super.keyTyped(c, keycode);
|
||||
}
|
||||
|
||||
|
||||
protected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
CCRenderState.changeTexture("nei:textures/gui/inv.png");
|
||||
|
||||
int x = guiLeft;
|
||||
int y = guiTop - 4;
|
||||
|
||||
drawTexturedModalRect(x - 23, y, 0, 0, 199, 204);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mousex, int mousey, float f)
|
||||
{
|
||||
|
||||
drawGuiContainerBackgroundLayer(f, mousex, mousey);
|
||||
drawDefaultBackground();
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glPushMatrix();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
bookmarksPanel.resize(getBookmarkDefaultSize());
|
||||
itemsPanel.resize(getItemsDefaultSize());
|
||||
|
||||
bookmarksPanel.draw(mousex, mousey);
|
||||
itemsPanel.draw(mousex, mousey);
|
||||
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glPopMatrix();
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
}
|
||||
|
||||
private Rectangle4i getBookmarkDefaultSize()
|
||||
{
|
||||
return new Rectangle4i(2, 2, guiLeft - 4, height - 4);
|
||||
}
|
||||
|
||||
protected Rectangle4i getItemsDefaultSize()
|
||||
{
|
||||
return new Rectangle4i(guiLeft + xSize + 2, 2, width - (guiLeft + xSize + 4), height - 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int x, int y, int button)
|
||||
{
|
||||
bookmarksPanel.mouseClicked(x, y, button);
|
||||
itemsPanel.mouseClicked(x, y, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseMovedOrUp(int x, int y, int button)
|
||||
{
|
||||
bookmarksPanel.mouseMovedOrUp(x, y, button);
|
||||
itemsPanel.mouseMovedOrUp(x, y, button);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,17 +8,13 @@ import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.TemplateRecipeHandler;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
import com.google.common.base.Objects;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.JsonToNBT;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class HandlerDumper extends DataDumper
|
||||
|
||||
@@ -2,17 +2,26 @@ package codechicken.nei.config;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
import codechicken.nei.recipe.CatalystInfo;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.HandlerInfo;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.event.FMLInterModComms;
|
||||
import cpw.mods.fml.common.event.FMLInterModComms.IMCMessage;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class IMCHandler {
|
||||
private static final Set<String> processedCatalystSenders = new HashSet<>();
|
||||
private IMCHandler() {}
|
||||
|
||||
public static void processIMC(List<FMLInterModComms.IMCMessage> messages) {
|
||||
@@ -20,10 +29,19 @@ public class IMCHandler {
|
||||
String type = message.key;
|
||||
if (type == null || type.isEmpty()) continue;
|
||||
if (CommonUtils.isClient()) {
|
||||
if (type.equals("registerHandlerInfo")) {
|
||||
handleRegisterHandlerInfo(message);
|
||||
} else if (type.equals("removeHandlerInfo")) {
|
||||
handleRemoveHandlerInfo(message);
|
||||
switch (type) {
|
||||
case "registerHandlerInfo":
|
||||
handleRegisterHandlerInfo(message);
|
||||
break;
|
||||
case "removeHandlerInfo":
|
||||
handleRemoveHandlerInfo(message);
|
||||
break;
|
||||
case "registerCatalystInfo":
|
||||
handleRegisterCatalystInfo(message);
|
||||
break;
|
||||
case "removeCatalystInfo":
|
||||
handleRemoveCatalystInfo(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +109,72 @@ public class IMCHandler {
|
||||
GuiRecipeTab.handlerRemoverFromIMC.add(handler);
|
||||
}
|
||||
|
||||
private static void handleRegisterCatalystInfo(IMCMessage message) {
|
||||
if (!message.isNBTMessage()) {
|
||||
logInvalidMessage(message, "NBT");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!processedCatalystSenders.contains(message.getSender())) {
|
||||
NEIClientConfig.logger.info("Processing registerCatalystInfo from " + message.getSender());
|
||||
processedCatalystSenders.add(message.getSender());
|
||||
}
|
||||
final NBTTagCompound tag = message.getNBTValue();
|
||||
final String handlerID = tag.getString("handlerID");
|
||||
if (handlerID.isEmpty()) {
|
||||
NEIClientConfig.logger.warn("Missing handlerID for registerCatalystInfo!");
|
||||
return;
|
||||
}
|
||||
final String itemName = tag.getString("itemName");
|
||||
final String nbtInfo = tag.hasKey("nbtInfo") ? tag.getString("nbtInfo") : null;
|
||||
if (itemName.isEmpty()) {
|
||||
NEIClientConfig.logger.warn(String.format("Missing itemName for registerCatalystInfo in `%s`!", handlerID));
|
||||
return;
|
||||
}
|
||||
final ItemStack itemStack = NEIServerUtils.getModdedItem(itemName, nbtInfo);
|
||||
if (itemStack == null) {
|
||||
NEIClientConfig.logger.warn(String.format("Cannot find item `%s`!", itemName));
|
||||
return;
|
||||
}
|
||||
final int priority = tag.getInteger("priority");
|
||||
|
||||
RecipeCatalysts.addOrPut(RecipeCatalysts.catalystsAdderFromIMC, handlerID, new CatalystInfo(itemStack, priority));
|
||||
NEIClientConfig.logger.info(String.format("Added catalyst `%s` to handler %s", itemStack.getDisplayName(), handlerID));
|
||||
}
|
||||
|
||||
private static void handleRemoveCatalystInfo(IMCMessage message) {
|
||||
if (!message.isNBTMessage()) {
|
||||
logInvalidMessage(message, "NBT");
|
||||
return;
|
||||
}
|
||||
|
||||
NEIClientConfig.logger.info("Processing removeCatalystInfo from " + message.getSender());
|
||||
final NBTTagCompound tag = message.getNBTValue();
|
||||
final String handlerID = tag.getString("handlerID");
|
||||
if (handlerID.isEmpty()) {
|
||||
NEIClientConfig.logger.warn("Missing handlerID for registerCatalystInfo!");
|
||||
return;
|
||||
}
|
||||
final String itemName = tag.getString("itemName");
|
||||
final String nbtInfo = tag.hasKey("nbtInfo") ? tag.getString("nbtInfo") : null;
|
||||
if (itemName.isEmpty()) {
|
||||
NEIClientConfig.logger.warn(String.format("Missing itemName for registerCatalystInfo in `%s`!", handlerID));
|
||||
return;
|
||||
}
|
||||
final ItemStack itemStack = NEIServerUtils.getModdedItem(itemName, nbtInfo);
|
||||
if (itemStack == null) {
|
||||
NEIClientConfig.logger.warn(String.format("Cannot find item `%s`!", itemName));
|
||||
return;
|
||||
}
|
||||
|
||||
if (RecipeCatalysts.catalystsRemoverFromIMC.containsKey(handlerID)) {
|
||||
RecipeCatalysts.catalystsRemoverFromIMC.get(handlerID).add(itemStack);
|
||||
} else {
|
||||
RecipeCatalysts.catalystsRemoverFromIMC.put(handlerID, new ArrayList<>(Collections.singletonList(itemStack)));
|
||||
}
|
||||
NEIClientConfig.logger.info(String.format("Removed catalyst `%s` from handler %s", itemStack.getDisplayName(), handlerID));
|
||||
}
|
||||
|
||||
|
||||
private static void logInvalidMessage(FMLInterModComms.IMCMessage message, String type) {
|
||||
FMLLog.bigWarning(String.format("Received invalid IMC '%s' from %s. Not a %s Message.", message.key, message.getSender(), type));
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ItemPanelDumper extends DataDumper
|
||||
@Override
|
||||
public Iterable<String[]> dump(int mode) {
|
||||
LinkedList<String[]> list = new LinkedList<>();
|
||||
for (ItemStack stack : ItemPanels.itemPanel.realItems)
|
||||
for (ItemStack stack : ItemPanels.itemPanel.getItems())
|
||||
list.add(new String[]{
|
||||
Item.itemRegistry.getNameForObject(stack.getItem()),
|
||||
Integer.toString(Item.getIdFromItem(stack.getItem())),
|
||||
@@ -123,7 +123,7 @@ public class ItemPanelDumper extends DataDumper
|
||||
|
||||
public void dumpNBT(File file) throws IOException {
|
||||
NBTTagList list = new NBTTagList();
|
||||
for (ItemStack stack : ItemPanels.itemPanel.realItems)
|
||||
for (ItemStack stack : ItemPanels.itemPanel.getItems())
|
||||
list.appendTag(stack.writeToNBT(new NBTTagCompound()));
|
||||
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
@@ -134,7 +134,7 @@ public class ItemPanelDumper extends DataDumper
|
||||
|
||||
public void dumpJson(File file) throws IOException {
|
||||
PrintWriter p = new PrintWriter(file);
|
||||
for (ItemStack stack : ItemPanels.itemPanel.realItems) {
|
||||
for (ItemStack stack : ItemPanels.itemPanel.getItems()) {
|
||||
NBTTagCompound tag = stack.writeToNBT(new NBTTagCompound());
|
||||
tag.removeTag("Count");
|
||||
p.println(tag);
|
||||
|
||||
@@ -4,8 +4,6 @@ import codechicken.nei.Image;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
public class OptionToggleButtonBoubs extends OptionButton {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package codechicken.nei.drawable;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
/*
|
||||
* Taken from Mantle 1.12-1.3.3.49 under the MIT License
|
||||
*
|
||||
* The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class GuiElementDuex {
|
||||
|
||||
// this is totally completely ugly but it's a simple solution that doesn't clutter everything too much >_>
|
||||
public static int defaultTexW = 256;
|
||||
public static int defaultTexH = 256;
|
||||
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int w;
|
||||
public final int h;
|
||||
|
||||
public int texW;
|
||||
public int texH;
|
||||
|
||||
public GuiElementDuex(int x, int y, int w, int h, int texW, int texH) {
|
||||
this(x, y, w, h);
|
||||
setTextureSize(texW, texH);
|
||||
|
||||
defaultTexW = texW;
|
||||
defaultTexH = texH;
|
||||
}
|
||||
|
||||
public GuiElementDuex(int x, int y, int w, int h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
setTextureSize(defaultTexW, defaultTexH);
|
||||
}
|
||||
|
||||
public GuiElementDuex setTextureSize(int w, int h) {
|
||||
texW = w;
|
||||
texH = h;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public GuiElementDuex shift(int xd, int yd) {
|
||||
return new GuiElementDuex(this.x + xd, this.y + yd, this.w, this.h, this.texW, this.texH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the element at the given x/y coordinates
|
||||
*
|
||||
* @param xPos X-Coordinate on the screen
|
||||
* @param yPos Y-Coordinate on the screen
|
||||
*/
|
||||
public int draw(int xPos, int yPos) {
|
||||
// drawModalRectWithCustomSizedTexture
|
||||
GuiScreen.func_146110_a(xPos, yPos, x, y, w, h, texW, texH);
|
||||
return w;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
public int w;
|
||||
public int h;
|
||||
|
||||
public Builder(int w, int h) {
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
public GuiElementDuex get(int x, int y, int w, int h) {
|
||||
return new GuiElementDuex(x, y, w, h, this.w, this.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package codechicken.nei.drawable;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
/*
|
||||
* Taken from Mantle 1.12-1.3.3.49 under the MIT License
|
||||
*
|
||||
* The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class GuiElementScalable extends GuiElementDuex {
|
||||
|
||||
public GuiElementScalable(int x, int y, int w, int h, int texW, int texH) {
|
||||
super(x, y, w, h, texW, texH);
|
||||
}
|
||||
|
||||
public GuiElementScalable(int x, int y, int w, int h) {
|
||||
super(x, y, w, h);
|
||||
}
|
||||
|
||||
public int drawScaledX(int xPos, int yPos, int width) {
|
||||
for(int i = 0; i < width / w; i++) {
|
||||
draw(xPos + i * w, yPos);
|
||||
}
|
||||
// remainder that doesn't fit total width
|
||||
int remainder = width % w;
|
||||
if(remainder > 0) {
|
||||
GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, h, texW, texH);
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
public int drawScaledY(int xPos, int yPos, int height) {
|
||||
for(int i = 0; i < height / h; i++) {
|
||||
draw(xPos, yPos + i * h);
|
||||
}
|
||||
// remainder that doesn't fit total width
|
||||
int remainder = height % h;
|
||||
if(remainder > 0) {
|
||||
// drawModalRectWithCustomSizedTexture
|
||||
GuiScreen.func_146110_a(xPos, yPos + height - remainder, x, y, w, remainder, texW, texH);
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
public int drawScaled(int xPos, int yPos, int width, int height) {
|
||||
// we draw full height row-wise
|
||||
int full = height / this.h;
|
||||
for(int i = 0; i < full; i++) {
|
||||
drawScaledX(xPos, yPos + i * this.h, width);
|
||||
}
|
||||
|
||||
yPos += full * this.h;
|
||||
|
||||
// and the remainder is drawn manually
|
||||
int yRest = height % this.h;
|
||||
// the same as drawScaledX but with the remaining height
|
||||
for(int i = 0; i < width / w; i++) {
|
||||
drawScaledY(xPos + i * w, yPos, yRest);
|
||||
}
|
||||
// remainder that doesn't fit total width
|
||||
int remainder = width % w;
|
||||
if(remainder > 0) {
|
||||
// drawModalRectWithCustomSizedTexture
|
||||
GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, yRest, texW, texH);
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiElementScalable shift(int xd, int yd) {
|
||||
GuiElementScalable element = new GuiElementScalable(this.x + xd, this.y + yd, this.w, this.h);
|
||||
element.setTextureSize(texW, texH);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import net.minecraft.util.EnumChatFormatting;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.PrintWriter;
|
||||
@@ -23,6 +24,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawMultilineTip;
|
||||
@@ -35,11 +37,11 @@ public class GuiContainerManager
|
||||
public GuiContainer window;
|
||||
|
||||
public static RenderItem drawItems = new RenderItem();
|
||||
public static LinkedList<IContainerTooltipHandler> tooltipHandlers = new LinkedList<>();
|
||||
public static LinkedList<IContainerInputHandler> inputHandlers = new LinkedList<>();
|
||||
public static LinkedList<IContainerDrawHandler> drawHandlers = new LinkedList<>();
|
||||
public static LinkedList<IContainerObjectHandler> objectHandlers = new LinkedList<>();
|
||||
public static LinkedList<IContainerSlotClickHandler> slotClickHandlers = new LinkedList<>();
|
||||
public static final LinkedList<IContainerTooltipHandler> tooltipHandlers = new HideousLinkedList<>(new CopyOnWriteArrayList<>());
|
||||
public static final LinkedList<IContainerInputHandler> inputHandlers = new HideousLinkedList<>(new CopyOnWriteArrayList<>());
|
||||
public static final LinkedList<IContainerDrawHandler> drawHandlers = new HideousLinkedList<>(new CopyOnWriteArrayList<>());
|
||||
public static final LinkedList<IContainerObjectHandler> objectHandlers = new HideousLinkedList<>(new CopyOnWriteArrayList<>());
|
||||
public static final LinkedList<IContainerSlotClickHandler> slotClickHandlers = new HideousLinkedList<>(new CopyOnWriteArrayList<>());
|
||||
|
||||
static {
|
||||
addSlotClickHandler(new DefaultSlotClickHandler());
|
||||
@@ -178,18 +180,48 @@ public class GuiContainerManager
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack) {
|
||||
drawItem(i, j, itemstack, getFontRenderer(itemstack));
|
||||
drawItem(i, j, itemstack, false);
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, boolean smallAmount) {
|
||||
drawItem(i, j, itemstack, smallAmount, null);
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, boolean smallAmount, String stackSize) {
|
||||
drawItem(i, j, itemstack, getFontRenderer(itemstack), smallAmount, stackSize);
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer) {
|
||||
drawItem(i, j, itemstack, fontRenderer, false, null);
|
||||
}
|
||||
|
||||
private static int modelviewDepth = -1;
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer) {
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer, boolean smallAmount, String stackSize) {
|
||||
enable3DRender();
|
||||
//for lighting correction
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
float zLevel = drawItems.zLevel += 100F;
|
||||
try {
|
||||
drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, itemstack, i, j);
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j);
|
||||
|
||||
if (stackSize == null) {
|
||||
stackSize = itemstack.stackSize > 1? String.valueOf(itemstack.stackSize): "";
|
||||
}
|
||||
|
||||
if (smallAmount) {
|
||||
|
||||
if (!stackSize.isEmpty()) {
|
||||
drawBigStackSize(i, j, stackSize);
|
||||
}
|
||||
|
||||
// stackSize = "". it needed for correct draw item with alpha and blend
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, "");
|
||||
} else {
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, stackSize);
|
||||
}
|
||||
|
||||
if (!checkMatrixStack())
|
||||
throw new IllegalStateException("Modelview matrix stack too deep");
|
||||
@@ -213,10 +245,29 @@ public class GuiContainerManager
|
||||
drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), i, j);
|
||||
}
|
||||
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
enable2DRender();
|
||||
drawItems.zLevel = zLevel - 100;
|
||||
}
|
||||
|
||||
//copy from appeng.client.render.AppEngRenderItem
|
||||
protected static void drawBigStackSize(int offsetX, int offsetY, String stackSize)
|
||||
{
|
||||
final float scaleFactor = fontRenderer.getUnicodeFlag() ? 0.85f : 0.5f;
|
||||
final float inverseScaleFactor = 1.0f / scaleFactor;
|
||||
|
||||
enable2DRender();
|
||||
GL11.glScaled(scaleFactor, scaleFactor, scaleFactor);
|
||||
|
||||
final int X = (int) ( ( (float) offsetX + 16.0f - fontRenderer.getStringWidth( stackSize ) * scaleFactor ) * inverseScaleFactor );
|
||||
final int Y = (int) ( ( (float) offsetY + 16.0f - 7.0f * scaleFactor ) * inverseScaleFactor );
|
||||
fontRenderer.drawStringWithShadow(stackSize, X, Y, 16777215);
|
||||
|
||||
GL11.glScaled(inverseScaleFactor, inverseScaleFactor, inverseScaleFactor);
|
||||
enable3DRender();
|
||||
|
||||
}
|
||||
|
||||
public static void enableMatrixStackLogging() {
|
||||
modelviewDepth = GL11.glGetInteger(GL11.GL_MODELVIEW_STACK_DEPTH);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
package codechicken.nei.guihook;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A hideous LinkedList that is backed by an arbitrary list, for alternative characteristics while preserving
|
||||
* binary compatibility...
|
||||
* @param <E>
|
||||
*/
|
||||
final class HideousLinkedList<E> extends LinkedList<E> {
|
||||
private final List<E> backing;
|
||||
|
||||
HideousLinkedList(List<E> backing) {
|
||||
this.backing = backing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return backing.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return backing.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return backing.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return backing.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return backing.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return backing.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
return backing.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFirst(E e) {
|
||||
backing.add(0, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFirst() {
|
||||
if (backing.size() == 0) throw new NoSuchElementException();
|
||||
return(backing.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeFirst() {
|
||||
E item = getFirst();
|
||||
backing.remove(0);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLast(E e) {
|
||||
backing.add(backing.size(), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getLast() {
|
||||
if (backing.size() == 0) throw new NoSuchElementException();
|
||||
return backing.get(backing.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeLast() {
|
||||
E item = getLast();
|
||||
backing.remove(backing.size() - 1);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peek() {
|
||||
return backing.size() > 0 ? backing.get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peekFirst() {
|
||||
return backing.size() > 0 ? getFirst() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peekLast() {
|
||||
return backing.size() > 0 ? getLast() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll() {
|
||||
return backing.size() > 0 ? removeFirst() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pollFirst() {
|
||||
return poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pollLast() {
|
||||
return backing.size() > 0 ? removeLast() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(E e) {
|
||||
addFirst(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pop() {
|
||||
return removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFirstOccurrence(Object e) {
|
||||
return remove(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLastOccurrence(Object e) {
|
||||
int idx = this.backing.lastIndexOf(e);
|
||||
if (idx != -1) {
|
||||
this.backing.remove(idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return backing.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return backing.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
return backing.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
return backing.addAll(index, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return backing.removeAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return backing.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<E> operator) {
|
||||
backing.replaceAll(operator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super E> c) {
|
||||
backing.sort(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
backing.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return backing.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return backing.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int index) {
|
||||
return backing.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E set(int index, E element) {
|
||||
return backing.set(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
backing.add(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(int index) {
|
||||
return backing.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return backing.indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return backing.lastIndexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator() {
|
||||
return backing.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
return backing.listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
return backing.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<E> spliterator() {
|
||||
return backing.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super E> filter) {
|
||||
return backing.removeIf(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<E> stream() {
|
||||
return backing.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<E> parallelStream() {
|
||||
return backing.parallelStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super E> action) {
|
||||
backing.forEach(action);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BookmarkRecipeId
|
||||
{
|
||||
|
||||
public int position = -1;
|
||||
|
||||
public int recipetype = -1;
|
||||
|
||||
public String handlerName = null;
|
||||
|
||||
public List<NBTTagCompound> ingredients = new ArrayList<>();
|
||||
|
||||
|
||||
public BookmarkRecipeId(String handlerName, List<?> stacks)
|
||||
{
|
||||
this.handlerName = handlerName;
|
||||
|
||||
for (Object pos : stacks) {
|
||||
|
||||
if (pos instanceof PositionedStack) {
|
||||
pos = getItemStackWithMinimumDamage(((PositionedStack) pos).items);
|
||||
}
|
||||
|
||||
if (pos instanceof ItemStack) {
|
||||
pos = StackInfo.itemStackToNBT((ItemStack) pos);
|
||||
}
|
||||
|
||||
if (pos instanceof NBTTagCompound) {
|
||||
ingredients.add((NBTTagCompound) pos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public BookmarkRecipeId(JsonObject json)
|
||||
{
|
||||
|
||||
if (json.get("handlerName") != null) {
|
||||
handlerName = json.get("handlerName").getAsString();
|
||||
}
|
||||
|
||||
if (json.get("ingredients") != null) {
|
||||
JsonArray arr = (JsonArray) json.get("ingredients");
|
||||
List<NBTTagCompound> ingredients = convertJsonArrayToIngredients(arr);
|
||||
|
||||
if (ingredients != null) {
|
||||
this.ingredients = ingredients;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public BookmarkRecipeId()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean equalsIngredients(List<PositionedStack> stacks)
|
||||
{
|
||||
|
||||
if (ingredients.size() != stacks.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Short idx = 0;
|
||||
|
||||
for (PositionedStack pStack : stacks) {
|
||||
final NBTTagCompound tagCompoundA = StackInfo.itemStackToNBT(getItemStackWithMinimumDamage(pStack.items));
|
||||
final NBTTagCompound tagCompoundB = ingredients.get(idx);
|
||||
|
||||
if (tagCompoundB == null || !tagCompoundB.equals(tagCompoundA)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ItemStack getItemStackWithMinimumDamage(ItemStack[] stacks)
|
||||
{
|
||||
int damage = Short.MAX_VALUE;
|
||||
ItemStack result = stacks[0];
|
||||
|
||||
if (stacks.length > 1) {
|
||||
for (ItemStack stack : stacks) {
|
||||
if (stack.getItemDamage() < damage) {
|
||||
damage = stack.getItemDamage();
|
||||
result = stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.copy();
|
||||
}
|
||||
|
||||
public JsonObject toJsonObject()
|
||||
{
|
||||
JsonObject json = new JsonObject();
|
||||
|
||||
if (handlerName != null) {
|
||||
json.add("handlerName", new JsonPrimitive(handlerName));
|
||||
json.add("ingredients", convertIngredientsToJsonArray(ingredients));
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
protected List<NBTTagCompound> convertJsonArrayToIngredients(JsonArray arr)
|
||||
{
|
||||
List<NBTTagCompound> ingredients = new ArrayList<>();
|
||||
|
||||
for (JsonElement elem : arr) {
|
||||
final NBTTagCompound nbt = (NBTTagCompound) NBTJson.toNbt(elem);
|
||||
|
||||
if (nbt == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ingredients.add(nbt);
|
||||
}
|
||||
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
protected JsonArray convertIngredientsToJsonArray(List<NBTTagCompound> ingredients)
|
||||
{
|
||||
JsonArray arr = new JsonArray();
|
||||
|
||||
for (NBTTagCompound nbTag : ingredients) {
|
||||
arr.add(NBTJson.toJsonObject(nbTag));
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
public boolean equals(Object anObject)
|
||||
{
|
||||
if (this == anObject) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (anObject instanceof BookmarkRecipeId) {
|
||||
final BookmarkRecipeId anRecipeId = (BookmarkRecipeId) anObject;
|
||||
|
||||
if (!handlerName.equals(anRecipeId.handlerName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ingredients.size() != anRecipeId.ingredients.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < ingredients.size(); idx++) {
|
||||
if (!ingredients.get(idx).equals(anRecipeId.ingredients.get(idx))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public BookmarkRecipeId copy()
|
||||
{
|
||||
return new BookmarkRecipeId(handlerName, ingredients);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class CatalystInfo {
|
||||
private final ItemStack stack;
|
||||
private final int priority;
|
||||
|
||||
public CatalystInfo(ItemStack stack, int priority) {
|
||||
this.stack = stack;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public ItemStack getStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
import com.google.common.collect.ForwardingList;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
// Do not directly extend ArrayList, see Effective Java Item 16
|
||||
public class CatalystInfoList extends ForwardingList<CatalystInfo> {
|
||||
private final String handlerID;
|
||||
private final List<CatalystInfo> catalystInfoList = new ArrayList<>();
|
||||
|
||||
public CatalystInfoList(String handlerID) {
|
||||
this.handlerID = handlerID;
|
||||
}
|
||||
|
||||
public CatalystInfoList(String handlerID, CatalystInfo catalystInfo) {
|
||||
this(handlerID);
|
||||
add(catalystInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<CatalystInfo> delegate() {
|
||||
return catalystInfoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(@Nonnull CatalystInfo catalystInfo) {
|
||||
if (contains(catalystInfo)) {
|
||||
NEIClientConfig.logger.info(String.format("catalyst %s is already registered to handler %s", catalystInfo.getStack().getDisplayName(), handlerID));
|
||||
return false;
|
||||
}
|
||||
super.add(catalystInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object object) {
|
||||
if (object instanceof CatalystInfo) {
|
||||
ItemStack stack = ((CatalystInfo) object).getStack();
|
||||
return contains(stack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack stack) {
|
||||
return catalystInfoList.stream().anyMatch(c -> NEIServerUtils.areStacksSameTypeCraftingWithNBT(c.getStack(), stack));
|
||||
}
|
||||
|
||||
public boolean remove(ItemStack stack) {
|
||||
Iterator<CatalystInfo> iter = catalystInfoList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ItemStack next = iter.next().getStack();
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(next, stack)) {
|
||||
iter.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void sort() {
|
||||
super.sort((c1, c2) -> c2.getPriority() - c1.getPriority());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.NEICPH;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
|
||||
public class CheatItemHandler extends INEIGuiAdapter
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, ItemStack draggedStack, int button)
|
||||
{
|
||||
final Slot overSlot = gui.getSlotAtPosition(mouseX, mouseY);
|
||||
|
||||
if (overSlot != null && overSlot.isItemValid(draggedStack)) {
|
||||
|
||||
if (NEIClientConfig.canCheatItem(draggedStack)) {
|
||||
int contents = overSlot.getHasStack() ? overSlot.getStack().stackSize : 0;
|
||||
final int add = button == 0 ? draggedStack.stackSize : 1;
|
||||
|
||||
if (overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack())) {
|
||||
contents = 0;
|
||||
}
|
||||
|
||||
final int total = Math.min(contents + add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize()));
|
||||
|
||||
if (total > contents) {
|
||||
NEIClientUtils.setSlotContents(overSlot.slotNumber, NEIServerUtils.copyStack(draggedStack, total), true);
|
||||
NEICPH.sendGiveItem(NEIServerUtils.copyStack(draggedStack, total), false, false);
|
||||
draggedStack.stackSize -= total - contents;
|
||||
}
|
||||
|
||||
} else {
|
||||
draggedStack.stackSize = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidContainerRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
public class FillFluidContainerHandler extends INEIGuiAdapter
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, ItemStack draggedStack, int button)
|
||||
{
|
||||
|
||||
if (button == 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (draggedStack.getItem() instanceof IFluidContainerItem || FluidContainerRegistry.isContainer(draggedStack)) {
|
||||
ItemPanelSlot mouseOverSlot = ItemPanels.itemPanel.getSlotMouseOver(mouseX, mouseY);
|
||||
|
||||
if (mouseOverSlot == null) {
|
||||
mouseOverSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseX, mouseY);
|
||||
}
|
||||
|
||||
if (mouseOverSlot != null) {
|
||||
FluidStack fluidStack = StackInfo.getFluid(mouseOverSlot.item);
|
||||
|
||||
if (fluidStack != null) {
|
||||
ItemStack container = fillContainer(draggedStack, fluidStack);
|
||||
|
||||
if (container != null) {
|
||||
container.stackSize = draggedStack.stackSize;
|
||||
|
||||
if (ItemPanels.itemPanel.draggedStack != null) {
|
||||
ItemPanels.itemPanel.draggedStack = container;
|
||||
} else {
|
||||
ItemPanels.bookmarkPanel.draggedStack = container;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (button == 1 && StackInfo.getFluid(container != null? container: draggedStack) != null) {
|
||||
ItemPanels.bookmarkPanel.addOrRemoveItem((container != null? container: draggedStack).copy());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected ItemStack fillContainer(ItemStack draggedStack, FluidStack fluidStack)
|
||||
{
|
||||
fluidStack = fluidStack.copy();
|
||||
draggedStack = draggedStack.copy();
|
||||
draggedStack.stackSize = 1;
|
||||
|
||||
if (fluidStack.amount == 0) {
|
||||
fluidStack.amount = 1000;
|
||||
}
|
||||
|
||||
if (FluidContainerRegistry.isContainer(draggedStack)) {
|
||||
|
||||
if (FluidContainerRegistry.getContainerCapacity(draggedStack) > 0) {
|
||||
draggedStack = FluidContainerRegistry.drainFluidContainer(draggedStack);
|
||||
}
|
||||
|
||||
return FluidContainerRegistry.fillFluidContainer(fluidStack, draggedStack);
|
||||
} else if (draggedStack.getItem() instanceof IFluidContainerItem) {
|
||||
IFluidContainerItem item = (IFluidContainerItem) draggedStack.getItem();
|
||||
|
||||
if (item.getCapacity(draggedStack) > 0) {
|
||||
item.drain(draggedStack, item.getCapacity(draggedStack), true);
|
||||
}
|
||||
|
||||
if (item.fill(draggedStack, fluidStack, true) > 0) {
|
||||
return draggedStack;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,13 +2,14 @@ package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.FurnaceRecipes;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
@@ -78,31 +79,23 @@ public class FuelRecipeHandler extends FurnaceRecipeHandler
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String specifyTransferRect() {
|
||||
return "fuel";
|
||||
}
|
||||
|
||||
public String getOverlayIdentifier() {
|
||||
return "fuel";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiRecipe gui, ItemStack stack, List<String> currenttip, int recipe) {
|
||||
public void drawExtras(int recipe) {
|
||||
super.drawExtras(recipe);
|
||||
CachedFuelRecipe crecipe = (CachedFuelRecipe) arecipes.get(recipe);
|
||||
FuelPair fuel = crecipe.fuel;
|
||||
float burnTime = fuel.burnTime / 200F;
|
||||
|
||||
if (gui.isMouseOver(fuel.stack, recipe) && burnTime < 1) {
|
||||
burnTime = 1F / burnTime;
|
||||
String s_time = Float.toString(burnTime);
|
||||
if (burnTime == Math.round(burnTime))
|
||||
s_time = Integer.toString((int) burnTime);
|
||||
|
||||
currenttip.add(translate("recipe.fuel.required", s_time));
|
||||
} else if ((gui.isMouseOver(crecipe.getResult(), recipe) || gui.isMouseOver(crecipe.getIngredient(), recipe)) && burnTime > 1) {
|
||||
String s_time = Float.toString(burnTime);
|
||||
if (burnTime == Math.round(burnTime))
|
||||
s_time = Integer.toString((int) burnTime);
|
||||
|
||||
currenttip.add(translate("recipe.fuel." + (gui.isMouseOver(crecipe.getResult(), recipe) ? "produced" : "processed"), s_time));
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
NumberFormat numberInstance = NumberFormat.getNumberInstance();
|
||||
numberInstance.setMaximumFractionDigits(2);
|
||||
String smeltCount = numberInstance.format(fuel.burnTime / 200f);
|
||||
Minecraft.getMinecraft().fontRenderer.drawString(translate("recipe.fuel.smeltCount", smeltCount), 73, 51, 0xFF000000);
|
||||
}
|
||||
}
|
||||
@@ -115,6 +115,11 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String specifyTransferRect() {
|
||||
return "smelting";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuiTexture() {
|
||||
return "textures/gui/container/furnace.png";
|
||||
|
||||
@@ -2,39 +2,57 @@ package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.core.TaskProfiler;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GuiCraftingRecipe extends GuiRecipe
|
||||
{
|
||||
public class GuiCraftingRecipe extends GuiRecipe {
|
||||
public static boolean openRecipeGui(String outputId, Object... results) {
|
||||
return openRecipeGui(outputId, false, results);
|
||||
}
|
||||
|
||||
|
||||
public static boolean openRecipeGui(String outputId, Boolean overlay, Object... results) {
|
||||
Minecraft mc = NEIClientUtils.mc();
|
||||
GuiScreen prevscreen = mc.currentScreen;// instanceof GuiContainer ? (GuiContainer) mc.currentScreen : null;
|
||||
|
||||
ArrayList<ICraftingHandler> handlers;
|
||||
TaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
profiler.start("recipe.concurrent.crafting");
|
||||
|
||||
|
||||
// Pre-find the fuels so we're not fighting over it
|
||||
FuelRecipeHandler.findFuelsOnceParallel();
|
||||
|
||||
try {
|
||||
handlers = serialCraftingHandlers.stream().map(h -> h.getRecipeHandler(outputId, results))
|
||||
.filter(h -> h.numRecipes() > 0)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
.filter(h -> h.numRecipes() > 0)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
handlers.addAll(ItemList.forkJoinPool.submit(() -> craftinghandlers.parallelStream()
|
||||
.map(h -> h.getRecipeHandler(outputId, results))
|
||||
.filter(h -> h.numRecipes() > 0)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get());
|
||||
.map(h -> h.getRecipeHandler(outputId, results))
|
||||
.filter(h -> h.numRecipes() > 0)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
if (player != null) {
|
||||
IChatComponent chat = new ChatComponentTranslation("nei.chat.recipe.error");
|
||||
chat.getChatStyle().setColor(EnumChatFormatting.RED);
|
||||
player.addChatComponentMessage(chat);
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
profiler.end();
|
||||
@@ -45,10 +63,51 @@ public class GuiCraftingRecipe extends GuiRecipe
|
||||
|
||||
handlers.sort(NEIClientConfig.HANDLER_COMPARATOR);
|
||||
|
||||
mc.displayGuiScreen(new GuiCraftingRecipe(prevscreen, handlers));
|
||||
BookmarkRecipeId recipeId = null;
|
||||
|
||||
if ("item".equals(outputId)) {
|
||||
recipeId = getRecipeId(prevscreen, (ItemStack) results[0]);
|
||||
}
|
||||
|
||||
GuiCraftingRecipe gui = new GuiCraftingRecipe(prevscreen, handlers, recipeId);
|
||||
|
||||
mc.displayGuiScreen(gui);
|
||||
|
||||
if (NEIClientConfig.saveCurrentRecipeInBookmarksEnabled())
|
||||
if (!NEIClientUtils.shiftKey() || overlay) {
|
||||
gui.openTargetRecipe(gui.recipeId);
|
||||
}
|
||||
|
||||
if (overlay) {
|
||||
if (!NEIClientConfig.saveCurrentRecipeInBookmarksEnabled() || gui.recipeId == null) {
|
||||
mc.displayGuiScreen(prevscreen);
|
||||
return false;
|
||||
}
|
||||
gui.overlayRecipe(gui.recipeId.position);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static BookmarkRecipeId getRecipeId(GuiScreen gui, ItemStack stackover) {
|
||||
|
||||
if (gui instanceof GuiRecipe) {
|
||||
final List<PositionedStack> ingredients = ((GuiRecipe) gui).getFocusedRecipeIngredients();
|
||||
final String handlerName = ((GuiRecipe) gui).getHandlerName();
|
||||
|
||||
if (ingredients != null && !ingredients.isEmpty()) {
|
||||
return new BookmarkRecipeId(handlerName, ingredients);
|
||||
}
|
||||
}
|
||||
|
||||
return ItemPanels.bookmarkPanel.getBookmarkRecipeId(stackover);
|
||||
}
|
||||
|
||||
private GuiCraftingRecipe(GuiScreen prevgui, ArrayList<ICraftingHandler> handlers, BookmarkRecipeId recipeId) {
|
||||
this(prevgui, handlers);
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
private GuiCraftingRecipe(GuiScreen prevgui, ArrayList<ICraftingHandler> handlers) {
|
||||
super(prevgui);
|
||||
currenthandlers = handlers;
|
||||
@@ -56,10 +115,10 @@ public class GuiCraftingRecipe extends GuiRecipe
|
||||
|
||||
public static void registerRecipeHandler(ICraftingHandler handler) {
|
||||
final String handlerId = handler.getHandlerId();
|
||||
if(craftinghandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)) || serialCraftingHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)))
|
||||
if (craftinghandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)) || serialCraftingHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)))
|
||||
return;
|
||||
|
||||
if(NEIClientConfig.serialHandlers.contains(handlerId))
|
||||
if (NEIClientConfig.serialHandlers.contains(handlerId))
|
||||
serialCraftingHandlers.add(handler);
|
||||
else
|
||||
craftinghandlers.add(handler);
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -62,8 +63,10 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
|
||||
public int page;
|
||||
public int recipetype;
|
||||
public BookmarkRecipeId recipeId;
|
||||
public ContainerRecipe slotcontainer;
|
||||
public GuiContainer firstGui;
|
||||
public GuiScreen firstGuiGeneral;
|
||||
public GuiScreen prevGui;
|
||||
public GuiButton nextpage;
|
||||
public GuiButton prevpage;
|
||||
@@ -75,6 +78,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
|
||||
private final Rectangle area = new Rectangle();
|
||||
private final GuiRecipeTabs recipeTabs;
|
||||
private final GuiRecipeCatalyst guiRecipeCatalyst;
|
||||
private IRecipeHandler handler;
|
||||
private HandlerInfo handlerInfo;
|
||||
|
||||
@@ -83,15 +87,19 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
protected GuiRecipe(GuiScreen prevgui) {
|
||||
super(new ContainerRecipe());
|
||||
recipeTabs = new GuiRecipeTabs(this);
|
||||
guiRecipeCatalyst = new GuiRecipeCatalyst(this);
|
||||
slotcontainer = (ContainerRecipe) inventorySlots;
|
||||
|
||||
this.prevGui = prevgui;
|
||||
this.firstGuiGeneral = prevgui;
|
||||
if(prevgui instanceof GuiContainer)
|
||||
this.firstGui = (GuiContainer)prevgui;
|
||||
|
||||
if (prevgui instanceof IGuiContainerOverlay)
|
||||
if (prevgui instanceof IGuiContainerOverlay) {
|
||||
this.firstGui = ((IGuiContainerOverlay) prevgui).getFirstScreen();
|
||||
|
||||
this.firstGuiGeneral = ((IGuiContainerOverlay) prevgui).getFirstScreenGeneral();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +117,11 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
private HeightHack() {
|
||||
trueHeight = height;
|
||||
|
||||
if (NEIClientConfig.heightHackHandlers.contains(handler.getHandlerId())) {
|
||||
boolean applyHeightHack =
|
||||
NEIClientConfig.heightHackHandlerRegex.stream()
|
||||
.map(pattern -> pattern.matcher(handler.getHandlerId()))
|
||||
.anyMatch(Matcher::matches);
|
||||
if (applyHeightHack) {
|
||||
// The old mods use the calculation ((height - 166) / 2) to compute the y-value of
|
||||
// the top edge of the NEI window.
|
||||
// guiTop is exactly that: the y-value of the top edge of the NEI window.
|
||||
@@ -193,20 +205,101 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
yShift = handlerInfo == null ? 0 : handlerInfo.getYShift();
|
||||
}
|
||||
|
||||
|
||||
public void setRecipePage(int idx) {
|
||||
setRecipePage(idx, 0);
|
||||
}
|
||||
|
||||
public void setRecipePage(int idx, int position) {
|
||||
recipetype = idx;
|
||||
if (recipetype < 0) recipetype = currenthandlers.size() - 1;
|
||||
else if (recipetype >= currenthandlers.size()) recipetype = 0;
|
||||
|
||||
handler = currenthandlers.get(recipetype);
|
||||
handlerInfo = getHandlerInfo(handler);
|
||||
page = 0;
|
||||
handlerInfo = GuiRecipeTab.getHandlerInfo(handler);
|
||||
page = Math.min(Math.max(0, position), handler.numRecipes() - 1) / getRecipesPerPage();
|
||||
recipeTabs.calcPageNumber();
|
||||
checkYShift();
|
||||
initOverlayButtons();
|
||||
}
|
||||
|
||||
public void openTargetRecipe(BookmarkRecipeId recipeId)
|
||||
{
|
||||
|
||||
if (recipeId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (recipeId.recipetype == -1 || recipeId.position == -1) {
|
||||
recipeId.recipetype = 0;
|
||||
recipeId.position = 0;
|
||||
|
||||
if (recipeId.handlerName != null) {
|
||||
|
||||
for (int j = 0; j < currenthandlers.size(); j++) {
|
||||
IRecipeHandler localHandler = currenthandlers.get(j);
|
||||
HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler);
|
||||
|
||||
if (localHandlerInfo.getHandlerName().equals(recipeId.handlerName)) {
|
||||
recipeId.recipetype = j;
|
||||
|
||||
if (!recipeId.ingredients.isEmpty()) {
|
||||
for (int i = 0; i < localHandler.numRecipes(); i++) {
|
||||
|
||||
if (recipeId.equalsIngredients(localHandler.getIngredientStacks(i))) {
|
||||
recipeId.position = i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setRecipePage(recipeId.recipetype, recipeId.position);
|
||||
}
|
||||
|
||||
public List<PositionedStack> getFocusedRecipeIngredients()
|
||||
{
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
|
||||
for (int idx = page * recipesPerPage; idx < handler.numRecipes() && idx < (page + 1) * recipesPerPage; idx++) {
|
||||
if (recipeInFocus(idx)) {
|
||||
return handler.getIngredientStacks(idx);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean recipeInFocus(int idx)
|
||||
{
|
||||
final PositionedStack result = handler.getResultStack(idx);
|
||||
if (result != null && isMouseOver(result, idx)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<PositionedStack> stacks = handler.getOtherStacks(idx);
|
||||
for (PositionedStack stack : stacks) {
|
||||
if (isMouseOver(stack, idx)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getHandlerName()
|
||||
{
|
||||
return handlerInfo.getHandlerName();
|
||||
}
|
||||
|
||||
public IRecipeHandler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
@@ -219,12 +312,11 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
return IntStream.range(minIndex, maxIndex).boxed().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int i) {
|
||||
if (i == Keyboard.KEY_ESCAPE) //esc
|
||||
{
|
||||
mc.displayGuiScreen(firstGui);
|
||||
mc.displayGuiScreen(firstGuiGeneral);
|
||||
return;
|
||||
}
|
||||
if (GuiContainerManager.getManager(this).lastKeyTyped(i, c))
|
||||
@@ -237,7 +329,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
}
|
||||
|
||||
if (i == mc.gameSettings.keyBindInventory.getKeyCode())
|
||||
mc.displayGuiScreen(firstGui);
|
||||
mc.displayGuiScreen(firstGuiGeneral);
|
||||
else if (i == NEIClientConfig.getKeyBinding("gui.back"))
|
||||
mc.displayGuiScreen(prevGui);
|
||||
else if (i == NEIClientConfig.getKeyBinding("gui.prev_machine"))
|
||||
@@ -354,36 +446,25 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
setRecipePage(--recipetype);
|
||||
}
|
||||
|
||||
public HandlerInfo getHandlerInfo(IRecipeHandler handler) {
|
||||
final String handlerID;
|
||||
if(handler instanceof TemplateRecipeHandler) {
|
||||
handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier());
|
||||
} else {
|
||||
handlerID = null;
|
||||
protected void overlayRecipe(int recipe) {
|
||||
if (handler == null || !handler.hasOverlay(firstGui, firstGui.inventorySlots, recipe)) {
|
||||
mc.displayGuiScreen(firstGui);
|
||||
return;
|
||||
}
|
||||
HandlerInfo info = GuiRecipeTab.getHandlerInfo(handler.getHandlerId(), handlerID);
|
||||
|
||||
if (info == null)
|
||||
return GuiRecipeTab.DEFAULT_HANDLER_INFO;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private void overlayRecipe(int recipe) {
|
||||
final IRecipeOverlayRenderer renderer = handler.getOverlayRenderer(firstGui, recipe);
|
||||
final IOverlayHandler overlayHandler = handler.getOverlayHandler(firstGui, recipe);
|
||||
final boolean shift = NEIClientUtils.shiftKey();
|
||||
|
||||
if (handler != null && (renderer == null || shift)) {
|
||||
mc.displayGuiScreen(firstGui);
|
||||
mc.displayGuiScreen(firstGui);
|
||||
if (renderer == null || shift) {
|
||||
overlayHandler.overlayRecipe(firstGui, currenthandlers.get(recipetype), recipe, shift);
|
||||
} else if (renderer != null) {
|
||||
mc.displayGuiScreen(firstGui);
|
||||
} else {
|
||||
LayoutManager.overlayRenderer = renderer;
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshPage() {
|
||||
RecipeCatalysts.updatePosition(ySize - BG_TOP_HEIGHT - (GuiRecipeCatalyst.fullBorder * 2));
|
||||
refreshSlots();
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
final boolean multiplepages = handler.numRecipes() > recipesPerPage;
|
||||
@@ -433,6 +514,13 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
PositionedStack result = handler.getResultStack(i);
|
||||
if (result != null)
|
||||
slotcontainer.addSlot(result, p.x, p.y);
|
||||
|
||||
List<PositionedStack> catalysts = RecipeCatalysts.getRecipeCatalysts(handler);
|
||||
for (PositionedStack catalyst : catalysts) {
|
||||
int xOffset = -GuiRecipeCatalyst.ingredientSize + 1;
|
||||
int yOffset = BG_TOP_Y + GuiRecipeCatalyst.fullBorder;
|
||||
slotcontainer.addSlot(catalyst, xOffset, yOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,6 +605,9 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
recipeTabs.draw(mouseX, mouseY);
|
||||
if (NEIClientConfig.areJEIStyleRecipeCatalystsVisible()) {
|
||||
guiRecipeCatalyst.draw();
|
||||
}
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
}
|
||||
|
||||
@@ -561,6 +652,11 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
return firstGui;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiScreen getFirstScreenGeneral() {
|
||||
return firstGuiGeneral;
|
||||
}
|
||||
|
||||
public boolean isMouseOver(PositionedStack stack, int recipe) {
|
||||
Slot stackSlot = slotcontainer.getSlotWithStack(stack, getRecipePosition(recipe).x, getRecipePosition(recipe).y);
|
||||
Point mousepos = GuiDraw.getMousePosition();
|
||||
@@ -579,8 +675,12 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int getRecipesPerPage() {
|
||||
return getRecipesPerPage(handlerInfo);
|
||||
}
|
||||
|
||||
private int getRecipesPerPage(HandlerInfo handlerInfo) {
|
||||
if(handlerInfo != null)
|
||||
return Math.max(Math.min(((ySize - (buttonHeight*3)) / handlerInfo.getHeight()), handlerInfo.getMaxRecipesPerPage()), 1);
|
||||
else
|
||||
@@ -618,9 +718,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
||||
// Because some of the handlers *cough avaritia* are oversized
|
||||
Rectangle rect = new Rectangle(area);
|
||||
|
||||
return rect.contains(x, y, w, h);
|
||||
return area.intersects(x, y, w, h);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import codechicken.nei.drawable.GuiElementDuex;
|
||||
import codechicken.nei.drawable.GuiElementScalable;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.util.Rectangle;
|
||||
|
||||
public class GuiRecipeCatalyst extends INEIGuiAdapter {
|
||||
private GuiRecipe guiRecipe;
|
||||
public static final int ingredientSize = 16;
|
||||
public static final int ingredientBorder = 1;
|
||||
public static final int tabBorder = 5;
|
||||
public static final int fullBorder = ingredientBorder + tabBorder;
|
||||
|
||||
private static final Rectangle catalystRect = new Rectangle();
|
||||
private static final Rectangle targetRect = new Rectangle();
|
||||
|
||||
public GuiRecipeCatalyst(GuiRecipe guiRecipe) {
|
||||
this.guiRecipe = guiRecipe;
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
if (guiRecipe == null) return;
|
||||
int catalystsSize = RecipeCatalysts.getRecipeCatalysts(guiRecipe.getHandler()).size();
|
||||
if (catalystsSize == 0) return;
|
||||
|
||||
int availableHeight = RecipeCatalysts.getHeight();
|
||||
int columnCount = RecipeCatalysts.getColumnCount(availableHeight, catalystsSize);
|
||||
int rowCount = RecipeCatalysts.getRowCount(availableHeight, catalystsSize);
|
||||
int width, height, xPos, yPos;
|
||||
|
||||
width = (ingredientBorder * 2) + (tabBorder * 2) + (columnCount * ingredientSize);
|
||||
height = (ingredientBorder * 2) + (tabBorder * 2) + (rowCount * ingredientSize);
|
||||
xPos = guiRecipe.guiLeft - width + tabBorder + 1;
|
||||
yPos = guiRecipe.guiTop;
|
||||
drawBordered("nei:textures/catalyst_tab.png", xPos, yPos, width, height, 28, 28, 6, 6, 6, 6);
|
||||
|
||||
width = (ingredientBorder * 2) + (columnCount * ingredientSize);
|
||||
height = (ingredientBorder * 2) + (rowCount * ingredientSize);
|
||||
xPos = guiRecipe.guiLeft - width + ingredientBorder + 1;
|
||||
yPos = guiRecipe.guiTop + fullBorder - ingredientBorder;
|
||||
drawBordered("nei:textures/slot.png", xPos, yPos, width, height, 18, 18, 1, 1, 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
||||
if (!(gui instanceof GuiRecipe)) return false;
|
||||
guiRecipe = (GuiRecipe) gui;
|
||||
int catalystsSize = RecipeCatalysts.getRecipeCatalysts(guiRecipe.getHandler()).size();
|
||||
if (catalystsSize == 0) return false;
|
||||
|
||||
int availableHeight = RecipeCatalysts.getHeight();
|
||||
int columnCount = RecipeCatalysts.getColumnCount(availableHeight, catalystsSize);
|
||||
int rowCount = RecipeCatalysts.getRowCount(availableHeight, catalystsSize);
|
||||
int margin = 4;
|
||||
|
||||
int width = (ingredientBorder * 2) + (tabBorder * 2) + (columnCount * ingredientSize) + margin;
|
||||
int height = (ingredientBorder * 2) + (tabBorder * 2) + (rowCount * ingredientSize) + margin;
|
||||
int xOffset = guiRecipe.guiLeft - width + tabBorder;
|
||||
int yOffset = guiRecipe.guiTop;
|
||||
catalystRect.setBounds(xOffset, yOffset, width, height);
|
||||
targetRect.setBounds(x, y, w, h);
|
||||
return targetRect.intersects(catalystRect);
|
||||
}
|
||||
|
||||
private void drawBordered(String location, int xPos, int yPos, int width, int height, int texWidth, int texHeight, int sliceLeft, int sliceRight, int sliceTop, int sliceBottom) {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(location));
|
||||
|
||||
GuiElementDuex cornerTopLeft = new GuiElementDuex(0, 0, sliceLeft, sliceTop, texWidth, texHeight);
|
||||
GuiElementDuex cornerTopRight = new GuiElementDuex(texWidth - sliceRight, 0, sliceRight, sliceTop, texWidth, texHeight);
|
||||
GuiElementDuex cornerBottomLeft = new GuiElementDuex(0, texHeight - sliceBottom, sliceLeft, sliceBottom, texWidth, texHeight);
|
||||
GuiElementDuex cornerBottomRight = new GuiElementDuex(texWidth - sliceRight, texHeight - sliceBottom, sliceRight, sliceBottom, texWidth, texHeight);
|
||||
|
||||
GuiElementScalable borderTop = new GuiElementScalable(sliceLeft, 0, texWidth - sliceLeft - sliceRight, sliceTop, texWidth, texHeight);
|
||||
GuiElementScalable borderBottom = new GuiElementScalable(sliceLeft, texHeight - sliceBottom, texWidth - sliceLeft - sliceRight, sliceBottom, texWidth, texHeight);
|
||||
GuiElementScalable borderLeft = new GuiElementScalable(0, sliceTop, sliceLeft, texHeight - sliceTop - sliceBottom, texWidth, texHeight);
|
||||
GuiElementScalable borderRight = new GuiElementScalable(texWidth - sliceRight, sliceTop, sliceRight, texHeight - sliceTop - sliceBottom, texWidth, texHeight);
|
||||
GuiElementScalable center = new GuiElementScalable(sliceLeft, sliceTop, texWidth - sliceLeft - sliceRight, texHeight - sliceTop - sliceBottom, texWidth, texHeight);
|
||||
|
||||
int midW = width - borderLeft.w - borderRight.w;
|
||||
int midH = height - borderTop.h - borderBottom.h;
|
||||
|
||||
// top row
|
||||
int x = xPos;
|
||||
int y = yPos;
|
||||
x += cornerTopLeft.draw(x, y);
|
||||
x += borderTop.drawScaledX(x, y, midW);
|
||||
cornerTopRight.draw(x, y);
|
||||
|
||||
// center row
|
||||
x = xPos;
|
||||
y += borderTop.h;
|
||||
x += borderLeft.drawScaledY(x, y, midH);
|
||||
x += center.drawScaled(x, y, midW, midH);
|
||||
borderRight.drawScaledY(x, y, midH);
|
||||
|
||||
// bottom row
|
||||
x = xPos;
|
||||
y += midH;
|
||||
x += cornerBottomLeft.draw(x, y);
|
||||
x += borderBottom.drawScaledX(x, y, midW);
|
||||
cornerBottomRight.draw(x, y);
|
||||
}
|
||||
}
|
||||
@@ -64,9 +64,9 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
this.handlerName = handler.getHandlerId();
|
||||
this.guiRecipe = guiRecipe;
|
||||
this.selected = false;
|
||||
|
||||
|
||||
if(handler instanceof TemplateRecipeHandler) {
|
||||
handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier());
|
||||
handlerID = handler.getOverlayIdentifier();
|
||||
} else {
|
||||
handlerID = null;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
}
|
||||
|
||||
public void addTooltips(List<String> tooltip) {
|
||||
tooltip.add(handler.getRecipeName().trim());
|
||||
tooltip.add(handler.getRecipeTabName().trim());
|
||||
|
||||
String handlerMod = getHandlerMod(handlerName, handlerID);
|
||||
tooltip.add(EnumChatFormatting.BLUE + handlerMod);
|
||||
@@ -157,6 +157,24 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
selected = handler == current;
|
||||
}
|
||||
|
||||
public static HandlerInfo getHandlerInfo(IRecipeHandler handler)
|
||||
{
|
||||
final String handlerID;
|
||||
|
||||
if (handler instanceof TemplateRecipeHandler) {
|
||||
handlerID = handler.getOverlayIdentifier();
|
||||
} else {
|
||||
handlerID = null;
|
||||
}
|
||||
|
||||
HandlerInfo info = getHandlerInfo(handler.getHandlerId(), handlerID);
|
||||
|
||||
if (info == null)
|
||||
return GuiRecipeTab.DEFAULT_HANDLER_INFO;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public static HandlerInfo getHandlerInfo(String name, String name2) {
|
||||
HandlerInfo res = handlerMap.get(name);
|
||||
if (res == null) res = handlerMap.get(name2);
|
||||
@@ -189,7 +207,7 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
} else {
|
||||
File handlerFile = NEIClientConfig.handlerFile;
|
||||
if(!handlerFile.exists()) {
|
||||
NEIClientConfig.logger.info("Config file doesn't exit, creating");
|
||||
NEIClientConfig.logger.info("Config file doesn't exist, creating");
|
||||
try {
|
||||
assert handlerUrl != null;
|
||||
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
|
||||
@@ -254,9 +272,6 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
handlerMap.put(handler, info);
|
||||
NEIClientConfig.logger.info("Loaded " + handler);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.info("Error parsing CSV");
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.info("Error parsing CSV");
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -6,6 +6,10 @@ import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -25,16 +29,22 @@ public class GuiUsageRecipe extends GuiRecipe
|
||||
|
||||
profiler.start("recipe.concurrent.usage");
|
||||
try {
|
||||
handlers = serialUsageHandlers.stream().map(h -> h.getUsageHandler(inputId, ingredients))
|
||||
handlers = serialUsageHandlers.stream().map(h -> getUsageOrCatalystHandler(h, inputId, ingredients))
|
||||
.filter(h -> h.numRecipes() > 0)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
|
||||
handlers.addAll(ItemList.forkJoinPool.submit(() -> usagehandlers.parallelStream()
|
||||
.map(h -> h.getUsageHandler(inputId, ingredients))
|
||||
.map(h -> getUsageOrCatalystHandler(h, inputId, ingredients))
|
||||
.filter(h -> h.numRecipes() > 0)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
if (player != null) {
|
||||
IChatComponent chat = new ChatComponentTranslation("nei.chat.recipe.error");
|
||||
chat.getChatStyle().setColor(EnumChatFormatting.RED);
|
||||
player.addChatComponentMessage(chat);
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
profiler.end();
|
||||
@@ -45,10 +55,29 @@ public class GuiUsageRecipe extends GuiRecipe
|
||||
|
||||
handlers.sort(NEIClientConfig.HANDLER_COMPARATOR);
|
||||
|
||||
mc.displayGuiScreen(new GuiUsageRecipe(prevscreen, handlers));
|
||||
BookmarkRecipeId recipeId = null;
|
||||
|
||||
if (prevscreen instanceof GuiRecipe && ((GuiRecipe) prevscreen).recipeId != null) {
|
||||
recipeId = (((GuiRecipe) prevscreen).recipeId).copy();
|
||||
}
|
||||
|
||||
GuiUsageRecipe gui = new GuiUsageRecipe(prevscreen, handlers, recipeId);
|
||||
|
||||
mc.displayGuiScreen(gui);
|
||||
|
||||
if (!NEIClientUtils.shiftKey()) {
|
||||
gui.openTargetRecipe(recipeId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private GuiUsageRecipe(GuiContainer prevgui, ArrayList<IUsageHandler> handlers, BookmarkRecipeId recipeId)
|
||||
{
|
||||
this(prevgui, handlers);
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
private GuiUsageRecipe(GuiContainer prevgui, ArrayList<IUsageHandler> handlers) {
|
||||
super(prevgui);
|
||||
currenthandlers = handlers;
|
||||
@@ -69,6 +98,15 @@ public class GuiUsageRecipe extends GuiRecipe
|
||||
return currenthandlers;
|
||||
}
|
||||
|
||||
private static IUsageHandler getUsageOrCatalystHandler(IUsageHandler handler, String inputId, Object... ingredients) {
|
||||
boolean skipCatalyst = NEIClientUtils.controlKey();
|
||||
if (NEIClientConfig.areJEIStyleRecipeCatalystsVisible() && !skipCatalyst) {
|
||||
return handler.getUsageAndCatalystHandler(inputId, ingredients);
|
||||
} else {
|
||||
return handler.getUsageHandler(inputId, ingredients);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<IUsageHandler> currenthandlers;
|
||||
|
||||
public static ArrayList<IUsageHandler> usagehandlers = new ArrayList<>();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
@@ -16,7 +17,7 @@ import org.apache.logging.log4j.Level;
|
||||
public class HandlerInfo {
|
||||
public static int DEFAULT_HEIGHT = 65;
|
||||
public static int DEFAULT_WIDTH = 166;
|
||||
public static int DEFAULT_MAX_PER_PAGE = 2;
|
||||
public static int DEFAULT_MAX_PER_PAGE = 1;
|
||||
|
||||
private String handlerName;
|
||||
|
||||
@@ -53,48 +54,10 @@ public class HandlerInfo {
|
||||
public boolean setItem(String itemId, String nbtString) {
|
||||
if(hasImageOrItem())
|
||||
return false;
|
||||
|
||||
int meta = -1;
|
||||
if (!itemId.contains(":")) {
|
||||
NEIClientConfig.logger.info("Item ID missing colon for handler " + handlerName + " - " + modName);
|
||||
return false;
|
||||
}
|
||||
final String[] split = itemId.split(":");
|
||||
// ModID:ItemID
|
||||
String itemLookupId = split[0] + ":" + split[1];
|
||||
|
||||
if(split.length >= 3) {
|
||||
int mIdx = -1;
|
||||
if (split[2].matches("\\d+")) {
|
||||
mIdx = 2;
|
||||
} else {
|
||||
itemLookupId += ":" + split[2];
|
||||
if (split.length >= 4) mIdx = 3;
|
||||
}
|
||||
if (mIdx != -1) meta = Integer.parseInt(split[mIdx]);
|
||||
}
|
||||
|
||||
if (meta != -1) {
|
||||
itemStack = GameRegistry.makeItemStack(itemLookupId, meta, 1, nbtString == null ? "" : nbtString);
|
||||
} else {
|
||||
itemStack = GameRegistry.findItemStack(split[0], split[1], 1);
|
||||
if (nbtString != null && !nbtString.equals("")) {
|
||||
try {
|
||||
final NBTBase nbttag = JsonToNBT.func_150315_a(nbtString);
|
||||
if (!(nbttag instanceof NBTTagCompound)) {
|
||||
NEIClientConfig.logger.info("Unexpected NBT string - multiple values {}", nbtString);
|
||||
return false;
|
||||
}
|
||||
|
||||
itemStack.setTagCompound((NBTTagCompound) nbttag);
|
||||
} catch (NBTException e) {
|
||||
FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
itemStack = NEIServerUtils.getModdedItem(itemId, nbtString);
|
||||
if (itemStack == null)
|
||||
NEIClientConfig.logger.info("Couldn't find " + modName + " - " + itemLookupId);
|
||||
NEIClientConfig.logger.info("Couldn't find " + modName + " - " + itemId);
|
||||
else {
|
||||
this.itemId = itemId;
|
||||
this.nbtString = nbtString;
|
||||
|
||||
@@ -29,46 +29,55 @@ public interface IRecipeHandler
|
||||
* @return The name of this inventory.
|
||||
* To be displayed at the top of the viewing container.
|
||||
*/
|
||||
public String getRecipeName();
|
||||
String getRecipeName();
|
||||
|
||||
/**
|
||||
* For legacy compatibility reasons, this method's default implementation returns the recipe name. This is also the expected behavior
|
||||
*
|
||||
* @return The name of this inventory.
|
||||
* To be displayed in the tooltip in the tab at the top of the viewing container.
|
||||
*/
|
||||
default String getRecipeTabName() {
|
||||
return getRecipeName();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The number of recipes that this handler contains.
|
||||
*/
|
||||
public int numRecipes();
|
||||
int numRecipes();
|
||||
/**
|
||||
* Draw the background of this recipe handler (basically the slot layout image).
|
||||
* @param gui A GuiManager for drawing functions.
|
||||
* @param recipe The recipe index to draw at this position.
|
||||
*/
|
||||
public void drawBackground(int recipe);
|
||||
void drawBackground(int recipe);
|
||||
/**
|
||||
* Draw the foreground of this recipe handler (for things like progress bars).
|
||||
* @param gui A GuiManager for drawing functions.
|
||||
* @param recipe The recipe index to draw at this position.
|
||||
*/
|
||||
public void drawForeground(int recipe);
|
||||
void drawForeground(int recipe);
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to get items for.
|
||||
* @return A list of the ingredient {@link PositionedStack}s in this recipe relative to the top left corner of your recipe drawing space.
|
||||
*/
|
||||
public List<PositionedStack> getIngredientStacks(int recipe);
|
||||
List<PositionedStack> getIngredientStacks(int recipe);
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to get items for.
|
||||
* @param recipetype The recipe index to get items for.
|
||||
* @return A list of the other {@link PositionedStack}s in this recipe relative to the top left corner of your recipe drawing space. For example fuel in furnaces.
|
||||
*/
|
||||
public List<PositionedStack> getOtherStacks(int recipetype);
|
||||
List<PositionedStack> getOtherStacks(int recipetype);
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to get the result for.
|
||||
* @return The recipe result {@link PositionedStack} relative to the top left corner of your recipe drawing space.
|
||||
*/
|
||||
public PositionedStack getResultStack(int recipe);
|
||||
PositionedStack getResultStack(int recipe);
|
||||
/**
|
||||
* A tick function called for updating progress bars and cycling damage items.
|
||||
*/
|
||||
public void onUpdate();
|
||||
void onUpdate();
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to check for.
|
||||
@@ -76,24 +85,33 @@ public interface IRecipeHandler
|
||||
* @param container The container of the GUI.
|
||||
* @return true if this recipe can render an overlay for the specified type of inventory GUI.
|
||||
*/
|
||||
public boolean hasOverlay(GuiContainer gui, Container container, int recipe);
|
||||
boolean hasOverlay(GuiContainer gui, Container container, int recipe);
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to get the overlay renderer for.
|
||||
* @return An instance of {@link IRecipeOverlayRenderer} to be used for rendering the overlay of this specific recipe.
|
||||
*/
|
||||
public IRecipeOverlayRenderer getOverlayRenderer(GuiContainer gui, int recipe);
|
||||
IRecipeOverlayRenderer getOverlayRenderer(GuiContainer gui, int recipe);
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to get the overlay renderer for.
|
||||
* @return An instance of {@link IOverlayHandler} to be used for rendering the overlay of this specific recipe.
|
||||
*/
|
||||
public IOverlayHandler getOverlayHandler(GuiContainer gui, int recipe);
|
||||
IOverlayHandler getOverlayHandler(GuiContainer gui, int recipe);
|
||||
/**
|
||||
* Simply works with the {@link codechicken.nei.api.DefaultOverlayRenderer}
|
||||
* If the current container has been registered with this identifier, the question mark appears and an overlay guide can be drawn.
|
||||
*
|
||||
* @return The overlay identifier of this recipe type.
|
||||
*/
|
||||
default String getOverlayIdentifier() {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return The number of recipes that can fit on a page in the viewer (1 or 2)
|
||||
*/
|
||||
public int recipiesPerPage();
|
||||
int recipiesPerPage();
|
||||
/**
|
||||
*
|
||||
* @param gui An instance of the currentscreen
|
||||
@@ -101,16 +119,16 @@ public interface IRecipeHandler
|
||||
* @param recipe The recipe index being handled
|
||||
* @return The modified tooltip. DO NOT return null
|
||||
*/
|
||||
public List<String> handleTooltip(GuiRecipe gui, List<String> currenttip, int recipe);
|
||||
List<String> handleTooltip(GuiRecipe gui, List<String> currenttip, int recipe);
|
||||
/**
|
||||
*
|
||||
* @param gui An instance of the currentscreen
|
||||
* @param The itemstack currently under the mouse
|
||||
* @param The current tooltip, will contain item name and info
|
||||
* @param stack The itemstack currently under the mouse
|
||||
* @param currenttip The current tooltip, will contain item name and info
|
||||
* @param recipe The recipe index being handled
|
||||
* @return The modified tooltip. DO NOT return null
|
||||
*/
|
||||
public List<String> handleItemTooltip(GuiRecipe gui, ItemStack stack, List<String> currenttip, int recipe);
|
||||
List<String> handleItemTooltip(GuiRecipe gui, ItemStack stack, List<String> currenttip, int recipe);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -119,7 +137,7 @@ public interface IRecipeHandler
|
||||
* @param keyCode The KeyCode as defined in {@link Keyboard}
|
||||
* @return true to terminate further processing of this event.
|
||||
*/
|
||||
public boolean keyTyped(GuiRecipe gui, char keyChar, int keyCode, int recipe);
|
||||
boolean keyTyped(GuiRecipe gui, char keyChar, int keyCode, int recipe);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -127,7 +145,7 @@ public interface IRecipeHandler
|
||||
* @param button The button index being pressed, {0 = Left Click, 1 = Right Click, 2 = Middle Click}
|
||||
* @return true to terminate further processing of this event.
|
||||
*/
|
||||
public boolean mouseClicked(GuiRecipe gui, int button, int recipe);
|
||||
boolean mouseClicked(GuiRecipe gui, int button, int recipe);
|
||||
|
||||
/**
|
||||
* For legacy compatibility reasons, this method has a do-nothing default implementation.
|
||||
|
||||
@@ -15,5 +15,12 @@ public interface IUsageHandler extends IRecipeHandler
|
||||
* @param ingredients Objects representing the ingredients that matching recipes must contain.
|
||||
* @return An instance of {@link IUsageHandler} configured with a list of recipes that contain matching input
|
||||
*/
|
||||
public IUsageHandler getUsageHandler(String inputId, Object... ingredients);
|
||||
IUsageHandler getUsageHandler(String inputId, Object... ingredients);
|
||||
|
||||
/**
|
||||
* See {@link TemplateRecipeHandler#getUsageAndCatalystHandler} for implementation
|
||||
*/
|
||||
default IUsageHandler getUsageAndCatalystHandler(String inputId, Object... ingredients) {
|
||||
return getUsageHandler(inputId, ingredients);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import com.google.common.base.Objects;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RecipeCatalysts {
|
||||
private static final Map<String, CatalystInfoList> catalystsAdderFromAPI = new HashMap<>();
|
||||
private static final Map<String, List<ItemStack>> catalystsRemoverFromAPI = new HashMap<>();
|
||||
public static final Map<String, CatalystInfoList> catalystsAdderFromIMC = new HashMap<>();
|
||||
public static final Map<String, List<ItemStack>> catalystsRemoverFromIMC = new HashMap<>();
|
||||
private static final Map<String, CatalystInfoList> recipeCatalystMap = new HashMap<>();
|
||||
private static Map<String, List<PositionedStack>> positionedRecipeCatalystMap = new HashMap<>();
|
||||
private static final List<String> forceClassNameList = new ArrayList<>();
|
||||
private static int heightCache;
|
||||
|
||||
public static void addRecipeCatalyst(String handlerID, CatalystInfo catalystInfo) {
|
||||
if (handlerID == null || handlerID.isEmpty() || catalystInfo.getStack() == null) return;
|
||||
addOrPut(catalystsAdderFromAPI, handlerID, catalystInfo);
|
||||
}
|
||||
|
||||
public static void removeRecipeCatalyst(String handlerID, ItemStack stack) {
|
||||
if (handlerID == null || handlerID.isEmpty() || stack == null) return;
|
||||
if (catalystsRemoverFromAPI.containsKey(handlerID)) {
|
||||
catalystsRemoverFromAPI.get(handlerID).add(stack);
|
||||
} else {
|
||||
catalystsRemoverFromAPI.put(handlerID, new ArrayList<>(Collections.singletonList(stack)));
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, List<PositionedStack>> getPositionedRecipeCatalystMap() {
|
||||
return positionedRecipeCatalystMap;
|
||||
}
|
||||
|
||||
public static List<PositionedStack> getRecipeCatalysts(IRecipeHandler handler) {
|
||||
return getRecipeCatalysts(getRecipeID(handler));
|
||||
}
|
||||
|
||||
public static List<PositionedStack> getRecipeCatalysts(String handlerID) {
|
||||
if (!NEIClientConfig.areJEIStyleTabsVisible() || !NEIClientConfig.areJEIStyleRecipeCatalystsVisible()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return positionedRecipeCatalystMap.getOrDefault(handlerID, Collections.emptyList());
|
||||
}
|
||||
|
||||
public static boolean containsCatalyst(IRecipeHandler handler, ItemStack candidate) {
|
||||
return containsCatalyst(getRecipeID(handler), candidate);
|
||||
}
|
||||
|
||||
public static boolean containsCatalyst(String handlerID, ItemStack candidate) {
|
||||
if (recipeCatalystMap.containsKey(handlerID)) {
|
||||
return recipeCatalystMap.get(handlerID).contains(candidate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void updatePosition(int availableHeight, boolean force) {
|
||||
if (availableHeight == heightCache && !force) return;
|
||||
|
||||
Map<String, List<PositionedStack>> newMap = new HashMap<>();
|
||||
for (Map.Entry<String, CatalystInfoList> entry : recipeCatalystMap.entrySet()) {
|
||||
CatalystInfoList catalysts = entry.getValue();
|
||||
catalysts.sort();
|
||||
List<PositionedStack> newStacks = new ArrayList<>();
|
||||
int rowCount = getRowCount(availableHeight, catalysts.size());
|
||||
|
||||
for (int index = 0; index < catalysts.size(); index++) {
|
||||
ItemStack catalyst = catalysts.get(index).getStack();
|
||||
int column = index / rowCount;
|
||||
int row = index % rowCount;
|
||||
newStacks.add(new PositionedStack(catalyst, -column * GuiRecipeCatalyst.ingredientSize, row * GuiRecipeCatalyst.ingredientSize));
|
||||
}
|
||||
newMap.put(entry.getKey(), newStacks);
|
||||
}
|
||||
positionedRecipeCatalystMap = newMap;
|
||||
heightCache = availableHeight;
|
||||
}
|
||||
|
||||
public static void updatePosition(int availableHeight) {
|
||||
updatePosition(availableHeight, false);
|
||||
}
|
||||
|
||||
public static int getHeight() {
|
||||
return heightCache;
|
||||
}
|
||||
|
||||
public static int getColumnCount(int availableHeight, int catalystsSize) {
|
||||
int maxItemsPerColumn = availableHeight / GuiRecipeCatalyst.ingredientSize;
|
||||
return NEIServerUtils.divideCeil(catalystsSize, maxItemsPerColumn);
|
||||
}
|
||||
|
||||
public static int getRowCount(int availableHeight, int catalystsSize) {
|
||||
int columnCount = getColumnCount(availableHeight, catalystsSize);
|
||||
return NEIServerUtils.divideCeil(catalystsSize, columnCount);
|
||||
}
|
||||
|
||||
public static void loadCatalystInfo() {
|
||||
final boolean fromJar = NEIClientConfig.loadCatalystsFromJar();
|
||||
NEIClientConfig.logger.info("Loading catalyst info from " + (fromJar ? "JAR" : "Config"));
|
||||
recipeCatalystMap.clear();
|
||||
URL handlerUrl = Thread.currentThread().getContextClassLoader().getResource("assets/nei/csv/catalysts.csv");
|
||||
|
||||
URL url;
|
||||
if (fromJar) {
|
||||
url = handlerUrl;
|
||||
if (url == null) {
|
||||
NEIClientConfig.logger.warn("Invalid URL for catalysts csv.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
File catalystFile = NEIClientConfig.catalystFile;
|
||||
if(!catalystFile.exists()) {
|
||||
NEIClientConfig.logger.info("Config file doesn't exist, creating");
|
||||
try {
|
||||
assert handlerUrl != null;
|
||||
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(catalystFile.getAbsoluteFile());
|
||||
FileChannel fileChannel = fileOutputStream.getChannel();
|
||||
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
url = NEIClientConfig.catalystFile.toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
NEIClientConfig.logger.warn("Invalid URL for catalysts csv (via config).");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||
CSVParser csvParser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(reader);
|
||||
for (CSVRecord record : csvParser) {
|
||||
final String handler = record.get("handler");
|
||||
final String modId = record.get("modId");
|
||||
final boolean requiresMod = Boolean.parseBoolean(record.get("modRequired"));
|
||||
final String excludedModId = record.get("excludedModId");
|
||||
final int priority = intOrDefault(record.get("priority"), 0);
|
||||
// todo
|
||||
final String minVersion = record.get("minVersion");
|
||||
final String maxVersion = record.get("maxVersion");
|
||||
//
|
||||
final boolean forceClassName = Boolean.parseBoolean(record.get("forceClassName"));
|
||||
|
||||
if (requiresMod && !Loader.isModLoaded(modId)) continue;
|
||||
if (excludedModId != null && Loader.isModLoaded(excludedModId)) continue;
|
||||
|
||||
String itemName = record.get("itemName");
|
||||
if (itemName == null || itemName.isEmpty()) continue;
|
||||
ItemStack stack = NEIServerUtils.getModdedItem(itemName, record.get("nbtInfo"));
|
||||
if (stack == null) {
|
||||
NEIClientConfig.logger.warn("Couldn't find ItemStack " + itemName);
|
||||
continue;
|
||||
}
|
||||
CatalystInfo catalystInfo = new CatalystInfo(stack, priority);
|
||||
|
||||
String handlerID;
|
||||
try {
|
||||
// gently handling copy&paste from handlers.csv
|
||||
Class<?> clazz = Class.forName(handler);
|
||||
Object object = clazz.newInstance();
|
||||
if (object instanceof IRecipeHandler) {
|
||||
if (forceClassName) {
|
||||
forceClassNameList.add(handler);
|
||||
}
|
||||
handlerID = getRecipeID((IRecipeHandler) object);
|
||||
} else {
|
||||
handlerID = handler;
|
||||
}
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
handlerID = handler;
|
||||
} catch (InstantiationException ignored) {
|
||||
NEIClientConfig.logger.warn("failed to create instance for " + handler);
|
||||
handlerID = handler;
|
||||
}
|
||||
|
||||
addOrPut(recipeCatalystMap, handlerID, catalystInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.warn("Error parsing CSV");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (Map.Entry<String, CatalystInfoList> entry : catalystsAdderFromAPI.entrySet()) {
|
||||
String handlerID = entry.getKey();
|
||||
for (CatalystInfo catalyst : entry.getValue()) {
|
||||
addOrPut(recipeCatalystMap, handlerID, catalyst);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, CatalystInfoList> entry : catalystsAdderFromIMC.entrySet()) {
|
||||
String handlerID = entry.getKey();
|
||||
for (CatalystInfo catalyst : entry.getValue()) {
|
||||
addOrPut(recipeCatalystMap, handlerID, catalyst);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<ItemStack>> entry : catalystsRemoverFromAPI.entrySet()) {
|
||||
String handlerID = entry.getKey();
|
||||
if (recipeCatalystMap.containsKey(handlerID)) {
|
||||
CatalystInfoList catalysts = recipeCatalystMap.get(handlerID);
|
||||
entry.getValue().forEach(catalysts::remove);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, List<ItemStack>> entry : catalystsRemoverFromIMC.entrySet()) {
|
||||
String handlerID = entry.getKey();
|
||||
if (recipeCatalystMap.containsKey(handlerID)) {
|
||||
CatalystInfoList catalysts = recipeCatalystMap.get(handlerID);
|
||||
entry.getValue().forEach(catalysts::remove);
|
||||
}
|
||||
}
|
||||
|
||||
updatePosition(getHeight(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically {@link NEIClientConfig#HANDLER_ID_FUNCTION}.
|
||||
* Force using {@link IRecipeHandler#getHandlerId()} if specified in catalysts.csv.
|
||||
* In other words, refuse to share handlerID defined in {@link TemplateRecipeHandler#getOverlayIdentifier()}.
|
||||
*/
|
||||
public static String getRecipeID(IRecipeHandler handler) {
|
||||
if (forceClassNameList.stream().anyMatch(s -> s.equals(handler.getHandlerId()))) {
|
||||
return handler.getHandlerId();
|
||||
}
|
||||
return Objects.firstNonNull(
|
||||
handler.getOverlayIdentifier(),
|
||||
handler.getHandlerId());
|
||||
}
|
||||
|
||||
public static void addOrPut(Map<String, CatalystInfoList> map, String handlerID, CatalystInfo catalyst) {
|
||||
if (map.containsKey(handlerID)) {
|
||||
map.get(handlerID).add(catalyst);
|
||||
} else {
|
||||
map.put(handlerID, new CatalystInfoList(handlerID, catalyst));
|
||||
}
|
||||
}
|
||||
|
||||
private static int intOrDefault(String str, int defaultValue) {
|
||||
if (str == null || str.equals("")) return defaultValue;
|
||||
try {
|
||||
return Integer.parseInt(str);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addRecipeCatalyst(List<ItemStack> stacks, Class<? extends IRecipeHandler> handler) {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static List<PositionedStack> getRecipeCatalysts(Class<? extends IRecipeHandler> handler) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean containsCatalyst(Class<? extends IRecipeHandler> handler, ItemStack candidate) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -120,4 +120,5 @@ public class RecipeInfo
|
||||
API.registerRecipeHandler(new ProfilerRecipeHandler(true));
|
||||
API.registerUsageHandler(new ProfilerRecipeHandler(false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +1,106 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class RecipeItemInputHandler implements IContainerInputHandler
|
||||
{
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode)
|
||||
{
|
||||
ItemStack stackover = GuiContainerManager.getStackMouseOver(gui);
|
||||
if(stackover == null)
|
||||
return false;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
if(keyCode == NEIClientConfig.getKeyBinding("gui.recipe"))
|
||||
public class RecipeItemInputHandler implements IContainerInputHandler {
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
ItemStack stackover = GuiContainerManager.getStackMouseOver(gui);
|
||||
if (stackover == null) return false;
|
||||
|
||||
if (keyCode == NEIClientConfig.getKeyBinding("gui.recipe"))
|
||||
return GuiCraftingRecipe.openRecipeGui("item", stackover.copy());
|
||||
|
||||
if(keyCode == NEIClientConfig.getKeyBinding("gui.usage"))
|
||||
if (keyCode == NEIClientConfig.getKeyBinding("gui.usage"))
|
||||
return GuiUsageRecipe.openRecipeGui("item", stackover.copy());
|
||||
|
||||
if(keyCode == NEIClientConfig.getKeyBinding("gui.bookmark")) {
|
||||
if (keyCode == NEIClientConfig.getKeyBinding("gui.bookmark")) {
|
||||
NEIClientConfig.logger.debug("Adding or removing {} from bookmarks", stackover.getDisplayName());
|
||||
ItemPanels.bookmarkPanel.addOrRemoveItem(stackover.copy());
|
||||
List<PositionedStack> ingredients = null;
|
||||
String handlerName = "";
|
||||
|
||||
if (gui instanceof GuiRecipe && NEIClientConfig.saveCurrentRecipeInBookmarksEnabled()) {
|
||||
ingredients = ((GuiRecipe) gui).getFocusedRecipeIngredients();
|
||||
handlerName = ((GuiRecipe) gui).getHandlerName();
|
||||
}
|
||||
|
||||
ItemPanels.bookmarkPanel.addOrRemoveItem(stackover.copy(), handlerName, ingredients);
|
||||
}
|
||||
|
||||
if (keyCode == NEIClientConfig.getKeyBinding("gui.overlay")) {
|
||||
if (NEIClientUtils.controlKey()) {
|
||||
LayoutManager.overlayRenderer = null;
|
||||
return true;
|
||||
}
|
||||
if (!NEIClientConfig.saveCurrentRecipeInBookmarksEnabled()) return false;
|
||||
final BookmarkRecipeId mouseOverRecipeId = ItemPanels.bookmarkPanel.getBookmarkMouseOverRecipeId();
|
||||
if (mouseOverRecipeId == null || mouseOverRecipeId.ingredients == null || mouseOverRecipeId.ingredients.isEmpty())
|
||||
return false;
|
||||
return GuiCraftingRecipe.openRecipeGui("item", true, stackover.copy());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button)
|
||||
{
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
ItemStack stackover = GuiContainerManager.getStackMouseOver(gui);
|
||||
|
||||
if(stackover == null)
|
||||
if (stackover == null) return false;
|
||||
|
||||
if (!(gui instanceof GuiRecipe)) return false;
|
||||
|
||||
//disabled open recipe gui if hold shift (player have move recipe)
|
||||
if (button == 0 && ItemPanels.bookmarkPanel.getStackMouseOver(mousex, mousey) != null && NEIClientUtils.shiftKey()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(gui instanceof GuiRecipe))
|
||||
return false;
|
||||
if (button == 0) return GuiCraftingRecipe.openRecipeGui("item", stackover.copy());
|
||||
|
||||
if(button == 0)
|
||||
return GuiCraftingRecipe.openRecipeGui("item", stackover.copy());
|
||||
if (button == 1) return GuiUsageRecipe.openRecipeGui("item", stackover.copy());
|
||||
|
||||
if(button == 1)
|
||||
return GuiUsageRecipe.openRecipeGui("item", stackover.copy());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID)
|
||||
{
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button)
|
||||
{
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button)
|
||||
{
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyID)
|
||||
{
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled)
|
||||
{
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled)
|
||||
{
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime)
|
||||
{
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import static codechicken.nei.LayoutManager.searchField;
|
||||
|
||||
public class SearchInputDropHandler extends INEIGuiAdapter
|
||||
{
|
||||
|
||||
protected static final Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");
|
||||
|
||||
@Override
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, ItemStack draggedStack, int button)
|
||||
{
|
||||
|
||||
if (searchField.contains(mouseX, mouseY)) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(draggedStack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
searchField.setText(formattingText(fluidStack.getLocalizedName()));
|
||||
} else {
|
||||
searchField.setText(formattingText(draggedStack.getDisplayName()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String formattingText(String displayName)
|
||||
{
|
||||
return SPECIAL_REGEX_CHARS.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(displayName)).replaceAll("\\\\$0");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler;
|
||||
import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class StackInfo
|
||||
{
|
||||
|
||||
|
||||
public static final ArrayList<IStackStringifyHandler> stackStringifyHandlers = new ArrayList<>();
|
||||
private static final HashMap<String, HashMap<String, String[]>> guidfilters = new HashMap<>();
|
||||
private static final WeakHashMap<ItemStack, String> guidcache = new WeakHashMap<>();
|
||||
|
||||
static {
|
||||
stackStringifyHandlers.add(new DefaultStackStringifyHandler());
|
||||
stackStringifyHandlers.add(new GTFluidStackStringifyHandler());
|
||||
}
|
||||
|
||||
public static NBTTagCompound itemStackToNBT(ItemStack stack)
|
||||
{
|
||||
return itemStackToNBT(stack, true);
|
||||
}
|
||||
|
||||
public static NBTTagCompound itemStackToNBT(ItemStack stack, boolean saveStackSize)
|
||||
{
|
||||
NBTTagCompound nbTag = null;
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && nbTag == null; i--) {
|
||||
nbTag = stackStringifyHandlers.get(i).convertItemStackToNBT(stack, saveStackSize);
|
||||
}
|
||||
|
||||
return nbTag;
|
||||
}
|
||||
|
||||
public static ItemStack loadFromNBT(NBTTagCompound nbtTag)
|
||||
{
|
||||
ItemStack stack = null;
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && nbtTag != null && stack == null; i--) {
|
||||
stack = stackStringifyHandlers.get(i).convertNBTToItemStack(nbtTag);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static boolean equalItemAndNBT(ItemStack stackA, ItemStack stackB, boolean useNBT)
|
||||
{
|
||||
if (!stackA.isItemEqual(stackB)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (useNBT) {
|
||||
NBTTagCompound tagCompoundA = itemStackToNBT(stackA, false);
|
||||
NBTTagCompound tagCompoundB = itemStackToNBT(stackB, false);
|
||||
|
||||
return tagCompoundA == null && tagCompoundB == null || tagCompoundA != null && tagCompoundB != null && tagCompoundA.equals(tagCompoundB);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static FluidStack getFluid(ItemStack stack)
|
||||
{
|
||||
FluidStack fluid = null;
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && fluid == null; i--) {
|
||||
fluid = stackStringifyHandlers.get(i).getFluid(stack);
|
||||
}
|
||||
|
||||
return fluid;
|
||||
}
|
||||
|
||||
public static String getItemStackGUID(ItemStack stack)
|
||||
{
|
||||
if (!guidcache.containsKey(stack)) {
|
||||
|
||||
final NBTTagCompound nbTag = itemStackToNBT(stack, false);
|
||||
|
||||
if (nbTag == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
nbTag.removeTag("Count");
|
||||
|
||||
if (nbTag.getShort("Damage") == 0) {
|
||||
nbTag.removeTag("Damage");
|
||||
}
|
||||
|
||||
if (nbTag.hasKey("tag") && nbTag.getCompoundTag("tag").hasNoTags()) {
|
||||
nbTag.removeTag("tag");
|
||||
}
|
||||
|
||||
if (nbTag.hasKey("strId") && guidfilters.containsKey(nbTag.getString("strId"))) {
|
||||
final ArrayList<String> keys = new ArrayList<>();
|
||||
final String strId = nbTag.getString("strId");
|
||||
|
||||
keys.add(strId);
|
||||
|
||||
guidfilters.get(strId).forEach((key, rule) -> {
|
||||
Object local = nbTag;
|
||||
|
||||
for (int i = 0; i < rule.length; i++) {
|
||||
|
||||
try {
|
||||
|
||||
if (local instanceof NBTTagCompound) {
|
||||
local = ((NBTTagCompound) local).getTag(rule[i]);
|
||||
} else if (local instanceof NBTTagList) {
|
||||
local = ((NBTTagList) local).tagList.get(Integer.parseInt(rule[i]));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (local instanceof NBTBase) {
|
||||
keys.add(((NBTBase)local).toString());
|
||||
} else if (local != null) {
|
||||
keys.add(String.valueOf(local));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, keys.toString());
|
||||
}
|
||||
} else {
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, nbTag.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return guidcache.get(stack);
|
||||
}
|
||||
|
||||
public static void loadGuidFilters()
|
||||
{
|
||||
|
||||
guidfilters.clear();
|
||||
|
||||
final File guidFlitersFile = new File(NEIClientConfig.configDir, "guidfilters.cfg");
|
||||
List<String> itemStrings = new ArrayList<>();
|
||||
|
||||
if (guidFlitersFile.exists()) {
|
||||
|
||||
try (FileReader reader = new FileReader(guidFlitersFile)) {
|
||||
NEIClientConfig.logger.info("Loading guid filters from file {}", guidFlitersFile);
|
||||
itemStrings = IOUtils.readLines(reader);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load bookmarks from file {}", guidFlitersFile, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else {
|
||||
final URL filterUrl = Thread.currentThread().getContextClassLoader().getResource("assets/nei/guidfilters.cfg");
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(filterUrl.openStream()))) {
|
||||
itemStrings = IOUtils.readLines(reader);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.info("Error parsing guid filters");
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.info("Error parsing guid filters");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (String guidStr: itemStrings) {
|
||||
final String[] parts = guidStr.split(",");
|
||||
final HashMap<String, String[]> rules = new HashMap<>();
|
||||
|
||||
for (int j = 1; j < parts.length; j++) {
|
||||
rules.put(parts[j], parts[j].split("\\."));
|
||||
}
|
||||
|
||||
guidfilters.put(parts[0], rules);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -219,6 +219,17 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* NBT-friendly version of {@link #contains(Collection, ItemStack)}
|
||||
*/
|
||||
public boolean containsWithNBT(Collection<PositionedStack> ingredients, ItemStack ingredient) {
|
||||
for (PositionedStack stack : ingredients)
|
||||
if (stack.containsWithNBT(ingredient))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ingred
|
||||
* @return true if any of the permutations of any of the ingredients contain this stack
|
||||
@@ -442,6 +453,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
*
|
||||
* @return The overlay identifier of this recipe type.
|
||||
*/
|
||||
@Override
|
||||
public String getOverlayIdentifier() {
|
||||
return null;
|
||||
}
|
||||
@@ -550,6 +562,36 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* First look up {@link RecipeCatalysts} whether target ingredient is registered for it.
|
||||
* If so, load all recipes for this handler.
|
||||
* Fallback to {@link TemplateRecipeHandler#getUsageHandler}.
|
||||
*/
|
||||
public IUsageHandler getUsageAndCatalystHandler(String inputId, Object... ingredients) {
|
||||
TemplateRecipeHandler handler = newInstance();
|
||||
if (inputId.equals("item")) {
|
||||
ItemStack candidate = (ItemStack) ingredients[0];
|
||||
if (RecipeCatalysts.containsCatalyst(handler, candidate)) {
|
||||
for (RecipeTransferRect rect : transferRects) {
|
||||
if (specifyTransferRect() == null || Objects.equals(rect.outputId, specifyTransferRect())) {
|
||||
handler.loadCraftingRecipes(rect.outputId, rect.results);
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
NEIClientConfig.logger.info("failed to load catalyst handler, implement `loadTransferRects` for your handler " + handler.getClass().getName());
|
||||
}
|
||||
}
|
||||
return this.getUsageHandler(inputId, ingredients);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this if you have multiple {@link RecipeTransferRect}s.
|
||||
* Used for {@link TemplateRecipeHandler#getUsageAndCatalystHandler}.
|
||||
*/
|
||||
public String specifyTransferRect() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int numRecipes() {
|
||||
return arecipes.size();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package codechicken.nei.recipe.stackinfo;
|
||||
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.FluidContainerRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
public class DefaultStackStringifyHandler implements IStackStringifyHandler
|
||||
{
|
||||
|
||||
public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize)
|
||||
{
|
||||
final String strId = Item.itemRegistry.getNameForObject(stack.getItem());
|
||||
|
||||
if (strId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final NBTTagCompound nbTag = new NBTTagCompound();
|
||||
nbTag.setString("strId", strId);
|
||||
nbTag.setInteger("Count", Math.max(saveStackSize? stack.stackSize: 1, 1));
|
||||
nbTag.setShort("Damage", (short)stack.getItemDamage());
|
||||
|
||||
if (stack.hasTagCompound()) {
|
||||
nbTag.setTag("tag", stack.getTagCompound());
|
||||
}
|
||||
|
||||
return nbTag;
|
||||
}
|
||||
|
||||
public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag)
|
||||
{
|
||||
final String strId = nbtTag.getString("strId");
|
||||
|
||||
nbtTag = (NBTTagCompound)nbtTag.copy();
|
||||
nbtTag.setInteger("id", GameData.getItemRegistry().getId(strId)); //getObject
|
||||
|
||||
final ItemStack stack = ItemStack.loadItemStackFromNBT(nbtTag);
|
||||
|
||||
if (stack != null) {
|
||||
stack.stackSize = nbtTag.getInteger("Count");
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
public FluidStack getFluid(ItemStack stack)
|
||||
{
|
||||
FluidStack fluidStack = FluidContainerRegistry.getFluidForFilledItem(stack);
|
||||
|
||||
if (fluidStack == null && stack.getItem() instanceof IFluidContainerItem) {
|
||||
fluidStack = ((IFluidContainerItem) stack.getItem()).getFluid(stack);
|
||||
}
|
||||
|
||||
return fluidStack;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package codechicken.nei.recipe.stackinfo;
|
||||
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class GTFluidStackStringifyHandler implements IStackStringifyHandler
|
||||
{
|
||||
|
||||
public static Class GTDisplayFluid = null;
|
||||
public static Method getFluidDisplayStack = null;
|
||||
public static Method getFluidFromDisplayStack = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
final Class gtUtility = Class.forName("gregtech.api.util.GT_Utility");
|
||||
|
||||
GTDisplayFluid = Class.forName("gregtech.common.items.GT_FluidDisplayItem");
|
||||
getFluidFromDisplayStack = gtUtility.getMethod("getFluidFromDisplayStack", ItemStack.class);
|
||||
getFluidDisplayStack = gtUtility.getMethod("getFluidDisplayStack", FluidStack.class, boolean.class);
|
||||
|
||||
} catch (Exception ignored) { /*Do nothing*/ }
|
||||
}
|
||||
|
||||
public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize)
|
||||
{
|
||||
|
||||
if (GTDisplayFluid != null && GTDisplayFluid.isInstance(stack.getItem())) {
|
||||
final FluidStack fluidStack = getFluid(stack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
final NBTTagCompound nbTag = new NBTTagCompound();
|
||||
nbTag.setString("gtFluidName", fluidStack.getFluid().getName());
|
||||
nbTag.setInteger("Count", saveStackSize? fluidStack.amount: 1);
|
||||
return nbTag;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag)
|
||||
{
|
||||
|
||||
if (getFluidDisplayStack != null && nbtTag.hasKey("gtFluidName")) {
|
||||
final String fluidName = nbtTag.getString("gtFluidName");
|
||||
final Fluid fluid = FluidRegistry.getFluid(fluidName);
|
||||
final int amount = nbtTag.getInteger("Count");
|
||||
|
||||
try {
|
||||
final Object obj = getFluidDisplayStack.invoke(null, new FluidStack(fluid, amount), true);
|
||||
|
||||
if (obj != null) {
|
||||
return (ItemStack) obj;
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public FluidStack getFluid(ItemStack stack)
|
||||
{
|
||||
|
||||
if (getFluidFromDisplayStack != null && GTDisplayFluid != null && GTDisplayFluid.isInstance(stack.getItem())) {
|
||||
try {
|
||||
final Object obj = getFluidFromDisplayStack.invoke(null, stack);
|
||||
|
||||
if (obj != null) {
|
||||
return (FluidStack) obj;
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package codechicken.nei.util;
|
||||
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagEnd;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
|
||||
public class NBTHelper {
|
||||
|
||||
/*
|
||||
* Taken from Botania r1.11-379 by Vazkii under the Botania License
|
||||
* You can obtain one at https://botaniamod.net/license.php
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns true if the `target` tag contains all of the tags and values present in the `template` tag. Recurses into
|
||||
* compound tags and matches all template keys and values; recurses into list tags and matches the template against
|
||||
* the first elements of target. Empty lists and compounds in the template will match target lists and compounds of
|
||||
* any size.
|
||||
*/
|
||||
public static boolean matchTag(@Nullable NBTBase template, @Nullable NBTBase target) {
|
||||
if (template instanceof NBTTagCompound && target instanceof NBTTagCompound) {
|
||||
return matchTagCompound((NBTTagCompound) template, (NBTTagCompound) target);
|
||||
} else if (template instanceof NBTTagList && target instanceof NBTTagList) {
|
||||
return matchTagList((NBTTagList) template, (NBTTagList) target);
|
||||
} else {
|
||||
return template == null || (target != null && target.equals(template));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matchTagCompound(NBTTagCompound template, NBTTagCompound target) {
|
||||
if (template.tagMap.size() > target.tagMap.size()) return false;
|
||||
|
||||
//noinspection unchecked
|
||||
for (String key : (Set<String>) template.func_150296_c()) {
|
||||
if (!matchTag(template.getTag(key), target.getTag(key))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean matchTagList(NBTTagList template, NBTTagList target) {
|
||||
if (template.tagCount() > target.tagCount()) return false;
|
||||
|
||||
for (int i = 0; i < template.tagCount(); i++) {
|
||||
if (!matchTag(get(template, i), get(target, i))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static NBTBase get(NBTTagList tag, int idx)
|
||||
{
|
||||
return idx >= 0 && idx < tag.tagList.size() ? (NBTBase)tag.tagList.get(idx) : null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
package codechicken.nei.util;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagByte;
|
||||
@@ -20,22 +17,21 @@ import net.minecraft.nbt.NBTTagLong;
|
||||
import net.minecraft.nbt.NBTTagShort;
|
||||
import net.minecraft.nbt.NBTTagString;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class NBTJson {
|
||||
private static final Pattern numberPattern = Pattern.compile("^([-+]?[\\d]+\\.?[0-9]*)([bBsSlLfFdD]?)$");
|
||||
private static final JsonParser parser = new JsonParser();
|
||||
private static final Gson gson = new GsonBuilder().create();
|
||||
private static final Pattern numberPattern = Pattern.compile("^([-+]?\\d+\\.?\\d*E*\\d*)([bBsSlLfFdD]?)$");
|
||||
|
||||
public static String toJson(NBTTagCompound tag) {
|
||||
final String jsonString = toJsonObject(tag).toString();
|
||||
return gson.toJson(parser.parse(jsonString));
|
||||
return toJson(toJsonObject(tag));
|
||||
}
|
||||
|
||||
public static String toJson(JsonElement json) {
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -46,10 +42,30 @@ public class NBTJson {
|
||||
final Map<String, NBTBase> tagMap = (Map<String, NBTBase>)nbtTagCompound.tagMap;
|
||||
|
||||
JsonObject root = new JsonObject();
|
||||
for (Map.Entry<String, NBTBase> nbtEntry : tagMap.entrySet() ) {
|
||||
|
||||
for (Map.Entry<String, NBTBase> nbtEntry : tagMap.entrySet()) {
|
||||
root.add(nbtEntry.getKey(), toJsonObject(nbtEntry.getValue()));
|
||||
}
|
||||
|
||||
return root;
|
||||
} else if (nbt instanceof NBTTagByte) {
|
||||
// Number (byte)
|
||||
return new JsonPrimitive(Byte.toString(((NBTTagByte) nbt).func_150290_f()) + 'B');
|
||||
} else if (nbt instanceof NBTTagShort) {
|
||||
// Number (short)
|
||||
return new JsonPrimitive(Short.toString(((NBTTagShort) nbt).func_150289_e()) + 'S');
|
||||
} else if (nbt instanceof NBTTagInt) {
|
||||
// Number (int)
|
||||
return new JsonPrimitive(((NBTTagInt) nbt).func_150287_d());
|
||||
} else if (nbt instanceof NBTTagLong) {
|
||||
// Number (long)
|
||||
return new JsonPrimitive(Long.toString(((NBTTagLong) nbt).func_150291_c()) + 'L');
|
||||
} else if (nbt instanceof NBTTagFloat) {
|
||||
// Number (float)
|
||||
return new JsonPrimitive(Float.toString(((NBTTagFloat) nbt).func_150288_h()) + 'F');
|
||||
} else if (nbt instanceof NBTTagDouble) {
|
||||
// Number (double)
|
||||
return new JsonPrimitive(Double.toString(((NBTTagDouble) nbt).func_150286_g()) + 'D');
|
||||
} else if (nbt instanceof NBTBase.NBTPrimitive) {
|
||||
// Number
|
||||
return new JsonPrimitive(((NBTBase.NBTPrimitive) nbt).func_150286_g());
|
||||
@@ -58,23 +74,48 @@ public class NBTJson {
|
||||
return new JsonPrimitive(((NBTTagString) nbt).func_150285_a_());
|
||||
} else if (nbt instanceof NBTTagList) {
|
||||
// Tag List
|
||||
JsonArray arr = new JsonArray();
|
||||
((NBTTagList) nbt).tagList.forEach(c -> arr.add(toJsonObject((NBTBase) c)));
|
||||
return arr;
|
||||
final NBTTagList list = (NBTTagList) nbt;
|
||||
|
||||
if (list.tagList.isEmpty()) {
|
||||
return createEmptyList(list);
|
||||
} else {
|
||||
JsonArray arr = new JsonArray();
|
||||
list.tagList.forEach(c -> arr.add(toJsonObject((NBTBase) c)));
|
||||
return arr;
|
||||
}
|
||||
|
||||
} else if (nbt instanceof NBTTagIntArray) {
|
||||
// Int Array
|
||||
JsonArray arr = new JsonArray();
|
||||
for(int i : ((NBTTagIntArray) nbt).func_150302_c()) {
|
||||
arr.add(new JsonPrimitive(i));
|
||||
final NBTTagIntArray list = (NBTTagIntArray) nbt;
|
||||
|
||||
if (list.func_150302_c().length == 0) {
|
||||
return createEmptyList(list);
|
||||
} else {
|
||||
JsonArray arr = new JsonArray();
|
||||
|
||||
for (int i : list.func_150302_c()) {
|
||||
arr.add(new JsonPrimitive(i));
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
return arr;
|
||||
|
||||
} else if (nbt instanceof NBTTagByteArray) {
|
||||
// Byte Array
|
||||
JsonArray arr = new JsonArray();
|
||||
for(int i : ((NBTTagByteArray) nbt).func_150292_c()) {
|
||||
arr.add(new JsonPrimitive(i));
|
||||
final NBTTagByteArray list = (NBTTagByteArray) nbt;
|
||||
|
||||
if (list.func_150292_c().length == 0) {
|
||||
return createEmptyList(list);
|
||||
} else {
|
||||
JsonArray arr = new JsonArray();
|
||||
|
||||
for (byte i : list.func_150292_c()) {
|
||||
arr.add(new JsonPrimitive(Byte.toString(i) + 'B'));
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
return arr;
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported NBT Tag: " + NBTBase.NBTTypes[nbt.getId()] + " - " + nbt);
|
||||
}
|
||||
@@ -86,7 +127,7 @@ public class NBTJson {
|
||||
final JsonPrimitive jsonPrimitive = (JsonPrimitive) jsonElement;
|
||||
final String jsonString = jsonPrimitive.getAsString();
|
||||
final Matcher m = numberPattern.matcher(jsonString);
|
||||
if(m.find()) {
|
||||
if (m.find()) {
|
||||
// Number
|
||||
final String numberString = m.group(1);
|
||||
if (m.groupCount() == 2 && m.group(2).length() > 0) {
|
||||
@@ -130,7 +171,13 @@ public class NBTJson {
|
||||
if (nbtList.stream().allMatch(n -> n instanceof NBTTagInt)) {
|
||||
return new NBTTagIntArray(nbtList.stream().mapToInt(i -> ((NBTTagInt)i).func_150287_d() ).toArray());
|
||||
} else if (nbtList.stream().allMatch(n -> n instanceof NBTTagByte)) {
|
||||
return new NBTTagByteArray(toByteArray(nbtList.stream().mapToInt(i -> ((NBTTagInt)i).func_150287_d() )));
|
||||
final byte[] abyte = new byte[nbtList.size()];
|
||||
|
||||
for (int i = 0; i < nbtList.size(); i++) {
|
||||
abyte[i] = ((NBTTagByte) nbtList.get(i)).func_150290_f();
|
||||
}
|
||||
|
||||
return new NBTTagByteArray(abyte);
|
||||
} else {
|
||||
NBTTagList nbtTagList = new NBTTagList();
|
||||
nbtList.forEach(nbtTagList::appendTag);
|
||||
@@ -141,18 +188,43 @@ public class NBTJson {
|
||||
} else if (jsonElement instanceof JsonObject) {
|
||||
// NBTTagCompound
|
||||
final JsonObject jsonObject = (JsonObject) jsonElement;
|
||||
NBTTagCompound nbtTagCompound = new NBTTagCompound();
|
||||
for (Map.Entry<String, JsonElement> jsonEntry : jsonObject.entrySet()) {
|
||||
nbtTagCompound.setTag(jsonEntry.getKey(), toNbt(jsonEntry.getValue()));
|
||||
final NBTBase custom = restoreEmptyList(jsonObject);
|
||||
|
||||
if (custom == null) {
|
||||
NBTTagCompound nbtTagCompound = new NBTTagCompound();
|
||||
|
||||
for (Map.Entry<String, JsonElement> jsonEntry : jsonObject.entrySet()) {
|
||||
nbtTagCompound.setTag(jsonEntry.getKey(), toNbt(jsonEntry.getValue()));
|
||||
}
|
||||
|
||||
return nbtTagCompound;
|
||||
} else {
|
||||
return custom;
|
||||
}
|
||||
return nbtTagCompound;
|
||||
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unhandled element " + jsonElement);
|
||||
}
|
||||
public static byte[] toByteArray(IntStream stream) {
|
||||
return stream.collect(ByteArrayOutputStream::new, (baos, i) -> baos.write((byte) i), (baos1, baos2) -> baos1.write(baos2.toByteArray(), 0, baos2.size()))
|
||||
.toByteArray();
|
||||
|
||||
protected static JsonObject createEmptyList(Object obj)
|
||||
{
|
||||
JsonObject empty = new JsonObject();
|
||||
empty.add("__custom_type", new JsonPrimitive(obj.getClass().getName()));
|
||||
return empty;
|
||||
}
|
||||
|
||||
protected static NBTBase restoreEmptyList(JsonObject obj)
|
||||
{
|
||||
|
||||
if (obj.has("__custom_type")) {
|
||||
try {
|
||||
final String className = obj.get("__custom_type").getAsString();
|
||||
return (NBTBase)Class.forName(className).newInstance();
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException th) {}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -208,6 +208,7 @@ gtPlusPlus.nei.GT_NEI_FluidReactor,GT++,gregtech:gt.blockmachines:998,,miscutils
|
||||
gtPlusPlus.nei.GT_NEI_MillingMachine,GT++,gregtech:gt.blockmachines:31027,,miscutils,TRUE,,,120,,2,,,,,,
|
||||
li.cil.oc.integration.nei.CallbackDocHandler,OpenComputers,OpenComputers:item:98,,OpenComputers,TRUE,,,120,,2,,,,,,
|
||||
li.cil.oc.integration.nei.ManualUsageHandler,OpenComputers,OpenComputers:item:98,,OpenComputers,TRUE,,,120,,2,,,,,,
|
||||
com.pam.harvestcraft.GardenRecipeHandler,Pam's Harvestcraft,harvestcraft:berrygarden,,harvestcraft,TRUE,,,100,,5,,,,,,
|
||||
tonius.neiintegration.mods.harvestcraft.RecipeHandlerApiary,Pam's Harvestcraft,harvestcraft:apiary,,harvestcraft,TRUE,,,70,,5,,,,,,There's only 1 though
|
||||
tonius.neiintegration.mods.harvestcraft.RecipeHandlerChurn,Pam's Harvestcraft,harvestcraft:churn,,harvestcraft,TRUE,,,65,,5,,,,,,Same as above
|
||||
tonius.neiintegration.mods.harvestcraft.RecipeHandlerOven,Pam's Harvestcraft,harvestcraft:oven,,harvestcraft,TRUE,,,65,,5,,,,,,
|
||||
@@ -354,7 +355,7 @@ vazkii.botania.client.integration.nei.recipe.RecipeHandlerRunicAltar,Botania,Bot
|
||||
vazkii.botania.client.integration.nei.recipe.RecipeHandlerManaPool,Botania,Botania:pool,,Botania,TRUE,,,90,137,4,,,,,,
|
||||
vazkii.botania.client.integration.nei.recipe.RecipeHandlerElvenTrade,Botania,Botania:alfheimPortal,,Botania,TRUE,,,90,130,4,,,,,,
|
||||
vazkii.botania.client.integration.nei.recipe.RecipeHandlerBrewery,Botania,Botania:brewery,,Botania,TRUE,,,,,4,,,,,,
|
||||
vazkii.botania.client.integration.nei.recipe.RecipeHandlerPureDaisy,Botania,Botania:specialFlower,"{""type"": ""puredaisy""}",Botania,TRUE,,,,,4,,,,,,
|
||||
vazkii.botania.client.integration.nei.recipe.RecipeHandlerPureDaisy,Botania,Botania:specialFlower,"{type:puredaisy}",Botania,TRUE,,,,,4,,,,,,
|
||||
vazkii.botania.client.integration.nei.recipe.RecipeHandlerLexicaBotania,Botania,Botania:lexicon,,Botania,TRUE,,,,,,,,,,,
|
||||
com.jaquadro.minecraft.storagedrawers.integration.notenoughitems.UpgradeItemRecipeHandler,Storage Drawers,minecraft:crafting_table,,StorageDrawers,TRUE,,,65,166,5,,,,,,
|
||||
ieArcFurnace,Immersive Engineering,ImmersiveEngineering:graphiteElectrode,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
|
||||
@@ -410,6 +411,7 @@ mekanism.client.nei.ChemicalOxidizerRecipeHandler,Mekanism,Mekanism:MachineBlock
|
||||
mekanism.client.nei.ChemicalWasherRecipeHandler,Mekanism,Mekanism:MachineBlock2:7,,Mekanism,TRUE,,,70,,5,,,,,,
|
||||
mekanism.client.nei.CombinerRecipeHandler,Mekanism,Mekanism:MachineBlock:2,,Mekanism,TRUE,,,68,,5,,,,,,
|
||||
mekanism.client.nei.CrusherRecipeHandler,Mekanism,Mekanism:MachineBlock:3,,Mekanism,TRUE,,,68,,5,,,,,,
|
||||
mekanism.client.nei.EnrichmentChamberRecipeHandler,Mekanism,Mekanism:MachineBlock:0,,Mekanism,TRUE,,,68,,5,,,,,,
|
||||
mekanism.client.nei.MetallurgicInfuserRecipeHandler,Mekanism,Mekanism:MachineBlock:8,,Mekanism,TRUE,,,56,,5,,,,,,
|
||||
mekanism.client.nei.OsmiumCompressorRecipeHandler,Mekanism,Mekanism:MachineBlock:1,,Mekanism,TRUE,,,68,,5,,,,,,
|
||||
mekanism.client.nei.PRCRecipeHandler,Mekanism,Mekanism:MachineBlock2:10,,Mekanism,TRUE,,,68,,5,,,,,,
|
||||
@@ -422,26 +424,31 @@ mekanism.client.nei.SolarNeutronRecipeHandler,Mekanism,Mekanism:MachineBlock3:1,
|
||||
mekanism.client.nei.ThermalEvaporationRecipeHandler,Mekanism,Mekanism:BasicBlock:14,,Mekanism,TRUE,,,62,,5,,,,,,
|
||||
exnihilo.compatibility.nei.RecipeHandlerHammer,Ex Nihilo,exnihilo:hammer_iron,,exnihilo,TRUE,,,58,,5,,,,,,
|
||||
exnihilo.compatibility.nei.RecipeHandlerSieve,Ex Nihilo,exnihilo:sifting_table,,exnihilo,TRUE,,,130,,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.AlloySmelterRecipeHandler,GregTech-Addon,gregtech_addon:machine:56,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.AssemblerRecipeHandler,GregTech-Addon,gregtech_addon:machine:60,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.BenderRecipeHandler,GregTech-Addon,gregtech_addon:machine:59,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.BlastRecipeHandler,GregTech-Addon,gregtech_addon:machine:29,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.BronzeBlastRecipeHandler,GregTech-Addon,gregtech_addon:machine:136,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.CannerRecipeHandler,GregTech-Addon,gregtech_addon:machine:57,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.CentrifugeRecipeHandler,GregTech-Addon,gregtech_addon:machine:62,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.ChemicalRecipeHandler,GregTech-Addon,gregtech_addon:machine:41,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.CutterRecipeHandler,GregTech-Addon,gregtech_addon:machine:113,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.DistillationRecipeHandler,GregTech-Addon,gregtech_addon:machine:44,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.ElectrolyzerRecipeHandler,GregTech-Addon,gregtech_addon:machine:25,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.ExtruderRecipeHandler,GregTech-Addon,gregtech_addon:machine:115,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.FusionRecipeHandler,GregTech-Addon,gregtech_addon:machine:80,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.GeneratorHandler,GregTech-Addon,,,gregtech_addon,TRUE,,15,145,166,2,nei:textures/nei_tabbed_sprites.png,80,0,14,14,
|
||||
gregtechmod.mistaqur.nei.handlers.GrinderRecipeHandler,GregTech-Addon,gregtech_addon:machine:28,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.ImplosionRecipeHandler,GregTech-Addon,gregtech_addon:machine:31,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.LatheRecipeHandler,GregTech-Addon,gregtech_addon:machine:111,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.SawmillRecipeHandler,GregTech-Addon,gregtech_addon:machine:32,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.VacuumFreezerRecipeHandler,GregTech-Addon,gregtech_addon:machine:38,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtechmod.mistaqur.nei.handlers.WiremillRecipeHandler,GregTech-Addon,gregtech_addon:machine:55,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Alloy,GregTech-Addon,gregtech_addon:machine:56,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Assembler,GregTech-Addon,gregtech_addon:machine:60,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Bender,GregTech-Addon,gregtech_addon:machine:59,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Blast,GregTech-Addon,gregtech_addon:machine:29,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.BronzeBlast,GregTech-Addon,gregtech_addon:machine:136,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Canner,GregTech-Addon,gregtech_addon:machine:57,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.centrifuge,GregTech-Addon,gregtech_addon:machine:62,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.chemicalreactor,GregTech-Addon,gregtech_addon:machine:41,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Cutter,GregTech-Addon,gregtech_addon:machine:113,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Distillation,GregTech-Addon,gregtech_addon:machine:44,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.electrolyzer,GregTech-Addon,gregtech_addon:machine:25,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.extruder,GregTech-Addon,gregtech_addon:machine:115,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.fusion,GregTech-Addon,gregtech_addon:machine:80,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.thermal_generator,GregTech-Addon,gregtech_addon:machine:35,,gregtech_addon,TRUE,,15,145,166,2,,80,0,14,14,
|
||||
gregtech.diesel_generator,GregTech-Addon,gregtech_addon:machine:33,,gregtech_addon,TRUE,,15,145,166,2,,80,0,14,14,
|
||||
gregtech.gas_turbine,GregTech-Addon,gregtech_addon:machine:108,,gregtech_addon,TRUE,,15,145,166,2,,80,0,14,14,
|
||||
gregtech.semifluid_generator,GregTech-Addon,gregtech_addon:machine:36,,gregtech_addon,TRUE,,15,145,166,2,,80,0,14,14,
|
||||
gregtech.plasma_generator,GregTech-Addon,gregtech_addon:machine:37,,gregtech_addon,TRUE,,15,145,166,2,,80,0,14,14,
|
||||
gregtech.magic_generator,GregTech-Addon,gregtech_addon:machine:42,,gregtech_addon,TRUE,,15,145,166,2,,80,0,14,14,
|
||||
gregtech.Grinder,GregTech-Addon,gregtech_addon:machine:28,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Implosion,GregTech-Addon,gregtech_addon:machine:31,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Lathe,GregTech-Addon,gregtech_addon:machine:111,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Sawmill,GregTech-Addon,gregtech_addon:machine:32,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.VacuumFreezer,GregTech-Addon,gregtech_addon:machine:38,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
gregtech.Wiremill,GregTech-Addon,gregtech_addon:machine:55,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
|
||||
cofh.thermaldynamics.plugins.nei.RecipeHandlerCover,Thermal Dynamics,ThermalDynamics:cover,"{Block:""minecraft:glass"",Meta:0b}",ThermalDynamics,TRUE,,,65,166,5,,,,,,
|
||||
neresources.nei.NEIAdvSeedHandler,Not Enough Resources,minecraft:wheat,,neresources,TRUE,,,65,166,5,,,,,,
|
||||
neresources.nei.NEIDungeonHandler,Not Enough Resources,minecraft:chest,,neresources,TRUE,,,130,166,2,,,,,,
|
||||
@@ -449,3 +456,28 @@ neresources.nei.NEIEnchantmentHandler,Not Enough Resources,minecraft:anvil,,nere
|
||||
neresources.nei.NEIMobHandler,Not Enough Resources,minecraft:skull:4,,neresources,TRUE,,,130,166,2,,,,,,
|
||||
neresources.nei.NEIOreHandler,Not Enough Resources,minecraft:diamond_ore,,neresources,TRUE,,,65,166,5,,,,,,
|
||||
neresources.nei.NEIPlantHandler,Not Enough Resources,minecraft:wheat,,neresources,TRUE,,,130,166,2,,,,,,
|
||||
wanion.biggercraftingtables.nei.BigShapedRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables,,biggercraftingtables,TRUE,,,130,,2,,,,,,
|
||||
wanion.biggercraftingtables.nei.BigShapelessRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables,,biggercraftingtables,TRUE,,,130,,2,,,,,,
|
||||
wanion.biggercraftingtables.nei.HugeShapedRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables:1,,biggercraftingtables,TRUE,,,130,,2,,,,,,
|
||||
wanion.biggercraftingtables.nei.HugeShapelessRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables:1,,biggercraftingtables,TRUE,,,130,,2,,,,,,
|
||||
net.machinemuse.numina.nei.JSONRecipeHandler,Modular Powersuits,powersuits:tile.tinkerTable,,powersuits,TRUE,,,65,166,5,,,,,,
|
||||
com.teammetallurgy.metallurgy.nei.CrusherHandler,Metallurgy 4,Metallurgy:crusher,,Metallurgy,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.MetalFurnaceRecipeHandler,NuclearCraft,NuclearCraft:furnaceIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.ElectricFurnaceRecipeHandler,NuclearCraft,NuclearCraft:electricFurnaceIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.NuclearFurnaceRecipeHandler,NuclearCraft,NuclearCraft:nuclearFurnaceIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.FactoryRecipeHandler,NuclearCraft,NuclearCraft:factoryIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.AssemblerRecipeHandler,NuclearCraft,NuclearCraft:assemblerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.SeparatorRecipeHandler,NuclearCraft,NuclearCraft:separatorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.HastenerRecipeHandler,NuclearCraft,NuclearCraft:hastenerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.CollectorRecipeHandler,NuclearCraft,NuclearCraft:collectorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.OxidiserRecipeHandler,NuclearCraft,NuclearCraft:oxidiserIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.IoniserRecipeHandler,NuclearCraft,NuclearCraft:ioniserIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.IrradiatorRecipeHandler,NuclearCraft,NuclearCraft:irradiatorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.CoolerRecipeHandler,NuclearCraft,NuclearCraft:coolerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.HeliumExtractorRecipeHandler,NuclearCraft,NuclearCraft:heliumExtractorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.RecyclerRecipeHandler,NuclearCraft,NuclearCraft:recyclerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
|
||||
nc.crafting.nei.NuclearWorkspaceRecipeHandler,NuclearCraft,NuclearCraft:nuclearWorkspace,,NuclearCraft,TRUE,,,130,,2,,,,,,
|
||||
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker,EtFuturum Requiem,etfuturum:lit_smoker,,etfuturum,TRUE,,,65,166,5,,,,,,
|
||||
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace,EtFuturum Requiem,etfuturum:lit_blast_furnace,,etfuturum,TRUE,,,65,166,5,,,,,,
|
||||
connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler,Campfire Backport,campfirebackport:campfire,,campfirebackport,TRUE,,,65,166,5,,,,,,
|
||||
connor135246.campfirebackport.client.compat.nei.NEICampfireStateChangerHandler,Campfire Backport,campfirebackport:campfire_base,,campfirebackport,TRUE,,,65,166,5,,,,,,
|
||||
|
@@ -0,0 +1,56 @@
|
||||
AdvancedSolarPanel:hybrid_solar_helmet,Damage
|
||||
BuildCraft|Transport:pipeFacade
|
||||
DraconicEvolution:draconicAxe,tag.Energy
|
||||
DraconicEvolution:draconicPickaxe,tag.Energy
|
||||
DraconicEvolution:wyvernPickaxe,tag.Energy
|
||||
ExtraUtilities:microblocks,Damage
|
||||
Forestry:beePrincessGE,tag.Genome.Chromosomes
|
||||
ForgeMicroblock:microblock,Damage
|
||||
Genetics:serumArray,tag.genes
|
||||
GraviSuite:itemPlasmaCell,tag.Fluid.FluidName
|
||||
IC2:itemCropSeed,tag.name
|
||||
IC2:itemFluidCell,tag.Fluid.FluidName
|
||||
NodalMechanics:item.nodalmechanics.matrix,tag.Aspects.0.key
|
||||
TConstruct:ArrowAmmo,tag.InfiTool
|
||||
TConstruct:BoltAmmo,tag.InfiTool
|
||||
TConstruct:Crossbow,tag.InfiTool
|
||||
TConstruct:Javelin,tag.InfiTool
|
||||
TConstruct:LongBow,tag.InfiTool
|
||||
TConstruct:ShortBow,tag.InfiTool
|
||||
TConstruct:Shuriken,tag.InfiTool
|
||||
TConstruct:ThrowingKnife,tag.InfiTool
|
||||
TConstruct:battleaxe,tag.InfiTool
|
||||
TConstruct:battlesign,tag.InfiTool
|
||||
TConstruct:broadsword,tag.InfiTool
|
||||
TConstruct:chisel,tag.InfiTool
|
||||
TConstruct:cleaver,tag.InfiTool
|
||||
TConstruct:cutlass,tag.InfiTool
|
||||
TConstruct:dagger,tag.InfiTool
|
||||
TConstruct:excavator,tag.InfiTool
|
||||
TConstruct:frypan,tag.InfiTool
|
||||
TConstruct:hammer,tag.InfiTool
|
||||
TConstruct:hatchet,tag.InfiTool
|
||||
TConstruct:longsword,tag.InfiTool
|
||||
TConstruct:lumberaxe,tag.InfiTool
|
||||
TConstruct:mattock,tag.InfiTool
|
||||
TConstruct:pickaxe,tag.InfiTool
|
||||
TConstruct:potionLauncher
|
||||
TConstruct:rapier,tag.InfiTool
|
||||
TConstruct:scythe,tag.InfiTool
|
||||
TConstruct:shovel,tag.InfiTool
|
||||
Thaumcraft:ItemEssence,tag.Aspects.0.key
|
||||
Thaumcraft:ItemWispEssence,tag.Aspects.0.key
|
||||
WitchingGadgets:item.WG_InfusedGem,tag.Aspect
|
||||
adventurebackpack:adventureBackpack,Damage
|
||||
appliedenergistics2:item.ItemFacade
|
||||
bartworks:BioLabParts,Damage,tag.Name
|
||||
battlegear2:knights_armour.boots
|
||||
battlegear2:knights_armour.helmet
|
||||
battlegear2:knights_armour.legs
|
||||
battlegear2:knights_armour.plate
|
||||
miscutils:itemBlueprint
|
||||
miscutils:particleIon,Damage
|
||||
miscutils:personalHealingDevice
|
||||
tectech:item.em.debugContainer,tag.symbols
|
||||
tinkersdefense:Heater Shield,tag.InfiTool
|
||||
tinkersdefense:Round Shield,tag.InfiTool
|
||||
@@ -66,6 +66,7 @@ nei.chat.rain.on=Rain turned on
|
||||
nei.chat.rain.off=Rain turned off
|
||||
nei.chat.time=Day %d. %d:00
|
||||
nei.chat.give.noitem=No such item.
|
||||
nei.chat.recipe.error=There was error during loading recipe. Please check log for details.
|
||||
|
||||
nei.options=NEI Options
|
||||
nei.options.back=Back
|
||||
@@ -94,6 +95,7 @@ nei.options.keys.gui.prev_machine=Prev Machine
|
||||
nei.options.keys.gui.search=Focus Search Bar
|
||||
nei.options.keys.gui.bookmark=Add Bookmark
|
||||
nei.options.keys.gui.hide_bookmarks=Toggle Bookmark Panel Visibility
|
||||
nei.options.keys.gui.overlay=Overlay Recipe
|
||||
nei.options.keys.world=World
|
||||
nei.options.keys.world.chunkoverlay=Chunk Boundary Overlay
|
||||
nei.options.keys.world.moboverlay=Mob Spawn Overlay
|
||||
@@ -108,6 +110,12 @@ nei.options.keys.world.creative=Gamemode
|
||||
nei.options.keys.world.creative.tip=Cycle Gamemode
|
||||
|
||||
nei.options.inventory=Inventory
|
||||
nei.options.inventory.worldSpecificBookmarks=World Specific Bookmarks
|
||||
nei.options.inventory.worldSpecificBookmarks.true=Yes
|
||||
nei.options.inventory.worldSpecificBookmarks.false=No
|
||||
nei.options.inventory.worldSpecificPresets=World Specific Presets
|
||||
nei.options.inventory.worldSpecificPresets.true=Yes
|
||||
nei.options.inventory.worldSpecificPresets.false=No
|
||||
nei.options.inventory.bookmarksEnabled=Bookmarks Panel Visibility
|
||||
nei.options.inventory.bookmarksEnabled.true=Visible
|
||||
nei.options.inventory.bookmarksEnabled.false=Hidden
|
||||
@@ -117,6 +125,18 @@ nei.options.inventory.jei_style_tabs.false=No [Weirdo]
|
||||
nei.options.inventory.jei_style_item_presence_overlay=JEI Style Item Overlay on ?-Hover
|
||||
nei.options.inventory.jei_style_item_presence_overlay.true=Yes
|
||||
nei.options.inventory.jei_style_item_presence_overlay.false=No
|
||||
nei.options.inventory.jei_style_recipe_catalyst=JEI Style Recipe Catalysts
|
||||
nei.options.inventory.jei_style_recipe_catalyst.true=Yes
|
||||
nei.options.inventory.jei_style_recipe_catalyst.false=No
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=Save Current Recipe in Bookmarks
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=Enabled
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=Disabled
|
||||
nei.options.inventory.useNBTInBookmarks=Use NBT in Bookmarks
|
||||
nei.options.inventory.useNBTInBookmarks.true=Yes
|
||||
nei.options.inventory.useNBTInBookmarks.false=No
|
||||
nei.options.inventory.showRecipeMarker=Show Recipe Marker
|
||||
nei.options.inventory.showRecipeMarker.true=Yes
|
||||
nei.options.inventory.showRecipeMarker.false=No
|
||||
nei.options.inventory.creative_tab_style=Creative or JEI tab style
|
||||
nei.options.inventory.creative_tab_style.true=Creative
|
||||
nei.options.inventory.creative_tab_style.false=JEI
|
||||
@@ -159,6 +179,9 @@ nei.options.inventory.disableMouseScrollTransfer.false=False
|
||||
nei.options.inventory.invertMouseScrollTransfer=Invert Mouse Wheel Transfer Direction
|
||||
nei.options.inventory.invertMouseScrollTransfer.true=True
|
||||
nei.options.inventory.invertMouseScrollTransfer.false=False
|
||||
nei.options.inventory.cacheItemRendering=Cache Item Rendering
|
||||
nei.options.inventory.cacheItemRendering.true=True
|
||||
nei.options.inventory.cacheItemRendering.false=False
|
||||
|
||||
nei.options.command=Commands
|
||||
nei.options.command.creative=Gamemode
|
||||
@@ -177,10 +200,15 @@ nei.options.world.highlight_tips.hide=Hidden
|
||||
nei.options.world.highlight_tips.show=Shown
|
||||
nei.options.world.highlight_tips.sample=Sample
|
||||
|
||||
nei.options.world.panels=Panels Settings
|
||||
|
||||
nei.options.tools=Tools
|
||||
nei.options.tools.handler_load_from_config=Load handlers from Config
|
||||
nei.options.tools.handler_load_from_config.true=Config
|
||||
nei.options.tools.handler_load_from_config.false=JAR
|
||||
nei.options.tools.catalyst_load_from_config=Load catalysts from Config
|
||||
nei.options.tools.catalyst_load_from_config.true=Config
|
||||
nei.options.tools.catalyst_load_from_config.false=JAR
|
||||
nei.options.tools.dump=Data Dumps
|
||||
nei.options.tools.dump.dump=Dump
|
||||
nei.options.tools.dump.dumped=%s IDs dumped to %s
|
||||
@@ -216,8 +244,12 @@ nei.recipe.shaped=Shaped Crafting
|
||||
nei.recipe.shapeless=Shapeless Crafting
|
||||
nei.recipe.furnace=Smelting
|
||||
nei.recipe.fuel=Fuel
|
||||
nei.recipe.fuel.smeltCount=Smelts %s items
|
||||
# Deprecated
|
||||
nei.recipe.fuel.required=%s required
|
||||
# Deprecated
|
||||
nei.recipe.fuel.processed=%s processed
|
||||
# Deprecated
|
||||
nei.recipe.fuel.produced=%s produced
|
||||
nei.recipe.firework=Fireworks
|
||||
nei.recipe.firework.tooltip0=Dyes add colours to the charges
|
||||
@@ -262,4 +294,13 @@ nei.subsets.Items.Tools.Shovels=Shovels
|
||||
nei.subsets.Items.Weapons=Weapons
|
||||
nei.subsets.Items.Weapons.Ranged=Ranged
|
||||
nei.subsets.Items.Weapons.Swords=Swords
|
||||
nei.subsets.Mod=Mod
|
||||
nei.subsets.Mod=Mod
|
||||
|
||||
nei.presets.blacklist.label=B
|
||||
nei.presets.blacklist.tooltip=Blacklist
|
||||
nei.presets.whitelist.label=W
|
||||
nei.presets.whitelist.tooltip=Whitelist
|
||||
nei.presets.textfield.tooltip.1=Enter - save
|
||||
nei.presets.textfield.tooltip.2=Escape - cancel
|
||||
nei.presets.label.tooltip=Double click to edit
|
||||
nei.presets.label.selected=%s Presets
|
||||
@@ -174,14 +174,14 @@ nei.recipe.fuel.processed=Обработано: %s
|
||||
nei.recipe.fuel.produced=Произведено: %s
|
||||
nei.recipe.firework=Фейерверки
|
||||
nei.recipe.firework.tooltip0=Красители добавляют цвета на звёздочку
|
||||
nei.recipe.firework.tooltip1=Recolouring adds fade colours to the charge
|
||||
nei.recipe.firework.tooltip2=Multiple charges can be spawned from one rocket
|
||||
nei.recipe.firework.tooltip1=Перекрашивание добавляет исчезающие цвета к заряду
|
||||
nei.recipe.firework.tooltip2=Одна ракета может выпустить несколько зарядов
|
||||
nei.recipe.brewing=Зельеварение
|
||||
nei.recipe.profiler.crafting=Профилирование создания
|
||||
nei.recipe.profiler.usage=Использование профилирования
|
||||
|
||||
nei.itemsort.minecraft=Minecraft
|
||||
nei.itemsort.minecraft.tip=Сортирует предметы сначало из оригинального Minecraft
|
||||
nei.itemsort.minecraft.tip=Сортирует предметы сначала из оригинального Minecraft
|
||||
nei.itemsort.mod=По модификации
|
||||
nei.itemsort.mod.tip=Группирует предметы в один мод, на основе имени мода
|
||||
nei.itemsort.id=ID предмета
|
||||
@@ -215,4 +215,4 @@ nei.subsets.Items.Tools.Shovels=Лопаты
|
||||
nei.subsets.Items.Weapons=Оружие
|
||||
nei.subsets.Items.Weapons.Ranged=Дальнего боя
|
||||
nei.subsets.Items.Weapons.Swords=Мечи
|
||||
nei.subsets.Mod=Модификации
|
||||
nei.subsets.Mod=Модификации
|
||||
@@ -108,6 +108,12 @@ nei.options.keys.world.creative=游戏模式
|
||||
nei.options.keys.world.creative.tip=循环游戏模式
|
||||
|
||||
nei.options.inventory=物品栏
|
||||
nei.options.inventory.worldSpecificBookmarks=书签存储位置
|
||||
nei.options.inventory.worldSpecificBookmarks.true=存档内
|
||||
nei.options.inventory.worldSpecificBookmarks.false=全局
|
||||
nei.options.inventory.worldSpecificPresets=预设存储位置
|
||||
nei.options.inventory.worldSpecificPresets.true=存档内
|
||||
nei.options.inventory.worldSpecificPresets.false=全局
|
||||
nei.options.inventory.bookmarksEnabled=显示/隐藏书签页
|
||||
nei.options.inventory.bookmarksEnabled.true=显示
|
||||
nei.options.inventory.bookmarksEnabled.false=隐藏
|
||||
@@ -117,6 +123,15 @@ nei.options.inventory.jei_style_tabs.false=否 [不会吧]
|
||||
nei.options.inventory.jei_style_item_presence_overlay=JEI风格物品覆盖?-悬停
|
||||
nei.options.inventory.jei_style_item_presence_overlay.true=是
|
||||
nei.options.inventory.jei_style_item_presence_overlay.false=否
|
||||
nei.options.inventory.jei_style_recipe_catalyst=JEI风格可执行合成表机器显示[测试中]
|
||||
nei.options.inventory.jei_style_recipe_catalyst.true=是
|
||||
nei.options.inventory.jei_style_recipe_catalyst.false=否
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=保存书签中的当前合成表
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=启用
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=禁用
|
||||
nei.options.inventory.useNBTInBookmarks=在书签中启用NBT
|
||||
nei.options.inventory.useNBTInBookmarks.true=是
|
||||
nei.options.inventory.useNBTInBookmarks.false=否
|
||||
nei.options.inventory.creative_tab_style=创造模式/JEI标签页
|
||||
nei.options.inventory.creative_tab_style.true=创造模式
|
||||
nei.options.inventory.creative_tab_style.false=JEI
|
||||
@@ -178,9 +193,12 @@ nei.options.world.highlight_tips.show=显示
|
||||
nei.options.world.highlight_tips.sample=样本
|
||||
|
||||
nei.options.tools=工具
|
||||
nei.options.tools.handler_load_from_config=从Config加载预设(handler)
|
||||
nei.options.tools.handler_load_from_config=从Config加载handler(加工所使用的机器类别)
|
||||
nei.options.tools.handler_load_from_config.true=Config
|
||||
nei.options.tools.handler_load_from_config.false=JAR
|
||||
nei.options.tools.catalyst_load_from_config=从Config加载catalysts(加工所使用的具体机器等)
|
||||
nei.options.tools.catalyst_load_from_config.true=Config
|
||||
nei.options.tools.catalyst_load_from_config.false=JAR
|
||||
nei.options.tools.dump=数据存储
|
||||
nei.options.tools.dump.dump=存储
|
||||
nei.options.tools.dump.dumped=%s ID已保存到.minecraft/%s
|
||||
@@ -216,8 +234,12 @@ nei.recipe.shaped=有序合成
|
||||
nei.recipe.shapeless=无序合成
|
||||
nei.recipe.furnace=烧制
|
||||
nei.recipe.fuel=燃料
|
||||
nei.recipe.fuel.smeltCount=可冶炼%s个物品
|
||||
# Deprecated
|
||||
nei.recipe.fuel.required=需要%s个
|
||||
# Deprecated
|
||||
nei.recipe.fuel.processed=可烧制%s个
|
||||
# Deprecated
|
||||
nei.recipe.fuel.produced=可制作%s个
|
||||
nei.recipe.firework=烟花
|
||||
nei.recipe.firework.tooltip0=添加多种染料可增加烟火之星的颜色
|
||||
@@ -263,3 +285,12 @@ nei.subsets.Items.Weapons=武器
|
||||
nei.subsets.Items.Weapons.Ranged=远程
|
||||
nei.subsets.Items.Weapons.Swords=剑
|
||||
nei.subsets.Mod=Mod
|
||||
|
||||
nei.presets.blacklist.label=黑
|
||||
nei.presets.blacklist.tooltip=黑名单
|
||||
nei.presets.whitelist.label=白
|
||||
nei.presets.whitelist.tooltip=白名单
|
||||
nei.presets.textfield.tooltip.1=Enter - 保存
|
||||
nei.presets.textfield.tooltip.2=Esc - 取消
|
||||
nei.presets.label.tooltip=双击编辑
|
||||
nei.presets.label.selected=%s 预设
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 103 B |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"repo": "https://github.com/GTNewHorizons/CodeChickenLib/releases/download/1.1.5.3/",
|
||||
"file": "CodeChickenLib-1.7.10-1.1.5.3.jar",
|
||||
"dev": "CodeChickenLib-1.7.10-1.1.5.3-dev.jar",
|
||||
"class": "codechicken.lib.asm.ASMHelper",
|
||||
"coreLib": true
|
||||
}
|
||||
@@ -4,13 +4,8 @@
|
||||
"name": "${modName}",
|
||||
"version": "${modVersion}",
|
||||
"mcversion": "${minecraftVersion}",
|
||||
"description": "Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more; GTNH Version
|
||||
|
||||
|
||||
<plugins>
|
||||
|
||||
Supporters: EmuCraft Team, Victor Zimmer, lexi85, Ace_Trainer_Tullius, Bacon_Donut, Iarinu",
|
||||
"url": "http://www.minecraftforum.net/topic/909223",
|
||||
"description": "Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more; GTNH Version includes many enhancements.",
|
||||
"url": "https://github.com/GTNewHorizons/NotEnoughItems",
|
||||
"credits": "Alexandria - original idea",
|
||||
"license": "LGPL-3.0",
|
||||
"authorList": [ "ChickenBones", "mitchej123" ],
|
||||
|
||||
Reference in new issue
Block a user