42 Commits
1.13 ... 1.17

Author SHA1 Message Date
Christian Knaapen
68a5bab704 Fixed multiplayer: cache not working. 2022-01-16 15:56:09 +01:00
Christian Knaapen
9ae02b16de Tweaks and cleanup 2021-12-05 17:53:47 +01:00
Christian Knaapen
80e355a806 Revamped the radial menu. Removed some old code. 2021-12-05 14:30:57 +01:00
Christian Knaapen
700a3062f7 Hotfix: Fixed crash when rendering overlay: Invalid shaders/core/dissolve.json: Couldn't compile fragment program. 2021-11-02 01:40:17 +01:00
Christian Knaapen
f45d3ffad7 Added golden and diamond randomizer bags (with container, screen, icon and recipe). Updated recipes for reach upgrades. 2021-10-31 16:52:08 +01:00
Christian Knaapen
c8cfa515d0 Fixed icons in radial menu. Cleaned up radial menu code a bit. 2021-10-30 21:34:53 +02:00
Christian Knaapen
6760388bc7 Fixed block preview shader dissolve effect. Fixed reach upgrade item icons. 2021-10-30 20:00:47 +02:00
Christian Knaapen
80c475ff54 Fixed block preview shader being glitchy. Now shows block without effects. 2021-10-30 16:32:23 +02:00
Christian Knaapen
5b8fafd9f7 Fixed randomizer bag inventory not opening. 2021-10-16 13:24:33 +02:00
Christian Knaapen
43d0a02faf Moved dissolve shader to Minecraft's new custom shader rendertype. 2021-09-26 19:38:02 +02:00
Christian Knaapen
4b1997e44f [TASK] Fixed rendering modifier lines and areas. Rendering block previews no longer crashes (renders black). 2021-09-26 12:48:36 +02:00
Christian Knaapen
3930844208 Fixed capabilities and setup events. 2021-09-12 16:58:09 +02:00
Christian Knaapen
d9df8b0d0e Fixed remaining compiler errors. Using deferred registries now, and cleaned up mods.toml file. 2021-09-12 13:54:25 +02:00
Christian Knaapen
178a4ca4e1 Fixed 200+ compiler errors. 23 left. 2021-09-01 17:37:09 +02:00
Christian Knaapen
2297c38574 WIP Update to 1.17 2021-09-01 14:51:44 +02:00
Christian Knaapen
72d1085a54 Updated mapping to 1.16.5 official names. 2021-09-01 14:13:08 +02:00
Christian Knaapen
47f38d0a58 Bumped version number 2021-05-20 21:11:38 +02:00
Alexei Robyn
54d9c3a92f Merged in fakeplayer-fix-1.16 (pull request #3)
Fix FakePlayer-related crashes

Approved-by: Requios
2021-05-20 18:16:16 +00:00
Alexei Robyn
f77a937c6c Fix FakePlayer-related crashes 2021-05-20 14:14:58 +10:00
Christian Knaapen
b41f102f0c Using deferred registry for Randomizer Bag container, which fixes startup crash in 1.16.4 and 1.16.5. 2021-02-03 20:50:09 +01:00
grimm auld
f2fee42c58 Merged in 1.16 (pull request #2)
1.16

Approved-by: Requios
2021-02-02 20:28:16 +00:00
grimmauld
d63786f6e2 merge version bump 2021-02-02 12:52:18 +01:00
Christian Knaapen
a6bb10f06d Version update 2021-01-31 13:38:23 +01:00
grimmauld
5fe5978777 Fix some stuff 2021-01-29 23:43:12 +01:00
grimmauld
7b5f055d22 Get stuff running on 1.16.3 2021-01-29 23:12:11 +01:00
Christian Knaapen
bc6bebe387 Fixed radial menu icons not rendering. Partially fixed shader. 2020-09-03 20:37:50 +02:00
Christian Knaapen
a7961c22a6 Started on GUI for player settings. 2020-08-27 02:24:04 +02:00
Christian Knaapen
96e9e9bb3b Retina display fix 2020-08-26 21:11:51 +02:00
Christian Knaapen
4b22cea9ab Fixes from 1.14 (Fixed freezing when looking up + setting NBT data). 2020-08-25 15:43:15 +02:00
Christian Knaapen
d440325b2a Shader works partially 2020-08-25 15:36:43 +02:00
Christian Knaapen
4bab684369 Working on block previews, updated mappings. 2020-08-24 22:35:13 +02:00
Christian Knaapen
804ed4354b Modifier rendering complete (lines and planes) 2020-08-24 18:18:30 +02:00
Christian Knaapen
31f3cf3233 More work on rendering, mostly test code and a custom rendertype. 2020-08-23 19:27:36 +02:00
Christian Knaapen
e22ad0c311 Initial 1.15 commit 2020-03-15 15:05:57 +01:00
Christian Knaapen
74d74390d2 Fixed undo/redo crashing. 2020-03-15 13:24:13 +01:00
Christian Knaapen
f764fac778 Fixed randomizer bag not opening. Fixed server crash. 2020-03-08 15:10:16 +01:00
Christian Knaapen
42661f884c Removed reach condition for crafting recipes, too much effort to maintain for such a small feature.
Fixed saving modifier settings on closing the gui (don't override onClose() but removed()).
2019-12-23 15:55:32 +01:00
Christian Knaapen
df27697ecb Fixed checkbox graphics (copied GuiCheckBox from previous version). Fixed missing icons in radial menu (moved texture stitch event to ModEventHandler). 2019-12-23 15:13:43 +01:00
Christian Knaapen
fb622bcf99 Removed logging in network messages. 2019-12-23 13:10:25 +01:00
Christian Knaapen
4e3b1ef2ce Fixed crash when placing ladders. Tweaked circle, cylinder and sphere to have the same outer radius whether they are full or hollow. 2019-12-23 13:08:02 +01:00
Christian Knaapen
83b23fe763 Fixed screens, except containerscreen. Fixed clientproxy and BlockRayTraceResult (cast if type = block). 2019-12-06 15:23:05 +01:00
Christian Knaapen
ac429ca64e Initial 1.14 commit. Migrated using xml mapping (in User\.IntelliJIdea2019.3\config\migration). Went through all classes to fix minor issues.
Main tasks left to do: screens, blockBreak animation, ClientProxy/BlockRayTraceResult.
2019-12-04 20:43:40 +01:00
122 changed files with 9401 additions and 8020 deletions

1
.gitignore vendored
View File

@@ -20,6 +20,7 @@ build
# other
eclipse
run
logs/*
# Files from Forge MDK
forge*changelog.txt

520
LICENSE.txt Normal file
View File

@@ -0,0 +1,520 @@
Unless noted below, Minecraft Forge, Forge Mod Loader, and all
parts herein are licensed under the terms of the LGPL 2.1 found
here http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt and
copied below.
Homepage: http://minecraftforge.net/
https://github.com/MinecraftForge/MinecraftForge
A note on authorship:
All source artifacts are property of their original author, with
the exclusion of the contents of the patches directory and others
copied from it from time to time. Authorship of the contents of
the patches directory is retained by the Minecraft Forge project.
This is because the patches are partially machine generated
artifacts, and are changed heavily due to the way forge works.
Individual attribution within them is impossible.
Consent:
All contributions to Forge must consent to the release of any
patch content to the Forge project.
A note on infectivity:
The LGPL is chosen specifically so that projects may depend on Forge
features without being infected with its license. That is the
purpose of the LGPL. Mods and others using this code via ordinary
Java mechanics for referencing libraries are specifically not bound
by Forge's license for the Mod code.
=== MCP Data ===
This software includes data from the Minecraft Coder Pack (MCP), with kind permission
from them. The license to MCP data is not transitive - distribution of this data by
third parties requires independent licensing from the MCP team. This data is not
redistributable without permission from the MCP team.
=== Sharing ===
I grant permission for some parts of FML to be redistributed outside the terms of the LGPL, for the benefit of
the minecraft modding community. All contributions to these parts should be licensed under the same additional grant.
-- Runtime patcher --
License is granted to redistribute the runtime patcher code (src/main/java/net/minecraftforge/fml/common/patcher
and subdirectories) under any alternative open source license as classified by the OSI (http://opensource.org/licenses)
-- ASM transformers --
License is granted to redistribute the ASM transformer code (src/main/java/net/minecraftforge/common/asm/ and subdirectories)
under any alternative open source license as classified by the OSI (http://opensource.org/licenses)
=========================================================================
This software includes portions from the Apache Maven project at
http://maven.apache.org/ specifically the ComparableVersion.java code. It is
included based on guidelines at
http://www.softwarefreedom.org/resources/2007/gpl-non-gpl-collaboration.html
with notices intact. The only change is a non-functional change of package name.
This software contains a partial repackaging of javaxdelta, a BSD licensed program for generating
binary differences and applying them, sourced from the subversion at http://sourceforge.net/projects/javaxdelta/
authored by genman, heikok, pivot.
The only changes are to replace some Trove collection types with standard Java collections, and repackaged.
=========================================================================
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

View File

@@ -1 +0,0 @@
The 1.12 repository can be found here: https://bitbucket.org/Requios/effortless-building/src/master/

View File

@@ -1,11 +1,10 @@
buildscript {
repositories {
maven { url = 'https://files.minecraftforge.net/maven' }
jcenter()
mavenCentral()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1+', changing: true
}
}
apply plugin: 'net.minecraftforge.gradle'
@@ -13,11 +12,12 @@ apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
version = '1.13.2-2.16'
version = '1.17.1-2.31'
group = 'nl.requios.effortlessbuilding' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'effortlessbuilding'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
// Mojang ships Java 16 to end users in 1.17+ instead of Java 8 in 1.16 or lower, so your mod should target Java 16.
java.toolchain.languageVersion = JavaLanguageVersion.of(16)
minecraft {
// The mappings can be changed at any time, and must be in the following format.
@@ -25,10 +25,9 @@ minecraft {
// stable_# Stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: 'snapshot', version: '20180921-1.13'
mappings channel: 'official', version: '1.17.1'
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
// accessTransformer = file('build/resources/main/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
@@ -64,6 +63,25 @@ minecraft {
}
}
}
data {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment (SCAN,REGISTRIES,REGISTRYDUMP)
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'effortlessbuilding', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
mods {
effortlessbuilding {
source sourceSets.main
}
}
}
}
}
@@ -71,7 +89,7 @@ dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.13.2-25.0.219'
minecraft 'net.minecraftforge:forge:1.17.1-37.0.50'
// You may put jars on which you depend on in ./libs or you may define them like so..
// compile "some.group:artifact:version:classifier"
@@ -109,18 +127,15 @@ jar {
}
// Example configuration to allow publishing using the maven-publish task
// we define a custom artifact that is sourced from the reobfJar output task
// and then declare that to be published
// Note you'll need to add a repository here
def reobfFile = file("$buildDir/reobfJar/output.jar")
def reobfArtifact = artifacts.add('default', reobfFile) {
type 'jar'
builtBy 'reobfJar'
}
// This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
//publish.dependsOn('reobfJar')
publishing {
publications {
mavenJava(MavenPublication) {
artifact reobfArtifact
artifact jar
}
}
repositories {

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip

71
gradlew vendored
View File

@@ -1,4 +1,20 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -56,7 +72,7 @@ case "`uname`" in
Darwin* )
darwin=true
;;
MINGW* )
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -138,35 +156,28 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
ARGV=("$@")
eval set -- $DEFAULT_JVM_OPTS
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
IFS=$'
' read -rd '' -a JAVA_OPTS_ARR <<< "$(echo $JAVA_OPTS | xargs -n1)"
IFS=$'
' read -rd '' -a GRADLE_OPTS_ARR <<< "$(echo $GRADLE_OPTS | xargs -n1)"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
exec "$JAVACMD" "$@" "${JAVA_OPTS_ARR[@]}" "${GRADLE_OPTS_ARR[@]}" "-Dorg.gradle.appname=$APP_BASE_NAME" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "${ARGV[@]}"

43
gradlew.bat vendored
View File

@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

@@ -4,131 +4,132 @@ import net.minecraftforge.common.ForgeConfigSpec;
public class BuildConfig {
private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
public static final Reach reach = new Reach(builder);
public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder);
public static final Visuals visuals = new Visuals(builder);
public static final ForgeConfigSpec spec = builder.build();
private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
public static final Reach reach = new Reach(builder);
public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder);
public static final Visuals visuals = new Visuals(builder);
public static final ForgeConfigSpec spec = builder.build();
public static class Reach {
public final ForgeConfigSpec.ConfigValue<Boolean> enableReachUpgrades;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachCreative;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel0;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel1;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel2;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel3;
public static class Reach {
public final ForgeConfigSpec.ConfigValue<Boolean> enableReachUpgrades;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachCreative;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel0;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel1;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel2;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel3;
public Reach(ForgeConfigSpec.Builder builder) {
builder.push("Reach");
enableReachUpgrades = builder
.comment("Reach: how far away the player can place blocks using mirror/array etc.",
"Enable the crafting of reach upgrades to increase reach.",
"If disabled, reach is set to level 3 for survival players.")
.define("enableReachUpgrades", true);
public Reach(ForgeConfigSpec.Builder builder) {
builder.push("Reach");
enableReachUpgrades = builder
.comment("Reach: how far away the player can place blocks using mirror/array etc.",
"Enable the crafting of reach upgrades to increase reach.",
"If disabled, reach is set to level 3 for survival players.")
.define("enableReachUpgrades", true);
maxReachCreative = builder
.comment("Maximum reach in creative",
"Keep in mind that chunks need to be loaded to be able to place blocks inside.")
.define("maxReachCreative", 200);
maxReachCreative = builder
.comment("Maximum reach in creative",
"Keep in mind that chunks need to be loaded to be able to place blocks inside.")
.define("maxReachCreative", 200);
maxReachLevel0 = builder
.comment("Maximum reach in survival without upgrades",
"Reach upgrades are craftable consumables that permanently increase reach.",
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.")
.define("maxReachLevel0", 20);
maxReachLevel0 = builder
.comment("Maximum reach in survival without upgrades",
"Reach upgrades are craftable consumables that permanently increase reach.",
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.")
.define("maxReachLevel0", 20);
maxReachLevel1 = builder
.comment("Maximum reach in survival with one upgrade")
.define("maxReachLevel1", 50);
maxReachLevel1 = builder
.comment("Maximum reach in survival with one upgrade")
.define("maxReachLevel1", 50);
maxReachLevel2 = builder
.comment("Maximum reach in survival with two upgrades")
.define("maxReachLevel2", 100);
maxReachLevel2 = builder
.comment("Maximum reach in survival with two upgrades")
.define("maxReachLevel2", 100);
maxReachLevel3 = builder
.comment("Maximum reach in survival with three upgrades")
.define("maxReachLevel3", 200);
maxReachLevel3 = builder
.comment("Maximum reach in survival with three upgrades")
.define("maxReachLevel3", 200);
builder.pop();
}
}
builder.pop();
}
}
public static class SurvivalBalancers {
public final ForgeConfigSpec.ConfigValue<Boolean> breakFar;
public final ForgeConfigSpec.ConfigValue<Boolean> increasedMiningTime;
public final ForgeConfigSpec.ConfigValue<Integer> miningTimePercentage;
public final ForgeConfigSpec.ConfigValue<Integer> quickReplaceMiningLevel;
public final ForgeConfigSpec.ConfigValue<Integer> undoStackSize;
public static class SurvivalBalancers {
public final ForgeConfigSpec.ConfigValue<Boolean> breakFar;
public final ForgeConfigSpec.ConfigValue<Boolean> increasedMiningTime;
public final ForgeConfigSpec.ConfigValue<Integer> miningTimePercentage;
public final ForgeConfigSpec.ConfigValue<Integer> quickReplaceMiningLevel;
public final ForgeConfigSpec.ConfigValue<Integer> undoStackSize;
public SurvivalBalancers(ForgeConfigSpec.Builder builder) {
builder.push("SurvivalBalancers");
public SurvivalBalancers(ForgeConfigSpec.Builder builder) {
builder.push("SurvivalBalancers");
breakFar = builder
.comment("Allows a survival player to break blocks that are far away, in addition to placing blocks.",
"Note: this allows insta-breaking of blocks in survival.")
.define("breakFar", false);
breakFar = builder
.comment("Allows a survival player to break blocks that are far away, in addition to placing blocks.",
"Note: this allows insta-breaking of blocks in survival.")
.define("breakFar", false);
increasedMiningTime = builder
.comment("Increases the time to mine a block when breaking multiple at once.",
"Mining time depends on how many blocks, what type of blocks, and the percentage below.",
"Example: breaking 1 dirt + 1 obsidian takes the time of breaking 1 dirt + 1 obsidian.")
.define("increasedMiningTime", true);
increasedMiningTime = builder
.comment("Increases the time to mine a block when breaking multiple at once.",
"Mining time depends on how many blocks, what type of blocks, and the percentage below.",
"Example: breaking 1 dirt + 1 obsidian takes the time of breaking 1 dirt + 1 obsidian.")
.define("increasedMiningTime", true);
miningTimePercentage = builder
.comment("How much the mining time of each additional block counts towards an increased mining time.",
"A percentage between 0% and 100%, where 0% is the same as disabling it,",
"and 100% takes as much time as breaking each block individually.",
"The block in front of you always counts as 100%.")
.defineInRange("miningTimePercentage", 50, 0, 200);
miningTimePercentage = builder
.comment("How much the mining time of each additional block counts towards an increased mining time.",
"A percentage between 0% and 100%, where 0% is the same as disabling it,",
"and 100% takes as much time as breaking each block individually.",
"The block in front of you always counts as 100%.")
.defineInRange("miningTimePercentage", 50, 0, 200);
quickReplaceMiningLevel = builder
.comment("Determines what blocks can be replaced in survival.",
"-1: only blocks that can be harvested by hand (default)",
"0: blocks that can be harvested with wooden or gold tools",
"1: blocks that can be harvested with stone tools",
"2: blocks that can be harvested with iron tools",
"3: blocks that can be harvested with diamond tools")
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
quickReplaceMiningLevel = builder
.comment("Determines what blocks can be replaced in survival.",
"-1: only blocks that can be harvested by hand (default)",
"0: blocks that can be harvested with wooden or gold tools",
"1: blocks that can be harvested with stone tools",
"2: blocks that can be harvested with iron tools",
"3: blocks that can be harvested with diamond tools",
"4: blocks that can be harvested with netherite tools")
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
undoStackSize = builder
.comment("How many placements are remembered for the undo functionality.")
.worldRestart()
.define("undoStackSize", 10);
undoStackSize = builder
.comment("How many placements are remembered for the undo functionality.")
.worldRestart()
.define("undoStackSize", 10);
builder.pop();
}
}
builder.pop();
}
}
public static class Visuals {
public final ForgeConfigSpec.ConfigValue<Boolean> alwaysShowBlockPreview;
public final ForgeConfigSpec.ConfigValue<Double> dissolveTimeMultiplier;
public final ForgeConfigSpec.ConfigValue<Integer> shaderTreshold;
public final ForgeConfigSpec.ConfigValue<Boolean> useShaders;
public static class Visuals {
public final ForgeConfigSpec.ConfigValue<Boolean> alwaysShowBlockPreview;
public final ForgeConfigSpec.ConfigValue<Double> dissolveTimeMultiplier;
public final ForgeConfigSpec.ConfigValue<Integer> shaderThreshold;
public final ForgeConfigSpec.ConfigValue<Boolean> useShaders;
public Visuals(ForgeConfigSpec.Builder builder) {
builder.push("Visuals");
public Visuals(ForgeConfigSpec.Builder builder) {
builder.push("Visuals");
alwaysShowBlockPreview = builder
.comment("Show a block preview if you have a block in hand even in the 'Normal' build mode")
.define("alwaysShowBlockPreview", false);
alwaysShowBlockPreview = builder
.comment("Show a block preview if you have a block in hand even in the 'Normal' build mode")
.define("alwaysShowBlockPreview", false);
dissolveTimeMultiplier = builder
.comment("How long the dissolve effect takes when placing blocks.",
"Default between 30 and 60 ticks, you can multiply that here.",
"Recommended values:",
"Snappy: 0.7",
"Relaxing: 1.5")
.define("dissolveTimeMultiplier", 1.0);
dissolveTimeMultiplier = builder
.comment("How long the dissolve effect takes when placing blocks.",
"Default between 30 and 60 ticks, you can multiply that here.",
"Recommended values:",
"Snappy: 0.7",
"Relaxing: 1.5")
.define("dissolveTimeMultiplier", 1.0);
shaderTreshold = builder
.comment("Switch to using the simple performance shader when placing more than this many blocks.")
.define("shaderTreshold", 1500);
shaderThreshold = builder
.comment("Switch to using the simple performance shader when placing more than this many blocks.")
.define("shaderTreshold", 1500);
useShaders = builder
.comment("Use fancy shaders while placing blocks")
.define("useShaders", true);
useShaders = builder
.comment("Use fancy shaders while placing blocks")
.define("useShaders", true);
builder.pop();
}
}
builder.pop();
}
}
}

View File

@@ -1,153 +1,114 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.Item;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fmllegacy.RegistryObject;
import net.minecraftforge.fmllegacy.network.IContainerFactory;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.command.CommandReach;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler;
import nl.requios.effortlessbuilding.helper.ReachConditionFactory;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade1;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade2;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade3;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.item.*;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import nl.requios.effortlessbuilding.proxy.IProxy;
import nl.requios.effortlessbuilding.proxy.ServerProxy;
import nl.requios.effortlessbuilding.render.ShaderHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(EffortlessBuilding.MODID)
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
public class EffortlessBuilding
{
public static final String MODID = "effortlessbuilding";
public static final String NAME = "Effortless Building";
public static final String VERSION = "1.13.2-2.16";
public class EffortlessBuilding {
public static EffortlessBuilding instance;
public static final String MODID = "effortlessbuilding";
public static final Logger logger = LogManager.getLogger();
public static final Logger logger = LogManager.getLogger();
public static EffortlessBuilding instance;
public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new);
public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new);
//Registration
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
private static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, EffortlessBuilding.MODID);
public static final ItemRandomizerBag ITEM_RANDOMIZER_BAG = new ItemRandomizerBag();
public static final ItemReachUpgrade1 ITEM_REACH_UPGRADE_1 = new ItemReachUpgrade1();
public static final ItemReachUpgrade2 ITEM_REACH_UPGRADE_2 = new ItemReachUpgrade2();
public static final ItemReachUpgrade3 ITEM_REACH_UPGRADE_3 = new ItemReachUpgrade3();
public static final RegistryObject<Item> RANDOMIZER_BAG_ITEM = ITEMS.register("randomizer_bag", RandomizerBagItem::new);
public static final RegistryObject<Item> GOLDEN_RANDOMIZER_BAG_ITEM = ITEMS.register("golden_randomizer_bag", GoldenRandomizerBagItem::new);
public static final RegistryObject<Item> DIAMOND_RANDOMIZER_BAG_ITEM = ITEMS.register("diamond_randomizer_bag", DiamondRandomizerBagItem::new);
public static final RegistryObject<Item> REACH_UPGRADE_1_ITEM = ITEMS.register("reach_upgrade1", ReachUpgrade1Item::new);
public static final RegistryObject<Item> REACH_UPGRADE_2_ITEM = ITEMS.register("reach_upgrade2", ReachUpgrade2Item::new);
public static final RegistryObject<Item> REACH_UPGRADE_3_ITEM = ITEMS.register("reach_upgrade3", ReachUpgrade3Item::new);
public static final Block[] BLOCKS = {
};
public static final RegistryObject<MenuType<RandomizerBagContainer>> RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("randomizer_bag", () -> registerContainer(RandomizerBagContainer::new));
public static final RegistryObject<MenuType<GoldenRandomizerBagContainer>> GOLDEN_RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("golden_randomizer_bag", () -> registerContainer(GoldenRandomizerBagContainer::new));
public static final RegistryObject<MenuType<DiamondRandomizerBagContainer>> DIAMOND_RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("diamond_randomizer_bag", () -> registerContainer(DiamondRandomizerBagContainer::new));
public static final Item[] ITEMS = {
ITEM_RANDOMIZER_BAG,
ITEM_REACH_UPGRADE_1,
ITEM_REACH_UPGRADE_2,
ITEM_REACH_UPGRADE_3
};
public EffortlessBuilding() {
instance = this;
public static final ResourceLocation RANDOMIZER_BAG_GUI = new ResourceLocation(EffortlessBuilding.MODID, "randomizer_bag");
// Register ourselves for server and other game events we are interested in
FMLJavaModLoadingContext.get().getModEventBus().register(this);
public EffortlessBuilding() {
instance = this;
ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
CONTAINERS.register(FMLJavaModLoadingContext.get().getModEventBus());
// Register the setup method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
// Register the enqueueIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC);
// Register the processIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC);
// Register the clientSetup method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
//Register config
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, BuildConfig.spec);
}
//Register config
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, BuildConfig.spec);
public static <T extends AbstractContainerMenu> MenuType<T> registerContainer(IContainerFactory<T> fact){
MenuType<T> type = new MenuType<T>(fact);
return type;
}
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void setup(final FMLCommonSetupEvent event) {
PacketHandler.register();
@SubscribeEvent
public void setup(final FMLCommonSetupEvent event)
{
CapabilityManager.INSTANCE.register(ModifierCapabilityManager.IModifierCapability.class, new ModifierCapabilityManager.Storage(), ModifierCapabilityManager.ModifierCapability::new);
CapabilityManager.INSTANCE.register(ModeCapabilityManager.IModeCapability.class, new ModeCapabilityManager.Storage(), ModeCapabilityManager.ModeCapability::new);
proxy.setup(event);
PacketHandler.register();
CompatHelper.setup();
}
//Register recipe condition
CraftingHelper.register(new ResourceLocation(MODID, "enable_reach_upgrades"), new ReachConditionFactory());
@SubscribeEvent
public void clientSetup(final FMLClientSetupEvent event) {
proxy.clientSetup(event);
}
//TODO 1.13 config
// ConfigManager.sync(MODID, Config.Type.INSTANCE);
@SubscribeEvent
public void registerCapabilities(RegisterCapabilitiesEvent event){
event.register(ModifierCapabilityManager.IModifierCapability.class);
event.register(ModeCapabilityManager.IModeCapability.class);
}
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.GUIFACTORY, () -> RandomizerBagGuiHandler::openGui);
public static void log(String msg) {
logger.info(msg);
}
proxy.setup(event);
public static void log(Player player, String msg) {
log(player, msg, false);
}
CompatHelper.setup();
}
public static void log(Player player, String msg, boolean actionBar) {
player.displayClientMessage(new TextComponent(msg), actionBar);
}
@SubscribeEvent
public void clientSetup(final FMLClientSetupEvent event) {
proxy.clientSetup(event);
}
@SubscribeEvent
public void enqueueIMC(final InterModEnqueueEvent event) {
// some example code to dispatch IMC to another mod
// InterModComms.sendTo("examplemod", "helloworld", () -> { logger.info("Hello world from the MDK"); return "Hello world";});
}
@SubscribeEvent
public void processIMC(final InterModProcessEvent event) {
// some example code to receive and process InterModComms from other mods
// logger.info("Got IMC {}", event.getIMCStream().
// map(m->m.getMessageSupplier().get()).
// collect(Collectors.toList()));
}
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event) {
CommandReach.register(event.getCommandDispatcher());
}
public static void log(String msg){
logger.info(msg);
}
public static void log(EntityPlayer player, String msg){
log(player, msg, false);
}
public static void log(EntityPlayer player, String msg, boolean actionBar){
player.sendStatusMessage(new TextComponentString(msg), actionBar);
}
//Log with translation supported, call either on client or server (which then sends a message)
public static void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
proxy.logTranslate(player, prefix, translationKey, suffix, actionBar);
}
}

View File

@@ -1,22 +1,21 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.stats.Stat;
import net.minecraft.stats.StatList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
import net.minecraftforge.fmlserverevents.FMLServerStartingEvent;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
@@ -24,6 +23,7 @@ import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.command.CommandReach;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.AddUndoMessage;
@@ -33,181 +33,183 @@ import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
import java.util.List;
import static net.minecraftforge.fml.common.gameevent.PlayerEvent.*;
@Mod.EventBusSubscriber(modid = EffortlessBuilding.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class EventHandler {
@Mod.EventBusSubscriber
public class EventHandler
{
@SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof FakePlayer) return;
if (event.getObject() instanceof Player) {
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider());
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_mode"), new ModeCapabilityManager.Provider());
}
}
@SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof EntityPlayer) {
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider());
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_mode"), new ModeCapabilityManager.Provider());
}
}
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event) {
CommandReach.register(event.getServer().getCommands().getDispatcher());
}
//TODO 1.13 config
// @SubscribeEvent
// public static void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event)
// {
// if (event.getModID().equals(EffortlessBuilding.MODID))
// {
// ConfigManager.sync(EffortlessBuilding.MODID, Config.Type.INSTANCE);
// }
// }
@SubscribeEvent
public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) {
if (event.getWorld().isClientSide()) return;
// @SubscribeEvent
// public static void onServerTick(TickEvent.ServerTickEvent event) {
//
// }
if (!(event.getEntity() instanceof Player)) return;
@SubscribeEvent
//Only called serverside (except with lilypads...)
public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) {
if (event.getWorld().isRemote()) return;
if (event.getEntity() instanceof FakePlayer) return;
if (!(event.getEntity() instanceof EntityPlayer)) return;
//Cancel event if necessary
ServerPlayer player = ((ServerPlayer) event.getEntity());
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
//Cancel event if necessary
EntityPlayerMP player = ((EntityPlayerMP) event.getEntity());
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL) {
event.setCanceled(true);
} else if (modifierSettings.doQuickReplace()) {
//Cancel event and send message if QuickReplace
event.setCanceled(true);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(true));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
} else {
//NORMAL mode, let vanilla handle block placing
//But modifiers should still work
if (buildMode != BuildModes.BuildModeEnum.NORMAL) {
event.setCanceled(true);
} else if (modifierSettings.doQuickReplace()) {
//Cancel event and send message if QuickReplace
event.setCanceled(true);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(true));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
} else {
//NORMAL mode, let vanilla handle block placing
//But modifiers should still work
//Send message to client, which sends message back with raytrace info
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(false));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
}
//Send message to client, which sends message back with raytrace info
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(false));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
}
// Stat<ResourceLocation> blocksPlacedStat = StatList.CUSTOM.get(new ResourceLocation(EffortlessBuilding.MODID, "blocks_placed"));
// player.getStats().increment(player, blocksPlacedStat, 1);
//
// System.out.println(player.getStats().getValue(blocksPlacedStat));
}
}
@SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote()) return;
@SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isClientSide()) return;
//Cancel event if necessary
//If cant break far then dont cancel event ever
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode();
if (buildMode != BuildModes.BuildModeEnum.NORMAL && ReachHelper.canBreakFar(event.getPlayer())) {
event.setCanceled(true);
} else {
//NORMAL mode, let vanilla handle block breaking
//But modifiers and QuickReplace should still work
//Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work
BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false);
if (event.getPlayer() instanceof FakePlayer) return;
//Add to undo stack in client
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) event.getPlayer()), new AddUndoMessage(event.getPos(), event.getState(), Blocks.AIR.getDefaultState()));
}
}
//Cancel event if necessary
//If cant break far then dont cancel event ever
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode();
if (buildMode != BuildModes.BuildModeEnum.NORMAL && ReachHelper.canBreakFar(event.getPlayer())) {
event.setCanceled(true);
} else {
//NORMAL mode, let vanilla handle block breaking
//But modifiers and QuickReplace should still work
//Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work
BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false);
@SubscribeEvent
public static void breakSpeed(PlayerEvent.BreakSpeed event) {
//Disable if config says so
if (!BuildConfig.survivalBalancers.increasedMiningTime.get()) return;
//Add to undo stack in client
if (event.getPlayer() instanceof ServerPlayer && event.getState() != null && event.getPos() != null) {
PacketDistributor.PacketTarget packetTarget = PacketDistributor.PLAYER.with(() -> (ServerPlayer) event.getPlayer());
if (packetTarget != null)
PacketHandler.INSTANCE.send(packetTarget, new AddUndoMessage(event.getPos(), event.getState(), Blocks.AIR.defaultBlockState()));
}
}
}
EntityPlayer player = event.getEntityPlayer();
World world = player.world;
BlockPos pos = event.getPos();
@SubscribeEvent
public static void breakSpeed(PlayerEvent.BreakSpeed event) {
//Disable if config says so
if (!BuildConfig.survivalBalancers.increasedMiningTime.get()) return;
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
if (event.getPlayer() instanceof FakePlayer) return;
float originalBlockHardness = event.getState().getBlockHardness(world, pos);
if (originalBlockHardness < 0) return; //Dont break bedrock
float totalBlockHardness = 0;
//get coordinates
List<BlockPos> coordinates = BuildModifiers.findCoordinates(player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
//get existing blockstates at those coordinates
IBlockState blockState = world.getBlockState(coordinate);
//add hardness for each blockstate, if can break
if (SurvivalHelper.canBreak(world, player, coordinate))
totalBlockHardness += blockState.getBlockHardness(world, coordinate);
}
Player player = event.getPlayer();
Level world = player.level;
BlockPos pos = event.getPos();
//Grabbing percentage from config
float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage.get() / 100;
totalBlockHardness *= percentage;
totalBlockHardness += originalBlockHardness;
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
float newSpeed = event.getOriginalSpeed() / totalBlockHardness * originalBlockHardness;
if (Float.isNaN(newSpeed) || newSpeed == 0f) newSpeed = 1f;
event.setNewSpeed(newSpeed);
float originalBlockHardness = event.getState().getDestroySpeed(world, pos);
if (originalBlockHardness < 0) return; //Dont break bedrock
float totalBlockHardness = 0;
//get coordinates
List<BlockPos> coordinates = BuildModifiers.findCoordinates(player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
//get existing blockstates at those coordinates
BlockState blockState = world.getBlockState(coordinate);
//add hardness for each blockstate, if can break
if (SurvivalHelper.canBreak(world, player, coordinate))
totalBlockHardness += blockState.getDestroySpeed(world, coordinate);
}
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
}
//Grabbing percentage from config
float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage.get() / 100;
totalBlockHardness *= percentage;
totalBlockHardness += originalBlockHardness;
@SubscribeEvent
public static void onPlayerLoggedIn(PlayerLoggedInEvent event) {
EntityPlayer player = event.getPlayer();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
float newSpeed = event.getOriginalSpeed() / totalBlockHardness * originalBlockHardness;
if (Float.isNaN(newSpeed) || newSpeed == 0f) newSpeed = 1f;
event.setNewSpeed(newSpeed);
@SubscribeEvent
public static void onPlayerLoggedOut(PlayerLoggedOutEvent event) {
EntityPlayer player = event.getPlayer();
if (player.getEntityWorld().isRemote) return;
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
}
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), new ClearUndoMessage());
}
@SubscribeEvent
public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
if (event.getPlayer() instanceof FakePlayer) return;
Player player = event.getPlayer();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerRespawn(PlayerRespawnEvent event) {
EntityPlayer player = event.getPlayer();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
if (event.getPlayer() instanceof FakePlayer) return;
Player player = event.getPlayer();
if (player.getCommandSenderWorld().isClientSide) return;
@SubscribeEvent
public static void onPlayerChangedDimension(PlayerChangedDimensionEvent event) {
EntityPlayer player = event.getPlayer();
if (player.getEntityWorld().isRemote) return;
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new ClearUndoMessage());
}
//Set build mode to normal
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
modeSettings.setBuildMode(BuildModes.BuildModeEnum.NORMAL);
ModeSettingsManager.setModeSettings(player, modeSettings);
@SubscribeEvent
public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
if (event.getPlayer() instanceof FakePlayer) return;
Player player = event.getPlayer();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
//Disable modifiers
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.getMirrorSettings().enabled = false;
modifierSettings.getRadialMirrorSettings().enabled = false;
modifierSettings.getArraySettings().enabled = false;
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
@SubscribeEvent
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
if (event.getPlayer() instanceof FakePlayer) return;
Player player = event.getPlayer();
if (player.getCommandSenderWorld().isClientSide) return;
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
//Set build mode to normal
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
modeSettings.setBuildMode(BuildModes.BuildModeEnum.NORMAL);
ModeSettingsManager.setModeSettings(player, modeSettings);
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), new ClearUndoMessage());
}
//Disable modifiers
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.getMirrorSettings().enabled = false;
modifierSettings.getRadialMirrorSettings().enabled = false;
modifierSettings.getArraySettings().enabled = false;
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
//Attach capabilities on death, otherwise crash
EntityPlayer oldPlayer = event.getOriginal();
oldPlayer.revive();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
EntityPlayer newPlayer = event.getEntityPlayer();
ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
ModeSettingsManager.setModeSettings(newPlayer, ModeSettingsManager.getModeSettings(oldPlayer));
}
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new ClearUndoMessage());
}
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
if (event.getPlayer() instanceof FakePlayer) return;
//Attach capabilities on death, otherwise crash
Player oldPlayer = event.getOriginal();
oldPlayer.revive();
Player newPlayer = event.getPlayer();
ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
ModeSettingsManager.setModeSettings(newPlayer, ModeSettingsManager.getModeSettings(oldPlayer));
}
}

View File

@@ -0,0 +1,31 @@
package nl.requios.effortlessbuilding;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RegisterShadersEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.render.BuildRenderTypes;
import java.io.IOException;
import java.util.HashMap;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD, value = {Dist.CLIENT})
public class ModClientEventHandler {
@SubscribeEvent
public static void registerShaders(RegisterShadersEvent event) throws IOException {
event.registerShader(new ShaderInstance(event.getResourceManager(),
new ResourceLocation(EffortlessBuilding.MODID, "dissolve"),
DefaultVertexFormat.BLOCK),
shaderInstance -> BuildRenderTypes.dissolveShaderInstance = shaderInstance);
}
}

View File

@@ -1,30 +0,0 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
// You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
// Event bus for receiving Registry Events)
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
public class ModEventHandler {
@SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) {
event.getRegistry().registerAll(EffortlessBuilding.BLOCKS);
}
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event)
{
event.getRegistry().registerAll(EffortlessBuilding.ITEMS);
for (Block block : EffortlessBuilding.BLOCKS)
{
event.getRegistry().register(new ItemBlock(block, new Item.Properties()).setRegistryName(block.getRegistryName()));
}
}
}

View File

@@ -1,40 +1,39 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;
public abstract class BaseBuildMode implements IBuildMode {
//In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click
protected Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
protected Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
protected Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
protected Dictionary<UUID, EnumFacing> sideHitTable = new Hashtable<>();
protected Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>();
//In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click
protected Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
protected Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
protected Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
protected Dictionary<UUID, Direction> sideHitTable = new Hashtable<>();
protected Dictionary<UUID, Vec3> hitVecTable = new Hashtable<>();
@Override
public void initialize(EntityPlayer player) {
rightClickClientTable.put(player.getUniqueID(), 0);
rightClickServerTable.put(player.getUniqueID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
sideHitTable.put(player.getUniqueID(), EnumFacing.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO);
}
@Override
public void initialize(Player player) {
rightClickClientTable.put(player.getUUID(), 0);
rightClickServerTable.put(player.getUUID(), 0);
firstPosTable.put(player.getUUID(), BlockPos.ZERO);
sideHitTable.put(player.getUUID(), Direction.UP);
hitVecTable.put(player.getUUID(), Vec3.ZERO);
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return sideHitTable.get(player.getUniqueID());
}
@Override
public Direction getSideHit(Player player) {
return sideHitTable.get(player.getUUID());
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return hitVecTable.get(player.getUniqueID());
}
@Override
public Vec3 getHitVec(Player player) {
return hitVecTable.get(player.getUUID());
}
}

View File

@@ -1,11 +1,11 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceFluidMode;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.buildmodes.*;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
@@ -20,226 +20,252 @@ import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.OptionEnum;
public class BuildModes {
//Static variables are shared between client and server in singleplayer
//We need them separate
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingClient = new Hashtable<>();
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingServer = new Hashtable<>();
//Static variables are shared between client and server in singleplayer
//We need them separate
public static Dictionary<Player, Boolean> currentlyBreakingClient = new Hashtable<>();
public static Dictionary<Player, Boolean> currentlyBreakingServer = new Hashtable<>();
public enum BuildModeEnum {
NORMAL("effortlessbuilding.mode.normal", new Normal()),
NORMAL_PLUS("effortlessbuilding.mode.normal_plus", new NormalPlus(), OptionEnum.BUILD_SPEED),
LINE("effortlessbuilding.mode.line", new Line() /*, OptionEnum.THICKNESS*/),
WALL("effortlessbuilding.mode.wall", new Wall(), OptionEnum.FILL),
FLOOR("effortlessbuilding.mode.floor", new Floor(), OptionEnum.FILL),
DIAGONAL_LINE("effortlessbuilding.mode.diagonal_line", new DiagonalLine() /*, OptionEnum.THICKNESS*/),
DIAGONAL_WALL("effortlessbuilding.mode.diagonal_wall", new DiagonalWall() /*, OptionEnum.FILL*/),
SLOPE_FLOOR("effortlessbuilding.mode.slope_floor", new SlopeFloor(), OptionEnum.RAISED_EDGE),
CIRCLE("effortlessbuilding.mode.circle", new Circle(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CYLINDER("effortlessbuilding.mode.cylinder", new Cylinder(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
SPHERE("effortlessbuilding.mode.sphere", new Sphere(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CUBE("effortlessbuilding.mode.cube", new Cube(), OptionEnum.CUBE_FILL);
//Uses a network message to get the previous raytraceresult from the player
//The server could keep track of all raytraceresults but this might lag with many players
//Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(Player player, BlockPlacedMessage message) {
public String name;
public IBuildMode instance;
public OptionEnum[] options;
//Check if not in the middle of breaking
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) {
//Cancel breaking
initializeMode(player);
return;
}
BuildModeEnum(String name, IBuildMode instance, OptionEnum... options) {
this.name = name;
this.instance = instance;
this.options = options;
}
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode();
//Uses a network message to get the previous raytraceresult from the player
//The server could keep track of all raytraceresults but this might lag with many players
//Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) {
BlockPos startPos = null;
//Check if not in the middle of breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) {
//Cancel breaking
initializeMode(player);
return;
}
if (message.isBlockHit() && message.getBlockPos() != null) {
startPos = message.getBlockPos();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode();
//Offset in direction of sidehit if not quickreplace and not replaceable
//TODO 1.13 replaceable
boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable();
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, message.getSideHit());
if (!modifierSettings.doQuickReplace() && !replaceable && !becomesDoubleSlab) {
startPos = startPos.relative(message.getSideHit());
}
BlockPos startPos = null;
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && replaceable) {
startPos = startPos.below();
}
if (message.isBlockHit() && message.getBlockPos() != null) {
startPos = message.getBlockPos();
//Check if player reach does not exceed startpos
int maxReach = ReachHelper.getMaxReach(player);
if (buildMode != BuildModeEnum.NORMAL && player.blockPosition().distSqr(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
}
//Offset in direction of sidehit if not quickreplace and not replaceable
//TODO 1.13 replaceable
boolean replaceable = player.world.getBlockState(startPos).getMaterial().isReplaceable();
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, message.getSideHit());
if (!modifierSettings.doQuickReplace() && !replaceable && !becomesDoubleSlab) {
startPos = startPos.offset(message.getSideHit());
}
//Even when no starting block is found, call buildmode instance
//We might want to place things in the air
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace());
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && replaceable) {
startPos = startPos.down();
}
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, false);
return;
}
//Check if player reach does not exceed startpos
int maxReach = ReachHelper.getMaxReach(player);
if (buildMode != BuildModeEnum.NORMAL && player.getPosition().distanceSq(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (coordinates.size() > limit) {
coordinates = coordinates.subList(0, limit);
}
//Even when no starting block is found, call buildmode instance
//We might want to place things in the air
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace());
Direction sideHit = buildMode.instance.getSideHit(player);
if (sideHit == null) sideHit = message.getSideHit();
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, false);
return;
}
Vec3 hitVec = buildMode.instance.getHitVec(player);
if (hitVec == null) hitVec = message.getHitVec();
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (coordinates.size() > limit) {
coordinates = coordinates.subList(0, limit);
}
BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec, message.getPlaceStartPos());
EnumFacing sideHit = buildMode.instance.getSideHit(player);
if (sideHit == null) sideHit = message.getSideHit();
//Only works when finishing a buildmode is equal to placing some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
Vec3d hitVec = buildMode.instance.getHitVec(player);
if (hitVec == null) hitVec = message.getHitVec();
}
BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec, message.getPlaceStartPos());
//Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(Player player, BlockBrokenMessage message) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null;
onBlockBroken(player, startPos, true);
}
//Only works when finishing a buildmode is equal to placing some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
public static void onBlockBroken(Player player, BlockPos startPos, boolean breakStartPos) {
}
//Check if not in the middle of placing
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing
initializeMode(player);
return;
}
//Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null;
onBlockBroken(player, startPos, true);
}
//If first click
if (currentlyBreaking.get(player) == null) {
//If startpos is null, dont do anything
if (startPos == null) return;
}
public static void onBlockBroken(EntityPlayer player, BlockPos startPos, boolean breakStartPos) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if not in the middle of placing
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing
initializeMode(player);
return;
}
//Get coordinates
BuildModeEnum buildMode = modeSettings.getBuildMode();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, Direction.UP, Vec3.ZERO, true);
//If first click
if (currentlyBreaking.get(player) == null) {
//If startpos is null, dont do anything
if (startPos == null) return;
}
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, true);
return;
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Let buildmodifiers break blocks
BuildModifiers.onBlockBroken(player, coordinates, breakStartPos);
//Get coordinates
BuildModeEnum buildMode = modeSettings.getBuildMode();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, EnumFacing.UP, Vec3d.ZERO, true);
//Only works when finishing a buildmode is equal to breaking some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
}
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, true);
return;
}
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos, boolean skipRaytrace) {
List<BlockPos> coordinates = new ArrayList<>();
//Let buildmodifiers break blocks
BuildModifiers.onBlockBroken(player, coordinates, breakStartPos);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace));
//Only works when finishing a buildmode is equal to breaking some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
}
return coordinates;
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos, boolean skipRaytrace) {
List<BlockPos> coordinates = new ArrayList<>();
public static void initializeMode(Player player) {
//Resetting mode, so not placing or breaking
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace));
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
}
return coordinates;
}
public static boolean isCurrentlyPlacing(Player player) {
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && !currentlyBreaking.get(player);
}
public static void initializeMode(EntityPlayer player) {
//Resetting mode, so not placing or breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player);
public static boolean isCurrentlyBreaking(Player player) {
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && currentlyBreaking.get(player);
}
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
}
//Either placing or breaking
public static boolean isActive(Player player) {
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null;
}
public static boolean isCurrentlyPlacing(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && !currentlyBreaking.get(player);
}
//Find coordinates on a line bound by a plane
public static Vec3 findXBound(double x, Vec3 start, Vec3 look) {
//then y and z are
double y = (x - start.x) / look.x * look.y + start.y;
double z = (x - start.x) / look.x * look.z + start.z;
public static boolean isCurrentlyBreaking(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && currentlyBreaking.get(player);
}
//Either placing or breaking
public static boolean isActive(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null;
}
return new Vec3(x, y, z);
}
//-- Common build mode functionality --//
//-- Common build mode functionality --//
//Find coordinates on a line bound by a plane
public static Vec3d findXBound(double x, Vec3d start, Vec3d look) {
//then y and z are
double y = (x - start.x) / look.x * look.y + start.y;
double z = (x - start.x) / look.x * look.z + start.z;
public static Vec3 findYBound(double y, Vec3 start, Vec3 look) {
//then x and z are
double x = (y - start.y) / look.y * look.x + start.x;
double z = (y - start.y) / look.y * look.z + start.z;
return new Vec3d(x, y, z);
}
return new Vec3(x, y, z);
}
public static Vec3d findYBound(double y, Vec3d start, Vec3d look) {
//then x and z are
double x = (y - start.y) / look.y * look.x + start.x;
double z = (y - start.y) / look.y * look.z + start.z;
public static Vec3 findZBound(double z, Vec3 start, Vec3 look) {
//then x and y are
double x = (z - start.z) / look.z * look.x + start.x;
double y = (z - start.z) / look.z * look.y + start.y;
return new Vec3d(x, y, z);
}
return new Vec3(x, y, z);
}
public static Vec3d findZBound(double z, Vec3d start, Vec3d look) {
//then x and y are
double x = (z - start.z) / look.z * look.x + start.x;
double y = (z - start.z) / look.z * look.y + start.y;
//Use this instead of player.getLookVec() in any buildmodes code
public static Vec3 getPlayerLookVec(Player player) {
Vec3 lookVec = player.getLookAngle();
double x = lookVec.x;
double y = lookVec.y;
double z = lookVec.z;
return new Vec3d(x, y, z);
}
//Further calculations (findXBound etc) don't like any component being 0 or 1 (e.g. dividing by 0)
//isCriteriaValid below will take up to 2 minutes to raytrace blocks towards infinity if that is the case
//So make sure they are close to but never exactly 0 or 1
if (Math.abs(x) < 0.0001) x = 0.0001;
if (Math.abs(x - 1.0) < 0.0001) x = 0.9999;
if (Math.abs(x + 1.0) < 0.0001) x = -0.9999;
public static boolean isCriteriaValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace, Vec3d lineBound, Vec3d planeBound, double distToPlayerSq) {
boolean intersects = false;
if (!skipRaytrace) {
//collision within a 1 block radius to selected is fine
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, lineBound, RayTraceFluidMode.NEVER, true, false);
intersects = rayTraceResult != null && rayTraceResult.type == RayTraceResult.Type.BLOCK &&
planeBound.subtract(rayTraceResult.hitVec).lengthSquared() > 4;
}
if (Math.abs(y) < 0.0001) y = 0.0001;
if (Math.abs(y - 1.0) < 0.0001) y = 0.9999;
if (Math.abs(y + 1.0) < 0.0001) y = -0.9999;
return planeBound.subtract(start).dotProduct(look) > 0 &&
distToPlayerSq > 2 && distToPlayerSq < reach * reach &&
!intersects;
}
if (Math.abs(z) < 0.0001) z = 0.0001;
if (Math.abs(z - 1.0) < 0.0001) z = 0.9999;
if (Math.abs(z + 1.0) < 0.0001) z = -0.9999;
return new Vec3(x, y, z);
}
public static boolean isCriteriaValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace, Vec3 lineBound, Vec3 planeBound, double distToPlayerSq) {
boolean intersects = false;
if (!skipRaytrace) {
//collision within a 1 block radius to selected is fine
ClipContext rayTraceContext = new ClipContext(start, lineBound, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player);
HitResult rayTraceResult = player.level.clip(rayTraceContext);
intersects = rayTraceResult != null && rayTraceResult.getType() == HitResult.Type.BLOCK &&
planeBound.subtract(rayTraceResult.getLocation()).lengthSqr() > 4;
}
return planeBound.subtract(start).dot(look) > 0 &&
distToPlayerSq > 2 && distToPlayerSq < reach * reach &&
!intersects;
}
public enum BuildModeEnum {
NORMAL("effortlessbuilding.mode.normal", new Normal()),
NORMAL_PLUS("effortlessbuilding.mode.normal_plus", new NormalPlus(), OptionEnum.BUILD_SPEED),
LINE("effortlessbuilding.mode.line", new Line() /*, OptionEnum.THICKNESS*/),
WALL("effortlessbuilding.mode.wall", new Wall(), OptionEnum.FILL),
FLOOR("effortlessbuilding.mode.floor", new Floor(), OptionEnum.FILL),
DIAGONAL_LINE("effortlessbuilding.mode.diagonal_line", new DiagonalLine() /*, OptionEnum.THICKNESS*/),
DIAGONAL_WALL("effortlessbuilding.mode.diagonal_wall", new DiagonalWall() /*, OptionEnum.FILL*/),
SLOPE_FLOOR("effortlessbuilding.mode.slope_floor", new SlopeFloor(), OptionEnum.RAISED_EDGE),
CIRCLE("effortlessbuilding.mode.circle", new Circle(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CYLINDER("effortlessbuilding.mode.cylinder", new Cylinder(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
SPHERE("effortlessbuilding.mode.sphere", new Sphere(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CUBE("effortlessbuilding.mode.cube", new Cube(), OptionEnum.CUBE_FILL);
public String name;
public IBuildMode instance;
public OptionEnum[] options;
BuildModeEnum(String name, IBuildMode instance, OptionEnum... options) {
this.name = name;
this.instance = instance;
this.options = options;
}
}
}

View File

@@ -1,25 +1,25 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import java.util.List;
public interface IBuildMode {
//Fired when a player selects a buildmode and when it needs to initializeMode
void initialize(EntityPlayer player);
//Fired when a player selects a buildmode and when it needs to initializeMode
void initialize(Player player);
//Fired when a block would be placed
//Return a list of coordinates where you want to place blocks
List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace);
//Fired when a block would be placed
//Return a list of coordinates where you want to place blocks
List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace);
//Fired continuously for visualization purposes
List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace);
//Fired continuously for visualization purposes
List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace);
EnumFacing getSideHit(EntityPlayer player);
Direction getSideHit(Player player);
Vec3d getHitVec(EntityPlayer player);
Vec3 getHitVec(Player player);
}

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.entity.player.Player;
import net.minecraft.ChatFormatting;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
@@ -9,174 +9,183 @@ import nl.requios.effortlessbuilding.proxy.ClientProxy;
public class ModeOptions {
public enum ActionEnum {
UNDO("effortlessbuilding.action.undo"),
REDO("effortlessbuilding.action.redo"),
REPLACE("effortlessbuilding.action.replace"),
OPEN_MODIFIER_SETTINGS("effortlessbuilding.action.open_modifier_settings"),
private static ActionEnum buildSpeed = ActionEnum.NORMAL_SPEED;
private static ActionEnum fill = ActionEnum.FULL;
private static ActionEnum cubeFill = ActionEnum.CUBE_FULL;
private static ActionEnum raisedEdge = ActionEnum.SHORT_EDGE;
private static ActionEnum lineThickness = ActionEnum.THICKNESS_1;
private static ActionEnum circleStart = ActionEnum.CIRCLE_START_CORNER;
NORMAL_SPEED("effortlessbuilding.action.normal_speed"),
FAST_SPEED("effortlessbuilding.action.fast_speed"),
public static ActionEnum getOptionSetting(OptionEnum option) {
switch (option) {
case BUILD_SPEED:
return getBuildSpeed();
case FILL:
return getFill();
case CUBE_FILL:
return getCubeFill();
case RAISED_EDGE:
return getRaisedEdge();
case LINE_THICKNESS:
return getLineThickness();
case CIRCLE_START:
return getCircleStart();
default:
return null;
}
}
FULL("effortlessbuilding.action.full"),
HOLLOW("effortlessbuilding.action.hollow"),
public static ActionEnum getBuildSpeed() {
return buildSpeed;
}
CUBE_FULL("effortlessbuilding.action.full"),
CUBE_HOLLOW("effortlessbuilding.action.hollow"),
CUBE_SKELETON("effortlessbuilding.action.skeleton"),
public static ActionEnum getFill() {
return fill;
}
SHORT_EDGE("effortlessbuilding.action.short_edge"),
LONG_EDGE("effortlessbuilding.action.long_edge"),
public static ActionEnum getCubeFill() {
return cubeFill;
}
THICKNESS_1("effortlessbuilding.action.thickness_1"),
THICKNESS_3("effortlessbuilding.action.thickness_3"),
THICKNESS_5("effortlessbuilding.action.thickness_5"),
public static ActionEnum getRaisedEdge() {
return raisedEdge;
}
CIRCLE_START_CORNER("effortlessbuilding.action.start_corner"),
CIRCLE_START_CENTER("effortlessbuilding.action.start_center");
public static ActionEnum getLineThickness() {
return lineThickness;
}
public String name;
public static ActionEnum getCircleStart() {
return circleStart;
}
ActionEnum(String name) {
this.name = name;
}
}
//Called on both client and server
public static void performAction(Player player, ActionEnum action) {
if (action == null) return;
public enum OptionEnum {
BUILD_SPEED("effortlessbuilding.action.build_speed", ActionEnum.NORMAL_SPEED, ActionEnum.FAST_SPEED),
FILL("effortlessbuilding.action.filling", ActionEnum.FULL, ActionEnum.HOLLOW),
CUBE_FILL("effortlessbuilding.action.filling", ActionEnum.CUBE_FULL, ActionEnum.CUBE_HOLLOW, ActionEnum.CUBE_SKELETON),
RAISED_EDGE("effortlessbuilding.action.raised_edge", ActionEnum.SHORT_EDGE, ActionEnum.LONG_EDGE),
LINE_THICKNESS("effortlessbuilding.action.thickness", ActionEnum.THICKNESS_1, ActionEnum.THICKNESS_3, ActionEnum.THICKNESS_5),
CIRCLE_START("effortlessbuilding.action.circle_start", ActionEnum.CIRCLE_START_CORNER, ActionEnum.CIRCLE_START_CENTER);
switch (action) {
case UNDO:
UndoRedo.undo(player);
break;
case REDO:
UndoRedo.redo(player);
break;
case REPLACE:
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + ChatFormatting.GOLD + "Quick Replace " + ChatFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"), true);
break;
case OPEN_MODIFIER_SETTINGS:
if (player.level.isClientSide)
ClientProxy.openModifierSettings();
break;
case OPEN_PLAYER_SETTINGS:
if (player.level.isClientSide)
ClientProxy.openPlayerSettings();
break;
public String name;
public ActionEnum[] actions;
case NORMAL_SPEED:
buildSpeed = ActionEnum.NORMAL_SPEED;
break;
case FAST_SPEED:
buildSpeed = ActionEnum.FAST_SPEED;
break;
case FULL:
fill = ActionEnum.FULL;
break;
case HOLLOW:
fill = ActionEnum.HOLLOW;
break;
case CUBE_FULL:
cubeFill = ActionEnum.CUBE_FULL;
break;
case CUBE_HOLLOW:
cubeFill = ActionEnum.CUBE_HOLLOW;
break;
case CUBE_SKELETON:
cubeFill = ActionEnum.CUBE_SKELETON;
break;
case SHORT_EDGE:
raisedEdge = ActionEnum.SHORT_EDGE;
break;
case LONG_EDGE:
raisedEdge = ActionEnum.LONG_EDGE;
break;
case THICKNESS_1:
lineThickness = ActionEnum.THICKNESS_1;
break;
case THICKNESS_3:
lineThickness = ActionEnum.THICKNESS_3;
break;
case THICKNESS_5:
lineThickness = ActionEnum.THICKNESS_5;
break;
case CIRCLE_START_CENTER:
circleStart = ActionEnum.CIRCLE_START_CENTER;
break;
case CIRCLE_START_CORNER:
circleStart = ActionEnum.CIRCLE_START_CORNER;
break;
}
OptionEnum(String name, ActionEnum... actions){
this.name = name;
this.actions = actions;
}
}
if (player.level.isClientSide &&
action != ActionEnum.REPLACE &&
action != ActionEnum.OPEN_MODIFIER_SETTINGS &&
action != ActionEnum.OPEN_PLAYER_SETTINGS) {
private static ActionEnum buildSpeed = ActionEnum.NORMAL_SPEED;
private static ActionEnum fill = ActionEnum.FULL;
private static ActionEnum cubeFill = ActionEnum.CUBE_FULL;
private static ActionEnum raisedEdge = ActionEnum.SHORT_EDGE;
private static ActionEnum lineThickness = ActionEnum.THICKNESS_1;
private static ActionEnum circleStart = ActionEnum.CIRCLE_START_CORNER;
EffortlessBuilding.logTranslate(player, "", action.name, "", true);
}
}
public static ActionEnum getOptionSetting(OptionEnum option) {
switch (option) {
case BUILD_SPEED:
return getBuildSpeed();
case FILL:
return getFill();
case CUBE_FILL:
return getCubeFill();
case RAISED_EDGE:
return getRaisedEdge();
case LINE_THICKNESS:
return getLineThickness();
case CIRCLE_START:
return getCircleStart();
default:
return null;
}
}
public enum ActionEnum {
UNDO("effortlessbuilding.action.undo"),
REDO("effortlessbuilding.action.redo"),
REPLACE("effortlessbuilding.action.replace"),
OPEN_MODIFIER_SETTINGS("effortlessbuilding.action.open_modifier_settings"),
OPEN_PLAYER_SETTINGS("effortlessbuilding.action.open_player_settings"),
public static ActionEnum getBuildSpeed() {
return buildSpeed;
}
NORMAL_SPEED("effortlessbuilding.action.normal_speed"),
FAST_SPEED("effortlessbuilding.action.fast_speed"),
public static ActionEnum getFill() {
return fill;
}
FULL("effortlessbuilding.action.full"),
HOLLOW("effortlessbuilding.action.hollow"),
public static ActionEnum getCubeFill() {
return cubeFill;
}
CUBE_FULL("effortlessbuilding.action.full"),
CUBE_HOLLOW("effortlessbuilding.action.hollow"),
CUBE_SKELETON("effortlessbuilding.action.skeleton"),
public static ActionEnum getRaisedEdge() {
return raisedEdge;
}
SHORT_EDGE("effortlessbuilding.action.short_edge"),
LONG_EDGE("effortlessbuilding.action.long_edge"),
public static ActionEnum getLineThickness() {
return lineThickness;
}
THICKNESS_1("effortlessbuilding.action.thickness_1"),
THICKNESS_3("effortlessbuilding.action.thickness_3"),
THICKNESS_5("effortlessbuilding.action.thickness_5"),
public static ActionEnum getCircleStart() {
return circleStart;
}
CIRCLE_START_CORNER("effortlessbuilding.action.start_corner"),
CIRCLE_START_CENTER("effortlessbuilding.action.start_center");
//Called on both client and server
public static void performAction(EntityPlayer player, ActionEnum action) {
if (action == null) return;
public String name;
switch (action) {
case UNDO:
UndoRedo.undo(player);
break;
case REDO:
UndoRedo.redo(player);
break;
case REPLACE:
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"), true);
break;
case OPEN_MODIFIER_SETTINGS:
if (player.world.isRemote)
ClientProxy.openModifierSettings();
break;
ActionEnum(String name) {
this.name = name;
}
}
case NORMAL_SPEED:
buildSpeed = ActionEnum.NORMAL_SPEED;
break;
case FAST_SPEED:
buildSpeed = ActionEnum.FAST_SPEED;
break;
case FULL:
fill = ActionEnum.FULL;
break;
case HOLLOW:
fill = ActionEnum.HOLLOW;
break;
case CUBE_FULL:
cubeFill = ActionEnum.CUBE_FULL;
break;
case CUBE_HOLLOW:
cubeFill = ActionEnum.CUBE_HOLLOW;
break;
case CUBE_SKELETON:
cubeFill = ActionEnum.CUBE_SKELETON;
break;
case SHORT_EDGE:
raisedEdge = ActionEnum.SHORT_EDGE;
break;
case LONG_EDGE:
raisedEdge = ActionEnum.LONG_EDGE;
break;
case THICKNESS_1:
lineThickness = ActionEnum.THICKNESS_1;
break;
case THICKNESS_3:
lineThickness = ActionEnum.THICKNESS_3;
break;
case THICKNESS_5:
lineThickness = ActionEnum.THICKNESS_5;
break;
case CIRCLE_START_CENTER:
circleStart = ActionEnum.CIRCLE_START_CENTER;
break;
case CIRCLE_START_CORNER:
circleStart = ActionEnum.CIRCLE_START_CORNER;
break;
}
public enum OptionEnum {
BUILD_SPEED("effortlessbuilding.action.build_speed", ActionEnum.NORMAL_SPEED, ActionEnum.FAST_SPEED),
FILL("effortlessbuilding.action.filling", ActionEnum.FULL, ActionEnum.HOLLOW),
CUBE_FILL("effortlessbuilding.action.filling", ActionEnum.CUBE_FULL, ActionEnum.CUBE_HOLLOW, ActionEnum.CUBE_SKELETON),
RAISED_EDGE("effortlessbuilding.action.raised_edge", ActionEnum.SHORT_EDGE, ActionEnum.LONG_EDGE),
LINE_THICKNESS("effortlessbuilding.action.thickness", ActionEnum.THICKNESS_1, ActionEnum.THICKNESS_3, ActionEnum.THICKNESS_5),
CIRCLE_START("effortlessbuilding.action.circle_start", ActionEnum.CIRCLE_START_CORNER, ActionEnum.CIRCLE_START_CENTER);
if (player.world.isRemote && action != ActionEnum.REPLACE && action != ActionEnum.OPEN_MODIFIER_SETTINGS) {
ClientProxy.logTranslate(action.name);
}
}
public String name;
public ActionEnum[] actions;
OptionEnum(String name, ActionEnum... actions) {
this.name = name;
this.actions = actions;
}
}
}

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -16,83 +16,83 @@ import javax.annotation.Nonnull;
@Mod.EventBusSubscriber
public class ModeSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null
@Nonnull
public static ModeSettings getModeSettings(EntityPlayer player) {
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.modeCapability, null);
//Retrieves the buildsettings of a player through the modeCapability capability
//Never returns null
@Nonnull
public static ModeSettings getModeSettings(Player player) {
if (modeCapability.isPresent()) {
ModeCapabilityManager.IModeCapability capability = modeCapability.orElse(null);
if (capability.getModeData() == null) {
capability.setModeData(new ModeSettings());
}
return capability.getModeData();
}
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.MODE_CAPABILITY, null);
//Player does not have modeCapability capability
//Return dummy settings
return new ModeSettings();
// throw new IllegalArgumentException("Player does not have modeCapability capability");
}
if (modeCapability.isPresent()) {
ModeCapabilityManager.IModeCapability capability = modeCapability.orElse(null);
if (capability.getModeData() == null){
capability.setModeData(new ModeSettings());
}
return capability.getModeData();
}
public static void setModeSettings(EntityPlayer player, ModeSettings modeSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildmode settings, player is null");
return;
}
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.modeCapability, null);
EffortlessBuilding.logger.warn("Player does not have modeCapability: " + player);
//Return dummy settings
return new ModeSettings();
}
modeCapability.ifPresent((capability) -> {
capability.setModeData(modeSettings);
public static void setModeSettings(Player player, ModeSettings modeSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildmode settings, player is null");
return;
}
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.MODE_CAPABILITY, null);
BuildModes.initializeMode(player);
});
modeCapability.ifPresent((capability) -> {
capability.setModeData(modeSettings);
if (!modeCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildmode settings failed.");
}
}
BuildModes.initializeMode(player);
});
public static String sanitize(ModeSettings modeSettings, EntityPlayer player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
if (!modeCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildmode settings failed.");
}
}
//TODO sanitize
public static String sanitize(ModeSettings modeSettings, Player player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
return error;
}
//TODO sanitize
public static class ModeSettings {
private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.NORMAL;
return error;
}
public ModeSettings() {
}
public static void handleNewPlayer(Player player) {
//Makes sure player has mode settings (if it doesnt it will create it)
getModeSettings(player);
public ModeSettings(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
//Only on server
if (!player.level.isClientSide) {
//Send to client
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), msg);
}
}
public BuildModes.BuildModeEnum getBuildMode() {
return this.buildMode;
}
public static class ModeSettings {
private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.NORMAL;
public void setBuildMode(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
}
public ModeSettings() {
}
public static void handleNewPlayer(EntityPlayer player){
//Makes sure player has mode settings (if it doesnt it will create it)
getModeSettings(player);
public ModeSettings(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
//Only on server
if (!player.world.isRemote) {
//Send to client
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), msg);
}
}
public BuildModes.BuildModeEnum getBuildMode() {
return this.buildMode;
}
public void setBuildMode(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
}
}

View File

@@ -1,215 +1,213 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.buildmodes.DiagonalLine;
import nl.requios.effortlessbuilding.buildmode.buildmodes.Floor;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public abstract class ThreeClicksBuildMode extends BaseBuildMode {
protected Dictionary<UUID, BlockPos> secondPosTable = new Hashtable<>();
protected Dictionary<UUID, BlockPos> secondPosTable = new Hashtable<>();
static class HeightCriteria {
Vec3d planeBound;
Vec3d lineBound;
double distToLineSq;
double distToPlayerSq;
//Finds height after floor has been chosen in buildmodes with 3 clicks
public static BlockPos findHeight(Player player, BlockPos secondPos, boolean skipRaytrace) {
Vec3 look = BuildModes.getPlayerLookVec(player);
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
HeightCriteria(Vec3d planeBound, BlockPos secondPos, Vec3d start) {
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, secondPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
List<HeightCriteria> criteriaList = new ArrayList<>(3);
//Make it from a plane into a line, on y axis only
private Vec3d toLongestLine(Vec3d boundVec, BlockPos secondPos) {
BlockPos bound = new BlockPos(boundVec);
return new Vec3d(secondPos.getX(), bound.getY(), secondPos.getZ());
}
//X
Vec3 xBound = BuildModes.findXBound(secondPos.getX(), start, look);
criteriaList.add(new HeightCriteria(xBound, secondPos, start));
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
//Z
Vec3 zBound = BuildModes.findZBound(secondPos.getZ(), start, look);
criteriaList.add(new HeightCriteria(zBound, secondPos, start));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
}
}
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
@Override
public void initialize(EntityPlayer player) {
super.initialize(player);
secondPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
}
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
//If only 1 is valid, choose that one
HeightCriteria selected = criteriaList.get(0);
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
HeightCriteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
}
return new BlockPos(selected.lineBound);
}
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
@Override
public void initialize(Player player) {
super.initialize(player);
secondPosTable.put(player.getUUID(), BlockPos.ZERO);
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else if (rightClickNr == 2) {
//Second click, find other floor point
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
BlockPos secondPos = findSecondPos(player, firstPos, true);
@Override
public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (secondPos == null) {
rightClickTable.put(player.getUniqueID(), 1);
return list;
}
Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUUID());
rightClickNr++;
rightClickTable.put(player.getUUID(), rightClickNr);
secondPosTable.put(player.getUniqueID(), secondPos);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUUID(), 0);
return list;
}
} else {
//Third click, place diagonal wall with height
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
//First click, remember starting position
firstPosTable.put(player.getUUID(), blockPos);
sideHitTable.put(player.getUUID(), sideHit);
hitVecTable.put(player.getUUID(), hitVec);
//Keep list empty, dont place any blocks yet
} else if (rightClickNr == 2) {
//Second click, find other floor point
BlockPos firstPos = firstPosTable.get(player.getUUID());
BlockPos secondPos = findSecondPos(player, firstPos, true);
return list;
}
if (secondPos == null) {
rightClickTable.put(player.getUUID(), 1);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
secondPosTable.put(player.getUUID(), secondPos);
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else if (rightClickNr == 1) {
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
} else {
//Third click, place diagonal wall with height
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUUID(), 0);
}
BlockPos secondPos = findSecondPos(player, firstPos, true);
if (secondPos == null) return list;
return list;
}
//Limit amount of blocks you can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
@Override
public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUUID());
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else if (rightClickNr == 1) {
BlockPos firstPos = firstPosTable.get(player.getUUID());
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
BlockPos secondPos = findSecondPos(player, firstPos, true);
if (secondPos == null) return list;
//Add diagonal line from first to second
list.addAll(getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2));
//Limit amount of blocks you can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
} else {
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
BlockPos secondPos = secondPosTable.get(player.getUniqueID());
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, skipRaytrace);
if (thirdPos == null) return list;
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//Limit amount of blocks you can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
//Add diagonal line from first to second
list.addAll(getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2));
int x1 = firstPos.getX(), x2 = secondPos.getX(), x3 = thirdPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY(), y3 = thirdPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ(), z3 = thirdPos.getZ();
} else {
BlockPos firstPos = firstPosTable.get(player.getUUID());
BlockPos secondPos = secondPosTable.get(player.getUUID());
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, skipRaytrace);
if (thirdPos == null) return list;
if (x3 - x1 >= axisLimit) x3 = x1 + axisLimit - 1;
if (x1 - x3 >= axisLimit) x3 = x1 - axisLimit + 1;
if (y3 - y1 >= axisLimit) y3 = y1 + axisLimit - 1;
if (y1 - y3 >= axisLimit) y3 = y1 - axisLimit + 1;
if (z3 - z1 >= axisLimit) z3 = z1 + axisLimit - 1;
if (z1 - z3 >= axisLimit) z3 = z1 - axisLimit + 1;
//Limit amount of blocks you can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
//Add diagonal line from first to third
list.addAll(getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3));
}
int x1 = firstPos.getX(), x2 = secondPos.getX(), x3 = thirdPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY(), y3 = thirdPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ(), z3 = thirdPos.getZ();
return list;
}
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//Finds the place of the second block pos
protected abstract BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace);
if (x3 - x1 >= axisLimit) x3 = x1 + axisLimit - 1;
if (x1 - x3 >= axisLimit) x3 = x1 - axisLimit + 1;
if (y3 - y1 >= axisLimit) y3 = y1 + axisLimit - 1;
if (y1 - y3 >= axisLimit) y3 = y1 - axisLimit + 1;
if (z3 - z1 >= axisLimit) z3 = z1 + axisLimit - 1;
if (z1 - z3 >= axisLimit) z3 = z1 - axisLimit + 1;
//Finds the place of the third block pos
protected abstract BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace);
//Add diagonal line from first to third
list.addAll(getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3));
}
//After first and second pos are known, we want to visualize the blocks in a way (like floor for cube)
protected abstract List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2);
return list;
}
//After first, second and third pos are known, we want all the blocks
protected abstract List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3);
//Finds the place of the second block pos
protected abstract BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace);
//Finds height after floor has been chosen in buildmodes with 3 clicks
public static BlockPos findHeight(EntityPlayer player, BlockPos secondPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//Finds the place of the third block pos
protected abstract BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace);
List<HeightCriteria> criteriaList = new ArrayList<>(3);
//After first and second pos are known, we want to visualize the blocks in a way (like floor for cube)
protected abstract List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2);
//X
Vec3d xBound = BuildModes.findXBound(secondPos.getX(), start, look);
criteriaList.add(new HeightCriteria(xBound, secondPos, start));
//After first, second and third pos are known, we want all the blocks
protected abstract List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3);
//Z
Vec3d zBound = BuildModes.findZBound(secondPos.getZ(), start, look);
criteriaList.add(new HeightCriteria(zBound, secondPos, start));
static class HeightCriteria {
Vec3 planeBound;
Vec3 lineBound;
double distToLineSq;
double distToPlayerSq;
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
HeightCriteria(Vec3 planeBound, BlockPos secondPos, Vec3 start) {
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, secondPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSqr();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
}
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
//Make it from a plane into a line, on y axis only
private Vec3 toLongestLine(Vec3 boundVec, BlockPos secondPos) {
BlockPos bound = new BlockPos(boundVec);
return new Vec3(secondPos.getX(), bound.getY(), secondPos.getZ());
}
//If only 1 is valid, choose that one
HeightCriteria selected = criteriaList.get(0);
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
HeightCriteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
}
return new BlockPos(selected.lineBound);
}
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
}
}
}

View File

@@ -1,9 +1,9 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
@@ -13,74 +13,74 @@ import java.util.UUID;
public abstract class TwoClicksBuildMode extends BaseBuildMode {
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
@Override
public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUUID());
rightClickNr++;
rightClickTable.put(player.getUUID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUUID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place blocks
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
//First click, remember starting position
firstPosTable.put(player.getUUID(), blockPos);
sideHitTable.put(player.getUUID(), sideHit);
hitVecTable.put(player.getUUID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place blocks
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUUID(), 0);
}
return list;
}
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
@Override
public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUUID());
BlockPos firstPos = firstPosTable.get(player.getUUID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
BlockPos secondPos = findSecondPos(player, firstPos, skipRaytrace);
if (secondPos == null) return list;
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
BlockPos secondPos = findSecondPos(player, firstPos, skipRaytrace);
if (secondPos == null) return list;
//Limit amount of blocks we can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
//Limit amount of blocks we can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
list.addAll(getAllBlocks(player, x1, y1, z1, x2, y2, z2));
}
list.addAll(getAllBlocks(player, x1, y1, z1, x2, y2, z2));
}
return list;
}
return list;
}
//Finds the place of the second block pos based on criteria (floor must be on same height as first click, wall on same plane etc)
protected abstract BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace);
//Finds the place of the second block pos based on criteria (floor must be on same height as first click, wall on same plane etc)
protected abstract BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace);
//After first and second pos are known, we want all the blocks
protected abstract List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2);
//After first and second pos are known, we want all the blocks
protected abstract List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2);
}

View File

@@ -1,88 +1,89 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class Circle extends TwoClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static List<BlockPos> getCircleBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
float centerX = x1;
float centerZ = z1;
public static List<BlockPos> getCircleBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
//Adjust for CIRCLE_START
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
z1 = (int) (centerZ - (z2 - centerZ));
}
float centerX = x1;
float centerZ = z1;
float radiusX = Mth.abs(x2 - centerX);
float radiusZ = Mth.abs(z2 - centerZ);
//Adjust for CIRCLE_START
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
z1 = (int) (centerZ - (z2 - centerZ));
}
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
else
addHollowCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
float radiusX = MathHelper.abs(x2 - centerX);
float radiusZ = MathHelper.abs(z2 - centerZ);
return list;
}
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
else
addHollowCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
public static void addCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
return list;
}
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
public static void addCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, y1, n));
}
}
}
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
public static void addHollowCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, y1, n));
}
}
}
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
public static void addHollowCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, y1, n));
}
}
}
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
private static float distance(float x1, float z1, float x2, float z2) {
return Mth.sqrt((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1));
}
float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, y1, n));
}
}
}
public static float calculateEllipseRadius(float centerX, float centerZ, float radiusX, float radiusZ, int x, int z) {
//https://math.stackexchange.com/questions/432902/how-to-get-the-radius-of-an-ellipse-at-a-specific-angle-by-knowing-its-semi-majo
float theta = (float) Mth.atan2(z - centerZ, x - centerX);
float part1 = radiusX * radiusX * Mth.sin(theta) * Mth.sin(theta);
float part2 = radiusZ * radiusZ * Mth.cos(theta) * Mth.cos(theta);
return radiusX * radiusZ / Mth.sqrt(part1 + part2);
}
private static float distance(float x1, float z1, float x2, float z2) {
return MathHelper.sqrt((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1));
}
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static float calculateEllipseRadius(float centerX, float centerZ, float radiusX, float radiusZ, int x, int z) {
//https://math.stackexchange.com/questions/432902/how-to-get-the-radius-of-an-ellipse-at-a-specific-angle-by-knowing-its-semi-majo
float theta = (float) MathHelper.atan2(z - centerZ, x - centerX);
float part1 = radiusX * radiusX * MathHelper.sin(theta) * MathHelper.sin(theta);
float part2 = radiusZ * radiusZ * MathHelper.cos(theta) * MathHelper.cos(theta);
return radiusX * radiusZ / MathHelper.sqrt(part1 + part2);
}
@Override
protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
}

View File

@@ -1,104 +1,101 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class Cube extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static List<BlockPos> getFloorBlocksUsingCubeFill(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
if (ModeOptions.getCubeFill() == ModeOptions.ActionEnum.CUBE_SKELETON)
Floor.addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
else
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocksUsingCubeFill(player, x1, y1, z1, x2, y2, z2);
}
return list;
}
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCubeBlocks(player, x1, y1, z1, x3, y3, z3);
}
public static List<BlockPos> getCubeBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
public static List<BlockPos> getFloorBlocksUsingCubeFill(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
switch (ModeOptions.getCubeFill()) {
case CUBE_FULL:
addCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_HOLLOW:
addHollowCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_SKELETON:
addSkeletonCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
}
if (ModeOptions.getCubeFill() == ModeOptions.ActionEnum.CUBE_SKELETON)
Floor.addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
else
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
return list;
}
return list;
}
public static void addCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
public static List<BlockPos> getCubeBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
switch (ModeOptions.getCubeFill()) {
case CUBE_FULL:
addCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_HOLLOW:
addHollowCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_SKELETON:
addSkeletonCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
}
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(l, m, n));
}
}
}
}
return list;
}
public static void addHollowCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
Wall.addXWallBlocks(list, x1, y1, y2, z1, z2);
Wall.addXWallBlocks(list, x2, y1, y2, z1, z2);
public static void addCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
Wall.addZWallBlocks(list, x1, x2, y1, y2, z1);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z2);
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
Floor.addFloorBlocks(list, x1, x2, y2, z1, z2);
}
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(l, m, n));
}
}
}
}
public static void addSkeletonCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
Line.addXLineBlocks(list, x1, x2, y1, z1);
Line.addXLineBlocks(list, x1, x2, y1, z2);
Line.addXLineBlocks(list, x1, x2, y2, z1);
Line.addXLineBlocks(list, x1, x2, y2, z2);
public static void addHollowCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
Wall.addXWallBlocks(list, x1, y1, y2, z1, z2);
Wall.addXWallBlocks(list, x2, y1, y2, z1, z2);
Line.addYLineBlocks(list, y1, y2, x1, z1);
Line.addYLineBlocks(list, y1, y2, x1, z2);
Line.addYLineBlocks(list, y1, y2, x2, z1);
Line.addYLineBlocks(list, y1, y2, x2, z2);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z1);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z2);
Line.addZLineBlocks(list, z1, z2, x1, y1);
Line.addZLineBlocks(list, z1, z2, x1, y2);
Line.addZLineBlocks(list, z1, z2, x2, y1);
Line.addZLineBlocks(list, z1, z2, x2, y2);
}
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
Floor.addFloorBlocks(list, x1, x2, y2, z1, z2);
}
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static void addSkeletonCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
Line.addXLineBlocks(list, x1, x2, y1, z1);
Line.addXLineBlocks(list, x1, x2, y1, z2);
Line.addXLineBlocks(list, x1, x2, y2, z1);
Line.addXLineBlocks(list, x1, x2, y2, z2);
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
Line.addYLineBlocks(list, y1, y2, x1, z1);
Line.addYLineBlocks(list, y1, y2, x1, z2);
Line.addYLineBlocks(list, y1, y2, x2, z1);
Line.addYLineBlocks(list, y1, y2, x2, z2);
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocksUsingCubeFill(player, x1, y1, z1, x2, y2, z2);
}
Line.addZLineBlocks(list, z1, z2, x1, y1);
Line.addZLineBlocks(list, z1, z2, x1, y2);
Line.addZLineBlocks(list, z1, z2, x2, y1);
Line.addZLineBlocks(list, z1, z2, x2, y2);
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCubeBlocks(player, x1, y1, z1, x3, y3, z3);
}
}

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.ArrayList;
@@ -9,42 +9,42 @@ import java.util.List;
public class Cylinder extends ThreeClicksBuildMode {
@Override
public BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static List<BlockPos> getCylinderBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
@Override
public BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Get circle blocks (using CIRCLE_START and FILL options built-in)
List<BlockPos> circleBlocks = Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
@Override
public List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
int lowest = Math.min(y1, y3);
int highest = Math.max(y1, y3);
@Override
public List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCylinderBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
//Copy circle on y axis
for (int y = lowest; y <= highest; y++) {
for (BlockPos blockPos : circleBlocks) {
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
public static List<BlockPos> getCylinderBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
return list;
}
//Get circle blocks (using CIRCLE_START and FILL options built-in)
List<BlockPos> circleBlocks = Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
@Override
public BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
int lowest = Math.min(y1, y3);
int highest = Math.max(y1, y3);
@Override
public BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Copy circle on y axis
for (int y = lowest; y <= highest; y++) {
for (BlockPos blockPos : circleBlocks) {
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
@Override
public List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
return list;
}
@Override
public List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCylinderBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,54 +1,53 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class DiagonalLine extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
//Add diagonal line from first to second
public static List<BlockPos> getDiagonalLineBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, float sampleMultiplier) {
List<BlockPos> list = new ArrayList<>();
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
Vec3 first = new Vec3(x1, y1, z1).add(0.5, 0.5, 0.5);
Vec3 second = new Vec3(x2, y2, z2).add(0.5, 0.5, 0.5);
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
//Add diagonal line from first to second
return getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 10);
}
int iterations = (int) Math.ceil(first.distanceTo(second) * sampleMultiplier);
for (double t = 0; t <= 1.0; t += 1.0 / iterations) {
Vec3 lerp = first.add(second.subtract(first).scale(t));
BlockPos candidate = new BlockPos(lerp);
//Only add if not equal to the last in the list
if (list.isEmpty() || !list.get(list.size() - 1).equals(candidate))
list.add(candidate);
}
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//Add diagonal line from first to third
return getDiagonalLineBlocks(player, x1, y1, z1, x3, y3, z3, 10);
}
return list;
}
//Add diagonal line from first to second
public static List<BlockPos> getDiagonalLineBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, float sampleMultiplier) {
List<BlockPos> list = new ArrayList<>();
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
Vec3d first = new Vec3d(x1, y1, z1).add(0.5, 0.5, 0.5);
Vec3d second = new Vec3d(x2, y2, z2).add(0.5, 0.5, 0.5);
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
int iterations = (int) Math.ceil(first.distanceTo(second) * sampleMultiplier);
for (double t = 0; t <= 1.0; t += 1.0/iterations) {
Vec3d lerp = first.add(second.subtract(first).scale(t));
BlockPos candidate = new BlockPos(lerp);
//Only add if not equal to the last in the list
if (list.isEmpty() || !list.get(list.size() - 1).equals(candidate))
list.add(candidate);
}
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
//Add diagonal line from first to second
return getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 10);
}
return list;
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//Add diagonal line from first to third
return getDiagonalLineBlocks(player, x1, y1, z1, x3, y3, z3, 10);
}
}

View File

@@ -1,52 +1,51 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class DiagonalWall extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
//Add diagonal wall from first to second
public static List<BlockPos> getDiagonalWallBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
}
int lowest = Math.min(y1, y3);
int highest = Math.max(y1, y3);
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getDiagonalWallBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
//Copy diagonal line on y axis
for (int y = lowest; y <= highest; y++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
//Add diagonal wall from first to second
public static List<BlockPos> getDiagonalWallBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
return list;
}
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
int lowest = Math.min(y1, y3);
int highest = Math.max(y1, y3);
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Copy diagonal line on y axis
for (int y = lowest; y <= highest; y++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
}
return list;
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getDiagonalWallBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,93 +1,94 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class Floor extends TwoClicksBuildMode {
static class Criteria {
Vec3d planeBound;
double distToPlayerSq;
public static BlockPos findFloor(Player player, BlockPos firstPos, boolean skipRaytrace) {
Vec3 look = BuildModes.getPlayerLookVec(player);
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Criteria(Vec3d planeBound, Vec3d start) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
List<Criteria> criteriaList = new ArrayList<>(3);
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
//Y
Vec3 yBound = BuildModes.findYBound(firstPos.getY(), start, look);
criteriaList.add(new Criteria(yBound, start));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
}
}
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return findFloor(player, firstPos, skipRaytrace);
}
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
public static BlockPos findFloor(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//Then only 1 can be valid, return that one
Criteria selected = criteriaList.get(0);
List<Criteria> criteriaList = new ArrayList<>(3);
return new BlockPos(selected.planeBound);
}
//Y
Vec3d yBound = BuildModes.findYBound(firstPos.getY(), start, look);
criteriaList.add(new Criteria(yBound, start));
public static List<BlockPos> getFloorBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addFloorBlocks(list, x1, x2, y1, z1, z2);
else
addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
return list;
}
//Then only 1 can be valid, return that one
Criteria selected = criteriaList.get(0);
public static void addFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
return new BlockPos(selected.planeBound);
}
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
public static List<BlockPos> getFloorBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
list.add(new BlockPos(l, y, n));
}
}
}
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addFloorBlocks(list, x1, x2, y1, z1, z2);
else
addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
public static void addHollowFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
Line.addXLineBlocks(list, x1, x2, y, z1);
Line.addXLineBlocks(list, x1, x2, y, z2);
Line.addZLineBlocks(list, z1, z2, x1, y);
Line.addZLineBlocks(list, z1, z2, x2, y);
}
return list;
}
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return findFloor(player, firstPos, skipRaytrace);
}
public static void addFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
@Override
protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
static class Criteria {
Vec3 planeBound;
double distToPlayerSq;
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
Criteria(Vec3 planeBound, Vec3 start) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
}
list.add(new BlockPos(l, y, n));
}
}
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
public static void addHollowFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
Line.addXLineBlocks(list, x1, x2, y, z1);
Line.addXLineBlocks(list, x1, x2, y, z2);
Line.addZLineBlocks(list, z1, z2, x1, y);
Line.addZLineBlocks(list, z1, z2, x2, y);
}
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
}
}
}

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -12,136 +12,136 @@ import java.util.List;
public class Line extends TwoClicksBuildMode {
static class Criteria {
Vec3d planeBound;
Vec3d lineBound;
double distToLineSq;
double distToPlayerSq;
public static BlockPos findLine(Player player, BlockPos firstPos, boolean skipRaytrace) {
Vec3 look = BuildModes.getPlayerLookVec(player);
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Criteria(Vec3d planeBound, BlockPos firstPos, Vec3d start) {
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, firstPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
List<Criteria> criteriaList = new ArrayList<>(3);
//Make it from a plane into a line
//Select the axis that is longest
private Vec3d toLongestLine(Vec3d boundVec, BlockPos firstPos) {
BlockPos bound = new BlockPos(boundVec);
//X
Vec3 xBound = BuildModes.findXBound(firstPos.getX(), start, look);
criteriaList.add(new Criteria(xBound, firstPos, start));
BlockPos firstToSecond = bound.subtract(firstPos);
firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ()));
int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ()));
if (longest == firstToSecond.getX()) {
return new Vec3d(bound.getX(), firstPos.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getY()) {
return new Vec3d(firstPos.getX(), bound.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getZ()) {
return new Vec3d(firstPos.getX(), firstPos.getY(), bound.getZ());
}
return null;
}
//Y
Vec3 yBound = BuildModes.findYBound(firstPos.getY(), start, look);
criteriaList.add(new Criteria(yBound, firstPos, start));
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
//Z
Vec3 zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
criteriaList.add(new Criteria(zBound, firstPos, start));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
}
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
}
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return findLine(player, firstPos, skipRaytrace);
}
//If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
public static BlockPos findLine(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
List<Criteria> criteriaList = new ArrayList<>(3);
}
//X
Vec3d xBound = BuildModes.findXBound(firstPos.getX(), start, look);
criteriaList.add(new Criteria(xBound, firstPos, start));
return new BlockPos(selected.lineBound);
}
//Y
Vec3d yBound = BuildModes.findYBound(firstPos.getY(), start, look);
criteriaList.add(new Criteria(yBound, firstPos, start));
public static List<BlockPos> getLineBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
//Z
Vec3d zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
criteriaList.add(new Criteria(zBound, firstPos, start));
if (x1 != x2) {
addXLineBlocks(list, x1, x2, y1, z1);
} else if (y1 != y2) {
addYLineBlocks(list, y1, y2, x1, z1);
} else {
addZLineBlocks(list, z1, z2, x1, y1);
}
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
return list;
}
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
public static void addXLineBlocks(List<BlockPos> list, int x1, int x2, int y, int z) {
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
//If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
public static void addYLineBlocks(List<BlockPos> list, int y1, int y2, int x, int z) {
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
public static void addZLineBlocks(List<BlockPos> list, int z1, int z2, int x, int y) {
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return findLine(player, firstPos, skipRaytrace);
}
return new BlockPos(selected.lineBound);
}
@Override
protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getLineBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getLineBlocks(player, x1, y1, z1, x2, y2, z2);
}
static class Criteria {
Vec3 planeBound;
Vec3 lineBound;
double distToLineSq;
double distToPlayerSq;
public static List<BlockPos> getLineBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
Criteria(Vec3 planeBound, BlockPos firstPos, Vec3 start) {
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, firstPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSqr();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
}
if (x1 != x2) {
addXLineBlocks(list, x1, x2, y1, z1);
} else if (y1 != y2) {
addYLineBlocks(list, y1, y2, x1, z1);
} else {
addZLineBlocks(list, z1, z2, x1, y1);
}
//Make it from a plane into a line
//Select the axis that is longest
private Vec3 toLongestLine(Vec3 boundVec, BlockPos firstPos) {
BlockPos bound = new BlockPos(boundVec);
return list;
}
BlockPos firstToSecond = bound.subtract(firstPos);
firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ()));
int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ()));
if (longest == firstToSecond.getX()) {
return new Vec3(bound.getX(), firstPos.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getY()) {
return new Vec3(firstPos.getX(), bound.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getZ()) {
return new Vec3(firstPos.getX(), firstPos.getY(), bound.getZ());
}
return null;
}
public static void addXLineBlocks(List<BlockPos> list, int x1, int x2, int y, int z) {
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
public static void addYLineBlocks(List<BlockPos> list, int y1, int y2, int x, int z) {
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
}
public static void addZLineBlocks(List<BlockPos> list, int z1, int z2, int x, int y) {
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
}

View File

@@ -1,41 +1,41 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import java.util.ArrayList;
import java.util.List;
public class Normal implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
@Override
public void initialize(Player player) {
}
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Direction getSideHit(Player player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
@Override
public Vec3 getHitVec(Player player) {
return null;
}
}

View File

@@ -1,41 +1,41 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import java.util.ArrayList;
import java.util.List;
public class NormalPlus implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
@Override
public void initialize(Player player) {
}
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Direction getSideHit(Player player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
@Override
public Vec3 getHitVec(Player player) {
return null;
}
}

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -11,85 +11,85 @@ import java.util.List;
public class SlopeFloor extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
//Add slope floor from first to second
public static List<BlockPos> getSlopeFloorBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
//Determine whether to use x or z axis to slope up
boolean onXAxis = true;
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
int xLength = Math.abs(x2 - x1);
int zLength = Math.abs(z2 - z1);
//Add slope floor from first to second
public static List<BlockPos> getSlopeFloorBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
if (ModeOptions.getRaisedEdge() == ModeOptions.ActionEnum.SHORT_EDGE) {
//Slope along short edge
if (zLength > xLength) onXAxis = false;
} else {
//Slope along long edge
if (zLength <= xLength) onXAxis = false;
}
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
if (onXAxis) {
//Along X goes up
//Determine whether to use x or z axis to slope up
boolean onXAxis = true;
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y3, z1, 1f);
int xLength = Math.abs(x2 - x1);
int zLength = Math.abs(z2 - z1);
//Limit amount of blocks we can place
int lowest = Math.min(z1, z2);
int highest = Math.max(z1, z2);
if (ModeOptions.getRaisedEdge() == ModeOptions.ActionEnum.SHORT_EDGE) {
//Slope along short edge
if (zLength > xLength) onXAxis = false;
} else {
//Slope along long edge
if (zLength <= xLength) onXAxis = false;
}
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
if (onXAxis) {
//Along X goes up
//Copy diagonal line on x axis
for (int z = lowest; z <= highest; z++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), blockPos.getY(), z));
}
}
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y3, z1, 1f);
} else {
//Along Z goes up
//Limit amount of blocks we can place
int lowest = Math.min(z1, z2);
int highest = Math.max(z1, z2);
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x1, y3, z2, 1f);
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
//Limit amount of blocks we can place
int lowest = Math.min(x1, x2);
int highest = Math.max(x1, x2);
//Copy diagonal line on x axis
for (int z = lowest; z <= highest; z++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), blockPos.getY(), z));
}
}
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
} else {
//Along Z goes up
//Copy diagonal line on x axis
for (int x = lowest; x <= highest; x++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(x, blockPos.getY(), blockPos.getZ()));
}
}
}
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x1, y3, z2, 1f);
return list;
}
//Limit amount of blocks we can place
int lowest = Math.min(x1, x2);
int highest = Math.max(x1, x2);
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Copy diagonal line on x axis
for (int x = lowest; x <= highest; x++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(x, blockPos.getY(), blockPos.getZ()));
}
}
}
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
return list;
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
@@ -11,100 +11,100 @@ import java.util.List;
public class Sphere extends ThreeClicksBuildMode {
@Override
public BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static List<BlockPos> getSphereBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
@Override
public BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
float centerX = x1;
float centerY = y1;
float centerZ = z1;
@Override
public List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
//Adjust for CIRCLE_START
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerY = y1 + (y3 - y1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
y1 = (int) (centerY - (y3 - centerY));
z1 = (int) (centerZ - (z2 - centerZ));
}
@Override
public List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSphereBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
float radiusX = Mth.abs(x2 - centerX);
float radiusY = Mth.abs(y3 - centerY);
float radiusZ = Mth.abs(z2 - centerZ);
public static List<BlockPos> getSphereBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
else
addHollowSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
float centerX = x1;
float centerY = y1;
float centerZ = z1;
return list;
}
//Adjust for CIRCLE_START
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerY = y1 + (y3 - y1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
y1 = (int) (centerY - (y3 - centerY));
z1 = (int) (centerZ - (z2 - centerZ));
}
public static void addSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
float radiusX = MathHelper.abs(x2 - centerX);
float radiusY = MathHelper.abs(y3 - centerY);
float radiusZ = MathHelper.abs(z2 - centerZ);
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
else
addHollowSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
return list;
}
float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, m, n));
}
}
}
}
public static void addSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
public static void addHollowSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, m, n));
}
}
}
}
float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, m, n));
}
}
}
}
public static void addHollowSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
private static float distance(float x1, float y1, float z1, float x2, float y2, float z2) {
return Mth.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
}
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
public static float calculateSpheroidRadius(float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ, int x, int y, int z) {
//Twice ellipse radius
float radiusXZ = Circle.calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, x, z);
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
//TODO project x to plane
float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, m, n));
}
}
}
}
return Circle.calculateEllipseRadius(centerX, centerY, radiusXZ, radiusY, x, y);
}
private static float distance(float x1, float y1, float z1, float x2, float y2, float z2) {
return MathHelper.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
}
@Override
public BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static float calculateSpheroidRadius(float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ, int x, int y, int z) {
//Twice ellipse radius
float radiusXZ = Circle.calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, x, z);
@Override
public BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//TODO project x to plane
@Override
public List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
return Circle.calculateEllipseRadius(centerX, centerY, radiusXZ, radiusY, x, y);
}
@Override
public List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSphereBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,134 +1,135 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class Wall extends TwoClicksBuildMode {
static class Criteria {
Vec3d planeBound;
double distToPlayerSq;
double angle;
public static BlockPos findWall(Player player, BlockPos firstPos, boolean skipRaytrace) {
Vec3 look = BuildModes.getPlayerLookVec(player);
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Criteria(Vec3d planeBound, BlockPos firstPos, Vec3d start, Vec3d look) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
Vec3d wall = this.planeBound.subtract(new Vec3d(firstPos));
this.angle = wall.x * look.x + wall.z * look.z; //dot product ignoring y (looking up/down should not affect this angle)
}
List<Criteria> criteriaList = new ArrayList<>(3);
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
//X
Vec3 xBound = BuildModes.findXBound(firstPos.getX(), start, look);
criteriaList.add(new Criteria(xBound, firstPos, start, look));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
}
}
//Z
Vec3 zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
criteriaList.add(new Criteria(zBound, firstPos, start, look));
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return findWall(player, firstPos, skipRaytrace);
}
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
public static BlockPos findWall(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
List<Criteria> criteriaList = new ArrayList<>(3);
//If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
//X
Vec3d xBound = BuildModes.findXBound(firstPos.getX(), start, look);
criteriaList.add(new Criteria(xBound, firstPos, start, look));
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest
//Limit the angle to not be too extreme
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToPlayerSq < selected.distToPlayerSq && Math.abs(criteria.angle) - Math.abs(selected.angle) < 3)
selected = criteria;
}
}
//Z
Vec3d zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
criteriaList.add(new Criteria(zBound, firstPos, start, look));
return new BlockPos(selected.planeBound);
}
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
public static List<BlockPos> getWallBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
if (x1 == x2) {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addXWallBlocks(list, x1, y1, y2, z1, z2);
else
addXHollowWallBlocks(list, x1, y1, y2, z1, z2);
} else {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addZWallBlocks(list, x1, x2, y1, y2, z1);
else
addZHollowWallBlocks(list, x1, x2, y1, y2, z1);
}
//If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
return list;
}
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest
//Limit the angle to not be too extreme
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToPlayerSq < selected.distToPlayerSq && Math.abs(criteria.angle) - Math.abs(selected.angle) < 3)
selected = criteria;
}
}
public static void addXWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
return new BlockPos(selected.planeBound);
}
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getWallBlocks(player, x1, y1, z1, x2, y2, z2);
}
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
public static List<BlockPos> getWallBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
public static void addZWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
if (x1 == x2) {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addXWallBlocks(list, x1, y1, y2, z1, z2);
else
addXHollowWallBlocks(list, x1, y1, y2, z1, z2);
} else {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addZWallBlocks(list, x1, x2, y1, y2, z1);
else
addZHollowWallBlocks(list, x1, x2, y1, y2, z1);
}
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
return list;
}
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
public static void addXWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
public static void addXHollowWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
Line.addZLineBlocks(list, z1, z2, x, y1);
Line.addZLineBlocks(list, z1, z2, x, y2);
Line.addYLineBlocks(list, y1, y2, x, z1);
Line.addYLineBlocks(list, y1, y2, x, z2);
}
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
public static void addZHollowWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
Line.addXLineBlocks(list, x1, x2, y1, z);
Line.addXLineBlocks(list, x1, x2, y2, z);
Line.addYLineBlocks(list, y1, y2, x1, z);
Line.addYLineBlocks(list, y1, y2, x2, z);
}
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return findWall(player, firstPos, skipRaytrace);
}
public static void addZWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
@Override
protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getWallBlocks(player, x1, y1, z1, x2, y2, z2);
}
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
static class Criteria {
Vec3 planeBound;
double distToPlayerSq;
double angle;
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
Criteria(Vec3 planeBound, BlockPos firstPos, Vec3 start, Vec3 look) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
Vec3 wall = this.planeBound.subtract(Vec3.atLowerCornerOf(firstPos));
this.angle = wall.x * look.x + wall.z * look.z; //dot product ignoring y (looking up/down should not affect this angle)
}
public static void addXHollowWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
Line.addZLineBlocks(list, z1, z2, x, y1);
Line.addZLineBlocks(list, z1, z2, x, y2);
Line.addYLineBlocks(list, y1, y2, x, z1);
Line.addYLineBlocks(list, y1, y2, x, z2);
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
public static void addZHollowWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
Line.addXLineBlocks(list, x1, x2, y1, z);
Line.addXLineBlocks(list, x1, x2, y2, z);
Line.addYLineBlocks(list, y1, y2, x1, z);
Line.addYLineBlocks(list, y1, y2, x2, z);
}
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
}
}
}

View File

@@ -1,104 +1,104 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraft.core.Vec3i;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList;
import java.util.List;
public class Array {
public static class ArraySettings{
public boolean enabled = false;
public BlockPos offset = BlockPos.ORIGIN;
public int count = 5;
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
public ArraySettings() {
}
//find arraysettings for the player
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates;
public ArraySettings(boolean enabled, BlockPos offset, int count) {
this.enabled = enabled;
this.offset = offset;
this.count = count;
}
BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
public int getReach() {
//find largest offset
int x = Math.abs(offset.getX());
int y = Math.abs(offset.getY());
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
for (int i = 0; i < a.count; i++) {
pos = pos.offset(offset);
coordinates.add(pos);
}
return largestOffset * count;
}
}
return coordinates;
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>();
//find arraysettings for the player
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates;
//find arraysettings for the player that placed the block
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return blockStates;
BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
for (int i = 0; i < a.count; i++) {
pos = pos.add(offset);
coordinates.add(pos);
}
//Randomizer bag synergy
AbstractRandomizerBagItem randomizerBagItem = null;
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
return coordinates;
}
for (int i = 0; i < a.count; i++) {
pos = pos.offset(offset);
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, IBlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
//Randomizer bag synergy
if (randomizerBagItem != null) {
itemStack = randomizerBagItem.pickRandomStack(bagInventory);
blockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3(0, 0, 0), InteractionHand.MAIN_HAND);
}
//find arraysettings for the player that placed the block
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return blockStates;
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
blockStates.add(blockState);
itemStacks.add(itemStack);
}
BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
return blockStates;
}
//Randomizer bag synergy
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
}
public static boolean isEnabled(ArraySettings a) {
if (a == null || !a.enabled) return false;
for (int i = 0; i < a.count; i++) {
pos = pos.add(offset);
return a.offset.getX() != 0 || a.offset.getY() != 0 || a.offset.getZ() != 0;
}
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
blockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
}
public static class ArraySettings {
public boolean enabled = false;
public BlockPos offset = BlockPos.ZERO;
public int count = 5;
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
blockStates.add(blockState);
itemStacks.add(itemStack);
}
public ArraySettings() {
}
return blockStates;
}
public ArraySettings(boolean enabled, BlockPos offset, int count) {
this.enabled = enabled;
this.offset = offset;
this.count = count;
}
public static boolean isEnabled(ArraySettings a) {
if (a == null || !a.enabled) return false;
public int getReach() {
//find largest offset
int x = Math.abs(offset.getX());
int y = Math.abs(offset.getY());
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return false;
return true;
}
return largestOffset * count;
}
}
}

View File

@@ -1,50 +1,50 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import java.util.List;
public class BlockSet {
private List<BlockPos> coordinates;
private List<IBlockState> previousBlockStates;
private List<IBlockState> newBlockStates;
private Vec3d hitVec;
private BlockPos firstPos;
private BlockPos secondPos;
private final List<BlockPos> coordinates;
private final List<BlockState> previousBlockStates;
private final List<BlockState> newBlockStates;
private final Vec3 hitVec;
private final BlockPos firstPos;
private final BlockPos secondPos;
public BlockSet(List<BlockPos> coordinates, List<IBlockState> previousBlockStates, List<IBlockState> newBlockStates, Vec3d hitVec,
BlockPos firstPos, BlockPos secondPos) {
this.coordinates = coordinates;
this.previousBlockStates = previousBlockStates;
this.newBlockStates = newBlockStates;
this.hitVec = hitVec;
this.firstPos = firstPos;
this.secondPos = secondPos;
}
public BlockSet(List<BlockPos> coordinates, List<BlockState> previousBlockStates, List<BlockState> newBlockStates, Vec3 hitVec,
BlockPos firstPos, BlockPos secondPos) {
this.coordinates = coordinates;
this.previousBlockStates = previousBlockStates;
this.newBlockStates = newBlockStates;
this.hitVec = hitVec;
this.firstPos = firstPos;
this.secondPos = secondPos;
}
public List<BlockPos> getCoordinates() {
return coordinates;
}
public List<BlockPos> getCoordinates() {
return coordinates;
}
public List<IBlockState> getPreviousBlockStates() {
return previousBlockStates;
}
public List<BlockState> getPreviousBlockStates() {
return previousBlockStates;
}
public List<IBlockState> getNewBlockStates() {
return newBlockStates;
}
public List<BlockState> getNewBlockStates() {
return newBlockStates;
}
public Vec3d getHitVec() {
return hitVec;
}
public Vec3 getHitVec() {
return hitVec;
}
public BlockPos getFirstPos() {
return firstPos;
}
public BlockPos getFirstPos() {
return firstPos;
}
public BlockPos getSecondPos() {
return secondPos;
}
public BlockPos getSecondPos() {
return secondPos;
}
}

View File

@@ -1,260 +1,262 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.InventoryHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BuildModifiers {
//Called from BuildModes
public static void onBlockPlaced(EntityPlayer player, List<BlockPos> startCoordinates, EnumFacing sideHit, Vec3d hitVec, boolean placeStartPos) {
World world = player.world;
ItemRandomizerBag.renewRandomness();
//Called from BuildModes
public static void onBlockPlaced(Player player, List<BlockPos> startCoordinates, Direction sideHit, Vec3 hitVec, boolean placeStartPos) {
Level world = player.level;
AbstractRandomizerBagItem.renewRandomness();
//Format hitvec to 0.x
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z)));
//Format hitvec to 0.x
hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z)));
//find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
List<ItemStack> itemStacks = new ArrayList<>();
List<BlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
//check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
//remember previous blockstates for undo
List<IBlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<IBlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
//remember previous blockstates for undo
List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<BlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
if (world.isRemote) {
if (world.isClientSide) {
BlockPreviewRenderer.onBlocksPlaced();
BlockPreviewRenderer.onBlocksPlaced();
newBlockStates = blockStates;
newBlockStates = blockStates;
} else {
} else {
//place blocks
for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
//place blocks
for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
BlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (world.isBlockLoaded(blockPos, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
//try to find new stack, otherwise continue
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
if (itemStack.isEmpty()) continue;
}
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false, false);
}
}
if (world.isLoaded(blockPos)) {
//check itemstack empty
if (itemStack.isEmpty()) {
//try to find new stack, otherwise continue
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
if (itemStack.isEmpty()) continue;
}
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, Direction.UP, hitVec, false, false, false);
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block is placed by the time it gets here, and unplaced after this)
if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.getDefaultState());
//Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block is placed by the time it gets here, and unplaced after this)
if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.defaultBlockState());
//If all new blockstates are air then no use in adding it, no block was actually placed
//Can happen when e.g. placing one block in yourself
if (Collections.frequency(newBlockStates, Blocks.AIR.getDefaultState()) != newBlockStates.size()) {
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
}
}
//If all new blockstates are air then no use in adding it, no block was actually placed
//Can happen when e.g. placing one block in yourself
if (Collections.frequency(newBlockStates, Blocks.AIR.defaultBlockState()) != newBlockStates.size()) {
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
}
}
public static void onBlockBroken(EntityPlayer player, List<BlockPos> startCoordinates, boolean breakStartPos) {
World world = player.world;
public static void onBlockBroken(Player player, List<BlockPos> startCoordinates, boolean breakStartPos) {
Level world = player.level;
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
if (coordinates.isEmpty()) return;
if (coordinates.isEmpty()) return;
//remember previous blockstates for undo
List<IBlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<IBlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
//remember previous blockstates for undo
List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<BlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
if (world.isRemote) {
BlockPreviewRenderer.onBlocksBroken();
if (world.isClientSide) {
BlockPreviewRenderer.onBlocksBroken();
//list of air blockstates
for (int i = 0; i < coordinates.size(); i++) {
newBlockStates.add(Blocks.AIR.getDefaultState());
}
//list of air blockstates
for (int i = 0; i < coordinates.size(); i++) {
newBlockStates.add(Blocks.AIR.defaultBlockState());
}
} else {
} else {
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = !player.isCreative() &&
world.getBlockState(startCoordinates.get(0)).getBlockHardness(world, startCoordinates.get(0)) == 0f;
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = !player.isCreative() &&
world.getBlockState(startCoordinates.get(0)).getDestroySpeed(world, startCoordinates.get(0)) == 0f;
//break all those blocks
for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (world.isBlockLoaded(coordinate, false)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, player, coordinate, false);
}
}
}
//break all those blocks
for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (world.isLoaded(coordinate) && !world.isEmptyBlock(coordinate)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getDestroySpeed(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, player, coordinate, false);
}
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//Set first newBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block isn't broken yet by the time it gets here, and broken after this)
if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.getDefaultState());
//Set first newBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block isn't broken yet by the time it gets here, and broken after this)
if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.defaultBlockState());
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
Vec3d hitVec = new Vec3d(0.5, 0.5, 0.5);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
Vec3 hitVec = new Vec3(0.5, 0.5, 0.5);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, List<BlockPos> posList) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current blocks being placed too
coordinates.addAll(posList);
public static List<BlockPos> findCoordinates(Player player, List<BlockPos> posList) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current blocks being placed too
coordinates.addAll(posList);
//Find mirror/array/radial mirror coordinates for each blockpos
for (BlockPos blockPos : posList) {
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, blockPos));
coordinates.addAll(RadialMirror.findCoordinates(player, blockPos));
//get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.findCoordinates(player, coordinate));
}
}
//Find mirror/array/radial mirror coordinates for each blockpos
for (BlockPos blockPos : posList) {
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, blockPos));
coordinates.addAll(RadialMirror.findCoordinates(player, blockPos));
//get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.findCoordinates(player, coordinate));
}
}
return coordinates;
}
return coordinates;
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) {
return findCoordinates(player, new ArrayList<>(Arrays.asList(blockPos)));
}
public static List<BlockPos> findCoordinates(Player player, BlockPos blockPos) {
return findCoordinates(player, new ArrayList<>(Collections.singletonList(blockPos)));
}
public static List<IBlockState> findBlockStates(EntityPlayer player, List<BlockPos> posList, Vec3d hitVec, EnumFacing facing, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
itemStacks.clear();
public static List<BlockState> findBlockStates(Player player, List<BlockPos> posList, Vec3 hitVec, Direction facing, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>();
itemStacks.clear();
//Get itemstack
ItemStack itemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
itemStack = player.getHeldItem(EnumHand.OFF_HAND);
}
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
return blockStates;
}
//Get itemstack
ItemStack itemStack = player.getItemInHand(InteractionHand.MAIN_HAND);
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
itemStack = player.getItemInHand(InteractionHand.OFF_HAND);
}
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
return blockStates;
}
//Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack;
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
ItemRandomizerBag.resetRandomness();
//Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof BlockItem) itemBlock = itemStack;
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
AbstractRandomizerBagItem.resetRandomness();
//Add blocks in posList first
for (BlockPos blockPos : posList) {
if (!(itemStack.getItem() instanceof ItemBlock)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
blockStates.add(blockState);
itemStacks.add(itemBlock);
}
//Add blocks in posList first
for (BlockPos blockPos : posList) {
if (!(itemStack.getItem() instanceof BlockItem)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, InteractionHand.MAIN_HAND);
blockStates.add(blockState);
itemStacks.add(itemBlock);
}
for (BlockPos blockPos : posList) {
IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
for (BlockPos blockPos : posList) {
BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, InteractionHand.MAIN_HAND);
List<IBlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks);
blockStates.addAll(arrayBlockStates);
blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
IBlockState blockState1 = arrayBlockStates.get(i);
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
List<BlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks);
blockStates.addAll(arrayBlockStates);
blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
BlockState blockState1 = arrayBlockStates.get(i);
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
// List<BlockPos> coordinates = findCoordinates(player, startPos);
// for (int i = 0; i < blockStates.size(); i++) {
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
// }
}
}
return blockStates;
}
return blockStates;
}
public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) {
return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(modifierSettings.getArraySettings()) ||
RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) ||
modifierSettings.doQuickReplace();
}
public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) {
return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(modifierSettings.getArraySettings()) ||
RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) ||
modifierSettings.doQuickReplace();
}
public static IBlockState getBlockStateFromItem(ItemStack itemStack, EntityPlayer player, BlockPos blockPos, EnumFacing facing, Vec3d hitVec, EnumHand hand) {
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(new BlockItemUseContext(player.world, player, itemStack, blockPos, facing,
((float) hitVec.x), ((float) hitVec.y), ((float) hitVec.z)));
}
public static BlockState getBlockStateFromItem(ItemStack itemStack, Player player, BlockPos blockPos, Direction facing, Vec3 hitVec, InteractionHand hand) {
return Block.byItem(itemStack.getItem()).getStateForPlacement(new BlockPlaceContext(new UseOnContext(player, hand, new BlockHitResult(hitVec, facing, blockPos, false))));
}
//Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false;
//Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false;
//Check count, not actual values
if (coordinates1.size() == coordinates2.size()){
if (coordinates1.size() == 1){
return coordinates1.get(0).equals(coordinates2.get(0));
}
return true;
} else {
return false;
}
//Check count, not actual values
if (coordinates1.size() == coordinates2.size()) {
if (coordinates1.size() == 1) {
return coordinates1.get(0).equals(coordinates2.get(0));
}
return true;
} else {
return false;
}
// return coordinates1.equals(coordinates2);
}
}
}

View File

@@ -1,228 +1,234 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.BlockDirectional;
import net.minecraft.block.BlockDispenser;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.BlockStairs;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.world.level.block.DirectionalBlock;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.StairBlock;
import net.minecraft.world.level.block.state.BlockState;
public class Mirror {
public static class MirrorSettings {
public boolean enabled = false;
public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
public int radius = 10;
public boolean drawLines = true, drawPlanes = true;
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
public MirrorSettings() {
}
//find mirrorsettings for the player
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return coordinates;
public MirrorSettings(boolean mirrorEnabled, Vec3d position, boolean mirrorX, boolean mirrorY, boolean mirrorZ, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = mirrorEnabled;
this.position = position;
this.mirrorX = mirrorX;
this.mirrorY = mirrorY;
this.mirrorZ = mirrorZ;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates);
public int getReach() {
return radius * 2; //Change ModifierSettings#setReachUpgrade too
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
return coordinates;
}
//find mirrorsettings for the player
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return coordinates;
private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
}
return coordinates;
}
private static void coordinateMirrorY(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
coordinates.add(newBlockPos);
private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
}
if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
}
private static void coordinateMirrorZ(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
coordinates.add(newBlockPos);
}
private static void coordinateMirrorY(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
coordinates.add(newBlockPos);
public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>();
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
}
//find mirrorsettings for the player
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates;
private static void coordinateMirrorZ(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
coordinates.add(newBlockPos);
}
//Randomizer bag synergy
AbstractRandomizerBagItem randomizerBagItem = null;
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, IBlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
if (m.mirrorX)
blockStateMirrorX(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorY)
blockStateMirrorY(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorZ)
blockStateMirrorZ(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
//find mirrorsettings for the player
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates;
return blockStates;
}
//Randomizer bag synergy
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
}
private static void blockStateMirrorX(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
if (m.mirrorX) blockStateMirrorX(player, m, startPos, blockState, bagInventory, itemStack, EnumHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorY) blockStateMirrorY(player, m, startPos, blockState, bagInventory, itemStack, EnumHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorZ) blockStateMirrorZ(player, m, startPos, blockState, bagInventory, itemStack, EnumHand.MAIN_HAND, blockStates, itemStacks);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
return blockStates;
}
//Find blockstate
BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.world.level.block.Mirror.FRONT_BACK);
private static void blockStateMirrorX(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
}
if (m.mirrorY)
blockStateMirrorY(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
if (m.mirrorZ)
blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
}
//Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.util.Mirror.FRONT_BACK);
private static void blockStateMirrorY(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
if (m.mirrorY) blockStateMirrorY(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
if (m.mirrorZ) blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
}
//Find blockstate
BlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState);
private static void blockStateMirrorY(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
}
if (m.mirrorZ)
blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
}
//Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState);
private static void blockStateMirrorZ(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
if (m.mirrorZ) blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
}
//Find blockstate
BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.world.level.block.Mirror.LEFT_RIGHT);
private static void blockStateMirrorZ(EntityPlayer player, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState,
IItemHandler bagInventory, ItemStack itemStack, EnumHand hand, List<IBlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
}
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
}
public static boolean isEnabled(MirrorSettings m, BlockPos startPos) {
if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false;
//Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.util.Mirror.LEFT_RIGHT);
//within mirror distance
return !(startPos.getX() + 0.5 < m.position.x - m.radius) && !(startPos.getX() + 0.5 > m.position.x + m.radius) &&
!(startPos.getY() + 0.5 < m.position.y - m.radius) && !(startPos.getY() + 0.5 > m.position.y + m.radius) &&
!(startPos.getZ() + 0.5 < m.position.z - m.radius) && !(startPos.getZ() + 0.5 > m.position.z + m.radius);
}
//Store blockstate and itemstack
blockStates.add(newBlockState);
itemStacks.add(itemStack);
}
private static BlockState getVerticalMirror(BlockState blockState) {
//Stairs
if (blockState.getBlock() instanceof StairBlock) {
if (blockState.getValue(StairBlock.HALF) == Half.BOTTOM) {
return blockState.setValue(StairBlock.HALF, Half.TOP);
} else {
return blockState.setValue(StairBlock.HALF, Half.BOTTOM);
}
}
public static boolean isEnabled(MirrorSettings m, BlockPos startPos) {
if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false;
//Slabs
if (blockState.getBlock() instanceof SlabBlock) {
if (blockState.getValue(SlabBlock.TYPE) == SlabType.DOUBLE) {
return blockState;
} else if (blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) {
return blockState.setValue(SlabBlock.TYPE, SlabType.TOP);
} else {
return blockState.setValue(SlabBlock.TYPE, SlabType.BOTTOM);
}
}
//within mirror distance
if (startPos.getX() + 0.5 < m.position.x - m.radius || startPos.getX() + 0.5 > m.position.x + m.radius ||
startPos.getY() + 0.5 < m.position.y - m.radius || startPos.getY() + 0.5 > m.position.y + m.radius ||
startPos.getZ() + 0.5 < m.position.z - m.radius || startPos.getZ() + 0.5 > m.position.z + m.radius)
return false;
//Buttons, endrod, observer, piston
if (blockState.getBlock() instanceof DirectionalBlock) {
if (blockState.getValue(DirectionalBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DirectionalBlock.FACING, Direction.UP);
} else if (blockState.getValue(DirectionalBlock.FACING) == Direction.UP) {
return blockState.setValue(DirectionalBlock.FACING, Direction.DOWN);
}
}
return true;
}
//Dispenser, dropper
if (blockState.getBlock() instanceof DispenserBlock) {
if (blockState.getValue(DispenserBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DispenserBlock.FACING, Direction.UP);
} else if (blockState.getValue(DispenserBlock.FACING) == Direction.UP) {
return blockState.setValue(DispenserBlock.FACING, Direction.DOWN);
}
}
private static IBlockState getVerticalMirror(IBlockState blockState) {
//Stairs
if (blockState.getBlock() instanceof BlockStairs) {
if (blockState.get(BlockStairs.HALF) == Half.BOTTOM) {
return blockState.with(BlockStairs.HALF, Half.TOP);
} else {
return blockState.with(BlockStairs.HALF, Half.BOTTOM);
}
}
return blockState;
}
//Slabs
if (blockState.getBlock() instanceof BlockSlab) {
if (blockState.get(BlockSlab.TYPE) == SlabType.DOUBLE) {
return blockState;
} else if (blockState.get(BlockSlab.TYPE) == SlabType.BOTTOM) {
return blockState.with(BlockSlab.TYPE, SlabType.TOP);
} else {
return blockState.with(BlockSlab.TYPE, SlabType.BOTTOM);
}
}
public static class MirrorSettings {
public boolean enabled = false;
public Vec3 position = new Vec3(0.5, 64.5, 0.5);
public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
public int radius = 10;
public boolean drawLines = true, drawPlanes = true;
//Buttons, endrod, observer, piston
if (blockState.getBlock() instanceof BlockDirectional) {
if (blockState.get(BlockDirectional.FACING) == EnumFacing.DOWN) {
return blockState.with(BlockDirectional.FACING, EnumFacing.UP);
} else if (blockState.get(BlockDirectional.FACING) == EnumFacing.UP) {
return blockState.with(BlockDirectional.FACING, EnumFacing.DOWN);
}
}
public MirrorSettings() {
}
//Dispenser, dropper
if (blockState.getBlock() instanceof BlockDispenser) {
if (blockState.get(BlockDispenser.FACING) == EnumFacing.DOWN) {
return blockState.with(BlockDispenser.FACING, EnumFacing.UP);
} else if (blockState.get(BlockDispenser.FACING) == EnumFacing.UP) {
return blockState.with(BlockDispenser.FACING, EnumFacing.DOWN);
}
}
public MirrorSettings(boolean mirrorEnabled, Vec3 position, boolean mirrorX, boolean mirrorY, boolean mirrorZ, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = mirrorEnabled;
this.position = position;
this.mirrorX = mirrorX;
this.mirrorY = mirrorY;
this.mirrorZ = mirrorZ;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
return blockState;
}
public int getReach() {
return radius * 2; //Change ModifierSettings#setReachUpgrade too
}
}
}

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
@@ -13,197 +13,202 @@ import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.UUID;
@Mod.EventBusSubscriber
public class ModifierSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null
@Nonnull
public static ModifierSettings getModifierSettings(EntityPlayer player){
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.modifierCapability, null);
//Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null
@Nonnull
public static ModifierSettings getModifierSettings(Player player) {
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.MODIFIER_CAPABILITY, null);
if (modifierCapability.isPresent()) {
ModifierCapabilityManager.IModifierCapability capability = modifierCapability.orElse(null);
if (capability.getModifierData() == null) {
capability.setModifierData(new ModifierSettings());
}
return capability.getModifierData();
}
if (modifierCapability.isPresent()) {
ModifierCapabilityManager.IModifierCapability capability = modifierCapability.orElse(null);
if (capability.getModifierData() == null){
capability.setModifierData(new ModifierSettings());
}
return capability.getModifierData();
}
//Player does not have modifierCapability capability
//Return dummy settings
return new ModifierSettings();
// throw new IllegalArgumentException("Player does not have modifierCapability capability");
}
EffortlessBuilding.logger.warn("Player does not have modifierCapability: " + player);
//Return dummy settings
return new ModifierSettings();
}
public static void setModifierSettings(EntityPlayer player, ModifierSettings modifierSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildsettings, player is null");
return;
}
public static void setModifierSettings(Player player, ModifierSettings modifierSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildsettings, player is null");
return;
}
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.modifierCapability, null);
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.MODIFIER_CAPABILITY, null);
modifierCapability.ifPresent((capability) -> {
capability.setModifierData(modifierSettings);
});
modifierCapability.ifPresent((capability) -> {
capability.setModifierData(modifierSettings);
});
if (!modifierCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildsettings failed.");
}
}
if (!modifierCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildsettings failed.");
}
}
public static String sanitize(ModifierSettings modifierSettings, EntityPlayer player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
public static String sanitize(ModifierSettings modifierSettings, Player player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
//Mirror settings
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m.radius < 1) {
m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. ";
}
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to "+ (maxReach / 2) + ". ";
}
//Mirror settings
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m.radius < 1) {
m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. ";
}
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
}
//Array settings
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a.count < 0) {
a.count = 0;
error += "Array count may not be negative. It has been reset to 0.";
}
//Array settings
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a.count < 0) {
a.count = 0;
error += "Array count may not be negative. It has been reset to 0.";
}
if (a.getReach() > maxReach) {
a.count = 0;
error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. ";
}
if (a.getReach() > maxReach) {
a.count = 0;
error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. ";
}
//Radial mirror settings
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r.slices < 2) {
r.slices = 2;
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
}
//Radial mirror settings
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r.slices < 2) {
r.slices = 2;
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
}
if (r.radius < 1) {
r.radius = 1;
error += "Radial mirror radius has to be at least 1. This has been corrected. ";
}
if (r.getReach() > maxReach) {
r.radius = maxReach / 2;
error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to "+ (maxReach / 2) + ". ";
}
if (r.radius < 1) {
r.radius = 1;
error += "Radial mirror radius has to be at least 1. This has been corrected. ";
}
if (r.getReach() > maxReach) {
r.radius = maxReach / 2;
error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
}
//Other
if (modifierSettings.reachUpgrade < 0) {
modifierSettings.reachUpgrade = 0;
}
if (modifierSettings.reachUpgrade > 3) {
modifierSettings.reachUpgrade = 3;
}
//Other
if (modifierSettings.reachUpgrade < 0) {
modifierSettings.reachUpgrade = 0;
}
if (modifierSettings.reachUpgrade > 3) {
modifierSettings.reachUpgrade = 3;
}
return error;
}
return error;
}
public static class ModifierSettings {
private Mirror.MirrorSettings mirrorSettings;
private Array.ArraySettings arraySettings;
private RadialMirror.RadialMirrorSettings radialMirrorSettings;
private boolean quickReplace = false;
private int reachUpgrade = 0;
public static void handleNewPlayer(Player player) {
//Makes sure player has modifier settings (if it doesnt it will create it)
getModifierSettings(player);
public ModifierSettings() {
mirrorSettings = new Mirror.MirrorSettings();
arraySettings = new Array.ArraySettings();
radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
}
//Only on server
if (!player.level.isClientSide) {
//Send to client
ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), msg);
}
}
public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings;
this.quickReplace = quickReplace;
this.reachUpgrade = reachUpgrade;
}
public static class ModifierSettings {
private Mirror.MirrorSettings mirrorSettings;
private Array.ArraySettings arraySettings;
private RadialMirror.RadialMirrorSettings radialMirrorSettings;
private boolean quickReplace = false;
private int reachUpgrade = 0;
public Mirror.MirrorSettings getMirrorSettings() {
if (this.mirrorSettings == null) this.mirrorSettings = new Mirror.MirrorSettings();
return this.mirrorSettings;
}
public ModifierSettings() {
mirrorSettings = new Mirror.MirrorSettings();
arraySettings = new Array.ArraySettings();
radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
}
public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) {
if (mirrorSettings == null) return;
this.mirrorSettings = mirrorSettings;
}
public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings;
this.quickReplace = quickReplace;
this.reachUpgrade = reachUpgrade;
}
public Array.ArraySettings getArraySettings() {
if (this.arraySettings == null) this.arraySettings = new Array.ArraySettings();
return this.arraySettings;
}
public Mirror.MirrorSettings getMirrorSettings() {
if (this.mirrorSettings == null) this.mirrorSettings = new Mirror.MirrorSettings();
return this.mirrorSettings;
}
public void setArraySettings(Array.ArraySettings arraySettings) {
if (arraySettings == null) return;
this.arraySettings = arraySettings;
}
public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) {
if (mirrorSettings == null) return;
this.mirrorSettings = mirrorSettings;
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
return this.radialMirrorSettings;
}
public Array.ArraySettings getArraySettings() {
if (this.arraySettings == null) this.arraySettings = new Array.ArraySettings();
return this.arraySettings;
}
public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) {
if (radialMirrorSettings == null) return;
this.radialMirrorSettings = radialMirrorSettings;
}
public void setArraySettings(Array.ArraySettings arraySettings) {
if (arraySettings == null) return;
this.arraySettings = arraySettings;
}
public boolean doQuickReplace() {
return quickReplace;
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
return this.radialMirrorSettings;
}
public void setQuickReplace(boolean quickReplace) {
this.quickReplace = quickReplace;
}
public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) {
if (radialMirrorSettings == null) return;
this.radialMirrorSettings = radialMirrorSettings;
}
public int getReachUpgrade() {
return reachUpgrade;
}
public boolean doQuickReplace() {
return quickReplace;
}
public void setReachUpgrade(int reachUpgrade) {
this.reachUpgrade = reachUpgrade;
//Set mirror radius to max
int reach = 10;
switch (reachUpgrade) {
case 0: reach = BuildConfig.reach.maxReachLevel0.get(); break;
case 1: reach = BuildConfig.reach.maxReachLevel1.get(); break;
case 2: reach = BuildConfig.reach.maxReachLevel2.get(); break;
case 3: reach = BuildConfig.reach.maxReachLevel3.get(); break;
}
public void setQuickReplace(boolean quickReplace) {
this.quickReplace = quickReplace;
}
if (this.mirrorSettings != null)
this.mirrorSettings.radius = reach / 2;
if (this.radialMirrorSettings != null)
this.radialMirrorSettings.radius = reach / 2;
}
}
public int getReachUpgrade() {
return reachUpgrade;
}
public static void handleNewPlayer(EntityPlayer player){
//Makes sure player has modifier settings (if it doesnt it will create it)
getModifierSettings(player);
public void setReachUpgrade(int reachUpgrade) {
this.reachUpgrade = reachUpgrade;
//Set mirror radius to max
int reach = 10;
switch (reachUpgrade) {
case 0:
reach = BuildConfig.reach.maxReachLevel0.get();
break;
case 1:
reach = BuildConfig.reach.maxReachLevel1.get();
break;
case 2:
reach = BuildConfig.reach.maxReachLevel2.get();
break;
case 3:
reach = BuildConfig.reach.maxReachLevel3.get();
break;
}
//Only on server
if (!player.world.isRemote) {
//Send to client
ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), msg);
}
}
if (this.mirrorSettings != null)
this.mirrorSettings.radius = reach / 2;
if (this.radialMirrorSettings != null)
this.radialMirrorSettings.radius = reach / 2;
}
}
}

View File

@@ -1,195 +1,194 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList;
import java.util.List;
public class RadialMirror {
public static class RadialMirrorSettings {
public boolean enabled = false;
public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true, drawPlanes = false;
public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
public RadialMirrorSettings() {
}
//find radial mirror settings for the player
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return coordinates;
public RadialMirrorSettings(boolean enabled, Vec3d position, int slices, boolean alternate, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = enabled;
this.position = position;
this.slices = slices;
this.alternate = alternate;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
public int getReach() {
return radius * 2;
}
}
Vec3 startVec = new Vec3(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3 relStartVec = startVec.subtract(r.position);
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z);
if (startAngleToCenter < 0) startAngleToCenter += Math.PI;
double startAngleInSlice = startAngleToCenter % sliceAngle;
//find radial mirror settings for the player
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return coordinates;
for (int i = 1; i < r.slices; i++) {
double curAngle = sliceAngle * i;
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
//alternate mirroring of slices
if (r.alternate && i % 2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
Vec3d startVec = new Vec3d(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3d relStartVec = startVec.subtract(r.position);
Vec3 relNewVec = relStartVec.yRot((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (!coordinates.contains(newBlockPos) && !newBlockPos.equals(startPos)) coordinates.add(newBlockPos);
}
double startAngleToCenter = MathHelper.atan2(relStartVec.x, relStartVec.z);
if (startAngleToCenter < 0) startAngleToCenter += Math.PI;
double startAngleInSlice = startAngleToCenter % sliceAngle;
return coordinates;
}
for (int i = 1; i < r.slices; i++) {
double curAngle = sliceAngle * i;
public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>();
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//alternate mirroring of slices
if (r.alternate && i%2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
Vec3d relNewVec = relStartVec.rotateYaw((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (!coordinates.contains(newBlockPos) && !newBlockPos.equals(startPos)) coordinates.add(newBlockPos);
}
return coordinates;
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, IBlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//find radial mirror settings for the player that placed the block
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return blockStates;
//find radial mirror settings for the player that placed the block
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return blockStates;
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
//get angle between slices
double sliceAngle = 2 * Math.PI / r.slices;
Vec3d startVec = new Vec3d(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3d relStartVec = startVec.subtract(r.position);
Vec3 startVec = new Vec3(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3 relStartVec = startVec.subtract(r.position);
double startAngleToCenter = MathHelper.atan2(relStartVec.x, relStartVec.z);
double startAngleToCenterMod = startAngleToCenter < 0 ? startAngleToCenter + Math.PI : startAngleToCenter;
double startAngleInSlice = startAngleToCenterMod % sliceAngle;
double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z);
double startAngleToCenterMod = startAngleToCenter < 0 ? startAngleToCenter + Math.PI : startAngleToCenter;
double startAngleInSlice = startAngleToCenterMod % sliceAngle;
//Rotate the original blockstate
blockState = rotateOriginalBlockState(startAngleToCenter, blockState);
//Rotate the original blockstate
blockState = rotateOriginalBlockState(startAngleToCenter, blockState);
//Randomizer bag synergy
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
}
//Randomizer bag synergy
AbstractRandomizerBagItem randomizerBagItem = null;
IItemHandler bagInventory = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
IBlockState newBlockState;
for (int i = 1; i < r.slices; i++) {
newBlockState = blockState;
double curAngle = sliceAngle * i;
BlockState newBlockState;
for (int i = 1; i < r.slices; i++) {
newBlockState = blockState;
double curAngle = sliceAngle * i;
//alternate mirroring of slices
if (r.alternate && i%2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
//alternate mirroring of slices
if (r.alternate && i % 2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
Vec3d relNewVec = relStartVec.rotateYaw((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (coordinates.contains(newBlockPos) || newBlockPos.equals(startPos)) continue; //filter out duplicates
coordinates.add(newBlockPos);
Vec3 relNewVec = relStartVec.yRot((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (coordinates.contains(newBlockPos) || newBlockPos.equals(startPos)) continue; //filter out duplicates
coordinates.add(newBlockPos);
//Randomizer bag synergy
if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
newBlockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
//Randomizer bag synergy
if (randomizerBagItem != null) {
itemStack = randomizerBagItem.pickRandomStack(bagInventory);
newBlockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3(0, 0, 0), InteractionHand.MAIN_HAND);
newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState);
}
newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState);
}
//rotate
newBlockState = rotateBlockState(relNewVec, newBlockState, r.alternate && i%2 == 1);
//rotate
newBlockState = rotateBlockState(relNewVec, newBlockState, r.alternate && i % 2 == 1);
blockStates.add(newBlockState);
itemStacks.add(itemStack);
}
blockStates.add(newBlockState);
itemStacks.add(itemStack);
}
return blockStates;
}
return blockStates;
}
private static IBlockState rotateOriginalBlockState(double startAngleToCenter, IBlockState blockState) {
IBlockState newBlockState = blockState;
private static BlockState rotateOriginalBlockState(double startAngleToCenter, BlockState blockState) {
BlockState newBlockState = blockState;
if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180);
} else if (startAngleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90);
} else if (startAngleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90);
}
if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180);
} else if (startAngleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90);
} else if (startAngleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90);
}
return newBlockState;
}
return newBlockState;
}
private static IBlockState rotateBlockState(Vec3d relVec, IBlockState blockState, boolean alternate) {
IBlockState newBlockState;
double angleToCenter = MathHelper.atan2(relVec.x, relVec.z); //between -PI and PI
private static BlockState rotateBlockState(Vec3 relVec, BlockState blockState, boolean alternate) {
BlockState newBlockState;
double angleToCenter = Mth.atan2(relVec.x, relVec.z); //between -PI and PI
if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180);
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK);
}
} else if (angleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90);
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT);
}
} else if (angleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90);
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT);
}
} else {
newBlockState = blockState;
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK);
}
}
if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180);
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK);
}
} else if (angleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90);
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT);
}
} else if (angleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90);
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT);
}
} else {
newBlockState = blockState;
if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK);
}
}
return newBlockState;
}
return newBlockState;
}
public static boolean isEnabled(RadialMirrorSettings r, BlockPos startPos) {
if (r == null || !r.enabled) return false;
public static boolean isEnabled(RadialMirrorSettings r, BlockPos startPos) {
if (r == null || !r.enabled) return false;
if (new Vec3d(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(r.position).lengthSquared() >
r.radius * r.radius)
return false;
return !(new Vec3(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(r.position).lengthSqr() >
r.radius * r.radius);
}
return true;
}
public static class RadialMirrorSettings {
public boolean enabled = false;
public Vec3 position = new Vec3(0.5, 64.5, 0.5);
public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true, drawPlanes = false;
public RadialMirrorSettings() {
}
public RadialMirrorSettings(boolean enabled, Vec3 position, int slices, boolean alternate, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = enabled;
this.position = position;
this.slices = slices;
this.alternate = alternate;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() {
return radius * 2;
}
}
}

View File

@@ -1,15 +1,15 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraft.server.level.ServerLevel;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.FixedStack;
@@ -21,26 +21,26 @@ import java.util.*;
public class UndoRedo {
//Undo and redo stacks per player
//Gets added to twice in singleplayer (server and client) if not careful. So separate stacks.
private static Map<UUID, FixedStack<BlockSet>> undoStacksClient = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> undoStacksServer = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacksClient = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacksServer = new HashMap<>();
//Undo and redo stacks per player
//Gets added to twice in singleplayer (server and client) if not careful. So separate stacks.
private static final Map<UUID, FixedStack<BlockSet>> undoStacksClient = new HashMap<>();
private static final Map<UUID, FixedStack<BlockSet>> undoStacksServer = new HashMap<>();
private static final Map<UUID, FixedStack<BlockSet>> redoStacksClient = new HashMap<>();
private static final Map<UUID, FixedStack<BlockSet>> redoStacksServer = new HashMap<>();
//add to undo stack
public static void addUndo(EntityPlayer player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
//add to undo stack
public static void addUndo(Player player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.level.isClientSide ? undoStacksClient : undoStacksServer;
//Assert coordinates is as long as previous and new blockstate lists
if (blockSet.getCoordinates().size() != blockSet.getPreviousBlockStates().size() ||
blockSet.getCoordinates().size() != blockSet.getNewBlockStates().size()) {
EffortlessBuilding.logger.error("Coordinates and blockstate lists are not equal length. Coordinates: {}. Previous blockstates: {}. New blockstates: {}.",
blockSet.getCoordinates().size(), blockSet.getPreviousBlockStates().size(), blockSet.getNewBlockStates().size());
}
//Assert coordinates is as long as previous and new blockstate lists
if (blockSet.getCoordinates().size() != blockSet.getPreviousBlockStates().size() ||
blockSet.getCoordinates().size() != blockSet.getNewBlockStates().size()) {
EffortlessBuilding.logger.error("Coordinates and blockstate lists are not equal length. Coordinates: {}. Previous blockstates: {}. New blockstates: {}.",
blockSet.getCoordinates().size(), blockSet.getPreviousBlockStates().size(), blockSet.getNewBlockStates().size());
}
//Warn if previous and new blockstate are equal
//Can happen in a lot of valid cases
//Warn if previous and new blockstate are equal
//Can happen in a lot of valid cases
// for (int i = 0; i < blockSet.getCoordinates().size(); i++) {
// if (blockSet.getPreviousBlockStates().get(i).equals(blockSet.getNewBlockStates().get(i))) {
// EffortlessBuilding.logger.warn("Previous and new blockstates are equal at index {}. Blockstate: {}.",
@@ -48,182 +48,192 @@ public class UndoRedo {
// }
// }
//If no stack exists, make one
if (!undoStacks.containsKey(player.getUniqueID())) {
undoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
}
//If no stack exists, make one
if (!undoStacks.containsKey(player.getUUID())) {
undoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
}
undoStacks.get(player.getUniqueID()).push(blockSet);
}
undoStacks.get(player.getUUID()).push(blockSet);
}
private static void addRedo(EntityPlayer player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
private static void addRedo(Player player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.level.isClientSide ? redoStacksClient : redoStacksServer;
//(No asserts necessary, it's private)
//(No asserts necessary, it's private)
//If no stack exists, make one
if (!redoStacks.containsKey(player.getUniqueID())) {
redoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
}
//If no stack exists, make one
if (!redoStacks.containsKey(player.getUUID())) {
redoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
}
redoStacks.get(player.getUniqueID()).push(blockSet);
}
redoStacks.get(player.getUUID()).push(blockSet);
}
public static boolean undo(EntityPlayer player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
public static boolean undo(Player player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.level.isClientSide ? undoStacksClient : undoStacksServer;
if (!undoStacks.containsKey(player.getUniqueID())) return false;
if (!undoStacks.containsKey(player.getUUID())) return false;
FixedStack<BlockSet> undoStack = undoStacks.get(player.getUniqueID());
FixedStack<BlockSet> undoStack = undoStacks.get(player.getUUID());
if (undoStack.isEmpty()) return false;
if (undoStack.isEmpty()) return false;
BlockSet blockSet = undoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<IBlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec();
BlockSet blockSet = undoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<BlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<BlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3 hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, previousBlockStates);
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, previousBlockStates);
if (player.world.isRemote) {
BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
} else {
//break all those blocks, reset to what they were
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (player.level.isClientSide) {
BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
} else {
//break all those blocks, reset to what they were
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack
IBlockState previousBlockState = Blocks.AIR.getDefaultState();
if (itemStack.getItem() instanceof ItemBlock) {
previousBlockState = previousBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
}
//get blockstate from itemstack
BlockState previousBlockState = Blocks.AIR.defaultBlockState();
if (itemStack.getItem() instanceof BlockItem) {
previousBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
}
if (player.world.isBlockLoaded(coordinate, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, previousBlockStates.get(i));
//get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) {
previousBlockState = previousBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} else {
previousBlockState = Blocks.AIR.getDefaultState();
}
}
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true);
//if previousBlockState is air, placeBlock will set it to air
SurvivalHelper.placeBlock(player.world, player, coordinate, previousBlockState, itemStack, EnumFacing.UP, hitVec, true, false, false);
}
}
}
if (player.level.isLoaded(coordinate)) {
//check itemstack empty
if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, previousBlockStates.get(i));
//get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) {
previousBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
} else {
if (previousBlockStates.get(i).getBlock() != Blocks.AIR)
EffortlessBuilding.logTranslate(player, "", previousBlockStates.get(i).getBlock().getDescriptionId(), " not found in inventory", true);
previousBlockState = Blocks.AIR.defaultBlockState();
}
}
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.level, player, coordinate, true);
//if previousBlockState is air, placeBlock will set it to air
SurvivalHelper.placeBlock(player.level, player, coordinate, previousBlockState, itemStack, Direction.UP, hitVec, true, false, false);
}
}
}
//add to redo
addRedo(player, blockSet);
//add to redo
addRedo(player, blockSet);
return true;
}
return true;
}
public static boolean redo(EntityPlayer player) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
public static boolean redo(Player player) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.level.isClientSide ? redoStacksClient : redoStacksServer;
if (!redoStacks.containsKey(player.getUniqueID())) return false;
if (!redoStacks.containsKey(player.getUUID())) return false;
FixedStack<BlockSet> redoStack = redoStacks.get(player.getUniqueID());
FixedStack<BlockSet> redoStack = redoStacks.get(player.getUUID());
if (redoStack.isEmpty()) return false;
if (redoStack.isEmpty()) return false;
BlockSet blockSet = redoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<IBlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec();
BlockSet blockSet = redoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<BlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<BlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3 hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, newBlockStates);
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, newBlockStates);
if (player.world.isRemote) {
BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
} else {
//place blocks
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (player.level.isClientSide) {
BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
} else {
//place blocks
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack
IBlockState newBlockState = Blocks.AIR.getDefaultState();
if (itemStack.getItem() instanceof ItemBlock) {
newBlockState = newBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
}
//get blockstate from itemstack
BlockState newBlockState = Blocks.AIR.defaultBlockState();
if (itemStack.getItem() instanceof BlockItem) {
newBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
}
if (player.world.isBlockLoaded(coordinate, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, newBlockStates.get(i));
//get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) {
newBlockState = newBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} else {
newBlockState = Blocks.AIR.getDefaultState();
}
}
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true);
SurvivalHelper.placeBlock(player.world, player, coordinate, newBlockState, itemStack, EnumFacing.UP, hitVec, true, false, false);
}
}
}
if (player.level.isLoaded(coordinate)) {
//check itemstack empty
if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, newBlockStates.get(i));
//get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) {
newBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
} else {
if (newBlockStates.get(i).getBlock() != Blocks.AIR)
EffortlessBuilding.logTranslate(player, "", newBlockStates.get(i).getBlock().getDescriptionId(), " not found in inventory", true);
newBlockState = Blocks.AIR.defaultBlockState();
}
}
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.level, player, coordinate, true);
SurvivalHelper.placeBlock(player.level, player, coordinate, newBlockState, itemStack, Direction.UP, hitVec, true, false, false);
}
}
}
//add to undo
addUndo(player, blockSet);
//add to undo
addUndo(player, blockSet);
return true;
}
return true;
}
public static void clear(EntityPlayer player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
if (undoStacks.containsKey(player.getUniqueID())) {
undoStacks.get(player.getUniqueID()).clear();
}
if (redoStacks.containsKey(player.getUniqueID())) {
redoStacks.get(player.getUniqueID()).clear();
}
}
public static void clear(Player player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.level.isClientSide ? undoStacksClient : undoStacksServer;
Map<UUID, FixedStack<BlockSet>> redoStacks = player.level.isClientSide ? redoStacksClient : redoStacksServer;
if (undoStacks.containsKey(player.getUUID())) {
undoStacks.get(player.getUUID()).clear();
}
if (redoStacks.containsKey(player.getUUID())) {
redoStacks.get(player.getUUID()).clear();
}
}
private static List<ItemStack> findItemStacksInInventory(EntityPlayer player, List<IBlockState> blockStates) {
List<ItemStack> itemStacks = new ArrayList<>(blockStates.size());
for (IBlockState blockState : blockStates) {
itemStacks.add(findItemStackInInventory(player, blockState));
}
return itemStacks;
}
private static List<ItemStack> findItemStacksInInventory(Player player, List<BlockState> blockStates) {
List<ItemStack> itemStacks = new ArrayList<>(blockStates.size());
for (BlockState blockState : blockStates) {
itemStacks.add(findItemStackInInventory(player, blockState));
}
return itemStacks;
}
private static ItemStack findItemStackInInventory(EntityPlayer player, IBlockState blockState) {
ItemStack itemStack = ItemStack.EMPTY;
if (blockState == null) return itemStack;
private static ItemStack findItemStackInInventory(Player player, BlockState blockState) {
ItemStack itemStack = ItemStack.EMPTY;
if (blockState == null) return itemStack;
//First try previousBlockStates
//TODO try to find itemstack with right blockstate first
// then change line 103 back (get state from item)
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
//First try previousBlockStates
//TODO try to find itemstack with right blockstate first
// then change line 103 back (get state from item)
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
//then anything it drops
if (itemStack.isEmpty()) {
Item itemDropped = blockState.getBlock().getItemDropped(blockState, player.world, BlockPos.ORIGIN, 10).asItem();
if (itemDropped instanceof ItemBlock) {
Block block = ((ItemBlock) itemDropped).getBlock();
itemStack = InventoryHelper.findItemStackInInventory(player, block);
}
}
//then air
//(already empty)
//then anything it drops
if (itemStack.isEmpty()) {
//Cannot check drops on clientside because loot tables are server only
if (!player.level.isClientSide) {
List<ItemStack> itemsDropped = Block.getDrops(blockState, (ServerLevel) player.level, BlockPos.ZERO, null);
for (ItemStack itemStackDropped : itemsDropped) {
if (itemStackDropped.getItem() instanceof BlockItem) {
Block block = ((BlockItem) itemStackDropped.getItem()).getBlock();
itemStack = InventoryHelper.findItemStackInInventory(player, block);
}
}
}
}
return itemStack;
}
//then air
//(already empty)
return itemStack;
}
}

View File

@@ -1,35 +1,37 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ItemHandlerCapabilityProvider implements ICapabilitySerializable<NBTTagCompound> {
IItemHandler itemHandler = new ItemStackHandler(ItemRandomizerBag.INV_SIZE);
public class ItemHandlerCapabilityProvider implements ICapabilitySerializable<CompoundTag> {
IItemHandler itemHandler;
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side) {
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> itemHandler));
}
public ItemHandlerCapabilityProvider(int size) {
itemHandler = new ItemStackHandler(size);
}
@Override
public NBTTagCompound serializeNBT() {
return ((ItemStackHandler) itemHandler).serializeNBT();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> itemHandler));
}
@Override
public void deserializeNBT(NBTTagCompound nbt) {
((ItemStackHandler) itemHandler).deserializeNBT(nbt);
}
@Override
public CompoundTag serializeNBT() {
return ((ItemStackHandler) itemHandler).serializeNBT();
}
@Override
public void deserializeNBT(CompoundTag nbt) {
((ItemStackHandler) itemHandler).deserializeNBT(nbt);
}
}

View File

@@ -1,10 +1,11 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.INBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.core.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityProvider;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent;
@@ -15,89 +16,97 @@ import nl.requios.effortlessbuilding.buildmode.BuildModes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
@Mod.EventBusSubscriber
public class ModeCapabilityManager {
@CapabilityInject(IModeCapability.class)
public final static Capability<IModeCapability> modeCapability = null;
@CapabilityInject(IModeCapability.class)
public final static Capability<IModeCapability> MODE_CAPABILITY = null;
public interface IModeCapability {
ModeSettings getModeData();
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModeCapability> original = event.getOriginal().getCapability(MODE_CAPABILITY, null);
LazyOptional<IModeCapability> clone = event.getEntity().getCapability(MODE_CAPABILITY, null);
clone.ifPresent(cloneModeCapability ->
original.ifPresent(originalModeCapability ->
cloneModeCapability.setModeData(originalModeCapability.getModeData())));
}
void setModeData(ModeSettings modeSettings);
}
public interface IModeCapability {
ModeSettings getModeData();
public static class ModeCapability implements IModeCapability {
private ModeSettings modeSettings;
void setModeData(ModeSettings modeSettings);
}
@Override
public ModeSettings getModeData() {
return modeSettings;
}
public static class ModeCapability implements IModeCapability {
private ModeSettings modeSettings;
@Override
public void setModeData(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
}
@Override
public ModeSettings getModeData() {
return modeSettings;
}
public static class Storage implements Capability.IStorage<IModeCapability> {
@Override
public INBTBase writeNBT(Capability<IModeCapability> capability, IModeCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound();
ModeSettings modeSettings = instance.getModeData();
if (modeSettings == null) modeSettings = new ModeSettings();
@Override
public void setModeData(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
}
//compound.setInteger("buildMode", modeSettings.getBuildMode().ordinal());
public static class Provider extends CapabilityProvider<Provider> implements ICapabilitySerializable<Tag> {
//TODO add mode settings
private IModeCapability instance = new ModeCapability();
private LazyOptional<IModeCapability> modeCapabilityOptional = LazyOptional.of(() -> instance);
return compound;
}
public Provider() {
super(Provider.class);
gatherCapabilities();
}
@Override
public void readNBT(Capability<IModeCapability> capability, IModeCapability instance, EnumFacing side, INBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt;
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == MODE_CAPABILITY) return modeCapabilityOptional.cast();
return LazyOptional.empty();
}
//BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")];
@Override
public void invalidateCaps() {
super.invalidateCaps();
modeCapabilityOptional.invalidate();
}
//TODO add mode settings
@Override
public void reviveCaps() {
super.reviveCaps();
modeCapabilityOptional = LazyOptional.of(() -> instance);
}
ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.NORMAL);
instance.setModeData(modeSettings);
}
}
@Override
public Tag serializeNBT() {
CompoundTag compound = new CompoundTag();
ModeSettings modeSettings = instance.getModeData();
if (modeSettings == null) modeSettings = new ModeSettings();
public static class Provider implements ICapabilitySerializable<INBTBase> {
IModeCapability inst = modeCapability.getDefaultInstance();
//compound.putInteger("buildMode", modeSettings.getBuildMode().ordinal());
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side) {
return modeCapability.orEmpty(cap, LazyOptional.of(() -> inst));
}
//TODO add mode settings
@Override
public INBTBase serializeNBT() {
return modeCapability.getStorage().writeNBT(modeCapability, inst, null);
}
return compound;
}
@Override
public void deserializeNBT(INBTBase nbt) {
modeCapability.getStorage().readNBT(modeCapability, inst, null, nbt);
}
@Override
public void deserializeNBT(Tag nbt) {
CompoundTag compound = (CompoundTag) nbt;
}
//BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")];
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModeCapability> original = event.getOriginal().getCapability(modeCapability, null);
LazyOptional<IModeCapability> clone = event.getEntity().getCapability(modeCapability, null);
clone.ifPresent(cloneModeCapability ->
original.ifPresent(originalModeCapability ->
cloneModeCapability.setModeData(originalModeCapability.getModeData())));
}
//TODO add mode settings
ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.NORMAL);
instance.setModeData(modeSettings);
}
}
}

View File

@@ -1,18 +1,19 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.INBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityProvider;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
@@ -20,166 +21,170 @@ import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.*;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
@Mod.EventBusSubscriber
public class ModifierCapabilityManager {
@CapabilityInject(IModifierCapability.class)
public final static Capability<IModifierCapability> modifierCapability = null;
@CapabilityInject(IModifierCapability.class)
public final static Capability<IModifierCapability> MODIFIER_CAPABILITY = null;
public interface IModifierCapability {
ModifierSettings getModifierData();
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModifierCapability> original = event.getOriginal().getCapability(MODIFIER_CAPABILITY, null);
LazyOptional<IModifierCapability> clone = event.getEntity().getCapability(MODIFIER_CAPABILITY, null);
clone.ifPresent(cloneModifierCapability ->
original.ifPresent(originalModifierCapability ->
cloneModifierCapability.setModifierData(originalModifierCapability.getModifierData())));
}
void setModifierData(ModifierSettings modifierSettings);
}
public interface IModifierCapability {
ModifierSettings getModifierData();
public static class ModifierCapability implements IModifierCapability {
private ModifierSettings modifierSettings;
void setModifierData(ModifierSettings modifierSettings);
}
@Override
public ModifierSettings getModifierData() {
return modifierSettings;
}
public static class ModifierCapability implements IModifierCapability {
private ModifierSettings modifierSettings;
@Override
public void setModifierData(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
}
@Override
public ModifierSettings getModifierData() {
return modifierSettings;
}
public static class Storage implements Capability.IStorage<IModifierCapability> {
@Override
public INBTBase writeNBT(Capability<IModifierCapability> capability, IModifierCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound();
ModifierSettings modifierSettings = instance.getModifierData();
if (modifierSettings == null) modifierSettings = new ModifierSettings();
@Override
public void setModifierData(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
}
//MIRROR
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings();
compound.setBoolean("mirrorEnabled", m.enabled);
compound.setDouble("mirrorPosX", m.position.x);
compound.setDouble("mirrorPosY", m.position.y);
compound.setDouble("mirrorPosZ", m.position.z);
compound.setBoolean("mirrorX", m.mirrorX);
compound.setBoolean("mirrorY", m.mirrorY);
compound.setBoolean("mirrorZ", m.mirrorZ);
compound.setInt("mirrorRadius", m.radius);
compound.setBoolean("mirrorDrawLines", m.drawLines);
compound.setBoolean("mirrorDrawPlanes", m.drawPlanes);
public static class Provider extends CapabilityProvider<Provider> implements INBTSerializable<Tag> {
//ARRAY
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings();
compound.setBoolean("arrayEnabled", a.enabled);
compound.setInt("arrayOffsetX", a.offset.getX());
compound.setInt("arrayOffsetY", a.offset.getY());
compound.setInt("arrayOffsetZ", a.offset.getZ());
compound.setInt("arrayCount", a.count);
private final IModifierCapability instance = new ModifierCapability();
private LazyOptional<IModifierCapability> modifierCapabilityOptional = LazyOptional.of(() -> instance);
compound.setInt("reachUpgrade", modifierSettings.getReachUpgrade());
public Provider() {
super(Provider.class);
gatherCapabilities();
}
//compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == MODIFIER_CAPABILITY) return modifierCapabilityOptional.cast();
return LazyOptional.empty();
}
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.setBoolean("radialMirrorEnabled", r.enabled);
compound.setDouble("radialMirrorPosX", r.position.x);
compound.setDouble("radialMirrorPosY", r.position.y);
compound.setDouble("radialMirrorPosZ", r.position.z);
compound.setInt("radialMirrorSlices", r.slices);
compound.setBoolean("radialMirrorAlternate", r.alternate);
compound.setInt("radialMirrorRadius", r.radius);
compound.setBoolean("radialMirrorDrawLines", r.drawLines);
compound.setBoolean("radialMirrorDrawPlanes", r.drawPlanes);
@Override
public void invalidateCaps() {
super.invalidateCaps();
modifierCapabilityOptional.invalidate();
}
return compound;
}
@Override
public void reviveCaps() {
super.reviveCaps();
modifierCapabilityOptional = LazyOptional.of(() -> instance);
}
@Override
public void readNBT(Capability<IModifierCapability> capability, IModifierCapability instance, EnumFacing side, INBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt;
@Override
public Tag serializeNBT() {
CompoundTag compound = new CompoundTag();
ModifierSettings modifierSettings = instance.getModifierData();
if (modifierSettings == null) modifierSettings = new ModifierSettings();
//MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled");
Vec3d mirrorPosition = new Vec3d(
compound.getDouble("mirrorPosX"),
compound.getDouble("mirrorPosY"),
compound.getDouble("mirrorPosZ"));
boolean mirrorX = compound.getBoolean("mirrorX");
boolean mirrorY = compound.getBoolean("mirrorY");
boolean mirrorZ = compound.getBoolean("mirrorZ");
int mirrorRadius = compound.getInt("mirrorRadius");
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines");
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes");
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes);
//MIRROR
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings();
compound.putBoolean("mirrorEnabled", m.enabled);
compound.putDouble("mirrorPosX", m.position.x);
compound.putDouble("mirrorPosY", m.position.y);
compound.putDouble("mirrorPosZ", m.position.z);
compound.putBoolean("mirrorX", m.mirrorX);
compound.putBoolean("mirrorY", m.mirrorY);
compound.putBoolean("mirrorZ", m.mirrorZ);
compound.putInt("mirrorRadius", m.radius);
compound.putBoolean("mirrorDrawLines", m.drawLines);
compound.putBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY
boolean arrayEnabled = compound.getBoolean("arrayEnabled");
BlockPos arrayOffset = new BlockPos(
compound.getInt("arrayOffsetX"),
compound.getInt("arrayOffsetY"),
compound.getInt("arrayOffsetZ"));
int arrayCount = compound.getInt("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
//ARRAY
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings();
compound.putBoolean("arrayEnabled", a.enabled);
compound.putInt("arrayOffsetX", a.offset.getX());
compound.putInt("arrayOffsetY", a.offset.getY());
compound.putInt("arrayOffsetZ", a.offset.getZ());
compound.putInt("arrayCount", a.count);
int reachUpgrade = compound.getInt("reachUpgrade");
compound.putInt("reachUpgrade", modifierSettings.getReachUpgrade());
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
//compound.putBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
//RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3d radialMirrorPosition = new Vec3d(
compound.getDouble("radialMirrorPosX"),
compound.getDouble("radialMirrorPosY"),
compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInt("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInt("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.putBoolean("radialMirrorEnabled", r.enabled);
compound.putDouble("radialMirrorPosX", r.position.x);
compound.putDouble("radialMirrorPosY", r.position.y);
compound.putDouble("radialMirrorPosZ", r.position.z);
compound.putInt("radialMirrorSlices", r.slices);
compound.putBoolean("radialMirrorAlternate", r.alternate);
compound.putInt("radialMirrorRadius", r.radius);
compound.putBoolean("radialMirrorDrawLines", r.drawLines);
compound.putBoolean("radialMirrorDrawPlanes", r.drawPlanes);
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
instance.setModifierData(modifierSettings);
}
}
return compound;
}
public static class Provider implements ICapabilitySerializable<INBTBase> {
@Override
public void deserializeNBT(Tag nbt) {
CompoundTag compound = (CompoundTag) nbt;
IModifierCapability inst = modifierCapability.getDefaultInstance();
//MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled");
Vec3 mirrorPosition = new Vec3(
compound.getDouble("mirrorPosX"),
compound.getDouble("mirrorPosY"),
compound.getDouble("mirrorPosZ"));
boolean mirrorX = compound.getBoolean("mirrorX");
boolean mirrorY = compound.getBoolean("mirrorY");
boolean mirrorZ = compound.getBoolean("mirrorZ");
int mirrorRadius = compound.getInt("mirrorRadius");
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines");
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes");
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes);
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side) {
return modifierCapability.orEmpty(cap, LazyOptional.of(() -> inst));
}
//ARRAY
boolean arrayEnabled = compound.getBoolean("arrayEnabled");
BlockPos arrayOffset = new BlockPos(
compound.getInt("arrayOffsetX"),
compound.getInt("arrayOffsetY"),
compound.getInt("arrayOffsetZ"));
int arrayCount = compound.getInt("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
@Override
public INBTBase serializeNBT() {
return modifierCapability.getStorage().writeNBT(modifierCapability, inst, null);
}
int reachUpgrade = compound.getInt("reachUpgrade");
@Override
public void deserializeNBT(INBTBase nbt) {
modifierCapability.getStorage().readNBT(modifierCapability, inst, null, nbt);
}
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
}
//RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3 radialMirrorPosition = new Vec3(
compound.getDouble("radialMirrorPosX"),
compound.getDouble("radialMirrorPosY"),
compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInt("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInt("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
instance.setModifierData(modifierSettings);
}
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModifierCapability> original = event.getOriginal().getCapability(modifierCapability, null);
LazyOptional<IModifierCapability> clone = event.getEntity().getCapability(modifierCapability, null);
clone.ifPresent(cloneModifierCapability ->
original.ifPresent(originalModifierCapability ->
cloneModifierCapability.setModifierData(originalModifierCapability.getModifierData())));
}
}
}

View File

@@ -2,43 +2,42 @@ package nl.requios.effortlessbuilding.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
public class CommandReach {
public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(Commands.literal("reach").then(Commands.literal("set").then(Commands.argument("level", IntegerArgumentType.integer(0, 3)).executes((context) -> {
return setReachLevel(context.getSource().asPlayer(), IntegerArgumentType.getInteger(context, "level"));
}))).then(Commands.literal("get").executes((context -> {
return getReachLevel(context.getSource().asPlayer());
}))));
}
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("reach").then(Commands.literal("set").then(Commands.argument("level", IntegerArgumentType.integer(0, 3)).executes((context) -> {
return setReachLevel(context.getSource().getPlayerOrException(), IntegerArgumentType.getInteger(context, "level"));
}))).then(Commands.literal("get").executes((context -> {
return getReachLevel(context.getSource().getPlayerOrException());
}))));
}
private static int setReachLevel(EntityPlayerMP player, int level){
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setReachUpgrade(level);
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
//Send to client
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new ModifierSettingsMessage(modifierSettings));
private static int setReachLevel(ServerPlayer player, int level) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setReachUpgrade(level);
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
//Send to client
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new ModifierSettingsMessage(modifierSettings));
player.sendMessage(new TextComponentString("Reach level of " + player.getName().getString() + " set to " + modifierSettings.getReachUpgrade()));
player.sendMessage(new TextComponent("Reach level of " + player.getName().getString() + " set to " + modifierSettings.getReachUpgrade()), player.getUUID());
return 1;
}
return 1;
}
private static int getReachLevel(EntityPlayerMP player){
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
EffortlessBuilding.log(player, "Current reach: level "+reachUpgrade);
private static int getReachLevel(ServerPlayer player) {
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
EffortlessBuilding.log(player, "Current reach: level " + reachUpgrade);
return 1;
}
return 1;
}
}

View File

@@ -1,133 +1,63 @@
package nl.requios.effortlessbuilding.compatibility;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
public class CompatHelper {
//TODO 1.13 compatibility
// // Get a handle to the dank null item instance. This will remain null if the mod doesn't load
// // and all checks will fail, so it works.
// @GameRegistry.ObjectHolder("danknull:dank_null")
// public static final Item dankNullItem = null;
//
// public static IChiselsAndBitsProxy chiselsAndBitsProxy;
//
public static void setup() {
//TODO 1.13 compatibility
// if (Loader.isModLoaded("chiselsandbits")) {
// // reflection to avoid hard dependency
// try {
// chiselsAndBitsProxy = Class.forName("nl.requios.effortlessbuilding.compatibility.ActiveChiselsAndBitsProxy").asSubclass(ActiveChiselsAndBitsProxy.class).newInstance();
// } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
// e.printStackTrace();
// }
// } else {
// chiselsAndBitsProxy = new DummyChiselsAndBitsProxy();
// }
}
// Check if the item given is a proxy for blocks. For now, we check for the randomizer bag,
// /dank/null, or plain old blocks.
public static boolean isItemBlockProxy(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof ItemBlock)
return true;
if ((item instanceof ItemRandomizerBag))
return true;
//TODO 1.13 compatibility
// if (item == dankNullItem)
// return true;
return false;
}
public static void setup() {
// Get the block to be placed by this proxy. For the /dank/null, it's the slot stack
// pointed to by nbt integer selectedIndex.
public static ItemStack getItemBlockFromStack(ItemStack proxy) {
Item proxyItem = proxy.getItem();
}
if (proxyItem instanceof ItemBlock)
return proxy;
// Check if the item given is a proxy for blocks. For now, we check for the randomizer bag,
// /dank/null, or plain old blocks.
public static boolean isItemBlockProxy(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof BlockItem)
return true;
return item instanceof AbstractRandomizerBagItem;
}
//Randomizer Bag
if (proxyItem instanceof ItemRandomizerBag) {
ItemStack itemStack = proxy;
while (!(itemStack.getItem() instanceof ItemBlock || itemStack.isEmpty())) {
if (itemStack.getItem() instanceof ItemRandomizerBag)
itemStack = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack));
}
return itemStack;
}
// Get the block to be placed by this proxy. For the /dank/null, it's the slot stack
// pointed to by nbt integer selectedIndex.
public static ItemStack getItemBlockFromStack(ItemStack proxy) {
Item proxyItem = proxy.getItem();
//TODO 1.13 compatibility
//Dank Null
// if (proxyItem == dankNullItem) {
// int index = 0;
// if (proxy.hasTagCompound() && proxy.getTagCompound().hasKey("selectedIndex"))
// index = proxy.getTagCompound().getInteger("selectedIndex");
// return proxy.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
// }
if (proxyItem instanceof BlockItem)
return proxy;
return ItemStack.EMPTY;
}
//Randomizer Bag
if (proxyItem instanceof AbstractRandomizerBagItem) {
ItemStack itemStack = proxy;
while (!(itemStack.getItem() instanceof BlockItem || itemStack.isEmpty())) {
if (itemStack.getItem() instanceof AbstractRandomizerBagItem) {
AbstractRandomizerBagItem randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem();
itemStack = randomizerBagItem.pickRandomStack(randomizerBagItem.getBagInventory(itemStack));
}
}
return itemStack;
}
public static ItemStack getItemBlockByState(ItemStack stack, IBlockState state) {
if (state == null) return ItemStack.EMPTY;
return ItemStack.EMPTY;
}
Item blockItem = Item.getItemFromBlock(state.getBlock());
if (stack.getItem() instanceof ItemBlock)
return stack;
else if (stack.getItem() instanceof ItemRandomizerBag) {
IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(stack);
return ItemRandomizerBag.findStack(bagInventory, blockItem);
}
//TODO 1.13 compatibility
// else if (stack.getItem() == dankNullItem) {
// int index = itemHandlerSlotForItem(stack, blockItem);
// if (index >= 0)
// return stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
// }
return ItemStack.EMPTY;
}
public static ItemStack getItemBlockByState(ItemStack stack, BlockState state) {
if (state == null) return ItemStack.EMPTY;
// Handle IItemHandler slot stacks not being modifiable. We must call IItemHandler#extractItem,
// because the ItemStack returned by IItemHandler#getStackInSlot isn't modifiable.
public static void shrinkStack(ItemStack origStack, ItemStack curStack, EntityPlayer player) {
//TODO 1.13 compatibility, offhand support
//Hacky way to get the origstack, because given origStack is itemblock stack and never proxy
// origStack = player.getHeldItem(EnumHand.MAIN_HAND);
Item blockItem = Item.byBlock(state.getBlock());
if (stack.getItem() instanceof BlockItem)
return stack;
else if (stack.getItem() instanceof AbstractRandomizerBagItem) {
AbstractRandomizerBagItem randomizerBagItem = (AbstractRandomizerBagItem) stack.getItem();
IItemHandler bagInventory = randomizerBagItem.getBagInventory(stack);
return randomizerBagItem.findStack(bagInventory, blockItem);
}
// if (origStack.getItem() == dankNullItem) {
// int index = itemHandlerSlotForItem(origStack, curStack.getItem());
// origStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).extractItem(index, 1, false);
// } else
curStack.shrink(1);
}
private static int itemHandlerSlotForItem(ItemStack stack, Item blockItem) {
LazyOptional<IItemHandler> itemHandlerLazyOptional = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
IItemHandler handler = itemHandlerLazyOptional.orElse(null);
if (handler == null) {
EffortlessBuilding.logger.warn("Itemblock proxy has no item handler capability!");
return -1;
}
for (int i = 0; i < handler.getSlots(); i++) {
ItemStack ref = handler.getStackInSlot(i);
if (ref.getItem() instanceof ItemBlock)
if (ref.getItem() == blockItem)
return i;
}
return -1;
}
return ItemStack.EMPTY;
}
}

View File

@@ -0,0 +1,148 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.DiamondRandomizerBagItem;
public class DiamondRandomizerBagContainer extends AbstractContainerMenu {
private static final int INV_START = DiamondRandomizerBagItem.INV_SIZE,
INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1,
HOTBAR_END = HOTBAR_START + 8;
private final IItemHandler bagInventory;
public DiamondRandomizerBagContainer(MenuType<?> type, int id){
super(type, id);
bagInventory = null;
}
//Client
public DiamondRandomizerBagContainer(int id, Inventory playerInventory, FriendlyByteBuf packetBuffer) {
this(id, playerInventory);
}
//Server?
public DiamondRandomizerBagContainer(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, new ItemStackHandler(DiamondRandomizerBagItem.INV_SIZE));
}
public DiamondRandomizerBagContainer(int containerId, Inventory playerInventory, IItemHandler inventory) {
super(EffortlessBuilding.DIAMOND_RANDOMIZER_BAG_CONTAINER.get(), containerId);
bagInventory = inventory;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
this.addSlot(new SlotItemHandler(bagInventory, j + i * 9, 8 + j * 18, 18 + i * 18));
}
}
// add player inventory slots
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
}
}
// add hotbar slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
}
}
@Override
public boolean stillValid(Player playerIn) {
return true;
}
@Override
public Slot getSlot(int parSlotIndex) {
if (parSlotIndex >= slots.size())
parSlotIndex = slots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override
public ItemStack quickMoveStack(Player playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(slotIndex);
if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy();
// If item is in our custom inventory
if (slotIndex < INV_START) {
// try to place in player inventory / action bar
if (!this.moveItemStackTo(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY;
}
slot.onQuickCraft(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place in custom inventory or armor slots
else {
/**
* Implementation number 1: Shift-click into your custom inventory
*/
if (slotIndex >= INV_START) {
// place in custom inventory
if (!this.moveItemStackTo(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY;
}
}
}
if (itemstack1.getCount() == 0) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
}
return itemstack;
}
/**
* You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public void clicked(int slot, int dragType, ClickType clickTypeIn, Player player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getItem().equals(player.getItemInHand(InteractionHand.MAIN_HAND))) {
//Do nothing;
return;
}
super.clicked(slot, dragType, clickTypeIn, player);
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void removed(Player player) {
super.removed(player);
if (!player.level.isClientSide) {
broadcastChanges();
}
}
}

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public class DiamondRandomizerBagScreen extends AbstractContainerScreen<DiamondRandomizerBagContainer> {
private Inventory inventory;
private static final ResourceLocation guiTextures = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/diamondrandomizerbag.png");
public DiamondRandomizerBagScreen(DiamondRandomizerBagContainer randomizerBagContainer, Inventory playerInventory, Component title) {
super(randomizerBagContainer, playerInventory, title);
this.inventory = playerInventory;
imageHeight = 167;
}
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms);
super.render(ms, mouseX, mouseY, partialTicks);
this.renderTooltip(ms, mouseX, mouseY);
}
@Override
protected void renderLabels(PoseStack ms, int mouseX, int mouseY) {
this.font.draw(ms, this.title, 8, 6, 0x404040);
this.font.draw(ms, this.playerInventoryTitle, 8, imageHeight - 96 + 2, 0x404040);
}
@Override
protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) {
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1f);
RenderSystem.setShaderTexture(0, guiTextures);
int marginHorizontal = (width - imageWidth) / 2;
int marginVertical = (height - imageHeight) / 2;
blit(ms, marginHorizontal, marginVertical, 0, 0, imageWidth, imageHeight);
}
}

View File

@@ -0,0 +1,146 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.GoldenRandomizerBagItem;
public class GoldenRandomizerBagContainer extends AbstractContainerMenu {
private static final int INV_START = GoldenRandomizerBagItem.INV_SIZE,
INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1,
HOTBAR_END = HOTBAR_START + 8;
private final IItemHandler bagInventory;
public GoldenRandomizerBagContainer(MenuType<?> type, int id){
super(type, id);
bagInventory = null;
}
//Client
public GoldenRandomizerBagContainer(int id, Inventory playerInventory, FriendlyByteBuf packetBuffer) {
this(id, playerInventory);
}
//Server?
public GoldenRandomizerBagContainer(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, new ItemStackHandler(GoldenRandomizerBagItem.INV_SIZE));
}
public GoldenRandomizerBagContainer(int containerId, Inventory playerInventory, IItemHandler inventory) {
super(EffortlessBuilding.GOLDEN_RANDOMIZER_BAG_CONTAINER.get(), containerId);
bagInventory = inventory;
for (int i = 0; i < GoldenRandomizerBagItem.INV_SIZE; ++i) {
this.addSlot(new SlotItemHandler(bagInventory, i, 8 + (18 * i), 20));
}
// add player inventory slots
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
}
}
// add hotbar slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 109));
}
}
@Override
public boolean stillValid(Player playerIn) {
return true;
}
@Override
public Slot getSlot(int parSlotIndex) {
if (parSlotIndex >= slots.size())
parSlotIndex = slots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override
public ItemStack quickMoveStack(Player playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(slotIndex);
if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy();
// If item is in our custom inventory
if (slotIndex < INV_START) {
// try to place in player inventory / action bar
if (!this.moveItemStackTo(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY;
}
slot.onQuickCraft(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place in custom inventory or armor slots
else {
/**
* Implementation number 1: Shift-click into your custom inventory
*/
if (slotIndex >= INV_START) {
// place in custom inventory
if (!this.moveItemStackTo(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY;
}
}
}
if (itemstack1.getCount() == 0) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
}
return itemstack;
}
/**
* You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public void clicked(int slot, int dragType, ClickType clickTypeIn, Player player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getItem().equals(player.getItemInHand(InteractionHand.MAIN_HAND))) {
//Do nothing;
return;
}
super.clicked(slot, dragType, clickTypeIn, player);
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void removed(Player player) {
super.removed(player);
if (!player.level.isClientSide) {
broadcastChanges();
}
}
}

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public class GoldenRandomizerBagScreen extends AbstractContainerScreen<GoldenRandomizerBagContainer> {
private Inventory inventory;
private static final ResourceLocation guiTextures = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/goldenrandomizerbag.png");
public GoldenRandomizerBagScreen(GoldenRandomizerBagContainer randomizerBagContainer, Inventory playerInventory, Component title) {
super(randomizerBagContainer, playerInventory, title);
this.inventory = playerInventory;
imageHeight = 134;
}
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms);
super.render(ms, mouseX, mouseY, partialTicks);
this.renderTooltip(ms, mouseX, mouseY);
}
@Override
protected void renderLabels(PoseStack ms, int mouseX, int mouseY) {
this.font.draw(ms, this.title, 8, 6, 0x404040);
this.font.draw(ms, this.playerInventoryTitle, 8, imageHeight - 96 + 2, 0x404040);
}
@Override
protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) {
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1f);
RenderSystem.setShaderTexture(0, guiTextures);
int marginHorizontal = (width - imageWidth) / 2;
int marginVertical = (height - imageHeight) / 2;
blit(ms, marginHorizontal, marginVertical, 0, 0, imageWidth, imageHeight);
}
}

View File

@@ -1,130 +1,146 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.InteractionHand;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.RandomizerBagItem;
public class RandomizerBagContainer extends Container {
public class RandomizerBagContainer extends AbstractContainerMenu {
private final IItemHandler bagInventory;
private final int sizeInventory;
private static final int INV_START = RandomizerBagItem.INV_SIZE,
INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1,
HOTBAR_END = HOTBAR_START + 8;
private final IItemHandler bagInventory;
private static final int INV_START = ItemRandomizerBag.INV_SIZE, INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1, HOTBAR_END = HOTBAR_START + 8;
public RandomizerBagContainer(MenuType<?> type, int id){
super(type, id);
bagInventory = null;
}
public RandomizerBagContainer(InventoryPlayer parInventoryPlayer, IItemHandler parIInventory) {
bagInventory = parIInventory;
sizeInventory = bagInventory.getSlots();
for (int i = 0; i < sizeInventory; ++i) {
this.addSlot(new SlotItemHandler(bagInventory, i, 44 + (18 * i), 20));
}
//Client
public RandomizerBagContainer(int id, Inventory playerInventory, FriendlyByteBuf packetBuffer) {
this(id, playerInventory);
}
// add player inventory slots
int i;
for (i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(parInventoryPlayer, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
}
}
//Server?
public RandomizerBagContainer(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, new ItemStackHandler(RandomizerBagItem.INV_SIZE));
}
// add hotbar slots
for (i = 0; i < 9; ++i) {
addSlot(new Slot(parInventoryPlayer, i, 8 + i * 18, 109));
}
}
public RandomizerBagContainer(int containerId, Inventory playerInventory, IItemHandler inventory) {
super(EffortlessBuilding.RANDOMIZER_BAG_CONTAINER.get(), containerId);
bagInventory = inventory;
for (int i = 0; i < RandomizerBagItem.INV_SIZE; ++i) {
this.addSlot(new SlotItemHandler(bagInventory, i, 44 + (18 * i), 20));
}
// add player inventory slots
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
}
}
// add hotbar slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 109));
}
}
@Override
public boolean canInteractWith(EntityPlayer playerIn) {
return true;
}
public boolean stillValid(Player playerIn) {
return true;
}
@Override
public Slot getSlot(int parSlotIndex)
{
if(parSlotIndex >= inventorySlots.size())
parSlotIndex = inventorySlots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override
public Slot getSlot(int parSlotIndex) {
if (parSlotIndex >= slots.size())
parSlotIndex = slots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override
public ItemStack transferStackInSlot(EntityPlayer playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.inventorySlots.get(slotIndex);
@Override
public ItemStack quickMoveStack(Player playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(slotIndex);
if (slot != null && slot.getHasStack()) {
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();
if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy();
// If item is in our custom inventory
if (slotIndex < INV_START) {
// try to place in player inventory / action bar
if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY;
}
// If item is in our custom inventory
if (slotIndex < INV_START) {
// try to place in player inventory / action bar
if (!this.moveItemStackTo(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY;
}
slot.onSlotChange(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place in custom inventory or armor slots
else {
/**
* Implementation number 1: Shift-click into your custom inventory
*/
if (slotIndex >= INV_START) {
// place in custom inventory
if (!this.mergeItemStack(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY;
}
}
slot.onQuickCraft(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place in custom inventory or armor slots
else {
/**
* Implementation number 1: Shift-click into your custom inventory
*/
if (slotIndex >= INV_START) {
// place in custom inventory
if (!this.moveItemStackTo(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY;
}
}
}
}
if (itemstack1.getCount() == 0) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == 0) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
}
slot.onTake(playerIn, itemstack1);
}
return itemstack;
}
return itemstack;
}
/**
* You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public void clicked(int slot, int dragType, ClickType clickTypeIn, Player player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getItem().equals(player.getItemInHand(InteractionHand.MAIN_HAND))) {
//Do nothing;
return;
}
super.clicked(slot, dragType, clickTypeIn, player);
}
/**
* You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, EntityPlayer player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack().equals(player.getHeldItem(EnumHand.MAIN_HAND))) {
return ItemStack.EMPTY;
}
return super.slotClick(slot, dragType, clickTypeIn, player);
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void onContainerClosed(EntityPlayer player)
{
super.onContainerClosed(player);
if(!player.world.isRemote)
{
detectAndSendChanges();
}
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void removed(Player player) {
super.removed(player);
if (!player.level.isClientSide) {
broadcastChanges();
}
}
}

View File

@@ -1,49 +0,0 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
@OnlyIn(Dist.CLIENT)
public class RandomizerBagGuiContainer extends GuiContainer {
private static final ResourceLocation guiTextures =
new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png");
private final InventoryPlayer inventoryPlayer;
private final IItemHandler inventoryBag;
public RandomizerBagGuiContainer(InventoryPlayer inventoryPlayer, IItemHandler inventoryBag) {
super(new RandomizerBagContainer(inventoryPlayer, inventoryBag));
this.inventoryPlayer = inventoryPlayer;
this.inventoryBag = inventoryBag;
ySize = 134;
}
@Override
public void render(int mouseX, int mouseY, float partialTicks) {
drawDefaultBackground();
super.render(mouseX, mouseY, partialTicks);
this.renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
String s = "Randomizer Bag";
fontRenderer.drawString(s, 8, 6, 0x404040);
fontRenderer.drawString(inventoryPlayer.getDisplayName().getUnformattedComponentText(), 8, ySize - 96 + 2, 0x404040);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
GlStateManager.color3f(1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(guiTextures);
int marginHorizontal = (width - xSize) / 2;
int marginVertical = (height - ySize) / 2;
drawTexturedModalRect(marginHorizontal, marginVertical, 0, 0, xSize, ySize);
}
}

View File

@@ -1,112 +0,0 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.network.IGuiHandler;
import net.minecraftforge.fml.network.FMLPlayMessages;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import javax.annotation.Nullable;
public class RandomizerBagGuiHandler implements /*IGuiHandler, */IInteractionObject {
// @Nullable
// @Override
// public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
// if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// // Use the player's held item to create the container
// LazyOptional<IItemHandler> capabilityOptional = player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
//
// if (!capabilityOptional.isPresent()) {
// capabilityOptional = player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
// }
//
// return new RandomizerBagContainer(player.inventory, capabilityOptional.orElse(null));
// }
// return null;
// }
//
// @Nullable
// @Override
// @OnlyIn(Dist.CLIENT)
// public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
// if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// // Use the player's held item to create the client-side gui container
// LazyOptional<IItemHandler> capabilityOptional = player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
//
// if (!capabilityOptional.isPresent()) {
// capabilityOptional = player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
// }
//
// return new RandomizerBagGuiContainer(player.inventory, capabilityOptional.orElse(null));
// }
// return null;
// }
@OnlyIn(Dist.CLIENT)
public static GuiScreen openGui(FMLPlayMessages.OpenContainer openContainer) {
if (openContainer.getId().equals(EffortlessBuilding.RANDOMIZER_BAG_GUI)) {
EntityPlayerSP player = Minecraft.getInstance().player;
if (player.getHeldItem(EnumHand.MAIN_HAND).getItem() instanceof ItemRandomizerBag) {
IItemHandler itemHandler = player.getHeldItem(EnumHand.MAIN_HAND).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (itemHandler != null) {
return new RandomizerBagGuiContainer(player.inventory, itemHandler);
}
}
}
return null;
}
@Override
public Container createContainer(InventoryPlayer inventory, EntityPlayer player) {
if (player.getHeldItem(EnumHand.MAIN_HAND).getItem() instanceof ItemRandomizerBag) {
IItemHandler itemHandler = player.getHeldItem(EnumHand.MAIN_HAND).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (itemHandler != null) {
return new RandomizerBagContainer(inventory, itemHandler);
}
}
return null;
}
@Override
public String getGuiID() {
return EffortlessBuilding.RANDOMIZER_BAG_GUI.toString();
}
@Override
public ITextComponent getName() {
return new TextComponentString("Randomizer Bag");
}
@Override
public boolean hasCustomName() {
return false;
}
@Override
public ITextComponent getDisplayName() {
return new TextComponentString("Randomizer Bag");
}
@Nullable
@Override
public ITextComponent getCustomName() {
return null;
}
}

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public class RandomizerBagScreen extends AbstractContainerScreen<RandomizerBagContainer> {
private Inventory inventory;
private static final ResourceLocation guiTextures = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png");
public RandomizerBagScreen(RandomizerBagContainer randomizerBagContainer, Inventory playerInventory, Component title) {
super(randomizerBagContainer, playerInventory, title);
this.inventory = playerInventory;
imageHeight = 134;
}
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms);
super.render(ms, mouseX, mouseY, partialTicks);
this.renderTooltip(ms, mouseX, mouseY);
}
@Override
protected void renderLabels(PoseStack ms, int mouseX, int mouseY) {
this.font.draw(ms, this.title, 8, 6, 0x404040);
this.font.draw(ms, this.playerInventoryTitle, 8, imageHeight - 96 + 2, 0x404040);
}
@Override
protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) {
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1f);
RenderSystem.setShaderTexture(0, guiTextures);
int marginHorizontal = (width - imageWidth) / 2;
int marginVertical = (height - imageHeight) / 2;
blit(ms, marginHorizontal, marginVertical, 0, 0, imageWidth, imageHeight);
}
}

View File

@@ -0,0 +1,310 @@
package nl.requios.effortlessbuilding.gui.buildmode;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fmlclient.gui.widget.ExtendedButton;
import net.minecraftforge.fmlclient.gui.widget.Slider;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class PlayerSettingsGui extends Screen {
protected int left, right, top, bottom;
protected boolean showShaderList = false;
private Button shaderTypeButton;
private ShaderTypeList shaderTypeList;
private Button closeButton;
public PlayerSettingsGui() {
super(new TranslatableComponent("effortlessbuilding.screen.player_settings"));
}
@Override
protected void init() {
left = this.width / 2 - 140;
right = this.width / 2 + 140;
top = this.height / 2 - 100;
bottom = this.height / 2 + 100;
int yy = top;
shaderTypeList = new ShaderTypeList(this.minecraft);
addWidget(shaderTypeList);
//TODO set selected name
Component currentShaderName = ShaderType.DISSOLVE_BLUE.name;
shaderTypeButton = new ExtendedButton(right - 180, yy, 180, 20, currentShaderName, (button) -> {
showShaderList = !showShaderList;
});
addRenderableOnly(shaderTypeButton);
yy += 50;
Slider slider = new Slider(right - 200, yy, 200, 20, TextComponent.EMPTY, TextComponent.EMPTY, 0.5, 2.0, 1.0, true, true, (button) -> {
});
addRenderableOnly(slider);
closeButton = new ExtendedButton(left + 50, bottom - 20, 180, 20, new TextComponent("Done"), (button) -> this.minecraft.player.closeContainer());
addRenderableOnly(closeButton);
}
@Override
public void tick() {
super.tick();
}
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(ms);
int yy = top;
font.draw(ms, "Shader type", left, yy + 5, 0xFFFFFF);
yy += 50;
font.draw(ms, "Shader speed", left, yy + 5, 0xFFFFFF);
super.render(ms, mouseX, mouseY, partialTicks);
if (showShaderList)
this.shaderTypeList.render(ms, mouseX, mouseY, partialTicks);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
super.mouseClicked(mouseX, mouseY, mouseButton);
if (showShaderList) {
if (!shaderTypeList.isMouseOver(mouseX, mouseY) && !shaderTypeButton.isMouseOver(mouseX, mouseY))
showShaderList = false;
}
return true;
}
@Override
public void removed() {
ShaderTypeList.ShaderTypeEntry selectedShader = shaderTypeList.getSelected();
//TODO save and remove
}
public enum ShaderType {
DISSOLVE_BLUE("Dissolve Blue"),
DISSOLVE_ORANGE("Dissolve Orange");
public Component name;
ShaderType(Component name) {
this.name = name;
}
ShaderType(String name) {
this.name = new TextComponent(name);
}
}
//Inspired by LanguageScreen
@OnlyIn(Dist.CLIENT)
class ShaderTypeList extends ObjectSelectionList<PlayerSettingsGui.ShaderTypeList.ShaderTypeEntry> {
public ShaderTypeList(Minecraft mcIn) {
super(mcIn, 180, 140, top + 20, top + 100, 18);
this.setLeftPos(right - width);
for (int i = 0; i < 40; i++) {
for (ShaderType shaderType : ShaderType.values()) {
ShaderTypeEntry shaderTypeEntry = new ShaderTypeEntry(shaderType);
addEntry(shaderTypeEntry);
//TODO setSelected to this if appropriate
}
}
if (this.getSelected() != null) {
this.centerScrollOn(this.getSelected());
}
}
@Override
public int getRowWidth() {
return width;
}
@Override
public void setSelected(PlayerSettingsGui.ShaderTypeList.ShaderTypeEntry selected) {
super.setSelected(selected);
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
EffortlessBuilding.log("Selected shader " + selected.shaderType.name);
shaderTypeButton.setMessage(selected.shaderType.name);
// showShaderList = false;
}
@Override
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
if (!showShaderList) return false;
return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
}
@Override
public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) {
if (!showShaderList) return false;
return super.mouseReleased(p_mouseReleased_1_, p_mouseReleased_3_, p_mouseReleased_5_);
}
@Override
public boolean mouseDragged(double p_mouseDragged_1_, double p_mouseDragged_3_, int p_mouseDragged_5_, double p_mouseDragged_6_, double p_mouseDragged_8_) {
if (!showShaderList) return false;
return super.mouseDragged(p_mouseDragged_1_, p_mouseDragged_3_, p_mouseDragged_5_, p_mouseDragged_6_, p_mouseDragged_8_);
}
@Override
public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) {
if (!showShaderList) return false;
return super.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_);
}
@Override
public boolean isMouseOver(double p_isMouseOver_1_, double p_isMouseOver_3_) {
if (!showShaderList) return false;
return super.isMouseOver(p_isMouseOver_1_, p_isMouseOver_3_);
}
protected boolean isFocused() {
return PlayerSettingsGui.this.getFocused() == this;
}
@Override
protected int getScrollbarPosition() {
return right - 6;
}
//From AbstractList, disabled parts
@Override
public void render(PoseStack ms, int p_render_1_, int p_render_2_, float p_render_3_) {
this.renderBackground(ms);
int i = this.getScrollbarPosition();
int j = i + 6;
Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
// this.minecraft.getTextureManager().bindTexture(AbstractGui.BACKGROUND_LOCATION);
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
float f = 32.0F;
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
bufferbuilder.vertex(this.x0, this.y1, 0.0D).color(20, 20, 20, 180).endVertex();
bufferbuilder.vertex(this.x1, this.y1, 0.0D).color(20, 20, 20, 180).endVertex();
bufferbuilder.vertex(this.x1, this.y0, 0.0D).color(20, 20, 20, 180).endVertex();
bufferbuilder.vertex(this.x0, this.y0, 0.0D).color(20, 20, 20, 180).endVertex();
tessellator.end();
int k = this.getRowLeft();
int l = this.y0 + 4 - (int) this.getScrollAmount();
if (this.renderHeader) {
this.renderHeader(ms, k, l, tessellator);
}
this.renderList(ms, k, l, p_render_1_, p_render_2_, p_render_3_);
RenderSystem.disableDepthTest();
// this.renderHoleBackground(0, this.y0, 255, 255);
// this.renderHoleBackground(this.y1, this.height, 255, 255);
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
RenderSystem.disableTexture();
// int i1 = 4;
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.x0, (double)(this.y0 + 4), 0.0D).tex(0.0F, 1.0F).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x1, (double)(this.y0 + 4), 0.0D).tex(1.0F, 1.0F).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x1, (double)this.y0, 0.0D).tex(1.0F, 0.0F).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x0, (double)this.y0, 0.0D).tex(0.0F, 0.0F).color(0, 0, 0, 255).endVertex();
// tessellator.draw();
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.x0, (double)this.y1, 0.0D).tex(0.0F, 1.0F).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x1, (double)this.y1, 0.0D).tex(1.0F, 1.0F).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x1, (double)(this.y1 - 4), 0.0D).tex(1.0F, 0.0F).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x0, (double)(this.y1 - 4), 0.0D).tex(0.0F, 0.0F).color(0, 0, 0, 0).endVertex();
// tessellator.draw();
//SCROLLBAR
int j1 = this.getMaxScroll();
if (j1 > 0) {
int k1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition());
k1 = Mth.clamp(k1, 32, this.y1 - this.y0 - 8);
int l1 = (int) this.getScrollAmount() * (this.y1 - this.y0 - k1) / j1 + this.y0;
if (l1 < this.y0) {
l1 = this.y0;
}
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(i, this.y1, 0.0D).uv(0.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.vertex(j, this.y1, 0.0D).uv(1.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.vertex(j, this.y0, 0.0D).uv(1.0F, 0.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.vertex(i, this.y0, 0.0D).uv(0.0F, 0.0F).color(0, 0, 0, 255).endVertex();
tessellator.end();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(i, l1 + k1, 0.0D).uv(0.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.vertex(j, l1 + k1, 0.0D).uv(1.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.vertex(j, l1, 0.0D).uv(1.0F, 0.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.vertex(i, l1, 0.0D).uv(0.0F, 0.0F).color(128, 128, 128, 255).endVertex();
tessellator.end();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(i, l1 + k1 - 1, 0.0D).uv(0.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.vertex(j - 1, l1 + k1 - 1, 0.0D).uv(1.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.vertex(j - 1, l1, 0.0D).uv(1.0F, 0.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.vertex(i, l1, 0.0D).uv(0.0F, 0.0F).color(192, 192, 192, 255).endVertex();
tessellator.end();
}
// this.renderDecorations(p_render_1_, p_render_2_);
RenderSystem.enableTexture();
RenderSystem.disableBlend();
}
public int getMaxScroll() {
return Math.max(0, this.getMaxPosition() - (this.y1 - this.y0 - 4));
}
@OnlyIn(Dist.CLIENT)
public class ShaderTypeEntry extends ObjectSelectionList.Entry<ShaderTypeEntry> {
private final ShaderType shaderType;
public ShaderTypeEntry(ShaderType shaderType) {
this.shaderType = shaderType;
}
@Override
public void render(PoseStack ms, int itemIndex, int rowTop, int rowLeft, int rowWidth, int rowHeight, int mouseX, int mouseY, boolean hovered, float partialTicks) {
if (rowTop + 10 > ShaderTypeList.this.y0 && rowTop + rowHeight - 5 < ShaderTypeList.this.y1)
drawString(ms, font, shaderType.name, ShaderTypeList.this.x0 + 8, rowTop + 4, 0xFFFFFF);
}
@Override
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
if (p_mouseClicked_5_ == 0) {
setSelected(this);
return true;
} else {
return false;
}
}
@Override
public Component getNarration() {
return null;
}
}
}
}

View File

@@ -1,478 +1,506 @@
package nl.requios.effortlessbuilding.gui.buildmode;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.util.text.TextFormatting;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.core.Direction;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.network.ModeActionMessage;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.commons.lang3.text.WordUtils;
import org.lwjgl.opengl.GL11;
import com.google.common.base.Stopwatch;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.ModelLoader;
import static nl.requios.effortlessbuilding.buildmode.BuildModes.*;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*;
import nl.requios.effortlessbuilding.buildmode.BuildModes.BuildModeEnum;
import nl.requios.effortlessbuilding.buildmode.ModeOptions.ActionEnum;
import nl.requios.effortlessbuilding.buildmode.ModeOptions.OptionEnum;
/**
* From Chisels and Bits by AlgorithmX2
* Initially from Chisels and Bits by AlgorithmX2
* https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/client/gui/ChiselsAndBitsMenu.java
*/
public class RadialMenu extends GuiScreen {
private final float TIME_SCALE = 0.01f;
public static final RadialMenu instance = new RadialMenu();
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class RadialMenu extends Screen {
public static final RadialMenu instance = new RadialMenu();
public BuildModeEnum switchTo = null;
public ActionEnum doAction = null;
public boolean performedActionUsingMouse;
private float visibility;
public RadialMenu() {
super(new TranslatableComponent("effortlessbuilding.screen.radial_menu"));
}
public boolean isVisible() {
return Minecraft.getInstance().screen instanceof RadialMenu;
}
private float visibility = 0.0f;
private Stopwatch lastChange = Stopwatch.createStarted();
public BuildModeEnum switchTo = null;
public ActionEnum doAction = null;
public boolean actionUsed = false;
@Override
protected void init() {
super.init();
performedActionUsingMouse = false;
visibility = 0f;
}
private float clampVis(final float f) {
return Math.max( 0.0f, Math.min( 1.0f, f ) );
}
@Override
public void tick() {
super.tick();
if (!ClientProxy.isKeybindDown(2)) {
onClose();
}
}
@Override
public void render(PoseStack ms, final int mouseX, final int mouseY, final float partialTicks) {
BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(minecraft.player).getBuildMode();
ms.pushPose();
ms.translate(0, 0, 200);
visibility += 0.3f * partialTicks;
if (visibility > 1f) visibility = 1f;
final int startColor = (int) (visibility * 98) << 24;
final int endColor = (int) (visibility * 128) << 24;
fillGradient(ms, 0, 0, width, height, startColor, endColor);
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
final Tesselator tessellator = Tesselator.getInstance();
final BufferBuilder buffer = tessellator.getBuilder();
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
final double middleX = width / 2.0;
final double middleY = height / 2.0;
//Fix for high def (retina) displays: use custom mouse coordinates
//Borrowed from GameRenderer::updateCameraAndRender
int mouseXX = (int) (minecraft.mouseHandler.xpos() * (double) minecraft.getWindow().getGuiScaledWidth() / (double) minecraft.getWindow().getScreenWidth());
int mouseYY = (int) (minecraft.mouseHandler.ypos() * (double) minecraft.getWindow().getGuiScaledHeight() / (double) minecraft.getWindow().getScreenHeight());
final double mouseXCenter = mouseXX - middleX;
final double mouseYCenter = mouseYY - middleY;
double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter);
final double ringInnerEdge = 30;
final double ringOuterEdge = 65;
final double textDistance = 75;
final double buttonDistance = 105;
final double quarterCircle = Math.PI / 2.0;
if (mouseRadians < -quarterCircle) {
mouseRadians = mouseRadians + Math.PI * 2;
}
final ArrayList<MenuRegion> modes = new ArrayList<MenuRegion>();
final ArrayList<MenuButton> buttons = new ArrayList<MenuButton>();
//Add build modes
for (final BuildModeEnum mode : BuildModeEnum.values()) {
modes.add(new MenuRegion(mode));
}
//Add actions
buttons.add(new MenuButton(ActionEnum.UNDO.name, ActionEnum.UNDO, -buttonDistance - 26, -13, Direction.UP));
buttons.add(new MenuButton(ActionEnum.REDO.name, ActionEnum.REDO, -buttonDistance, -13, Direction.UP));
// buttons.add(new MenuButton(ActionEnum.OPEN_PLAYER_SETTINGS.name, ActionEnum.OPEN_PLAYER_SETTINGS, -buttonDistance - 26 - 13, 13, Direction.DOWN));
buttons.add(new MenuButton(ActionEnum.OPEN_MODIFIER_SETTINGS.name, ActionEnum.OPEN_MODIFIER_SETTINGS, -buttonDistance - 26, 13, Direction.DOWN));
buttons.add(new MenuButton(ActionEnum.REPLACE.name, ActionEnum.REPLACE, -buttonDistance, 13, Direction.DOWN));
//Add buildmode dependent options
OptionEnum[] options = currentBuildMode.options;
for (int i = 0; i < options.length; i++) {
for (int j = 0; j < options[i].actions.length; j++) {
ActionEnum action = options[i].actions[j];
buttons.add(new MenuButton(action.name, action, buttonDistance + j * 26, -13 + i * 39, Direction.DOWN));
}
}
switchTo = null;
doAction = null;
//Draw buildmode backgrounds
drawBuildModeBackgrounds(currentBuildMode, buffer, middleX, middleY, mouseXCenter, mouseYCenter, mouseRadians, ringInnerEdge, ringOuterEdge, quarterCircle, modes);
//Draw action backgrounds
drawActionBackgrounds(buffer, middleX, middleY, mouseXCenter, mouseYCenter, buttons);
tessellator.end();
RenderSystem.disableBlend();
RenderSystem.enableTexture();
drawIcons(ms, tessellator, buffer, middleX, middleY, ringInnerEdge, ringOuterEdge, modes, buttons);
drawTexts(ms, currentBuildMode, middleX, middleY, textDistance, buttonDistance, modes, buttons, options);
ms.popPose();
}
private void drawBuildModeBackgrounds(BuildModeEnum currentBuildMode, BufferBuilder buffer, double middleX, double middleY, double mouseXCenter, double mouseYCenter, double mouseRadians, double ringInnerEdge, double ringOuterEdge, double quarterCircle, ArrayList<MenuRegion> modes) {
if (!modes.isEmpty()) {
final int totalModes = Math.max(3, modes.size());
int currentMode = 0;
final double fragment = Math.PI * 0.005;
final double fragment2 = Math.PI * 0.0025;
final double perObject = 2.0 * Math.PI / totalModes;
for (int i = 0; i < modes.size(); i++) {
MenuRegion menuRegion = modes.get(i);
final double beginRadians = currentMode * perObject - quarterCircle;
final double endRadians = (currentMode + 1) * perObject - quarterCircle;
menuRegion.x1 = Math.cos(beginRadians);
menuRegion.x2 = Math.cos(endRadians);
menuRegion.y1 = Math.sin(beginRadians);
menuRegion.y2 = Math.sin(endRadians);
final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge;
final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge;
final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge;
final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge;
final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge;
final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge;
final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge;
final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge;
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 0.5f;
//check if current mode
int buildMode = currentBuildMode.ordinal();
if (buildMode == i) {
r = 0f;
g = 0.5f;
b = 1f;
a = 0.5f;
//menuRegion.highlighted = true; //draw text
}
//check if mouse is over this region
final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter)
|| inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter);
if (beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad) {
r = 0.6f;
g = 0.8f;
b = 1f;
a = 0.6f;
menuRegion.highlighted = true;
switchTo = menuRegion.mode;
}
buffer.vertex(middleX + x1m1, middleY + y1m1, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.vertex(middleX + x2m1, middleY + y2m1, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.vertex(middleX + x2m2, middleY + y2m2, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.vertex(middleX + x1m2, middleY + y1m2, getBlitOffset()).color(r, g, b, a).endVertex();
currentMode++;
}
}
}
private void drawActionBackgrounds(BufferBuilder buffer, double middleX, double middleY, double mouseXCenter, double mouseYCenter, ArrayList<MenuButton> buttons) {
for (final MenuButton btn : buttons) {
float r = 0.5f;
float g = 0.5f;
float b = 0.5f;
float a = 0.5f;
//highlight when active option
if (btn.action == getBuildSpeed() ||
btn.action == getFill() ||
btn.action == getCubeFill() ||
btn.action == getRaisedEdge() ||
btn.action == getLineThickness() ||
btn.action == getCircleStart()) {
r = 0.0f;
g = 0.5f;
b = 1f;
a = 0.6f;
}
//highlight when mouse over
if (btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter) {
r = 0.6f;
g = 0.8f;
b = 1f;
a = 0.6f;
btn.highlighted = true;
doAction = btn.action;
}
buffer.vertex(middleX + btn.x1, middleY + btn.y1, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.vertex(middleX + btn.x1, middleY + btn.y2, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.vertex(middleX + btn.x2, middleY + btn.y2, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.vertex(middleX + btn.x2, middleY + btn.y1, getBlitOffset()).color(r, g, b, a).endVertex();
}
}
private void drawIcons(PoseStack ms, Tesselator tessellator, BufferBuilder buffer, double middleX, double middleY, double ringInnerEdge, double ringOuterEdge, ArrayList<MenuRegion> modes, ArrayList<MenuButton> buttons) {
ms.pushPose();
RenderSystem.enableTexture();
RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
//Draw buildmode icons
for (final MenuRegion menuRegion : modes) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
RenderSystem.setShaderTexture(0, new ResourceLocation(EffortlessBuilding.MODID, "textures/icons/" + menuRegion.mode.name().toLowerCase() + ".png"));
blit(ms, (int) (middleX + x - 8), (int) (middleY + y - 8), 16, 16, 0, 0, 18, 18, 18, 18);
}
//Draw action icons
for (final MenuButton button : buttons) {
final double x = (button.x1 + button.x2) / 2 + 0.01;
final double y = (button.y1 + button.y2) / 2 + 0.01;
RenderSystem.setShaderTexture(0, new ResourceLocation(EffortlessBuilding.MODID, "textures/icons/" + button.action.name().toLowerCase() + ".png"));
blit(ms, (int) (middleX + x - 8), (int) (middleY + y - 8), 16, 16, 0, 0, 18, 18, 18, 18);
}
ms.popPose();
}
private void drawTexts(PoseStack ms, BuildModeEnum currentBuildMode, double middleX, double middleY, double textDistance, double buttonDistance, ArrayList<MenuRegion> modes, ArrayList<MenuButton> buttons, OptionEnum[] options) {
//font.drawStringWithShadow("Actions", (int) (middleX - buttonDistance - 13) - font.getStringWidth("Actions") * 0.5f, (int) middleY - 38, 0xffffffff);
//Draw option strings
for (int i = 0; i < currentBuildMode.options.length; i++) {
OptionEnum option = options[i];
font.drawShadow(ms, I18n.get(option.name), (int) (middleX + buttonDistance - 9), (int) middleY - 37 + i * 39, 0xeeeeeeff);
}
String credits = "Effortless Building";
font.drawShadow(ms, credits, width - font.width(credits) - 4, height - 10, 0x88888888);
//Draw buildmode text
for (final MenuRegion menuRegion : modes) {
if (menuRegion.highlighted) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5;
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5;
int fixed_x = (int) (x * textDistance);
final int fixed_y = (int) (y * textDistance) - font.lineHeight / 2;
final String text = I18n.get(menuRegion.mode.name);
if (x <= -0.2) {
fixed_x -= font.width(text);
} else if (-0.2 <= x && x <= 0.2) {
fixed_x -= font.width(text) / 2;
}
font.drawShadow(ms, text, (int) middleX + fixed_x, (int) middleY + fixed_y, 0xffffffff);
}
}
//Draw action text
for (final MenuButton button : buttons) {
if (button.highlighted) {
String text = ChatFormatting.AQUA + button.name;
//Add keybind in brackets
String keybind = findKeybind(button, currentBuildMode);
String keybindFormatted = "";
if (!keybind.isEmpty())
keybindFormatted = ChatFormatting.GRAY + "(" + WordUtils.capitalizeFully(keybind) + ")";
if (button.textSide == Direction.WEST) {
font.draw(ms, text, (int) (middleX + button.x1 - 8) - font.width(text),
(int) (middleY + button.y1 + 6), 0xffffffff);
} else if (button.textSide == Direction.EAST) {
font.draw(ms, text, (int) (middleX + button.x2 + 8),
(int) (middleY + button.y1 + 6), 0xffffffff);
} else if (button.textSide == Direction.UP || button.textSide == Direction.NORTH) {
font.draw(ms, keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(keybindFormatted) * 0.5),
(int) (middleY + button.y1 - 26), 0xffffffff);
font.draw(ms, text, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(text) * 0.5),
(int) (middleY + button.y1 - 14), 0xffffffff);
public void raiseVisibility() {
visibility = clampVis( visibility + lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE );
lastChange = Stopwatch.createStarted();
}
} else if (button.textSide == Direction.DOWN || button.textSide == Direction.SOUTH) {
public void decreaseVisibility() {
visibility = clampVis( visibility - lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE );
lastChange = Stopwatch.createStarted();
}
font.draw(ms, text, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(text) * 0.5),
(int) (middleY + button.y1 + 26), 0xffffffff);
public void setVisibility(float visibility) {
this.visibility = visibility;
}
public boolean isVisible() {
return visibility > 0.001;
}
public void configure(final int scaledWidth, final int scaledHeight ) {
mc = Minecraft.getInstance();
fontRenderer = mc.fontRenderer;
width = scaledWidth;
height = scaledHeight;
}
private static class MenuButton {
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public final ActionEnum action;
public String name;
public EnumFacing textSide;
public MenuButton(final String name, final ActionEnum action, final double x, final double y,
final EnumFacing textSide) {
this.name = I18n.format(name);
this.action = action;
x1 = x - 10;
x2 = x + 10;
y1 = y - 10;
y2 = y + 10;
this.textSide = textSide;
}
}
static class MenuRegion {
public final BuildModeEnum mode;
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public MenuRegion(final BuildModeEnum mode) {
this.mode = mode;
}
}
@Override
public void render(final int mouseX, final int mouseY, final float partialTicks) {
if (!isVisible()) return;
BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(Minecraft.getInstance().player).getBuildMode();
GlStateManager.pushMatrix();
GlStateManager.translatef( 0.0F, 0.0F, 200.0F );
final int startColor = (int) ( visibility * 98 ) << 24;
final int endColor = (int) ( visibility * 128 ) << 24;
drawGradientRect(0, 0, width, height, startColor, endColor);
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
GlStateManager.disableAlphaTest();
GlStateManager.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.shadeModel(GL11.GL_SMOOTH);
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder buffer = tessellator.getBuffer();
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
final double middleX = width / 2.0;
final double middleY = height / 2.0;
final double mouseXCenter = mouseX - middleX;
final double mouseYCenter = -mouseY + middleY;
double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter);
final double ringInnerEdge = 30;
final double ringOuterEdge = 65;
final double textDistance = 75;
final double buttonDistance = 105;
final double quarterCircle = Math.PI / 2.0;
if ( mouseRadians < -quarterCircle ) {
mouseRadians = mouseRadians + Math.PI * 2;
}
final ArrayList<MenuRegion> modes = new ArrayList<MenuRegion>();
final ArrayList<MenuButton> buttons = new ArrayList<MenuButton>();
//Add build modes
for (final BuildModeEnum mode : BuildModeEnum.values()) {
modes.add(new MenuRegion(mode));
}
//Add actions
buttons.add(new MenuButton(ActionEnum.UNDO.name, ActionEnum.UNDO, -buttonDistance - 26, -13, EnumFacing.UP));
buttons.add(new MenuButton(ActionEnum.REDO.name, ActionEnum.REDO, -buttonDistance, -13, EnumFacing.UP));
buttons.add(new MenuButton(ActionEnum.OPEN_MODIFIER_SETTINGS.name, ActionEnum.OPEN_MODIFIER_SETTINGS, -buttonDistance - 26, 13, EnumFacing.DOWN));
buttons.add(new MenuButton(ActionEnum.REPLACE.name, ActionEnum.REPLACE, -buttonDistance, 13, EnumFacing.DOWN));
//Add buildmode dependent options
OptionEnum[] options = currentBuildMode.options;
for (int i = 0; i < options.length; i++) {
for (int j = 0; j < options[i].actions.length; j++) {
ActionEnum action = options[i].actions[j];
buttons.add(new MenuButton(action.name, action, buttonDistance + j * 26, -13 + i * 39, EnumFacing.DOWN));
}
}
switchTo = null;
doAction = null;
//Draw buildmode backgrounds
if (!modes.isEmpty()) {
final int totalModes = Math.max( 3, modes.size() );
int currentMode = 0;
final double fragment = Math.PI * 0.005;
final double fragment2 = Math.PI * 0.0025;
final double perObject = 2.0 * Math.PI / totalModes;
for (int i = 0; i < modes.size(); i++) {
MenuRegion menuRegion = modes.get(i);
final double beginRadians = currentMode * perObject - quarterCircle;
final double endRadians = (currentMode + 1) * perObject - quarterCircle;
menuRegion.x1 = Math.cos(beginRadians);
menuRegion.x2 = Math.cos(endRadians);
menuRegion.y1 = Math.sin(beginRadians);
menuRegion.y2 = Math.sin(endRadians);
final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge;
final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge;
final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge;
final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge;
final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge;
final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge;
final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge;
final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge;
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 0.5f;
//check if current mode
int buildMode = currentBuildMode.ordinal();
if (buildMode == i) {
r = 0f;
g = 0.5f;
b = 1f;
a = 0.5f;
//menuRegion.highlighted = true; //draw text
}
//check if mouse is over this region
final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter)
|| inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter);
if (beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad) {
r = 0.6f;
g = 0.8f;
b = 1f;
a = 0.6f;
menuRegion.highlighted = true;
switchTo = menuRegion.mode;
}
buffer.pos(middleX + x1m1, middleY + y1m1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x2m1, middleY + y2m1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x2m2, middleY + y2m2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x1m2, middleY + y1m2, zLevel).color(r, g, b, a).endVertex();
currentMode++;
}
}
//Draw action backgrounds
for (final MenuButton btn : buttons) {
float r = 0.5f;
float g = 0.5f;
float b = 0.5f;
float a = 0.5f;
//highlight when active option
if (btn.action == getBuildSpeed() ||
btn.action == getFill() ||
btn.action == getCubeFill() ||
btn.action == getRaisedEdge() ||
btn.action == getLineThickness() ||
btn.action == getCircleStart()) {
r = 0.0f;
g = 0.5f;
b = 1f;
a = 0.6f;
}
//highlight when mouse over
if (btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter) {
r = 0.6f;
g = 0.8f;
b = 1f;
a = 0.6f;
btn.highlighted = true;
doAction = btn.action;
}
buffer.pos(middleX + btn.x1, middleY + btn.y1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x1, middleY + btn.y2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y1, zLevel).color(r, g, b, a).endVertex();
}
tessellator.draw();
GlStateManager.shadeModel(GL11.GL_FLAT);
GlStateManager.translatef(0f, 0f, 5f);
GlStateManager.enableTexture2D();
GlStateManager.color3f(1f, 1f, 1f);
GlStateManager.disableBlend();
GlStateManager.enableAlphaTest();
GlStateManager.bindTexture(Minecraft.getInstance().getTextureMap().getGlTextureId());
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
//Draw buildmode icons
for (final MenuRegion menuRegion : modes) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final TextureAtlasSprite sprite = ClientProxy.getBuildModeIcon(menuRegion.mode);
final double x1 = x - 8;
final double x2 = x + 8;
final double y1 = y - 8;
final double y2 = y + 8;
final float f = 1f;
final float a = 1f;
final double u1 = 0;
final double u2 = 16;
final double v1 = 0;
final double v2 = 16;
buffer.pos(middleX + x1, middleY + y1, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x1, middleY + y2, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x2, middleY + y2, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x2, middleY + y1, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
}
//Draw action icons
for (final MenuButton button : buttons) {
final float f = 1f;
final float a = 1f;
final double u1 = 0;
final double u2 = 16;
final double v1 = 0;
final double v2 = 16;
final TextureAtlasSprite sprite = ClientProxy.getModeOptionIcon(button.action);
final double btnmiddleX = (button.x1 + button.x2) / 2 + 0.01;
final double btnmiddleY = (button.y1 + button.y2) / 2 + 0.01;
final double btnx1 = btnmiddleX - 8;
final double btnx2 = btnmiddleX + 8;
final double btny1 = btnmiddleY - 8;
final double btny2 = btnmiddleY + 8;
buffer.pos(middleX + btnx1, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx1, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
}
tessellator.draw();
//Draw strings
//fontRenderer.drawStringWithShadow("Actions", (int) (middleX - buttonDistance - 13) - fontRenderer.getStringWidth("Actions") * 0.5f, (int) middleY - 38, 0xffffffff);
//Draw option strings
for (int i = 0; i < currentBuildMode.options.length; i++) {
OptionEnum option = options[i];
fontRenderer.drawStringWithShadow(I18n.format(option.name), (int) (middleX + buttonDistance - 9), (int) middleY - 37 + i * 39, 0xeeeeeeff);
}
String credits = "Effortless Building";
fontRenderer.drawStringWithShadow(credits, width - fontRenderer.getStringWidth(credits) - 4, height - 10, 0x88888888);
//Draw buildmode text
for (final MenuRegion menuRegion : modes) {
if (menuRegion.highlighted) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5;
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5;
int fixed_x = (int) (x * textDistance);
final int fixed_y = (int) (y * textDistance) - fontRenderer.FONT_HEIGHT / 2;
final String text = I18n.format(menuRegion.mode.name);
if ( x <= -0.2 ) {
fixed_x -= fontRenderer.getStringWidth(text);
} else if ( -0.2 <= x && x <= 0.2 ) {
fixed_x -= fontRenderer.getStringWidth(text) / 2;
}
fontRenderer.drawStringWithShadow(text, (int) middleX + fixed_x, (int) middleY + fixed_y, 0xffffffff);
}
}
//Draw action text
for (final MenuButton button : buttons) {
if (button.highlighted) {
String text = TextFormatting.AQUA + button.name;
int wrap = 120;
String keybind = "";
String keybindFormatted = "";
//Add keybind in brackets
if (button.action == ActionEnum.UNDO) {
keybind = ClientProxy.keyBindings[4].getKey().getName();
}
if (button.action == ActionEnum.REDO) {
keybind = ClientProxy.keyBindings[5].getKey().getName();
}
if (button.action == ActionEnum.REPLACE) {
keybind = ClientProxy.keyBindings[1].getKey().getName();
}
if (button.action == ActionEnum.OPEN_MODIFIER_SETTINGS) {
keybind = ClientProxy.keyBindings[0].getKey().getName();
}
if (currentBuildMode.options.length > 0) {
//Add (ctrl) to first two actions of first option
if (button.action == currentBuildMode.options[0].actions[0]
|| button.action == currentBuildMode.options[0].actions[1]) {
keybind = ClientProxy.keyBindings[6].getKey().getName();
if (keybind.equals("Left Control")) keybind = "Ctrl";
}
}
if (!keybind.isEmpty()) keybindFormatted = TextFormatting.GRAY + "(" + WordUtils.capitalizeFully(keybind) + ")";
if (button.textSide == EnumFacing.WEST) {
fontRenderer.drawSplitString( text, (int) (middleX + button.x1 - 8 ) - fontRenderer.getStringWidth(text),
(int) (middleY + button.y1 + 6), wrap, 0xffffffff);
} else if (button.textSide == EnumFacing.EAST) {
fontRenderer.drawSplitString(text, (int) (middleX + button.x2 + 8),
(int) (middleY + button.y1 + 6 ), wrap, 0xffffffff);
} else if (button.textSide == EnumFacing.UP || button.textSide == EnumFacing.NORTH) {
fontRenderer.drawSplitString( keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybindFormatted) * 0.5),
(int) (middleY + button.y1 - 26), wrap,0xffffffff);
fontRenderer.drawSplitString( text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5),
(int) (middleY + button.y1 - 14), wrap,0xffffffff);
} else if (button.textSide == EnumFacing.DOWN || button.textSide == EnumFacing.SOUTH) {
fontRenderer.drawSplitString(text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5),
(int) (middleY + button.y1 + 26), wrap, 0xffffffff);
fontRenderer.drawSplitString(keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybindFormatted) * 0.5),
(int) (middleY + button.y1 + 38), wrap, 0xffffffff);
}
}
}
GlStateManager.popMatrix();
}
private boolean inTriangle(final double x1, final double y1, final double x2, final double y2,
final double x3, final double y3, final double x, final double y ) {
final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y);
final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y);
final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y);
return sign(ab) == sign(bc) && sign(bc) == sign(ca);
}
private int sign(final double n) {
return n > 0 ? 1 : -1;
}
/**
* Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton
*/
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
EffortlessBuilding.log("mouse clicked");
// KeyBinding.updateKeyBindState();
// KeyBinding.setKeyBindState(ClientProxy.keyBindings[3].getKeyCode(), true);
// if (mouseButton == 0) {
// this.mc.displayGuiScreen(null);
//
// if (this.mc.currentScreen == null) {
// this.mc.setIngameFocus();
// }
// }
return super.mouseClicked(mouseX, mouseY, mouseButton);
}
font.draw(ms, keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(keybindFormatted) * 0.5),
(int) (middleY + button.y1 + 38), 0xffffffff);
}
}
}
}
private String findKeybind(MenuButton button, BuildModeEnum currentBuildMode){
String result = "";
int keybindingIndex = -1;
if (button.action == ActionEnum.UNDO) keybindingIndex = 3;
if (button.action == ActionEnum.REDO) keybindingIndex = 4;
if (button.action == ActionEnum.REPLACE) keybindingIndex = 1;
if (button.action == ActionEnum.OPEN_MODIFIER_SETTINGS) keybindingIndex = 0;
if (keybindingIndex != -1) {
KeyMapping keyMap = ClientProxy.keyBindings[keybindingIndex];
if (!keyMap.getKeyModifier().name().equals("none")) {
result = keyMap.getKeyModifier().name() + " ";
}
result += I18n.get(keyMap.getKey().getName());
}
if (currentBuildMode.options.length > 0) {
//Add (ctrl) to first two actions of first option
if (button.action == currentBuildMode.options[0].actions[0]
|| button.action == currentBuildMode.options[0].actions[1]) {
result = I18n.get(ClientProxy.keyBindings[5].getKey().getName());
if (result.equals("Left Control")) result = "Ctrl";
}
}
return result;
}
private boolean inTriangle(final double x1, final double y1, final double x2, final double y2,
final double x3, final double y3, final double x, final double y) {
final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y);
final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y);
final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y);
return sign(ab) == sign(bc) && sign(bc) == sign(ca);
}
private int sign(final double n) {
return n > 0 ? 1 : -1;
}
@Override
public boolean isPauseScreen() {
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
performAction(true);
return super.mouseClicked(mouseX, mouseY, mouseButton);
}
@Override
public void onClose() {
super.onClose();
//After onClose so it can open another screen
if (!performedActionUsingMouse) performAction(false);
}
private void performAction(boolean fromMouseClick) {
LocalPlayer player = Minecraft.getInstance().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
if (switchTo != null) {
playRadialMenuSound();
modeSettings.setBuildMode(switchTo);
ModeSettingsManager.setModeSettings(player, modeSettings);
PacketHandler.INSTANCE.sendToServer(new ModeSettingsMessage(modeSettings));
EffortlessBuilding.log(player, I18n.get(modeSettings.getBuildMode().name), true);
if (fromMouseClick) performedActionUsingMouse = true;
}
//Perform button action
ModeOptions.ActionEnum action = doAction;
if (action != null) {
playRadialMenuSound();
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
if (fromMouseClick) performedActionUsingMouse = true;
}
}
public static void playRadialMenuSound() {
final float volume = 0.1f;
if (volume >= 0.0001f) {
SimpleSoundInstance sound = new SimpleSoundInstance(SoundEvents.UI_BUTTON_CLICK, SoundSource.MASTER, volume, 1.0f, Minecraft.getInstance().player.blockPosition());
Minecraft.getInstance().getSoundManager().play(sound);
}
}
private static class MenuButton {
public final ActionEnum action;
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public String name;
public Direction textSide;
public MenuButton(final String name, final ActionEnum action, final double x, final double y,
final Direction textSide) {
this.name = I18n.get(name);
this.action = action;
x1 = x - 10;
x2 = x + 10;
y1 = y - 10;
y2 = y + 10;
this.textSide = textSide;
}
}
static class MenuRegion {
public final BuildModeEnum mode;
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public MenuRegion(final BuildModeEnum mode) {
this.mode = mode;
}
}
}

View File

@@ -1,204 +1,202 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCheckBoxFixed;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
private GuiCheckBox buttonArrayEnabled;
private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount;
private GuiCheckBoxFixed buttonArrayEnabled;
private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount;
public ArraySettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
public ArraySettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
@Override
public int initGui(int id, List<GuiButton> buttons) {
id = super.initGui(id, buttons);
@Override
public void init(List<Widget> renderables) {
super.init(renderables);
int y = top;
buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonArrayEnabled.isChecked());
}
};
buttons.add(buttonArrayEnabled);
int y = top;
buttonArrayEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonArrayEnabled.isChecked());
}
};
renderables.add(buttonArrayEnabled);
y = top + 20;
textArrayOffsetX = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 70, y, 50, 18);
textArrayOffsetX.setNumber(0);
textArrayOffsetX.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetX);
y = top + 20;
textArrayOffsetX = new GuiNumberField(font, renderables, left + 70, y, 50, 18);
textArrayOffsetX.setNumber(0);
textArrayOffsetX.setTooltip(new TextComponent("How much each copy is shifted."));
arrayNumberFieldList.add(textArrayOffsetX);
textArrayOffsetY = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 140, y, 50, 18);
textArrayOffsetY.setNumber(0);
textArrayOffsetY.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetY);
textArrayOffsetY = new GuiNumberField(font, renderables, left + 140, y, 50, 18);
textArrayOffsetY.setNumber(0);
textArrayOffsetY.setTooltip(new TextComponent("How much each copy is shifted."));
arrayNumberFieldList.add(textArrayOffsetY);
textArrayOffsetZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 210, y, 50, 18);
textArrayOffsetZ.setNumber(0);
textArrayOffsetZ.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetZ);
textArrayOffsetZ = new GuiNumberField(font, renderables, left + 210, y, 50, 18);
textArrayOffsetZ.setNumber(0);
textArrayOffsetZ.setTooltip(new TextComponent("How much each copy is shifted."));
arrayNumberFieldList.add(textArrayOffsetZ);
y = top + 50;
textArrayCount = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 55, y, 50, 18);
textArrayCount.setNumber(5);
textArrayCount.setTooltip("How many copies should be made.");
arrayNumberFieldList.add(textArrayCount);
y = top + 50;
textArrayCount = new GuiNumberField(font, renderables, left + 55, y, 50, 18);
textArrayCount.setNumber(5);
textArrayCount.setTooltip(new TextComponent("How many copies should be made."));
arrayNumberFieldList.add(textArrayCount);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) {
Array.ArraySettings a = modifierSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY());
textArrayOffsetZ.setNumber(a.offset.getZ());
textArrayCount.setNumber(a.count);
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) {
Array.ArraySettings a = modifierSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY());
textArrayOffsetZ.setNumber(a.offset.getZ());
textArrayCount.setNumber(a.count);
}
setCollapsed(!buttonArrayEnabled.isChecked());
setCollapsed(!buttonArrayEnabled.isChecked());
}
return id;
}
public void updateScreen() {
arrayNumberFieldList.forEach(GuiNumberField::update);
}
public void updateScreen() {
arrayNumberFieldList.forEach(GuiNumberField::update);
}
@Override
public void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
int yy = y;
int offset = 8;
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
int yy = y;
int offset = 8;
buttonArrayEnabled.render(ms, mouseX, mouseY, partialTicks);
if (buttonArrayEnabled.isChecked()) {
buttonArrayEnabled.y = yy;
font.draw(ms, "Array enabled", left + offset, yy + 2, 0xFFFFFF);
buttonArrayEnabled.render(mouseX, mouseY, partialTicks);
if (buttonArrayEnabled.isChecked()) {
buttonArrayEnabled.y = yy;
fontRenderer.drawString("Array enabled", left + offset, yy + 2, 0xFFFFFF);
yy = y + 20;
font.draw(ms, "Offset", left + offset, yy + 5, 0xFFFFFF);
font.draw(ms, "X", left + 50 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetX.y = yy;
font.draw(ms, "Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetY.y = yy;
font.draw(ms, "Z", left + 190 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetZ.y = yy;
yy = y + 20;
fontRenderer.drawString("Offset", left + offset, yy + 5, 0xFFFFFF);
fontRenderer.drawString("X", left + 50 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetY.y = yy;
fontRenderer.drawString("Z", left + 190 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetZ.y = yy;
yy = y + 50;
font.draw(ms, "Count", left + offset, yy + 5, 0xFFFFFF);
textArrayCount.y = yy;
yy = y + 50;
fontRenderer.drawString("Count", left + offset, yy + 5, 0xFFFFFF);
textArrayCount.y = yy;
int currentReach = Math.max(-1, getArrayReach());
int maxReach = ReachHelper.getMaxReach(mc.player);
ChatFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? ChatFormatting.GRAY : ChatFormatting.RED;
String reachText = "Reach: " + reachColor + currentReach + ChatFormatting.GRAY + "/" + ChatFormatting.GRAY + maxReach;
font.draw(ms, reachText, left + 176 + offset, yy + 5, 0xFFFFFF);
int currentReach = Math.max(-1, getArrayReach());
int maxReach = ReachHelper.getMaxReach(mc.player);
TextFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? TextFormatting.GRAY : TextFormatting.RED;
String reachText = "Reach: " + reachColor + currentReach + TextFormatting.GRAY + "/" + TextFormatting.GRAY + maxReach;
fontRenderer.drawString(reachText, left + 176 + offset, yy + 5, 0xFFFFFF);
arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(ms, mouseX, mouseY, partialTicks));
} else {
buttonArrayEnabled.y = yy;
font.draw(ms, "Array disabled", left + offset, yy + 2, 0x999999);
}
arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks));
} else {
buttonArrayEnabled.y = yy;
fontRenderer.drawString("Array disabled", left + offset, yy + 2, 0x999999);
}
}
}
public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonArrayEnabled.isChecked()) {
arrayNumberFieldList.forEach(numberField -> numberField.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonArrayEnabled.isChecked())
{
arrayNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : arrayNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : arrayNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideArrayEnabledLabel) {
buttonArrayEnabled.playDownSound(this.mc.getSoundManager());
buttonArrayEnabled.onClick(mouseX, mouseY);
}
if (insideArrayEnabledLabel) {
buttonArrayEnabled.playPressSound(this.mc.getSoundHandler());
buttonArrayEnabled.onClick(mouseX, mouseY);
}
return true;
}
return true;
}
public Array.ArraySettings getArraySettings() {
boolean arrayEnabled = buttonArrayEnabled.isChecked();
BlockPos arrayOffset = new BlockPos(0, 0, 0);
try {
arrayOffset = new BlockPos(textArrayOffsetX.getNumber(), textArrayOffsetY.getNumber(), textArrayOffsetZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array offset not a valid number.");
}
public Array.ArraySettings getArraySettings() {
boolean arrayEnabled = buttonArrayEnabled.isChecked();
BlockPos arrayOffset = new BlockPos(0, 0, 0);
try {
arrayOffset = new BlockPos(textArrayOffsetX.getNumber(), textArrayOffsetY.getNumber(), textArrayOffsetZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array offset not a valid number.");
}
int arrayCount = 5;
try {
arrayCount = (int) textArrayCount.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array count not a valid number.");
}
int arrayCount = 5;
try {
arrayCount = (int) textArrayCount.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array count not a valid number.");
}
return new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
}
return new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
}
@Override
protected String getName() {
return "Array";
}
@Override
protected String getName() {
return "Array";
}
@Override
protected int getExpandedHeight() {
return 80;
}
@Override
protected int getExpandedHeight() {
return 80;
}
private int getArrayReach() {
try {
//find largest offset
double x = Math.abs(textArrayOffsetX.getNumber());
double y = Math.abs(textArrayOffsetY.getNumber());
double z = Math.abs(textArrayOffsetZ.getNumber());
double largestOffset = Math.max(Math.max(x, y), z);
return (int) (largestOffset * textArrayCount.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
return -1;
}
}
private int getArrayReach() {
try
{
//find largest offset
double x = Math.abs(textArrayOffsetX.getNumber());
double y = Math.abs(textArrayOffsetY.getNumber());
double z = Math.abs(textArrayOffsetZ.getNumber());
double largestOffset = Math.max(Math.max(x, y), z);
return (int) (largestOffset * textArrayCount.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
return -1;
}
}
private boolean isCurrentReachValid(int currentReach, int maxReach) {
return currentReach <= maxReach && currentReach > -1;
}
private boolean isCurrentReachValid(int currentReach, int maxReach) {
return currentReach <= maxReach && currentReach > -1;
}
}

View File

@@ -1,23 +1,22 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiIconButton;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.gui.elements.*;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -26,280 +25,261 @@ import java.util.List;
@OnlyIn(Dist.CLIENT)
public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected List<GuiButton> mirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> mirrorNumberFieldList = new ArrayList<>();
protected List<Button> mirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> mirrorNumberFieldList = new ArrayList<>();
private GuiNumberField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius;
private GuiCheckBox buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
private GuiNumberField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius;
private GuiCheckBoxFixed buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
public MirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
public MirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
id = super.initGui(id, buttonList);
@Override
public void init(List<Widget> renderables) {
super.init(renderables);
int y = top - 2;
buttonMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonMirrorEnabled.isChecked());
}
};
buttonList.add(buttonMirrorEnabled);
int y = top - 2;
buttonMirrorEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonMirrorEnabled.isChecked());
}
};
renderables.add(buttonMirrorEnabled);
y = top + 18;
textMirrorPosX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 58, y, 62, 18);
textMirrorPosX.setNumber(0);
textMirrorPosX.setTooltip(
Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosX);
y = top + 18;
textMirrorPosX = new GuiNumberField(font, renderables, left + 58, y, 62, 18);
textMirrorPosX.setNumber(0);
textMirrorPosX.setTooltip(
Arrays.asList(new TextComponent("The position of the mirror."), new TextComponent("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorPosX);
textMirrorPosY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 138, y, 62, 18);
textMirrorPosY.setNumber(64);
textMirrorPosY.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosY);
textMirrorPosY = new GuiNumberField(font, renderables, left + 138, y, 62, 18);
textMirrorPosY.setNumber(64);
textMirrorPosY.setTooltip(Arrays.asList(new TextComponent("The position of the mirror."), new TextComponent("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorPosY);
textMirrorPosZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textMirrorPosZ.setNumber(0);
textMirrorPosZ.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
mirrorNumberFieldList.add(textMirrorPosZ);
textMirrorPosZ = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textMirrorPosZ.setNumber(0);
textMirrorPosZ.setTooltip(Arrays.asList(new TextComponent("The position of the mirror."), new TextComponent("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorPosZ);
y = top + 50;
buttonMirrorX = new GuiCheckBox(id++, left + 60, y, " X", true);
mirrorButtonList.add(buttonMirrorX);
y = top + 50;
buttonMirrorX = new GuiCheckBoxFixed(left + 60, y, " X", true);
mirrorButtonList.add(buttonMirrorX);
buttonMirrorY = new GuiCheckBox(id++, left + 100, y, " Y", false);
mirrorButtonList.add(buttonMirrorY);
buttonMirrorY = new GuiCheckBoxFixed(left + 100, y, " Y", false);
mirrorButtonList.add(buttonMirrorY);
buttonMirrorZ = new GuiCheckBox(id++, left + 140, y, " Z", false);
mirrorButtonList.add(buttonMirrorZ);
buttonMirrorZ = new GuiCheckBoxFixed(left + 140, y, " Z", false);
mirrorButtonList.add(buttonMirrorZ);
y = top + 47;
textMirrorRadius = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textMirrorRadius.setTooltip(Arrays.asList("How far the mirror reaches in any direction.",
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + ReachHelper.getMaxReach(mc.player) / 2,
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades."));
mirrorNumberFieldList.add(textMirrorRadius);
y = top + 47;
textMirrorRadius = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textMirrorRadius.setTooltip(Arrays.asList(new TextComponent("How far the mirror reaches in any direction."),
new TextComponent("Max: ").withStyle(ChatFormatting.GRAY).append(new TextComponent(String.valueOf(ReachHelper.getMaxReach(mc.player) / 2)).withStyle(ChatFormatting.GOLD)),
new TextComponent("Upgradeable in survival with reach upgrades.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorRadius);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z);
}
};
buttonCurrentPosition.setTooltip("Set mirror position to current player position");
mirrorIconButtonList.add(buttonCurrentPosition);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(left + 5, y, 0, 0, BUILDING_ICONS, button -> {
Vec3 pos = new Vec3(Math.floor(mc.player.getX()) + 0.5, Math.floor(mc.player.getY()) + 0.5, Math.floor(mc.player.getZ()) + 0.5);
textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z);
});
buttonCurrentPosition.setTooltip(new TextComponent("Set mirror position to current player position"));
mirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
}
}
};
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
mirrorIconButtonList.add(buttonToggleOdd);
buttonToggleOdd = new GuiIconButton(left + 35, y, 0, 20, BUILDING_ICONS, button -> {
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to corner of block"), new TextComponent("for even numbered builds")));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to middle of block"), new TextComponent("for odd numbered builds")));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
}
});
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to middle of block"), new TextComponent("for odd numbered builds")));
mirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
};
buttonDrawLines.setTooltip("Show lines");
mirrorIconButtonList.add(buttonDrawLines);
buttonDrawLines = new GuiIconButton(left + 65, y, 0, 40, BUILDING_ICONS, button -> {
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(new TextComponent(drawLines ? "Hide lines" : "Show lines"));
});
buttonDrawLines.setTooltip(new TextComponent("Show lines"));
mirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
};
buttonDrawPlanes.setTooltip("Show area");
mirrorIconButtonList.add(buttonDrawPlanes);
buttonDrawPlanes = new GuiIconButton(left + 95, y, 0, 60, BUILDING_ICONS, button -> {
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(new TextComponent(drawPlanes ? "Hide area" : "Show area"));
});
buttonDrawPlanes.setTooltip(new TextComponent("Show area"));
mirrorIconButtonList.add(buttonDrawPlanes);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) {
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y);
textMirrorPosZ.setNumber(m.position.z);
buttonMirrorX.setIsChecked(m.mirrorX);
buttonMirrorY.setIsChecked(m.mirrorY);
buttonMirrorZ.setIsChecked(m.mirrorZ);
textMirrorRadius.setNumber(m.radius);
drawLines = m.drawLines;
drawPlanes = m.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
if (textMirrorPosX.getNumber() == Math.floor(textMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) {
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y);
textMirrorPosZ.setNumber(m.position.z);
buttonMirrorX.setIsChecked(m.mirrorX);
buttonMirrorY.setIsChecked(m.mirrorY);
buttonMirrorZ.setIsChecked(m.mirrorZ);
textMirrorRadius.setNumber(m.radius);
drawLines = m.drawLines;
drawPlanes = m.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(new TextComponent(drawLines ? "Hide lines" : "Show lines"));
buttonDrawPlanes.setTooltip(new TextComponent(drawPlanes ? "Hide area" : "Show area"));
if (textMirrorPosX.getNumber() == Math.floor(textMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to middle of block"), new TextComponent("for odd numbered builds")));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to corner of block"), new TextComponent("for even numbered builds")));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
}
buttonList.addAll(mirrorButtonList);
buttonList.addAll(mirrorIconButtonList);
renderables.addAll(mirrorButtonList);
renderables.addAll(mirrorIconButtonList);
setCollapsed(!buttonMirrorEnabled.isChecked());
setCollapsed(!buttonMirrorEnabled.isChecked());
}
return id;
}
@Override
public void updateScreen() {
super.updateScreen();
mirrorNumberFieldList.forEach(GuiNumberField::update);
}
@Override
public void updateScreen() {
super.updateScreen();
mirrorNumberFieldList.forEach(GuiNumberField::update);
}
@Override
public void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
int yy = y;
int offset = 8;
int yy = y;
int offset = 8;
buttonMirrorEnabled.render(mouseX, mouseY, partialTicks);
if (buttonMirrorEnabled.isChecked()) {
buttonMirrorEnabled.y = yy;
fontRenderer.drawString("Mirror enabled", left + offset, yy + 2, 0xFFFFFF);
buttonMirrorEnabled.render(ms, mouseX, mouseY, partialTicks);
if (buttonMirrorEnabled.isChecked()) {
buttonMirrorEnabled.y = yy;
font.draw(ms, "Mirror enabled", left + offset, yy + 2, 0xFFFFFF);
yy = y + 18;
fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF);
fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF);
textMirrorPosX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textMirrorPosY.y = yy;
fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textMirrorPosZ.y = yy;
yy = y + 18;
font.draw(ms, "Position", left + offset, yy + 5, 0xFFFFFF);
font.draw(ms, "X", left + 40 + offset, yy + 5, 0xFFFFFF);
textMirrorPosX.y = yy;
font.draw(ms, "Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textMirrorPosY.y = yy;
font.draw(ms, "Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textMirrorPosZ.y = yy;
yy = y + 50;
fontRenderer.drawString("Direction", left + offset, yy + 2, 0xFFFFFF);
buttonMirrorX.y = yy;
buttonMirrorY.y = yy;
buttonMirrorZ.y = yy;
fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF);
textMirrorRadius.y = yy - 3;
yy = y + 50;
font.draw(ms, "Direction", left + offset, yy + 2, 0xFFFFFF);
buttonMirrorX.y = yy;
buttonMirrorY.y = yy;
buttonMirrorZ.y = yy;
font.draw(ms, "Radius", left + 176 + offset, yy + 2, 0xFFFFFF);
textMirrorRadius.y = yy - 3;
yy = y + 72;
buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
yy = y + 72;
buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
mirrorButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks));
mirrorIconButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks));
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks));
} else {
buttonMirrorEnabled.y = yy;
fontRenderer.drawString("Mirror disabled", left + offset, yy + 2, 0x999999);
}
mirrorButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
mirrorIconButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(ms, mouseX, mouseY, partialTicks));
} else {
buttonMirrorEnabled.y = yy;
font.draw(ms, "Mirror disabled", left + offset, yy + 2, 0x999999);
}
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonMirrorEnabled.isChecked())
{
mirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(scrollPane.parent, mouseX, mouseY));
mirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonMirrorEnabled.isChecked()) {
mirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
mirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
}
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : mirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : mirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideMirrorEnabledLabel) {
buttonMirrorEnabled.playPressSound(this.mc.getSoundHandler());
buttonMirrorEnabled.onClick(mouseX, mouseY);
}
if (insideMirrorEnabledLabel) {
buttonMirrorEnabled.playDownSound(this.mc.getSoundManager());
buttonMirrorEnabled.onClick(mouseX, mouseY);
}
return true;
}
return true;
}
public Mirror.MirrorSettings getMirrorSettings() {
boolean mirrorEnabled = buttonMirrorEnabled.isChecked();
public Mirror.MirrorSettings getMirrorSettings() {
boolean mirrorEnabled = buttonMirrorEnabled.isChecked();
Vec3d mirrorPos = new Vec3d(0, 64, 0);
try {
mirrorPos = new Vec3d(textMirrorPosX.getNumber(), textMirrorPosY.getNumber(), textMirrorPosZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror position not a valid number.");
}
Vec3 mirrorPos = new Vec3(0, 64, 0);
try {
mirrorPos = new Vec3(textMirrorPosX.getNumber(), textMirrorPosY.getNumber(), textMirrorPosZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror position not a valid number.");
}
boolean mirrorX = buttonMirrorX.isChecked();
boolean mirrorY = buttonMirrorY.isChecked();
boolean mirrorZ = buttonMirrorZ.isChecked();
boolean mirrorX = buttonMirrorX.isChecked();
boolean mirrorY = buttonMirrorY.isChecked();
boolean mirrorZ = buttonMirrorZ.isChecked();
int mirrorRadius = 50;
try {
mirrorRadius = (int) textMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
int mirrorRadius = 50;
try {
mirrorRadius = (int) textMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
return new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes);
}
return new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes);
}
@Override
protected String getName() {
return "Mirror";
}
@Override
protected String getName() {
return "Mirror";
}
@Override
protected int getExpandedHeight() {
return 100;
}
@Override
protected int getExpandedHeight() {
return 100;
}
}

View File

@@ -1,8 +1,12 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
@@ -15,133 +19,142 @@ import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public class ModifierSettingsGui extends GuiScreen {
public class ModifierSettingsGui extends Screen {
private GuiScrollPane scrollPane;
private GuiButton buttonClose;
private GuiScrollPane scrollPane;
private Button buttonClose;
private MirrorSettingsGui mirrorSettingsGui;
private ArraySettingsGui arraySettingsGui;
private RadialMirrorSettingsGui radialMirrorSettingsGui;
private MirrorSettingsGui mirrorSettingsGui;
private ArraySettingsGui arraySettingsGui;
private RadialMirrorSettingsGui radialMirrorSettingsGui;
@Override
//Create buttons and labels and add them to buttonList/labelList
public void initGui() {
int id = 0;
public ModifierSettingsGui() {
super(new TranslatableComponent("effortlessbuilding.screen.modifier_settings"));
}
scrollPane = new GuiScrollPane(this, fontRenderer, 8, height - 30);
@Override
//Create buttons and labels and add them to buttonList/labelList
protected void init() {
mirrorSettingsGui = new MirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(mirrorSettingsGui);
scrollPane = new GuiScrollPane(this, font, 8, height - 30);
arraySettingsGui = new ArraySettingsGui(scrollPane);
scrollPane.AddListEntry(arraySettingsGui);
mirrorSettingsGui = new MirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(mirrorSettingsGui);
radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(radialMirrorSettingsGui);
arraySettingsGui = new ArraySettingsGui(scrollPane);
scrollPane.AddListEntry(arraySettingsGui);
id = scrollPane.initGui(id, buttons);
radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(radialMirrorSettingsGui);
//Close button
int y = height - 26;
buttonClose = new GuiButton(id++, width / 2 - 100, y, "Close") {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
mc.player.closeScreen();
}
};
buttons.add(buttonClose);
scrollPane.init(renderables);
}
//Close button
int y = height - 26;
buttonClose = new Button(width / 2 - 100, y, 200, 20, new TextComponent("Close"), (button) -> {
Minecraft.getInstance().player.closeContainer();
});
addRenderableOnly(buttonClose);
}
@Override
//Process general logic, i.e. hide buttons
public void tick() {
scrollPane.updateScreen();
@Override
//Process general logic, i.e. hide buttons
public void tick() {
scrollPane.updateScreen();
handleMouseInput();
}
handleMouseInput();
}
@Override
//Set colors using GL11, use the fontRendererObj field to display text
//Use drawTexturedModalRect() to transfers areas of a texture resource to the screen
public void render(int mouseX, int mouseY, float partialTicks) {
this.drawDefaultBackground();
@Override
//Set colors using GL11, use the fontObj field to display text
//Use drawTexturedModalRect() to transfers areas of a texture resource to the screen
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(ms);
scrollPane.drawScreen(mouseX, mouseY, partialTicks);
scrollPane.render(ms, mouseX, mouseY, partialTicks);
buttonClose.render(mouseX, mouseY, partialTicks);
buttonClose.render(ms, mouseX, mouseY, partialTicks);
scrollPane.drawTooltip(this, mouseX, mouseY);
}
scrollPane.drawTooltip(ms, this, mouseX, mouseY);
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
scrollPane.charTyped(typedChar, keyCode);
if (keyCode == ClientProxy.keyBindings[0].getKey().getKeyCode()) {
mc.player.closeScreen();
}
return false;
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
scrollPane.charTyped(typedChar, keyCode);
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
super.mouseClicked(mouseX, mouseY, mouseButton);
buttons.forEach(button -> button.mouseClicked(mouseX, mouseY, mouseButton));
return scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
}
@Override
public boolean keyPressed(int keyCode, int p_96553_, int p_96554_) {
if (keyCode == ClientProxy.keyBindings[0].getKey().getValue()) {
minecraft.player.closeContainer();
return true;
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int state) {
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state))
{
return super.mouseReleased(mouseX, mouseY, state);
}
return false;
}
return super.keyPressed(keyCode, p_96553_, p_96554_);
}
public void handleMouseInput() {
//super.handleMouseInput();
scrollPane.handleMouseInput();
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
super.mouseClicked(mouseX, mouseY, mouseButton);
renderables.forEach(renderable -> {
if (renderable instanceof Button) {
Button button = (Button) renderable;
button.mouseClicked(mouseX, mouseY, mouseButton);
}
});
return scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
}
//Scrolling numbers
@Override
public boolean mouseReleased(double mouseX, double mouseY, int state) {
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state)) {
return super.mouseReleased(mouseX, mouseY, state);
}
return false;
}
public void handleMouseInput() {
//super.handleMouseInput();
scrollPane.handleMouseInput();
//Scrolling numbers
// int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
// int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
// numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY));
}
}
@Override
public void onGuiClosed() {
scrollPane.onGuiClosed();
@Override
public void removed() {
scrollPane.onGuiClosed();
//save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings();
Array.ArraySettings a = arraySettingsGui.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
//save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings();
Array.ArraySettings a = arraySettingsGui.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings();
modifierSettings.setMirrorSettings(m);
modifierSettings.setArraySettings(a);
modifierSettings.setRadialMirrorSettings(r);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(minecraft.player);
if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings();
modifierSettings.setMirrorSettings(m);
modifierSettings.setArraySettings(a);
modifierSettings.setRadialMirrorSettings(r);
//Sanitize
String error = ModifierSettingsManager.sanitize(modifierSettings, mc.player);
if (!error.isEmpty()) EffortlessBuilding.log(mc.player, error);
//Sanitize
String error = ModifierSettingsManager.sanitize(modifierSettings, minecraft.player);
if (!error.isEmpty()) EffortlessBuilding.log(minecraft.player, error);
ModifierSettingsManager.setModifierSettings(mc.player, modifierSettings);
ModifierSettingsManager.setModifierSettings(minecraft.player, modifierSettings);
//Send to server
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
//Send to server
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
//TODO fix not being able to scroll after this gui has opened
Minecraft.getInstance().mouseHelper.grabMouse();
}
Minecraft.getInstance().mouseHandler.grabMouse();
}
}

View File

@@ -1,23 +1,22 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiIconButton;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.gui.elements.*;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -26,285 +25,266 @@ import java.util.List;
@OnlyIn(Dist.CLIENT)
public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected List<GuiButton> radialMirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> radialMirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> radialMirrorNumberFieldList = new ArrayList<>();
protected List<Button> radialMirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> radialMirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> radialMirrorNumberFieldList = new ArrayList<>();
private GuiNumberField textRadialMirrorPosX, textRadialMirrorPosY, textRadialMirrorPosZ, textRadialMirrorSlices, textRadialMirrorRadius;
private GuiCheckBox buttonRadialMirrorEnabled, buttonRadialMirrorAlternate;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
private GuiNumberField textRadialMirrorPosX, textRadialMirrorPosY, textRadialMirrorPosZ, textRadialMirrorSlices, textRadialMirrorRadius;
private GuiCheckBoxFixed buttonRadialMirrorEnabled, buttonRadialMirrorAlternate;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd;
public RadialMirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
public RadialMirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane);
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
id = super.initGui(id, buttonList);
@Override
public void init(List<Widget> renderables) {
super.init(renderables);
int y = top - 2;
buttonRadialMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
}
};
buttonList.add(buttonRadialMirrorEnabled);
int y = top - 2;
buttonRadialMirrorEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
}
};
renderables.add(buttonRadialMirrorEnabled);
y = top + 18;
textRadialMirrorPosX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 58, y, 62, 18);
textRadialMirrorPosX.setNumber(0);
textRadialMirrorPosX.setTooltip(
Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
radialMirrorNumberFieldList.add(textRadialMirrorPosX);
y = top + 18;
textRadialMirrorPosX = new GuiNumberField(font, renderables, left + 58, y, 62, 18);
textRadialMirrorPosX.setNumber(0);
textRadialMirrorPosX.setTooltip(
Arrays.asList(new TextComponent("The position of the radial mirror."), new TextComponent("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorPosX);
textRadialMirrorPosY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 138, y, 62, 18);
textRadialMirrorPosY.setNumber(64);
textRadialMirrorPosY.setTooltip(Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
radialMirrorNumberFieldList.add(textRadialMirrorPosY);
textRadialMirrorPosY = new GuiNumberField(font, renderables, left + 138, y, 62, 18);
textRadialMirrorPosY.setNumber(64);
textRadialMirrorPosY.setTooltip(Arrays.asList(new TextComponent("The position of the radial mirror."), new TextComponent("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorPosY);
textRadialMirrorPosZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textRadialMirrorPosZ.setNumber(0);
textRadialMirrorPosZ.setTooltip(Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5."));
radialMirrorNumberFieldList.add(textRadialMirrorPosZ);
textRadialMirrorPosZ = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textRadialMirrorPosZ.setNumber(0);
textRadialMirrorPosZ.setTooltip(Arrays.asList(new TextComponent("The position of the radial mirror."), new TextComponent("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorPosZ);
y = top + 47;
textRadialMirrorSlices = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 55, y, 50, 18);
textRadialMirrorSlices.setNumber(4);
textRadialMirrorSlices.setTooltip(Arrays.asList("The number of repeating slices.", TextFormatting.GRAY + "Minimally 2."));
radialMirrorNumberFieldList.add(textRadialMirrorSlices);
y = top + 47;
textRadialMirrorSlices = new GuiNumberField(font, renderables, left + 55, y, 50, 18);
textRadialMirrorSlices.setNumber(4);
textRadialMirrorSlices.setTooltip(Arrays.asList(new TextComponent("The number of repeating slices."), new TextComponent("Minimally 2.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorSlices);
textRadialMirrorRadius = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 218, y, 62, 18);
textRadialMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textRadialMirrorRadius.setTooltip(Arrays.asList("How far the radial mirror reaches from its center position.",
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + ReachHelper.getMaxReach(mc.player) / 2,
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades."));
radialMirrorNumberFieldList.add(textRadialMirrorRadius);
textRadialMirrorRadius = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textRadialMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2)
textRadialMirrorRadius.setTooltip(Arrays.asList(new TextComponent("How far the radial mirror reaches from its center position."),
new TextComponent("Max: ").withStyle(ChatFormatting.GRAY).append(new TextComponent(String.valueOf(ReachHelper.getMaxReach(mc.player) / 2)).withStyle(ChatFormatting.GOLD)),
new TextComponent("Upgradeable in survival with reach upgrades.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorRadius);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textRadialMirrorPosX.setNumber(pos.x);
textRadialMirrorPosY.setNumber(pos.y);
textRadialMirrorPosZ.setNumber(pos.z);
}
};
buttonCurrentPosition.setTooltip("Set radial mirror position to current player position");
radialMirrorIconButtonList.add(buttonCurrentPosition);
y = top + 72;
buttonCurrentPosition = new GuiIconButton(left + 5, y, 0, 0, BUILDING_ICONS, button -> {
Vec3 pos = new Vec3(Math.floor(mc.player.getX()) + 0.5, Math.floor(mc.player.getY()) + 0.5, Math.floor(mc.player.getZ()) + 0.5);
textRadialMirrorPosX.setNumber(pos.x);
textRadialMirrorPosY.setNumber(pos.y);
textRadialMirrorPosZ.setNumber(pos.z);
});
buttonCurrentPosition.setTooltip(new TextComponent("Set radial mirror position to current player position"));
radialMirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5);
textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5);
textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber()));
textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber()));
textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.getNumber()));
}
}
};
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds"));
radialMirrorIconButtonList.add(buttonToggleOdd);
buttonToggleOdd = new GuiIconButton(left + 35, y, 0, 20, BUILDING_ICONS, button -> {
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to corner of block"), new TextComponent("for even numbered builds")));
textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5);
textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5);
textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set mirror position to middle of block"), new TextComponent("for odd numbered builds")));
textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber()));
textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber()));
textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.getNumber()));
}
});
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set radial mirror position to middle of block"), new TextComponent("for odd numbered builds")));
radialMirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
};
buttonDrawLines.setTooltip("Show lines");
radialMirrorIconButtonList.add(buttonDrawLines);
buttonDrawLines = new GuiIconButton(left + 65, y, 0, 40, BUILDING_ICONS, button -> {
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(new TextComponent(drawLines ? "Hide lines" : "Show lines"));
});
buttonDrawLines.setTooltip(new TextComponent("Show lines"));
radialMirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS) {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
};
buttonDrawPlanes.setTooltip("Show area");
radialMirrorIconButtonList.add(buttonDrawPlanes);
buttonDrawPlanes = new GuiIconButton(left + 95, y, 0, 60, BUILDING_ICONS, button -> {
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(new TextComponent(drawPlanes ? "Hide area" : "Show area"));
});
buttonDrawPlanes.setTooltip(new TextComponent("Show area"));
radialMirrorIconButtonList.add(buttonDrawPlanes);
y = top + 76;
buttonRadialMirrorAlternate = new GuiCheckBox(id++, left + 140, y, " Alternate", false);
radialMirrorButtonList.add(buttonRadialMirrorAlternate);
y = top + 76;
buttonRadialMirrorAlternate = new GuiCheckBoxFixed(left + 140, y, " Alternate", false);
radialMirrorButtonList.add(buttonRadialMirrorAlternate);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) {
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
buttonRadialMirrorEnabled.setIsChecked(r.enabled);
textRadialMirrorPosX.setNumber(r.position.x);
textRadialMirrorPosY.setNumber(r.position.y);
textRadialMirrorPosZ.setNumber(r.position.z);
textRadialMirrorSlices.setNumber(r.slices);
buttonRadialMirrorAlternate.setIsChecked(r.alternate);
textRadialMirrorRadius.setNumber(r.radius);
drawLines = r.drawLines;
drawPlanes = r.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
if (textRadialMirrorPosX.getNumber() == Math.floor(textRadialMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds"));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to corner of block", "for even numbered builds"));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) {
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
buttonRadialMirrorEnabled.setIsChecked(r.enabled);
textRadialMirrorPosX.setNumber(r.position.x);
textRadialMirrorPosY.setNumber(r.position.y);
textRadialMirrorPosZ.setNumber(r.position.z);
textRadialMirrorSlices.setNumber(r.slices);
buttonRadialMirrorAlternate.setIsChecked(r.alternate);
textRadialMirrorRadius.setNumber(r.radius);
drawLines = r.drawLines;
drawPlanes = r.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(new TextComponent(drawLines ? "Hide lines" : "Show lines"));
buttonDrawPlanes.setTooltip(new TextComponent(drawPlanes ? "Hide area" : "Show area"));
if (textRadialMirrorPosX.getNumber() == Math.floor(textRadialMirrorPosX.getNumber())) {
toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set radial mirror position to middle of block"), new TextComponent("for odd numbered builds")));
} else {
toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList(new TextComponent("Set radial mirror position to corner of block"), new TextComponent("for even numbered builds")));
}
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
}
buttonList.addAll(radialMirrorButtonList);
buttonList.addAll(radialMirrorIconButtonList);
renderables.addAll(radialMirrorButtonList);
renderables.addAll(radialMirrorIconButtonList);
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
}
return id;
}
public void updateScreen() {
radialMirrorNumberFieldList.forEach(GuiNumberField::update);
}
public void updateScreen() {
radialMirrorNumberFieldList.forEach(GuiNumberField::update);
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
@Override
public void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
int yy = y;
int offset = 8;
int yy = y;
int offset = 8;
buttonRadialMirrorEnabled.render(mouseX, mouseY, partialTicks);
if (buttonRadialMirrorEnabled.isChecked()) {
buttonRadialMirrorEnabled.y = yy;
fontRenderer.drawString("Radial mirror enabled", left + offset, yy + 2, 0xFFFFFF);
buttonRadialMirrorEnabled.render(ms, mouseX, mouseY, partialTicks);
if (buttonRadialMirrorEnabled.isChecked()) {
buttonRadialMirrorEnabled.y = yy;
font.draw(ms, "Radial mirror enabled", left + offset, yy + 2, 0xFFFFFF);
yy = y + 18;
fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF);
fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosY.y = yy;
fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosZ.y = yy;
yy = y + 18;
font.draw(ms, "Position", left + offset, yy + 5, 0xFFFFFF);
font.draw(ms, "X", left + 40 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosX.y = yy;
font.draw(ms, "Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosY.y = yy;
font.draw(ms, "Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosZ.y = yy;
yy = y + 50;
fontRenderer.drawString("Slices", left + offset, yy + 2, 0xFFFFFF);
textRadialMirrorSlices.y = yy - 3;
fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF);
textRadialMirrorRadius.y = yy - 3;
yy = y + 50;
font.draw(ms, "Slices", left + offset, yy + 2, 0xFFFFFF);
textRadialMirrorSlices.y = yy - 3;
font.draw(ms, "Radius", left + 176 + offset, yy + 2, 0xFFFFFF);
textRadialMirrorRadius.y = yy - 3;
yy = y + 72;
buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
yy = y + 72;
buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
yy = y + 76;
buttonRadialMirrorAlternate.y = yy;
yy = y + 76;
buttonRadialMirrorAlternate.y = yy;
radialMirrorButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks));
radialMirrorIconButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks));
radialMirrorNumberFieldList
.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks));
} else {
buttonRadialMirrorEnabled.y = yy;
fontRenderer.drawString("Radial mirror disabled", left + offset, yy + 2, 0x999999);
}
radialMirrorButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
radialMirrorIconButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
radialMirrorNumberFieldList
.forEach(numberField -> numberField.drawNumberField(ms, mouseX, mouseY, partialTicks));
} else {
buttonRadialMirrorEnabled.y = yy;
font.draw(ms, "Radial mirror disabled", left + offset, yy + 2, 0x999999);
}
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonRadialMirrorEnabled.isChecked())
{
radialMirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(scrollPane.parent, mouseX, mouseY));
radialMirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last
if (buttonRadialMirrorEnabled.isChecked()) {
radialMirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
radialMirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
}
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : radialMirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : radialMirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideRadialMirrorEnabledLabel) {
buttonRadialMirrorEnabled.playPressSound(this.mc.getSoundHandler());
buttonRadialMirrorEnabled.onClick(mouseX, mouseY);
}
if (insideRadialMirrorEnabledLabel) {
buttonRadialMirrorEnabled.playDownSound(this.mc.getSoundManager());
buttonRadialMirrorEnabled.onClick(mouseX, mouseY);
}
return true;
}
return true;
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked();
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked();
Vec3d radialMirrorPos = new Vec3d(0, 64, 0);
try {
radialMirrorPos = new Vec3d(textRadialMirrorPosX.getNumber(), textRadialMirrorPosY.getNumber(), textRadialMirrorPosZ
.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror position not a valid number.");
}
Vec3 radialMirrorPos = new Vec3(0, 64, 0);
try {
radialMirrorPos = new Vec3(textRadialMirrorPosX.getNumber(), textRadialMirrorPosY.getNumber(), textRadialMirrorPosZ
.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror position not a valid number.");
}
int radialMirrorSlices = 4;
try {
radialMirrorSlices = (int) textRadialMirrorSlices.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror slices not a valid number.");
}
int radialMirrorSlices = 4;
try {
radialMirrorSlices = (int) textRadialMirrorSlices.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror slices not a valid number.");
}
boolean radialMirrorAlternate = buttonRadialMirrorAlternate.isChecked();
boolean radialMirrorAlternate = buttonRadialMirrorAlternate.isChecked();
int radialMirrorRadius = 50;
try {
radialMirrorRadius = (int) textRadialMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
int radialMirrorRadius = 50;
try {
radialMirrorRadius = (int) textRadialMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
return new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPos, radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, drawLines, drawPlanes);
}
return new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPos, radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, drawLines, drawPlanes);
}
@Override
protected String getName() {
return "Radial mirror";
}
@Override
protected String getName() {
return "Radial mirror";
}
@Override
protected int getExpandedHeight() {
return 100;
}
@Override
protected int getExpandedHeight() {
return 100;
}
}

View File

@@ -0,0 +1,62 @@
package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.fmlclient.gui.GuiUtils;
import javax.annotation.ParametersAreNonnullByDefault;
/**
* This class provides a checkbox style control.
*/
@ParametersAreNonnullByDefault
public class GuiCheckBoxFixed extends Button {
private final int boxWidth;
private boolean isChecked;
public GuiCheckBoxFixed(int xPos, int yPos, String displayString, boolean isChecked) {
super(xPos, yPos, Minecraft.getInstance().font.width(displayString) + 2 + 11, 11, new TextComponent(displayString), b -> {
});
this.isChecked = isChecked;
this.boxWidth = 11;
this.height = 11;
this.width = this.boxWidth + 2 + Minecraft.getInstance().font.width(displayString);
}
@Override
public void renderButton(PoseStack ms, int mouseX, int mouseY, float partial) {
if (this.visible) {
Minecraft mc = Minecraft.getInstance();
this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.boxWidth && mouseY < this.y + this.height;
GuiUtils.drawContinuousTexturedBox(ms, WIDGETS_LOCATION, this.x, this.y, 0, 46, this.boxWidth, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset());
this.renderBg(ms, mc, mouseX, mouseY);
int color = 14737632;
if (packedFGColor != 0) {
color = packedFGColor;
} else if (!this.active) {
color = 10526880;
}
if (this.isChecked)
drawCenteredString(ms, mc.font, "x", this.x + this.boxWidth / 2 + 1, this.y + 1, 14737632);
drawString(ms, mc.font, getMessage(), this.x + this.boxWidth + 2, this.y + 2, color);
}
}
@Override
public void onPress() {
this.isChecked = !this.isChecked;
}
public boolean isChecked() {
return this.isChecked;
}
public void setIsChecked(boolean isChecked) {
this.isChecked = isChecked;
}
}

View File

@@ -1,93 +1,90 @@
package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.io.IOException;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScrollEntry {
public GuiScrollPane scrollPane;
protected FontRenderer fontRenderer;
protected Minecraft mc;
public GuiScrollPane scrollPane;
protected Font font;
protected Minecraft mc;
protected boolean isCollapsed = true;
protected int left, right, top, bottom;
protected boolean isCollapsed = true;
protected int left, right, top, bottom;
public GuiCollapsibleScrollEntry(GuiScrollPane scrollPane) {
this.scrollPane = scrollPane;
this.fontRenderer = scrollPane.fontRenderer;
this.mc = scrollPane.parent.mc;
}
public GuiCollapsibleScrollEntry(GuiScrollPane scrollPane) {
this.scrollPane = scrollPane;
this.font = scrollPane.font;
this.mc = Minecraft.getInstance();
}
@Override
public int initGui(int id, List<GuiButton> buttonList) {
@Override
public void init(List<Widget> renderables) {
left = scrollPane.getWidth() / 2 - 140;
right = scrollPane.getWidth() / 2 + 140;
top = scrollPane.getHeight() / 2 - 100;
bottom = scrollPane.getHeight() / 2 + 100;
}
left = scrollPane.width / 2 - 140;
right = scrollPane.width / 2 + 140;
top = scrollPane.height / 2 - 100;
bottom = scrollPane.height / 2 + 100;
@Override
public void updateScreen() {
}
return id;
}
@Override
public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
}
@Override
public void updateScreen() {
}
@Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
@Override
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
}
}
@Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
@Override
public boolean charTyped(char eventChar, int eventKey) {
return false;
}
}
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
return false;
}
@Override
public boolean charTyped(char eventChar, int eventKey) {
return false;
}
@Override
public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) {
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
return false;
}
}
@Override
public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) {
@Override
public void onGuiClosed() {
}
}
@Override
public int getHeight() {
return isCollapsed ? getCollapsedHeight() : getExpandedHeight();
}
@Override
public void onGuiClosed() {
}
public void setCollapsed(boolean collapsed) {
this.isCollapsed = collapsed;
}
@Override
public int getHeight() {
return isCollapsed ? getCollapsedHeight() : getExpandedHeight();
}
protected String getName() {
return "Collapsible scroll entry";
}
public void setCollapsed(boolean collapsed) {
this.isCollapsed = collapsed;
}
protected int getCollapsedHeight() {
return 24;
}
protected String getName() {
return "Collapsible scroll entry";
}
protected int getCollapsedHeight() {
return 24;
}
protected int getExpandedHeight() {
return 100;
}
protected int getExpandedHeight() {
return 100;
}
}

View File

@@ -1,78 +1,81 @@
package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.Button;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public class GuiIconButton extends GuiButton {
@ParametersAreNonnullByDefault
public class GuiIconButton extends Button {
private final ResourceLocation resourceLocation;
private final int iconX, iconY, iconWidth, iconHeight, iconAltX, iconAltY;
List<String> tooltip = new ArrayList<>();
private boolean useAltIcon = false;
private final ResourceLocation resourceLocation;
private final int iconX, iconY, iconWidth, iconHeight, iconAltX, iconAltY;
List<Component> tooltip = new ArrayList<>();
private boolean useAltIcon = false;
public GuiIconButton(int buttonId, int x, int y, int iconX, int iconY, ResourceLocation resourceLocation) {
this(buttonId, x, y, 20, 20, iconX, iconY, 20, 20, 20, 0, resourceLocation);
}
public GuiIconButton(int x, int y, int iconX, int iconY, ResourceLocation resourceLocation, Button.OnPress onPress) {
this(x, y, 20, 20, iconX, iconY, 20, 20, 20, 0, resourceLocation, onPress);
}
public GuiIconButton(int buttonId, int x, int y, int width, int height, int iconX, int iconY, int iconWidth, int iconHeight, int iconAltX, int iconAltY, ResourceLocation resourceLocation) {
super(buttonId, x, y, width, height, "");
this.iconX = iconX;
this.iconY = iconY;
this.iconWidth = iconWidth;
this.iconHeight = iconHeight;
this.iconAltX = iconAltX;
this.iconAltY = iconAltY;
this.resourceLocation = resourceLocation;
}
public GuiIconButton(int x, int y, int width, int height, int iconX, int iconY, int iconWidth, int iconHeight, int iconAltX, int iconAltY, ResourceLocation resourceLocation, Button.OnPress onPress) {
super(x, y, width, height, TextComponent.EMPTY, onPress);
this.iconX = iconX;
this.iconY = iconY;
this.iconWidth = iconWidth;
this.iconHeight = iconHeight;
this.iconAltX = iconAltX;
this.iconAltY = iconAltY;
this.resourceLocation = resourceLocation;
}
public void setTooltip(String tooltip) {
setTooltip(Arrays.asList(tooltip));
}
public void setTooltip(Component tooltip) {
setTooltip(Collections.singletonList(tooltip));
}
public void setTooltip(List<String> tooltip) {
this.tooltip = tooltip;
}
public void setTooltip(List<Component> tooltip) {
this.tooltip = tooltip;
}
public void setUseAlternateIcon(boolean useAlternateIcon) {
this.useAltIcon = useAlternateIcon;
}
public void setUseAlternateIcon(boolean useAlternateIcon) {
this.useAltIcon = useAlternateIcon;
}
@Override
public void render(int mouseX, int mouseY, float partialTicks) {
super.render(mouseX, mouseY, partialTicks);
if (this.visible)
{
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
Minecraft.getInstance().getTextureManager().bindTexture(this.resourceLocation);
int currentIconX = this.iconX;
int currentIconY = this.iconY;
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
super.render(ms, mouseX, mouseY, partialTicks);
if (this.visible) {
this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
RenderSystem.setShaderTexture(0, this.resourceLocation);
int currentIconX = this.iconX;
int currentIconY = this.iconY;
if (useAltIcon)
{
currentIconX += iconAltX;
currentIconY += iconAltY;
}
if (useAltIcon) {
currentIconX += iconAltX;
currentIconY += iconAltY;
}
this.drawTexturedModalRect(this.x, this.y, currentIconX, currentIconY, this.iconWidth, this.iconHeight);
}
}
//Draws a textured rectangle at the current z-value. Used to be drawTexturedModalRect in Gui.
this.blit(ms, this.x, this.y, currentIconX, currentIconY, this.iconWidth, this.iconHeight);
}
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
boolean flag = mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height;
public void drawTooltip(PoseStack ms, Screen screen, int mouseX, int mouseY) {
boolean flag = mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height;
if (flag) {
List<String> textLines = new ArrayList<>();
textLines.addAll(tooltip);
guiScreen.drawHoveringText(textLines, mouseX - 10, mouseY + 25);
}
}
if (flag) {
screen.renderComponentTooltip(ms, tooltip, mouseX - 10, mouseY + 25);
}
}
}

View File

@@ -1,151 +1,161 @@
package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.util.text.TextFormatting;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.io.IOException;
import javax.annotation.ParametersAreNonnullByDefault;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public class GuiNumberField extends Gui {
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class GuiNumberField extends GuiComponent {
public int x, y, width, height;
public int buttonWidth = 10;
public int x, y, width, height;
public int buttonWidth = 10;
protected GuiTextField textField;
protected GuiButton minusButton, plusButton;
protected EditBox textField;
protected Button minusButton, plusButton;
List<String> tooltip = new ArrayList<>();
List<Component> tooltip = new ArrayList<>();
public GuiNumberField(int id1, int id2, int id3, FontRenderer fontRenderer,
List<GuiButton> buttonList, int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
public GuiNumberField(Font font, List<Widget> renderables, int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
textField = new GuiTextField(id1, fontRenderer, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2);
minusButton = new GuiButton(id2, x, y - 1, buttonWidth, height + 2, "-") {
@Override
public void onClick(double mouseX, double mouseY) {
float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
textField = new EditBox(font, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2, TextComponent.EMPTY);
minusButton = new Button(x, y - 1, buttonWidth, height + 2, new TextComponent("-"), button -> {
float valueChanged = 1f;
if (Screen.hasControlDown()) valueChanged = 5f;
if (Screen.hasShiftDown()) valueChanged = 10f;
setNumber(getNumber() - valueChanged);
}
};
plusButton = new GuiButton(id3, x + width - buttonWidth, y - 1, buttonWidth, height + 2, "+") {
@Override
public void onClick(double mouseX, double mouseY) {
float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
setNumber(getNumber() - valueChanged);
});
plusButton = new Button(x + width - buttonWidth, y - 1, buttonWidth, height + 2, new TextComponent("+"), button -> {
float valueChanged = 1f;
if (Screen.hasControlDown()) valueChanged = 5f;
if (Screen.hasShiftDown()) valueChanged = 10f;
setNumber(getNumber() + valueChanged);
}
};
setNumber(getNumber() + valueChanged);
});
buttonList.add(minusButton);
buttonList.add(plusButton);
}
renderables.add(minusButton);
renderables.add(plusButton);
}
public void setNumber(double number) {
textField.setText(DecimalFormat.getInstance().format(number));
}
public double getNumber() {
if (textField.getValue().isEmpty()) return 0;
try {
return DecimalFormat.getInstance().parse(textField.getValue()).doubleValue();
} catch (ParseException e) {
return 0;
}
}
public double getNumber() {
if (textField.getText().isEmpty()) return 0;
try {
return DecimalFormat.getInstance().parse(textField.getText()).doubleValue();
} catch (ParseException e) {
return 0;
}
}
public void setNumber(double number) {
textField.setValue(DecimalFormat.getInstance().format(number));
}
public void setTooltip(String tooltip) {
setTooltip(Arrays.asList(tooltip));
}
public void setTooltip(Component tooltip) {
setTooltip(Collections.singletonList(tooltip));
}
public void setTooltip(List<String> tooltip) {
this.tooltip = tooltip;
}
public void setTooltip(List<Component> tooltip) {
this.tooltip = tooltip;
}
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton);
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton);
//Check if clicked inside textfield
boolean flag = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
//Check if clicked inside textfield
boolean flag = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
//Rightclicked inside textfield
if (flag && mouseButton == 1) {
textField.setText("");
textField.setFocused(true);
result = true;
}
//Rightclicked inside textfield
if (flag && mouseButton == 1) {
textField.setValue("");
textField.setFocus(true);
result = true;
}
return result;
}
return result;
}
public void drawNumberField(int mouseX, int mouseY, float partialTicks) {
textField.y = y + 1;
minusButton.y = y - 1;
plusButton.y = y - 1;
public void drawNumberField(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
textField.y = y + 1;
minusButton.y = y - 1;
plusButton.y = y - 1;
textField.drawTextField(mouseX, mouseY, partialTicks);
minusButton.render(mouseX, mouseY, partialTicks);
plusButton.render(mouseX, mouseY, partialTicks);
}
textField.render(ms, mouseX, mouseY, partialTicks);
minusButton.render(ms, mouseX, mouseY, partialTicks);
plusButton.render(ms, mouseX, mouseY, partialTicks);
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
boolean insideMinusButton = mouseX >= x && mouseX < x + buttonWidth && mouseY >= y && mouseY < y + height;
boolean insidePlusButton = mouseX >= x + width - buttonWidth && mouseX < x + width && mouseY >= y && mouseY < y + height;
public void drawTooltip(PoseStack ms, Screen screen, int mouseX, int mouseY) {
boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
boolean insideMinusButton = mouseX >= x && mouseX < x + buttonWidth && mouseY >= y && mouseY < y + height;
boolean insidePlusButton = mouseX >= x + width - buttonWidth && mouseX < x + width && mouseY >= y && mouseY < y + height;
List<String> textLines = new ArrayList<>();
// List<String> textLines = new ArrayList<>();
if (insideTextField) {
if (!tooltip.isEmpty())
textLines.addAll(tooltip);
List<Component> textLines = new ArrayList<>();
if (insideTextField) {
textLines.addAll(tooltip);
// textLines.add(TextFormatting.GRAY + "Tip: try scrolling.");
}
}
if (insideMinusButton) {
textLines.add("Hold " + TextFormatting.AQUA + "shift " + TextFormatting.RESET + "for " + TextFormatting.RED + "10");
textLines.add("Hold " + TextFormatting.AQUA + "ctrl " + TextFormatting.RESET + "for " + TextFormatting.RED + "5");
}
if (insideMinusButton) {
textLines.add(new TextComponent("Hold ").append(new TextComponent("shift ").withStyle(ChatFormatting.AQUA)).append("for ")
.append(new TextComponent("10").withStyle(ChatFormatting.RED)));
textLines.add(new TextComponent("Hold ").append(new TextComponent("ctrl ").withStyle(ChatFormatting.AQUA)).append("for ")
.append(new TextComponent("5").withStyle(ChatFormatting.RED)));
}
if (insidePlusButton) {
textLines.add("Hold " + TextFormatting.AQUA + "shift " + TextFormatting.RESET + "for " + TextFormatting.DARK_GREEN + "10");
textLines.add("Hold " + TextFormatting.AQUA + "ctrl " + TextFormatting.RESET + "for " + TextFormatting.DARK_GREEN + "5");
}
if (insidePlusButton) {
textLines.add(new TextComponent("Hold ").append(new TextComponent("shift ").withStyle(ChatFormatting.DARK_GREEN)).append("for ")
.append(new TextComponent("10").withStyle(ChatFormatting.RED)));
textLines.add(new TextComponent("Hold ").append(new TextComponent("ctrl ").withStyle(ChatFormatting.DARK_GREEN)).append("for ")
.append(new TextComponent("5").withStyle(ChatFormatting.RED)));
}
guiScreen.drawHoveringText(textLines, mouseX - 10, mouseY + 25);
screen.renderComponentTooltip(ms, textLines, mouseX - 10, mouseY + 25);
}
}
public void update() {
textField.tick();
}
public void update() {
textField.tick();
}
public boolean charTyped(char typedChar, int keyCode) {
if (!textField.isFocused()) return false;
public boolean charTyped(char typedChar, int keyCode) {
if (!textField.isFocused()) return false;
// if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK
// || keyCode == Keyboard.KEY_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT
// || keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN) {
return textField.charTyped(typedChar, keyCode);
return textField.charTyped(typedChar, keyCode);
// }
}
}
//Scroll inside textfield to change number
//Disabled because entire screen can be scrolled
//Scroll inside textfield to change number
//Disabled because entire screen can be scrolled
// public void handleMouseInput(int mouseX, int mouseY) {
// boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
//

View File

@@ -1,246 +1,223 @@
package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.MouseHelper;
import net.minecraft.client.gui.*;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.glfw.GLFW;
import sun.security.ssl.Debug;
import java.io.IOException;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public class GuiScrollPane extends GuiSlot {
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class GuiScrollPane extends SlotGui {
public GuiScreen parent;
public FontRenderer fontRenderer;
private List<IScrollEntry> listEntries;
private float scrollMultiplier = 1f;
public Screen parent;
public Font font;
private final List<IScrollEntry> listEntries;
private float scrollMultiplier = 1f;
private int mouseX;
private int mouseY;
private int mouseX;
private int mouseY;
public GuiScrollPane(GuiScreen parent, FontRenderer fontRenderer, int top, int bottom) {
super(parent.mc, parent.width, parent.height, top, bottom, 100);
this.parent = parent;
this.fontRenderer = fontRenderer;
this.setShowSelectionBox(false);
listEntries = new ArrayList<>();
MinecraftForge.EVENT_BUS.register(this);
}
public GuiScrollPane(Screen parent, Font font, int top, int bottom) {
super(Minecraft.getInstance(), parent.width, parent.height, top, bottom, 100);
this.parent = parent;
this.font = font;
this.renderSelection = false;
listEntries = new ArrayList<>();
MinecraftForge.EVENT_BUS.register(this);
}
public IScrollEntry getListEntry(int index) {
return listEntries.get(index);
}
public IScrollEntry getListEntry(int index) {
return listEntries.get(index);
}
public void AddListEntry(IScrollEntry listEntry){
listEntries.add(listEntry);
}
public void AddListEntry(IScrollEntry listEntry) {
listEntries.add(listEntry);
}
@Override
protected int getSize() {
return listEntries.size();
}
@Override
protected int getItemCount() {
return listEntries.size();
}
@Override
protected boolean isSelected(int slotIndex) {
return false;
}
@Override
protected boolean isSelectedItem(int slotIndex) {
return false;
}
@Override
protected int getScrollBarX() {
//return width / 2 + 140 + 10;
return width - 15;
}
@Override
protected int getScrollbarPosition() {
//return width / 2 + 140 + 10;
return width - 15;
}
@Override
public int getListWidth() {
return 280;
}
@Override
public int getRowWidth() {
return 280;
}
//Removed background
@Override
public void drawScreen(int mouseXIn, int mouseYIn, float partialTicks)
{
if (this.visible)
{
this.mouseX = mouseXIn;
this.mouseY = mouseYIn;
int scrollBarLeft = this.getScrollBarX();
int scrollBarRight = scrollBarLeft + 6;
this.bindAmountScrolled();
GlStateManager.disableLighting();
GlStateManager.disableFog();
//Removed background
@Override
public void render(PoseStack ms, int mouseXIn, int mouseYIn, float partialTicks) {
if (this.visible) {
this.mouseX = mouseXIn;
this.mouseY = mouseYIn;
this.renderBackground();
int scrollbarLeft = this.getScrollbarPosition();
int scrollbarRight = scrollbarLeft + 6;
this.capYPosition();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
int insideLeft = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
int insideTop = this.top + 4 - (int)this.amountScrolled;
Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
if (this.hasListHeader) {
this.drawListHeader(insideLeft, insideTop, tessellator);
}
int insideLeft = this.x0 + this.width / 2 - this.getRowWidth() / 2 + 2;
int insideTop = this.y0 + 4 - (int) this.yo;
if (this.renderHeader) {
this.renderHeader(insideLeft, insideTop, tessellator);
}
//All entries
this.drawSelectionBox(insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks);
GlStateManager.disableDepthTest();
//All entries
this.renderList(ms, insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks);
RenderSystem.disableDepthTest();
//Dirt overlays on top and bottom
// this.overlayBackground(0, this.top, 255, 255);
// this.overlayBackground(this.bottom, this.height, 255, 255);
//Dirt overlays on top and bottom
// this.renderHoleBackground(0, this.y0, 255, 255);
// this.renderHoleBackground(this.y1, this.height, 255, 255);
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
GlStateManager.disableAlphaTest();
GlStateManager.shadeModel(7425);
GlStateManager.disableTexture2D();
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
RenderSystem.disableTexture();
// //top fade
//top
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)(this.top + 5), 0.0D).tex(0.0D, 1.0D).color(100, 100, 100, 0).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.top + 5), 0.0D).tex(1.0D, 1.0D).color(100, 100, 100, 0).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.top, 0.0D).tex(1.0D, 0.0D).color(100, 100, 100, 100).endVertex();
// bufferbuilder.pos((double)this.left, (double)this.top, 0.0D).tex(0.0D, 0.0D).color(100, 100, 100, 100).endVertex();
// bufferbuilder.pos((double)this.x0, (double)(this.y0 + 4), 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x1, (double)(this.y0 + 4), 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x1, (double)this.y0, 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x0, (double)this.y0, 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex();
// tessellator.draw();
// //top line
//bottom
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)this.top, 0.0D).tex(0.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.top, 0.0D).tex(1.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.top - 1), 0.0D).tex(1.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.left, (double)(this.top - 1), 0.0D).tex(0.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.x0, (double)this.y1, 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x1, (double)this.y1, 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x1, (double)(this.y1 - 4), 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x0, (double)(this.y1 - 4), 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 0).endVertex();
// tessellator.draw();
// //bottom fade
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)this.bottom, 0.0D).tex(0.0D, 1.0D).color(10, 10, 10, 100).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.bottom, 0.0D).tex(1.0D, 1.0D).color(10, 10, 10, 100).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.bottom - 5), 0.0D).tex(1.0D, 0.0D).color(10, 10, 10, 0).endVertex();
// bufferbuilder.pos((double)this.left, (double)(this.bottom - 5), 0.0D).tex(0.0D, 0.0D).color(10, 10, 10, 0).endVertex();
// tessellator.draw();
//Draw scrollbar
int maxScroll = this.getMaxScroll();
if (maxScroll > 0) {
int k1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition());
k1 = Mth.clamp(k1, 32, this.y1 - this.y0 - 8);
int l1 = (int) this.yo * (this.y1 - this.y0 - k1) / maxScroll + this.y0;
if (l1 < this.y0) {
l1 = this.y0;
}
// //bottom line
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.left, (double)(this.bottom + 1), 0.0D).tex(0.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)(this.bottom + 1), 0.0D).tex(1.0D, 1.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.right, (double)this.bottom, 0.0D).tex(1.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// bufferbuilder.pos((double)this.left, (double)this.bottom, 0.0D).tex(0.0D, 0.0D).color(20, 20, 20, 255).endVertex();
// tessellator.draw();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(scrollbarLeft, this.y1, 0.0F).uv(0.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.vertex(scrollbarRight, this.y1, 0.0F).uv(1.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.vertex(scrollbarRight, this.y0, 0.0F).uv(1.0F, 0.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.vertex(scrollbarLeft, this.y0, 0.0F).uv(0.0F, 0.0F).color(0, 0, 0, 255).endVertex();
tessellator.end();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(scrollbarLeft, l1 + k1, 0.0F).uv(0.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.vertex(scrollbarRight, l1 + k1, 0.0F).uv(1.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.vertex(scrollbarRight, l1, 0.0F).uv(1.0F, 0.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.vertex(scrollbarLeft, l1, 0.0F).uv(0.0F, 0.0F).color(128, 128, 128, 255).endVertex();
tessellator.end();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(scrollbarLeft, l1 + k1 - 1, 0.0F).uv(0.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.vertex(scrollbarRight - 1, l1 + k1 - 1, 0.0F).uv(1.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.vertex(scrollbarRight - 1, l1, 0.0F).uv(1.0F, 0.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.vertex(scrollbarLeft, l1, 0.0F).uv(0.0F, 0.0F).color(192, 192, 192, 255).endVertex();
tessellator.end();
}
//Draw scrollbar
int maxScroll = this.getMaxScroll();
if (maxScroll > 0)
{
int k1 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
k1 = MathHelper.clamp(k1, 32, this.bottom - this.top - 8);
int l1 = (int)this.amountScrolled * (this.bottom - this.top - k1) / maxScroll + this.top;
//this.renderDecorations(mouseXIn, mouseYIn);
RenderSystem.enableTexture();
RenderSystem.disableBlend();
}
}
if (l1 < this.top)
{
l1 = this.top;
}
//SLOTHEIGHT MODIFICATIONS
//SlotHeight is still relied on for determining how much to scroll
@Override
protected int getMaxPosition() {
//Add every entry height
int height = this.headerHeight;
for (IScrollEntry entry : listEntries) {
height += entry.getHeight();
}
return height;
}
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)scrollBarLeft, (double)this.bottom, 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)this.bottom, 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)this.top, 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)scrollBarLeft, (double)this.top, 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex();
tessellator.draw();
@Override
protected void renderBackground() {
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)scrollBarLeft, (double)(l1 + k1), 0.0D).tex(0.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)(l1 + k1), 0.0D).tex(1.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)scrollBarRight, (double)l1, 0.0D).tex(1.0D, 0.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)scrollBarLeft, (double)l1, 0.0D).tex(0.0D, 0.0D).color(128, 128, 128, 255).endVertex();
tessellator.draw();
}
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)scrollBarLeft, (double)(l1 + k1 - 1), 0.0D).tex(0.0D, 1.0D).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)(scrollBarRight - 1), (double)(l1 + k1 - 1), 0.0D).tex(1.0D, 1.0D).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)(scrollBarRight - 1), (double)l1, 0.0D).tex(1.0D, 0.0D).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)scrollBarLeft, (double)l1, 0.0D).tex(0.0D, 0.0D).color(192, 192, 192, 255).endVertex();
tessellator.draw();
}
@Override
protected void renderItem(PoseStack ms, int slotIndex, int xPos, int yPos, int heightIn, int mouseXIn, int mouseYIn, float partialTicks) {
this.getListEntry(slotIndex).drawEntry(ms, slotIndex, xPos, yPos, this.getRowWidth(), heightIn, mouseXIn, mouseYIn,
this.getSlotIndexFromScreenCoords(mouseXIn, mouseYIn) == slotIndex, partialTicks);
}
GlStateManager.enableTexture2D();
GlStateManager.shadeModel(7424);
GlStateManager.enableAlphaTest();
GlStateManager.disableBlend();
}
}
public int getMaxPosition(int count) {
//Add all count entry heights
int height = this.headerHeight;
for (int i = 0; i < count; i++) {
IScrollEntry entry = listEntries.get(i);
height += entry.getHeight();
}
return height;
}
//SLOTHEIGHT MODIFICATIONS
//SlotHeight is still relied on for determining how much to scroll
@Override
protected int getContentHeight() {
//Add every entry height
int height = this.headerPadding;
for (IScrollEntry entry : listEntries) {
height += entry.getHeight();
}
return height;
}
public int getSlotIndexFromScreenCoords(double posX, double posY) {
int left = this.x0 + (this.width - this.getRowWidth()) / 2;
int right = this.x0 + (this.width + this.getRowWidth()) / 2;
double relativeMouseY = getRelativeMouseY(mouseY, 0);
@Override
protected void drawBackground() {
//Iterate over every entry until relativeMouseY falls within its height
for (int i = 0; i < listEntries.size(); i++) {
IScrollEntry entry = listEntries.get(i);
if (relativeMouseY <= entry.getHeight())
return posX < this.getScrollbarPosition() && posX >= left && posX <= right && i >= 0 &&
relativeMouseY >= 0 && i < this.getItemCount() ? i : -1;
relativeMouseY -= entry.getHeight();
}
return -1;
}
}
@Override
public List<? extends GuiEventListener> children() {
return null;
}
@Override
protected void drawSlot(int slotIndex, int xPos, int yPos, int heightIn, int mouseXIn, int mouseYIn, float partialTicks) {
this.getListEntry(slotIndex).drawEntry(slotIndex, xPos, yPos, this.getListWidth(), heightIn, mouseXIn, mouseYIn,
this.getSlotIndexFromScreenCoords(mouseXIn, mouseYIn) == slotIndex, partialTicks);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
double relativeX = getRelativeMouseX(mouseX);
public int getContentHeight(int count) {
//Add all count entry heights
int height = this.headerPadding;
for (int i = 0; i < count; i++) {
IScrollEntry entry = listEntries.get(i);
height += entry.getHeight();
}
return height;
}
public int getSlotIndexFromScreenCoords(double posX, double posY) {
int left = this.left + (this.width - this.getListWidth()) / 2;
int right = this.left + (this.width + this.getListWidth()) / 2;
double relativeMouseY = getRelativeMouseY(mouseY, 0);
//Iterate over every entry until relativeMouseY falls within its height
for (int i = 0; i < listEntries.size(); i++) {
IScrollEntry entry = listEntries.get(i);
if (relativeMouseY <= entry.getHeight())
return posX < this.getScrollBarX() && posX >= left && posX <= right && i >= 0 &&
relativeMouseY >= 0 && i < this.getSize() ? i : -1;
relativeMouseY -= entry.getHeight();
}
return -1;
}
@Override
protected boolean mouseClicked(int index, int button, double mouseX, double mouseY) {
int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
double relativeX = getRelativeMouseX(mouseX);
//Always pass through mouseclicked, to be able to unfocus textfields
for (int i = 0; i < this.listEntries.size(); i++) {
double relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mousePressed(selectedSlot, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY);
}
//Always pass through mouseclicked, to be able to unfocus textfields
for (int i = 0; i < this.listEntries.size(); i++) {
double relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mousePressed(selectedSlot, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY);
}
// if (this.isMouseYWithinSlotBounds(mouseY))
@@ -260,244 +237,230 @@ public class GuiScrollPane extends GuiSlot {
// }
// }
return false;
}
return false;
}
@Override
public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) {
for (int i = 0; i < this.getSize(); ++i)
{
double relativeX = getRelativeMouseX(mouseX);
double relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mouseReleased(i, (int) p_mouseReleased_1_, (int) p_mouseReleased_3_, p_mouseReleased_5_, (int) relativeX, (int) relativeY);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
for (int i = 0; i < this.getItemCount(); ++i) {
double relativeX = getRelativeMouseX(mouseX);
double relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mouseReleased(i, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY);
}
this.visible = true;
return false;
}
this.visible = true;
return false;
}
public void handleMouseInput() {
if (this.isMouseInList(this.mouseX, this.mouseY)) {
if (mc.mouseHelper.isLeftDown() && this.mouseY >= this.top &&
this.mouseY <= this.bottom) {
int i = this.left + (this.width - this.getListWidth()) / 2;
int j = this.left + (this.width + this.getListWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
public void handleMouseInput() {
if (this.isMouseInList(this.mouseX, this.mouseY)) {
if (minecraft.mouseHandler.isLeftPressed() && this.mouseY >= this.y0 &&
this.mouseY <= this.y1) {
int i = this.x0 + (this.width - this.getRowWidth()) / 2;
int j = this.x0 + (this.width + this.getRowWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (slotIndex > -1) {
this.mouseClicked(slotIndex, 0, this.mouseX, this.mouseY);
this.selectedElement = slotIndex;
} else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i, this.mouseY - this.top + (int) this.amountScrolled - 4);
}
}
if (slotIndex > -1) {
this.mouseClicked(this.mouseX, this.mouseY, 0);
} else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i, this.mouseY - this.y0 + (int) this.yo - 4);
}
}
if (mc.mouseHelper.isLeftDown() && this.isVisible()) {
if (this.initialClickY == -1) {
boolean flag1 = true;
if (minecraft.mouseHandler.isLeftPressed() && this.isVisible()) {
if (this.yDrag == -1) {
boolean flag1 = true;
if (this.mouseY >= this.top && this.mouseY <= this.bottom) {
int i2 = this.left + (this.width - this.getListWidth()) / 2;
int j2 = this.left + (this.width + this.getListWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (this.mouseY >= this.y0 && this.mouseY <= this.y1) {
int i2 = this.x0 + (this.width - this.getRowWidth()) / 2;
int j2 = this.x0 + (this.width + this.getRowWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (slotIndex > -1) {
//TODO 1.13 use flag
boolean flag = slotIndex == this.selectedElement &&
Util.milliTime() - this.lastClicked < 250L;
this.mouseClicked(slotIndex, this.mouseX, this.mouseY);
this.selectedElement = slotIndex;
this.lastClicked = Util.milliTime();
} else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i2,
this.mouseY - this.top + (int) this.amountScrolled - 4);
flag1 = false;
}
if (slotIndex > -1) {
this.mouseClicked(slotIndex, this.mouseX, this.mouseY);
} else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i2,
this.mouseY - this.y0 + (int) this.yo - 4);
flag1 = false;
}
int i3 = this.getScrollBarX();
int j1 = i3 + 6;
int i3 = this.getScrollbarPosition();
int j1 = i3 + 6;
if (this.mouseX >= i3 && this.mouseX <= j1) {
this.scrollMultiplier = -1.0F;
int maxScroll = this.getMaxScroll();
if (this.mouseX >= i3 && this.mouseX <= j1) {
this.scrollMultiplier = -1.0F;
int maxScroll = this.getMaxScroll();
if (maxScroll < 1) {
maxScroll = 1;
}
if (maxScroll < 1) {
maxScroll = 1;
}
int l1 = (int) ((float) ((this.bottom - this.top) * (this.bottom - this.top)) /
(float) this.getContentHeight());
l1 = MathHelper.clamp(l1, 32, this.bottom - this.top - 8);
this.scrollMultiplier /= (float) (this.bottom - this.top - l1) / (float) maxScroll;
} else {
this.scrollMultiplier = 1.0F;
}
int l1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) /
(float) this.getMaxPosition());
l1 = Mth.clamp(l1, 32, this.y1 - this.y0 - 8);
this.scrollMultiplier /= (float) (this.y1 - this.y0 - l1) / (float) maxScroll;
} else {
this.scrollMultiplier = 1.0F;
}
if (flag1) {
this.initialClickY = this.mouseY;
} else {
this.initialClickY = -2;
}
} else {
this.initialClickY = -2;
}
} else if (this.initialClickY >= 0) {
this.amountScrolled -= (float) (this.mouseY - this.initialClickY) * this.scrollMultiplier;
this.initialClickY = this.mouseY;
}
} else {
this.initialClickY = -1;
}
if (flag1) {
this.yDrag = this.mouseY;
} else {
this.yDrag = -2;
}
} else {
this.yDrag = -2;
}
} else if (this.yDrag >= 0) {
this.yo -= (float) (this.mouseY - this.yDrag) * this.scrollMultiplier;
this.yDrag = this.mouseY;
}
} else {
this.yDrag = -1;
}
}
}
}
}
//Through forge event instead of through the parent, because the parent no longer has scroll functionality in 1.13
@SubscribeEvent
public void mouseScrolled(GuiScreenEvent.MouseScrollEvent.Pre event) {
double scrollDelta = event.getScrollDelta();
if (scrollDelta != 0) {
if (scrollDelta > 0) {
scrollDelta = -1;
} else if (scrollDelta < 0) {
scrollDelta = 1;
}
//Draw in center if it fits
@Override
protected void renderList(PoseStack ms, int insideLeft, int insideTop, int mouseXIn, int mouseYIn, float partialTicks) {
int itemCount = this.getItemCount();
Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
this.amountScrolled += (float) (scrollDelta * this.slotHeight / 2);
}
}
//Find y to start with
int y = this.headerHeight + insideTop;
int contentHeight = getMaxPosition();
int insideHeight = this.y1 - this.y0 - 4;
//Draw in center if it fits
@Override
protected void drawSelectionBox(int insideLeft, int insideTop, int mouseXIn, int mouseYIn, float partialTicks)
{
int size = this.getSize();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
if (contentHeight < insideHeight) {
//it fits, so we can center it vertically
y += (insideHeight - contentHeight) / 2;
}
//Find y to start with
int y = this.headerPadding + insideTop;
int contentHeight = getContentHeight();
int insideHeight = this.bottom - this.top - 4;
//Draw all entries
for (int i = 0; i < itemCount; ++i) {
int entryHeight = listEntries.get(i).getHeight();
int entryHeight2 = entryHeight - 4;
if (contentHeight < insideHeight) {
//it fits, so we can center it vertically
y += (insideHeight - contentHeight) / 2;
}
if (y > this.y1 || y + entryHeight2 < this.y0) {
this.updateItemPosition(i, insideLeft, y, partialTicks);
}
//Draw all entries
for (int i = 0; i < size; ++i)
{
int entryHeight = listEntries.get(i).getHeight();
int entryHeight2 = entryHeight - 4;
if (this.renderSelection && this.isSelectedItem(i)) {
int i1 = this.x0 + this.width / 2 - this.getRowWidth() / 2;
int j1 = this.x0 + this.width / 2 + this.getRowWidth() / 2;
RenderSystem.disableTexture();
float f = this.isFocused() ? 1.0F : 0.5F;
RenderSystem.setShaderColor(f, f, f, 1.0F);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.vertex(i1, y + entryHeight2 + 2, 0.0D).endVertex();
bufferbuilder.vertex(j1, y + entryHeight2 + 2, 0.0D).endVertex();
bufferbuilder.vertex(j1, y - 2, 0.0D).endVertex();
bufferbuilder.vertex(i1, y - 2, 0.0D).endVertex();
tessellator.end();
RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.vertex(i1 + 1, y + entryHeight2 + 1, 0.0D).endVertex();
bufferbuilder.vertex(j1 - 1, y + entryHeight2 + 1, 0.0D).endVertex();
bufferbuilder.vertex(j1 - 1, y - 1, 0.0D).endVertex();
bufferbuilder.vertex(i1 + 1, y - 1, 0.0D).endVertex();
tessellator.end();
RenderSystem.enableTexture();
}
if (y > this.bottom || y + entryHeight2 < this.top)
{
this.updateItemPos(i, insideLeft, y, partialTicks);
}
this.renderItem(ms, i, insideLeft, y, entryHeight2, mouseXIn, mouseYIn, partialTicks);
y += entryHeight;
}
}
if (this.showSelectionBox && this.isSelected(i))
{
int i1 = this.left + this.width / 2 - this.getListWidth() / 2;
int j1 = this.left + this.width / 2 + this.getListWidth() / 2;
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableTexture2D();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)i1, (double)(y + entryHeight2 + 2), 0.0D).tex(0.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)j1, (double)(y + entryHeight2 + 2), 0.0D).tex(1.0D, 1.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)j1, (double)(y - 2), 0.0D).tex(1.0D, 0.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)i1, (double)(y - 2), 0.0D).tex(0.0D, 0.0D).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)(i1 + 1), (double)(y + entryHeight2 + 1), 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)(j1 - 1), (double)(y + entryHeight2 + 1), 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)(j1 - 1), (double)(y - 1), 0.0D).tex(1.0D, 0.0D).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)(i1 + 1), (double)(y - 1), 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex();
tessellator.draw();
GlStateManager.enableTexture2D();
}
private double getRelativeMouseX(double mouseX) {
int j = this.x0 + this.width / 2 - this.getRowWidth() / 2 + 2;
return mouseX - j;
}
this.drawSlot(i, insideLeft, y, entryHeight2, mouseXIn, mouseYIn, partialTicks);
y += entryHeight;
}
}
private double getRelativeMouseY(double mouseY, int contentIndex) {
int k = this.y0 + 4 - this.getScroll() + getMaxPosition(contentIndex) + this.headerHeight;
double relativeMouseY = mouseY - k;
private double getRelativeMouseX(double mouseX) {
int j = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
return mouseX - j;
}
//Content might be centered, adjust relative mouse y accordingly
int contentHeight = getMaxPosition();
int insideHeight = this.y1 - this.y0 - 4;
private double getRelativeMouseY(double mouseY, int contentIndex) {
int k = this.top + 4 - this.getAmountScrolled() + getContentHeight(contentIndex) + this.headerPadding;
double relativeMouseY = mouseY - k;
if (contentHeight < insideHeight) {
//it fits, so we can center it vertically
relativeMouseY -= (insideHeight - contentHeight) / 2f;
}
return relativeMouseY;
}
//Content might be centered, adjust relative mouse y accordingly
int contentHeight = getContentHeight();
int insideHeight = this.bottom - this.top - 4;
//PASSTHROUGHS
public void init(List<Widget> renderables) {
for (IScrollEntry entry : this.listEntries) {
entry.init(renderables);
}
}
if (contentHeight < insideHeight) {
//it fits, so we can center it vertically
relativeMouseY -= (insideHeight - contentHeight) / 2;
}
return relativeMouseY;
}
public void updateScreen() {
for (IScrollEntry entry : this.listEntries)
entry.updateScreen();
}
//PASSTHROUGHS
public int initGui(int id, List<GuiButton> buttonList) {
for (IScrollEntry entry : this.listEntries) {
id = entry.initGui(id, buttonList);
}
return id;
}
public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
for (IScrollEntry entry : this.listEntries)
entry.drawTooltip(ms, guiScreen, mouseX, mouseY);
}
public void updateScreen() {
for (IScrollEntry entry : this.listEntries)
entry.updateScreen();
}
@Override
public boolean charTyped(char eventChar, int eventKey) {
for (IScrollEntry entry : this.listEntries)
entry.charTyped(eventChar, eventKey);
return false;
}
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
for (IScrollEntry entry : this.listEntries)
entry.drawTooltip(guiScreen, mouseX, mouseY);
}
public void onGuiClosed() {
for (IScrollEntry entry : this.listEntries)
entry.onGuiClosed();
}
@Override
public boolean charTyped(char eventChar, int eventKey) {
for (IScrollEntry entry : this.listEntries)
entry.charTyped(eventChar, eventKey);
return false;
}
//Make protected values available
public int getWidth() {
return width;
}
public void onGuiClosed() {
for (IScrollEntry entry : this.listEntries)
entry.onGuiClosed();
}
public int getHeight() {
return height;
}
public interface IScrollEntry {
int initGui(int id, List<GuiButton> buttonList);
public interface IScrollEntry {
void init(List<Widget> renderables);
void updateScreen();
void updateScreen();
void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY);
void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY);
boolean charTyped(char eventChar, int eventKey);
boolean charTyped(char eventChar, int eventKey);
void onGuiClosed();
void onGuiClosed();
int getHeight();
int getHeight();
void updatePosition(int slotIndex, int x, int y, float partialTicks);
void updatePosition(int slotIndex, int x, int y, float partialTicks);
void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partialTicks);
void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partialTicks);
/**
* Called when the mouse is clicked within this entry. Returning true means that something within this entry was
* clicked and the list should not be dragged.
*/
boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY);
/**
* Called when the mouse is clicked within this entry. Returning true means that something within this entry was
* clicked and the list should not be dragged.
*/
boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY);
/**
* Fired when the mouse button is released. Arguments: index, x, y, mouseEvent, relativeX, relativeY
*/
void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY);
}
/**
* Fired when the mouse button is released. Arguments: index, x, y, mouseEvent, relativeX, relativeY
*/
void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY);
}
}

View File

@@ -0,0 +1,260 @@
package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Collections;
import java.util.List;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@SuppressWarnings("deprecation")
public abstract class SlotGui extends AbstractContainerEventHandler implements Widget {
protected final Minecraft minecraft;
protected final int itemHeight;
protected int width;
protected int height;
protected int y0;
protected int y1;
protected int x1;
protected int x0;
protected int yDrag = -2;
protected double yo;
protected boolean visible = true;
protected boolean renderSelection = true;
protected boolean renderHeader;
protected int headerHeight;
private boolean scrolling;
public SlotGui(Minecraft mcIn, int width, int height, int topIn, int bottomIn, int slotHeightIn) {
this.minecraft = mcIn;
this.width = width;
this.height = height;
this.y0 = topIn;
this.y1 = bottomIn;
this.itemHeight = slotHeightIn;
this.x0 = 0;
this.x1 = width;
}
public boolean isVisible() {
return this.visible;
}
protected abstract int getItemCount();
public List<? extends GuiEventListener> children() {
return Collections.emptyList();
}
protected boolean selectItem(int p_selectItem_1_, int p_selectItem_2_, double p_selectItem_3_, double p_selectItem_5_) {
return true;
}
protected abstract boolean isSelectedItem(int p_isSelectedItem_1_);
protected int getMaxPosition() {
return this.getItemCount() * this.itemHeight + this.headerHeight;
}
protected abstract void renderBackground();
protected void updateItemPosition(int p_updateItemPosition_1_, int p_updateItemPosition_2_, int p_updateItemPosition_3_, float p_updateItemPosition_4_) {
}
protected abstract void renderItem(PoseStack ms, int p_renderItem_1_, int p_renderItem_2_, int p_renderItem_3_, int p_renderItem_4_, int p_renderItem_5_, int p_renderItem_6_, float p_renderItem_7_);
protected void renderHeader(int p_renderHeader_1_, int p_renderHeader_2_, Tesselator p_renderHeader_3_) {
}
protected void clickedHeader(int p_clickedHeader_1_, int p_clickedHeader_2_) {
}
public int getItemAtPosition(double p_getItemAtPosition_1_, double p_getItemAtPosition_3_) {
int i = this.x0 + this.width / 2 - this.getRowWidth() / 2;
int j = this.x0 + this.width / 2 + this.getRowWidth() / 2;
int k = Mth.floor(p_getItemAtPosition_3_ - (double) this.y0) - this.headerHeight + (int) this.yo - 4;
int l = k / this.itemHeight;
return p_getItemAtPosition_1_ < (double) this.getScrollbarPosition() && p_getItemAtPosition_1_ >= (double) i && p_getItemAtPosition_1_ <= (double) j && l >= 0 && k >= 0 && l < this.getItemCount() ? l : -1;
}
protected void capYPosition() {
this.yo = Mth.clamp(this.yo, 0.0D, this.getMaxScroll());
}
public int getMaxScroll() {
return Math.max(0, this.getMaxPosition() - (this.y1 - this.y0 - 4));
}
public int getScroll() {
return (int) this.yo;
}
public boolean isMouseInList(double p_isMouseInList_1_, double p_isMouseInList_3_) {
return p_isMouseInList_3_ >= (double) this.y0 && p_isMouseInList_3_ <= (double) this.y1 && p_isMouseInList_1_ >= (double) this.x0 && p_isMouseInList_1_ <= (double) this.x1;
}
public abstract void render(PoseStack ms, int p_render_1_, int p_render_2_, float p_render_3_);
protected void updateScrollingState(double p_updateScrollingState_1_, double p_updateScrollingState_3_, int p_updateScrollingState_5_) {
this.scrolling = p_updateScrollingState_5_ == 0 && p_updateScrollingState_1_ >= (double) this.getScrollbarPosition() && p_updateScrollingState_1_ < (double) (this.getScrollbarPosition() + 6);
}
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
this.updateScrollingState(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
if (this.isVisible() && this.isMouseInList(p_mouseClicked_1_, p_mouseClicked_3_)) {
int i = this.getItemAtPosition(p_mouseClicked_1_, p_mouseClicked_3_);
if (i == -1 && p_mouseClicked_5_ == 0) {
this.clickedHeader((int) (p_mouseClicked_1_ - (double) (this.x0 + this.width / 2 - this.getRowWidth() / 2)), (int) (p_mouseClicked_3_ - (double) this.y0) + (int) this.yo - 4);
return true;
} else if (i != -1 && this.selectItem(i, p_mouseClicked_5_, p_mouseClicked_1_, p_mouseClicked_3_)) {
if (this.children().size() > i) {
this.setFocused(this.children().get(i));
}
this.setDragging(true);
return true;
} else {
return this.scrolling;
}
} else {
return false;
}
}
public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) {
if (this.getFocused() != null) {
this.getFocused().mouseReleased(p_mouseReleased_1_, p_mouseReleased_3_, p_mouseReleased_5_);
}
return false;
}
public boolean mouseDragged(double p_mouseDragged_1_, double p_mouseDragged_3_, int p_mouseDragged_5_, double p_mouseDragged_6_, double p_mouseDragged_8_) {
if (super.mouseDragged(p_mouseDragged_1_, p_mouseDragged_3_, p_mouseDragged_5_, p_mouseDragged_6_, p_mouseDragged_8_)) {
return true;
} else if (this.isVisible() && p_mouseDragged_5_ == 0 && this.scrolling) {
if (p_mouseDragged_3_ < (double) this.y0) {
this.yo = 0.0D;
} else if (p_mouseDragged_3_ > (double) this.y1) {
this.yo = this.getMaxScroll();
} else {
double d0 = this.getMaxScroll();
if (d0 < 1.0D) {
d0 = 1.0D;
}
int i = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition());
i = Mth.clamp(i, 32, this.y1 - this.y0 - 8);
double d1 = d0 / (double) (this.y1 - this.y0 - i);
if (d1 < 1.0D) {
d1 = 1.0D;
}
this.yo += p_mouseDragged_8_ * d1;
this.capYPosition();
}
return true;
} else {
return false;
}
}
public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) {
if (!this.isVisible()) {
return false;
} else {
this.yo -= p_mouseScrolled_5_ * (double) this.itemHeight / 2.0D;
return true;
}
}
public boolean keyPressed(int p_keyPressed_1_, int p_keyPressed_2_, int p_keyPressed_3_) {
if (!this.isVisible()) {
return false;
} else if (super.keyPressed(p_keyPressed_1_, p_keyPressed_2_, p_keyPressed_3_)) {
return true;
} else if (p_keyPressed_1_ == 264) {
this.moveSelection(1);
return true;
} else if (p_keyPressed_1_ == 265) {
this.moveSelection(-1);
return true;
} else {
return false;
}
}
protected void moveSelection(int p_moveSelection_1_) {
}
public boolean charTyped(char p_charTyped_1_, int p_charTyped_2_) {
return this.isVisible() && super.charTyped(p_charTyped_1_, p_charTyped_2_);
}
public boolean isMouseOver(double p_isMouseOver_1_, double p_isMouseOver_3_) {
return this.isMouseInList(p_isMouseOver_1_, p_isMouseOver_3_);
}
public int getRowWidth() {
return 220;
}
protected void renderList(PoseStack ms, int p_renderList_1_, int p_renderList_2_, int p_renderList_3_, int p_renderList_4_, float p_renderList_5_) {
int i = this.getItemCount();
Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
for (int j = 0; j < i; ++j) {
int k = p_renderList_2_ + j * this.itemHeight + this.headerHeight;
int l = this.itemHeight - 4;
if (k > this.y1 || k + l < this.y0) {
this.updateItemPosition(j, p_renderList_1_, k, p_renderList_5_);
}
if (this.renderSelection && this.isSelectedItem(j)) {
int i1 = this.x0 + this.width / 2 - this.getRowWidth() / 2;
int j1 = this.x0 + this.width / 2 + this.getRowWidth() / 2;
RenderSystem.disableTexture();
float f = this.isFocused() ? 1.0F : 0.5F;
RenderSystem.setShaderColor(f, f, f, 1.0F);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.vertex(i1, k + l + 2, 0.0D).endVertex();
bufferbuilder.vertex(j1, k + l + 2, 0.0D).endVertex();
bufferbuilder.vertex(j1, k - 2, 0.0D).endVertex();
bufferbuilder.vertex(i1, k - 2, 0.0D).endVertex();
tessellator.end();
RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.vertex(i1 + 1, k + l + 1, 0.0D).endVertex();
bufferbuilder.vertex(j1 - 1, k + l + 1, 0.0D).endVertex();
bufferbuilder.vertex(j1 - 1, k - 1, 0.0D).endVertex();
bufferbuilder.vertex(i1 + 1, k - 1, 0.0D).endVertex();
tessellator.end();
RenderSystem.enableTexture();
}
this.renderItem(ms, j, p_renderList_1_, k, l, p_renderList_3_, p_renderList_4_, p_renderList_5_);
}
}
protected boolean isFocused() {
return false;
}
protected int getScrollbarPosition() {
return this.width / 2 + 124;
}
}

View File

@@ -1,54 +1,52 @@
package nl.requios.effortlessbuilding.helper;
import nl.requios.effortlessbuilding.EffortlessBuilding;
//Stack with fixed size. Removes (overwrites) oldest element on push.
public class FixedStack<T> {
private T[] stack;
private int size;
private int top;
private int filled = 0; //how many valid items are in the stack
private final T[] stack;
private final int size;
private int top;
private int filled = 0; //how many valid items are in the stack
public FixedStack(T[] stack) {
this.stack = stack;
this.top = 0;
this.size = stack.length;
}
public FixedStack(T[] stack) {
this.stack = stack;
this.top = 0;
this.size = stack.length;
}
public void push(T object) {
if (top == stack.length)
top = 0;
public void push(T object) {
if (top == stack.length)
top = 0;
stack[top] = object;
top++;
stack[top] = object;
top++;
if (filled < size)
filled++;
}
if (filled < size)
filled++;
}
public T pop() {
if (filled <= 0) return null;
public T pop() {
if (filled <= 0) return null;
if (top - 1 < 0)
top = size;
if (top - 1 < 0)
top = size;
top--;
T object = stack[top];
filled--;
top--;
T object = stack[top];
filled--;
return object;
}
return object;
}
public void clear() {
top = 0;
filled = 0;
}
public void clear() {
top = 0;
filled = 0;
}
public int size() {
return size;
}
public int size() {
return size;
}
public boolean isEmpty() {
return filled <= 0;
}
public boolean isEmpty() {
return filled <= 0;
}
}

View File

@@ -1,31 +1,30 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
public class InventoryHelper {
public static ItemStack findItemStackInInventory(EntityPlayer player, Block block) {
for (ItemStack invStack : player.inventory.mainInventory) {
if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock &&
((ItemBlock) invStack.getItem()).getBlock().equals(block)) {
return invStack;
}
}
return ItemStack.EMPTY;
}
public static ItemStack findItemStackInInventory(Player player, Block block) {
for (ItemStack invStack : player.getInventory().items) {
if (!invStack.isEmpty() && invStack.getItem() instanceof BlockItem &&
((BlockItem) invStack.getItem()).getBlock().equals(block)) {
return invStack;
}
}
return ItemStack.EMPTY;
}
public static int findTotalBlocksInInventory(EntityPlayer player, Block block) {
int total = 0;
for (ItemStack invStack : player.inventory.mainInventory) {
if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock &&
((ItemBlock) invStack.getItem()).getBlock().equals(block)) {
total += invStack.getCount();
}
}
return total;
}
public static int findTotalBlocksInInventory(Player player, Block block) {
int total = 0;
for (ItemStack invStack : player.getInventory().items) {
if (!invStack.isEmpty() && invStack.getItem() instanceof BlockItem &&
((BlockItem) invStack.getItem()).getBlock().equals(block)) {
total += invStack.getCount();
}
}
return total;
}
}

View File

@@ -1,14 +0,0 @@
package nl.requios.effortlessbuilding.helper;
import com.google.gson.JsonObject;
import net.minecraftforge.common.crafting.IConditionSerializer;
import nl.requios.effortlessbuilding.BuildConfig;
import java.util.function.BooleanSupplier;
public class ReachConditionFactory implements IConditionSerializer {
@Override
public BooleanSupplier parse(JsonObject json) {
return () -> BuildConfig.reach.enableReachUpgrades.get();
}
}

View File

@@ -1,50 +1,54 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
public class ReachHelper {
public static int getMaxReach(EntityPlayer player) {
if (player.isCreative()) return BuildConfig.reach.maxReachCreative.get();
public static int getMaxReach(Player player) {
if (player.isCreative()) return BuildConfig.reach.maxReachCreative.get();
if (!BuildConfig.reach.enableReachUpgrades.get()) return BuildConfig.reach.maxReachLevel3.get();
if (!BuildConfig.reach.enableReachUpgrades.get()) return BuildConfig.reach.maxReachLevel3.get();
//Check buildsettings for reachUpgrade
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
switch (reachUpgrade) {
case 0: return BuildConfig.reach.maxReachLevel0.get();
case 1: return BuildConfig.reach.maxReachLevel1.get();
case 2: return BuildConfig.reach.maxReachLevel2.get();
case 3: return BuildConfig.reach.maxReachLevel3.get();
}
return BuildConfig.reach.maxReachLevel0.get();
}
//Check buildsettings for reachUpgrade
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
switch (reachUpgrade) {
case 0:
return BuildConfig.reach.maxReachLevel0.get();
case 1:
return BuildConfig.reach.maxReachLevel1.get();
case 2:
return BuildConfig.reach.maxReachLevel2.get();
case 3:
return BuildConfig.reach.maxReachLevel3.get();
}
return BuildConfig.reach.maxReachLevel0.get();
}
public static int getPlacementReach(EntityPlayer player) {
return getMaxReach(player) / 4;
}
public static int getPlacementReach(Player player) {
return getMaxReach(player) / 4;
}
public static int getMaxBlocksPlacedAtOnce(EntityPlayer player) {
if (player.isCreative()) return 1000000;
return MathHelper.ceil(Math.pow(getMaxReach(player), 1.6));
//Level 0: 121
//Level 1: 523
//Level 2: 1585
//Level 3: 4805
}
public static int getMaxBlocksPlacedAtOnce(Player player) {
if (player.isCreative()) return 1000000;
return Mth.ceil(Math.pow(getMaxReach(player), 1.6));
//Level 0: 121
//Level 1: 523
//Level 2: 1585
//Level 3: 4805
}
public static int getMaxBlocksPerAxis(EntityPlayer player) {
if (player.isCreative()) return 2000;
return MathHelper.ceil(getMaxReach(player) * 0.3);
//Level 0: 6
//Level 1: 15
//Level 2: 30
//Level 3: 60
}
public static int getMaxBlocksPerAxis(Player player) {
if (player.isCreative()) return 2000;
return Mth.ceil(getMaxReach(player) * 0.3);
//Level 0: 6
//Level 1: 15
//Level 2: 30
//Level 3: 60
}
public static boolean canBreakFar(EntityPlayer player) {
return player.isCreative() || BuildConfig.survivalBalancers.breakFar.get();
}
public static boolean canBreakFar(Player player) {
return player.isCreative() || BuildConfig.survivalBalancers.breakFar.get();
}
}

View File

@@ -1,98 +1,98 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockWorldState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World;
import net.minecraftforge.common.ToolType;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.sounds.SoundSource;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.data.ForgeBlockTagsProvider;
import net.minecraftforge.event.ForgeEventFactory;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
public class SurvivalHelper {
//Used for all placing of blocks in this mod.
//Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack.
//Based on ItemBlock#onItemUse
public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState,
ItemStack origstack, EnumFacing facing, Vec3d hitVec, boolean skipPlaceCheck,
boolean skipCollisionCheck, boolean playSound) {
if (!world.isBlockLoaded(pos, true)) return false;
ItemStack itemstack = origstack;
private static final Tag.Named<Block> NEEDS_NETHERITE_TOOL = BlockTags.bind("forge:needs_netherite_tool");
if (blockState.getBlock().isAir(blockState, world, pos) || itemstack.isEmpty()) {
dropBlock(world, player, pos);
world.removeBlock(pos);
return true;
}
//Used for all placing of blocks in this mod.
//Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack.
//Based on ItemBlock#onItemUse
public static boolean placeBlock(Level world, Player player, BlockPos pos, BlockState blockState,
ItemStack origstack, Direction facing, Vec3 hitVec, boolean skipPlaceCheck,
boolean skipCollisionCheck, boolean playSound) {
if (!world.isLoaded(pos)) return false;
ItemStack itemstack = origstack;
//Randomizer bag, other proxy item synergy
//Preliminary compatibility code for other items that hold blocks
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
if (blockState.isAir() || itemstack.isEmpty()) {
dropBlock(world, player, pos);
world.removeBlock(pos, false);
return true;
}
if (!(itemstack.getItem() instanceof ItemBlock))
return false;
Block block = ((ItemBlock) itemstack.getItem()).getBlock();
//Randomizer bag, other proxy item synergy
//Preliminary compatibility code for other items that hold blocks
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
if (!(itemstack.getItem() instanceof BlockItem))
return false;
Block block = ((BlockItem) itemstack.getItem()).getBlock();
//More manual with ItemBlock#placeBlockAt
if (skipPlaceCheck || canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) {
//Drop existing block
dropBlock(world, player, pos);
//More manual with ItemBlock#placeBlockAt
if (skipPlaceCheck || canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) {
//Drop existing block
dropBlock(world, player, pos);
//TryPlace sets block with offset, so we only do world.setBlockState now
//Remember count of itemstack before tryPlace, and set it back after.
//TryPlace reduces stack even in creative so it is not usable here.
// int origCount = itemstack.getCount();
//TryPlace sets block with offset and reduces itemstack count in creative, so we copy only parts of it
// BlockItemUseContext blockItemUseContext = new BlockItemUseContext(world, player, itemstack, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z);
// EnumActionResult result = ((ItemBlock) itemstack.getItem()).tryPlace(blockItemUseContext);
// itemstack.setCount(origCount);
if (!world.setBlock(pos, blockState, 3)) return false;
BlockItem.updateCustomBlockEntityTag(world, player, pos, itemstack); //Actually BlockItem::onBlockPlaced but that is protected
block.setPlacedBy(world, pos, blockState, player, itemstack);
if (player instanceof ServerPlayer) {
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, pos, itemstack);
}
//Set our (rotated) blockstate
world.setBlockState(pos, blockState, 3);
// blockState.onBlockAdded(world, pos, blockState);
// block.onBlockPlacedBy(world, pos, blockState, player, itemstack);
// world.notifyBlockUpdate(pos, blockState, world.getBlockState(pos), 3);
BlockState afterState = world.getBlockState(pos);
// if (result != EnumActionResult.SUCCESS) return false;
if (playSound) {
SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player);
world.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
}
IBlockState afterState = world.getBlockState(pos);
if (!player.isCreative() && Block.byItem(itemstack.getItem()) == block) {
itemstack.shrink(1);
}
if (playSound) {
SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player);
world.playSound(null, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
}
return true;
}
return false;
if (!player.isCreative() && Block.getBlockFromItem(itemstack.getItem()) == block) {
CompatHelper.shrinkStack(origstack, itemstack, player);
}
return true;
}
return false;
//Using ItemBlock#onItemUse
//Using ItemBlock#onItemUse
// EnumActionResult result;
// PlayerInteractEvent.RightClickBlock event = ForgeHooks.onRightClickBlock(player, EnumHand.MAIN_HAND, pos, facing, net.minecraftforge.common.ForgeHooks.rayTraceEyeHitVec(player, ReachHelper.getPlacementReach(player)));
// if (player.isCreative())
@@ -115,40 +115,40 @@ public class SurvivalHelper {
// return false;
// }
}
}
//Used for all breaking of blocks in this mod.
//Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory
public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos, boolean skipChecks) {
if (!world.isBlockLoaded(pos, false)) return false;
//Used for all breaking of blocks in this mod.
//Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory
public static boolean breakBlock(Level world, Player player, BlockPos pos, boolean skipChecks) {
if (!world.isLoaded(pos) && !world.isEmptyBlock(pos)) return false;
//Check if can break
if (skipChecks || canBreak(world, player, pos)) {
//Check if can break
if (skipChecks || canBreak(world, player, pos)) {
// player.addStat(StatList.getBlockStats(world.getNewBlockState(pos).getBlock()));
// player.addExhaustion(0.005F);
//Drop existing block
dropBlock(world, player, pos);
//Drop existing block
dropBlock(world, player, pos);
//Damage tool
player.getHeldItemMainhand().onBlockDestroyed(world, world.getBlockState(pos), pos, player);
//Damage tool
player.getMainHandItem().mineBlock(world, world.getBlockState(pos), pos, player);
world.removeBlock(pos);
return true;
}
return false;
}
world.removeBlock(pos, false);
return true;
}
return false;
}
//Gives items directly to player
public static void dropBlock(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return;
//Gives items directly to player
public static void dropBlock(Level world, Player player, BlockPos pos) {
if (player.isCreative()) return;
IBlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
BlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand());
block.playerDestroy(world, player, pos, blockState, world.getBlockEntity(pos), player.getMainHandItem());
//TODO drop items in inventory instead of world
//TODO drop items in inventory instead of world
// List<ItemStack> drops = new ArrayList<>();
//
@@ -176,166 +176,142 @@ public class SurvivalHelper {
// {
// ItemHandlerHelper.giveItemToPlayer(player, drop);
// }
}
}
/**
* Check if player can place a block.
* Turn randomizer bag into itemstack inside before.
* @param world
* @param player
* @param pos
* @param newBlockState the blockstate that is going to be placed
* @param itemStack the itemstack used for placing
* @param skipCollisionCheck skips collision check with entities
* @param sidePlacedOn
* @return Whether the player may place the block at pos with itemstack
*/
public static boolean canPlace(World world, EntityPlayer player, BlockPos pos, IBlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, EnumFacing sidePlacedOn) {
/**
* Check if player can place a block.
* Turn randomizer bag into itemstack inside before.
*
* @param world
* @param player
* @param pos
* @param newBlockState the blockstate that is going to be placed
* @param itemStack the itemstack used for placing
* @param skipCollisionCheck skips collision check with entities
* @param sidePlacedOn
* @return Whether the player may place the block at pos with itemstack
*/
public static boolean canPlace(Level world, Player player, BlockPos pos, BlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, Direction sidePlacedOn) {
//Check if itemstack is correct
if (!(itemStack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) {
//Check if itemstack is correct
if (!(itemStack.getItem() instanceof BlockItem) || Block.byItem(itemStack.getItem()) != newBlockState.getBlock()) {
// EffortlessBuilding.log(player, "Cannot (re)place block", true);
// EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString());
//Happens when breaking blocks, no need to notify in that case
return false;
}
//Happens when breaking blocks, no need to notify in that case
return false;
}
Block block = ((ItemBlock) itemStack.getItem()).getBlock();
Block block = ((BlockItem) itemStack.getItem()).getBlock();
return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) &&
mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) &&
canReplace(world, player, pos);
}
return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) &&
mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) &&
canReplace(world, player, pos);
}
//Can be harvested with hand? (or in creative)
private static boolean canReplace(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return true;
//Can be harvested with hand? (or in creative)
private static boolean canReplace(Level world, Player player, BlockPos pos) {
if (player.isCreative()) return true;
IBlockState state = world.getBlockState(pos);
BlockState state = world.getBlockState(pos);
switch (BuildConfig.survivalBalancers.quickReplaceMiningLevel.get()) {
case -1: return state.getMaterial().isToolNotRequired();
case 0: return state.getBlock().getHarvestLevel(state) <= 0;
case 1: return state.getBlock().getHarvestLevel(state) <= 1;
case 2: return state.getBlock().getHarvestLevel(state) <= 2;
case 3: return state.getBlock().getHarvestLevel(state) <= 3;
}
int miningLevel = BuildConfig.survivalBalancers.quickReplaceMiningLevel.get();
switch (miningLevel) {
case -1:
return !state.requiresCorrectToolForDrops();
case 0:
return !state.is(BlockTags.NEEDS_STONE_TOOL) &&
!state.is(BlockTags.NEEDS_IRON_TOOL) &&
!state.is(BlockTags.NEEDS_DIAMOND_TOOL) &&
!state.is(NEEDS_NETHERITE_TOOL);
case 1:
return !state.is(BlockTags.NEEDS_IRON_TOOL) &&
!state.is(BlockTags.NEEDS_DIAMOND_TOOL) &&
!state.is(NEEDS_NETHERITE_TOOL);
case 2:
return !state.is(BlockTags.NEEDS_DIAMOND_TOOL) &&
!state.is(NEEDS_NETHERITE_TOOL);
case 3:
return !state.is(NEEDS_NETHERITE_TOOL);
case 4:
return true;
}
return false;
}
return false;
}
//From EntityPlayer#canPlayerEdit
private static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack)
{
if (!world.isBlockModifiable(player, pos)) return false;
//From EntityPlayer#canPlayerEdit
private static boolean canPlayerEdit(Player player, Level world, BlockPos pos, ItemStack stack) {
if (!world.mayInteract(player, pos)) return false;
if (player.abilities.allowEdit)
{
//True in creative and survival mode
return true;
}
else
{
//Adventure mode
BlockWorldState blockworldstate = new BlockWorldState(world, pos, false);
return stack.canPlaceOn(world.getTags(), blockworldstate);
if (player.getAbilities().mayBuild) {
//True in creative and survival mode
return true;
} else {
//Adventure mode
BlockInWorld blockworldstate = new BlockInWorld(world, pos, false);
return stack.hasAdventureModePlaceTagForBlock(world.getTagManager(), blockworldstate);
}
}
}
}
//From World#mayPlace
private static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
{
IBlockState iblockstate1 = world.getBlockState(pos);
VoxelShape voxelShape = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionShape(world, pos);
//From World#mayPlace
private static boolean mayPlace(Level world, Block blockIn, BlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, Direction sidePlacedOn, @Nullable Entity placer) {
BlockState iblockstate1 = world.getBlockState(pos);
VoxelShape voxelShape = skipCollisionCheck ? null : blockIn.defaultBlockState().getCollisionShape(world, pos);
if (voxelShape != null && !world.checkNoEntityCollision(iblockstate1, pos))
{
return false;
}
if (voxelShape != null && !world.isUnobstructed(placer, voxelShape)) {
return false;
}
//Check if double slab
if (placer != null && doesBecomeDoubleSlab(((EntityPlayer) placer), pos, sidePlacedOn)) {
return true;
}
//Check if double slab
if (placer != null && doesBecomeDoubleSlab(((Player) placer), pos, sidePlacedOn)) {
return true;
}
//Check if same block
//Necessary otherwise extra items will be dropped
if (iblockstate1 == newBlockState) {
return false;
}
//Check if same block
//Necessary otherwise extra items will be dropped
if (iblockstate1 == newBlockState) {
return false;
}
if (iblockstate1.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL)
{
return true;
}
//TODO 1.14 check what Material.CIRCUITS has become
if (iblockstate1.getMaterial() == Material.BUILDABLE_GLASS && blockIn == Blocks.ANVIL) {
return true;
}
//Check quickreplace
if (placer instanceof EntityPlayer && ModifierSettingsManager.getModifierSettings(((EntityPlayer) placer)).doQuickReplace()) {
return true;
}
//Check quickreplace
if (placer instanceof Player && ModifierSettingsManager.getModifierSettings(((Player) placer)).doQuickReplace()) {
return true;
}
//TODO 1.13 replaceable
return iblockstate1.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/;
}
//TODO 1.13 replaceable
return iblockstate1.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/;
}
//Can break using held tool? (or in creative)
public static boolean canBreak(Level world, Player player, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if (!world.getFluidState(pos).isEmpty()) return false;
//Can break using held tool? (or in creative)
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
IBlockState blockState = world.getBlockState(pos);
if (!world.getFluidState(pos).isEmpty()) return false;
if (player.isCreative()) return true;
if (player.isCreative()) return true;
return ForgeEventFactory.doPlayerHarvestCheck(player, blockState, true);
}
return canHarvestBlock(blockState.getBlock(), player, world, pos);
}
public static boolean doesBecomeDoubleSlab(Player player, BlockPos pos, Direction facing) {
BlockState placedBlockState = player.level.getBlockState(pos);
//From ForgeHooks#canHarvestBlock
public static boolean canHarvestBlock(@Nonnull Block block, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
ItemStack itemstack = player.getItemInHand(InteractionHand.MAIN_HAND);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockFromStack(itemstack);
//Dont break bedrock
if (state.getBlockHardness(world, pos) < 0) {
return false;
}
if (itemstack.isEmpty() || !(itemstack.getItem() instanceof BlockItem) || !(((BlockItem) itemstack.getItem()).getBlock() instanceof SlabBlock))
return false;
SlabBlock heldSlab = (SlabBlock) ((BlockItem) itemstack.getItem()).getBlock();
if (state.getMaterial().isToolNotRequired())
{
return true;
}
ItemStack stack = player.getHeldItemMainhand();
ToolType tool = block.getHarvestTool(state);
if (stack.isEmpty() || tool == null)
{
return player.canHarvestBlock(state);
}
if (stack.getDamage() >= stack.getMaxDamage()) return false;
int toolLevel = stack.getItem().getHarvestLevel(stack, tool, player, state);
if (toolLevel < 0)
{
return player.canHarvestBlock(state);
}
return toolLevel >= block.getHarvestLevel(state);
}
public static boolean doesBecomeDoubleSlab(EntityPlayer player, BlockPos pos, EnumFacing facing) {
IBlockState placedBlockState = player.world.getBlockState(pos);
ItemStack itemstack = player.getHeldItem(EnumHand.MAIN_HAND);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockFromStack(itemstack);
if (itemstack.isEmpty() || !(itemstack.getItem() instanceof ItemBlock) || !(((ItemBlock) itemstack.getItem()).getBlock() instanceof BlockSlab)) return false;
BlockSlab heldSlab = (BlockSlab) ((ItemBlock) itemstack.getItem()).getBlock();
if (placedBlockState.getBlock() == heldSlab) {
//TODO 1.13
if (placedBlockState.getBlock() == heldSlab) {
//TODO 1.13
// IProperty<?> variantProperty = heldSlab.getVariantProperty();
// Comparable<?> placedVariant = placedBlockState.getValue(variantProperty);
// BlockSlab.EnumBlockHalf placedHalf = placedBlockState.getValue(BlockSlab.HALF);
@@ -346,7 +322,7 @@ public class SurvivalHelper {
// {
// return true;
// }
}
return false;
}
}
return false;
}
}

View File

@@ -0,0 +1,230 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.MenuProvider;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.InteractionResult;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fmllegacy.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class AbstractRandomizerBagItem extends Item {
private static long currentSeed = 1337;
private static final Random rand = new Random(currentSeed);
public AbstractRandomizerBagItem() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
public abstract int getInventorySize();
public abstract MenuProvider getContainerProvider(ItemStack item);
/**
* Get the inventory of a randomizer bag by checking the capability.
*/
public IItemHandler getBagInventory(ItemStack bag) {
return bag.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).orElse(null);
}
/**
* Pick a random slot from the bag. Empty slots will never get chosen.
*/
public ItemStack pickRandomStack(IItemHandler bagInventory) {
//Find how many stacks are non-empty, and save them in a list
int nonempty = 0;
List<ItemStack> nonEmptyStacks = new ArrayList<>();
List<Integer> originalSlots = new ArrayList<>(getInventorySize());
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty()) {
nonempty++;
nonEmptyStacks.add(stack);
originalSlots.add(i);
}
}
if (nonEmptyStacks.size() != originalSlots.size())
throw new Error("NonEmptyStacks and OriginalSlots not same size");
if (nonempty == 0) return ItemStack.EMPTY;
//Pick random slot
int randomSlot = rand.nextInt(nonempty);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
int originalSlot = originalSlots.get(randomSlot);
if (originalSlot < 0 || originalSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
return bagInventory.getStackInSlot(originalSlot);
}
public ItemStack findStack(IItemHandler bagInventory, Item item) {
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == item) {
return stack;
}
}
return ItemStack.EMPTY;
}
public static void resetRandomness() {
rand.setSeed(currentSeed);
}
public static void renewRandomness() {
currentSeed = Calendar.getInstance().getTimeInMillis();
rand.setSeed(currentSeed);
}
@Override
public InteractionResult useOn(UseOnContext ctx) {
Player player = ctx.getPlayer();
Level world = ctx.getLevel();
BlockPos pos = ctx.getClickedPos();
Direction facing = ctx.getClickedFace();
ItemStack item = ctx.getItemInHand();
Vec3 hitVec = ctx.getClickLocation();
if (player == null) return InteractionResult.FAIL;
if (ctx.getPlayer() != null && ctx.getPlayer().isShiftKeyDown()) { //ctx.isPlacerSneaking()
if (world.isClientSide) return InteractionResult.SUCCESS;
//Open inventory
NetworkHooks.openGui((ServerPlayer) player, getContainerProvider(item));
} else {
if (world.isClientSide) return InteractionResult.SUCCESS;
//Only place manually if in normal vanilla mode
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL || modifierSettings.doQuickReplace()) {
return InteractionResult.FAIL;
}
//Use item
//Get bag inventory
//TODO offhand support
ItemStack bag = player.getItemInHand(InteractionHand.MAIN_HAND);
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return InteractionResult.FAIL;
ItemStack toPlace = pickRandomStack(bagInventory);
if (toPlace.isEmpty()) return InteractionResult.FAIL;
//Previously: use onItemUse to place block (no synergy)
//bag.setItemDamage(toPlace.getMetadata());
//toPlace.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
//TODO replaceable
if (!world.getBlockState(pos).getBlock().canBeReplaced(world.getBlockState(pos), Fluids.EMPTY)) {
pos = pos.relative(facing);
}
BlockPlaceContext blockItemUseContext = new BlockPlaceContext(new UseOnContext(player, InteractionHand.MAIN_HAND, new BlockHitResult(hitVec, facing, pos, false)));
BlockState blockState = Block.byItem(toPlace.getItem()).getStateForPlacement(blockItemUseContext);
SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, hitVec, false, false, true);
//Synergy
//Works without calling
// BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, pos, blockState);
// BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
// Mirror.onBlockPlaced(placeEvent);
// Array.onBlockPlaced(placeEvent);
}
return InteractionResult.SUCCESS;
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
ItemStack bag = player.getItemInHand(hand);
if (player.isShiftKeyDown()) {
if (world.isClientSide) return new InteractionResultHolder<>(InteractionResult.SUCCESS, bag);
//Open inventory
NetworkHooks.openGui((ServerPlayer) player, getContainerProvider(bag));
} else {
//Use item
//Get bag inventory
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return new InteractionResultHolder<>(InteractionResult.FAIL, bag);
ItemStack toUse = pickRandomStack(bagInventory);
if (toUse.isEmpty()) return new InteractionResultHolder<>(InteractionResult.FAIL, bag);
return toUse.use(world, player, hand);
}
return new InteractionResultHolder<>(InteractionResult.PASS, bag);
}
@Override
public int getUseDuration(ItemStack p_77626_1_) {
return 1;
}
@Nullable
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) {
return new ItemHandlerCapabilityProvider(getInventorySize());
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(new TextComponent(ChatFormatting.BLUE + "Rightclick" + ChatFormatting.GRAY + " to place a random block"));
tooltip.add(new TextComponent(ChatFormatting.BLUE + "Sneak + rightclick" + ChatFormatting.GRAY + " to open inventory"));
if (world != null && world.players().size() > 1) {
tooltip.add(new TextComponent(ChatFormatting.YELLOW + "Experimental on servers: may lose inventory"));
}
}
@Override
public String getDescriptionId() {
return this.getRegistryName().toString();
}
}

View File

@@ -0,0 +1,46 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagContainer;
import javax.annotation.Nullable;
public class DiamondRandomizerBagItem extends AbstractRandomizerBagItem{
public static final int INV_SIZE = 27;
@Override
public int getInventorySize() {
return 27;
}
@Override
public MenuProvider getContainerProvider(ItemStack bag) {
return new ContainerProvider(bag);
}
public static class ContainerProvider implements MenuProvider {
private final ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public Component getDisplayName() {
return new TranslatableComponent("effortlessbuilding:diamond_randomizer_bag");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new DiamondRandomizerBagContainer(containerId, playerInventory, ((AbstractRandomizerBagItem)bag.getItem()).getBagInventory(bag));
}
}
}

View File

@@ -0,0 +1,46 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagContainer;
import javax.annotation.Nullable;
public class GoldenRandomizerBagItem extends AbstractRandomizerBagItem{
public static final int INV_SIZE = 9;
@Override
public int getInventorySize() {
return 9;
}
@Override
public MenuProvider getContainerProvider(ItemStack bag) {
return new ContainerProvider(bag);
}
public static class ContainerProvider implements MenuProvider {
private final ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public Component getDisplayName() {
return new TranslatableComponent("effortlessbuilding:golden_randomizer_bag");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new GoldenRandomizerBagContainer(containerId, playerInventory, ((AbstractRandomizerBagItem)bag.getItem()).getBagInventory(bag));
}
}
}

View File

@@ -1,218 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.*;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
public class ItemRandomizerBag extends Item {
public static final int INV_SIZE = 5;
private static long currentSeed = 1337;
private static Random rand = new Random(currentSeed);
public ItemRandomizerBag() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag");
}
@Override
public EnumActionResult onItemUse(ItemUseContext ctx) {
EntityPlayer player = ctx.getPlayer();
World world = ctx.getWorld();
BlockPos pos = ctx.getPos();
EnumFacing facing = ctx.getFace();
ItemStack item = ctx.getItem();
if (player == null) return EnumActionResult.FAIL;
if (ctx.isPlacerSneaking()) {
if (world.isRemote) return EnumActionResult.SUCCESS;
//Open inventory
NetworkHooks.openGui((EntityPlayerMP) player, new RandomizerBagGuiHandler());
} else {
if (world.isRemote) return EnumActionResult.SUCCESS;
//Only place manually if in normal vanilla mode
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL || modifierSettings.doQuickReplace()) {
return EnumActionResult.FAIL;
}
//Use item
//Get bag inventory
//TODO offhand support
ItemStack bag = player.getHeldItem(EnumHand.MAIN_HAND);
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return EnumActionResult.FAIL;
ItemStack toPlace = pickRandomStack(bagInventory);
if (toPlace.isEmpty()) return EnumActionResult.FAIL;
//Previously: use onItemUse to place block (no synergy)
//bag.setItemDamage(toPlace.getMetadata());
//toPlace.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
//TODO replaceable
if (!world.getBlockState(pos).getBlock().getMaterial(world.getBlockState(pos)).isReplaceable()) {
pos = pos.offset(facing);
}
BlockItemUseContext blockItemUseContext = new BlockItemUseContext(world, player, item, pos, facing, ctx.getHitX(), ctx.getHitY(), ctx.getHitZ());
IBlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(blockItemUseContext);
SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(ctx.getHitX(), ctx.getHitY(), ctx.getHitZ()), false, false, true);
//Synergy
//Works without calling
// BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, pos, blockState);
// BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
// Mirror.onBlockPlaced(placeEvent);
// Array.onBlockPlaced(placeEvent);
}
return EnumActionResult.SUCCESS;
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
ItemStack bag = player.getHeldItem(hand);
if (player.isSneaking()) {
if (world.isRemote) return new ActionResult<>(EnumActionResult.SUCCESS, bag);
//Open inventory
NetworkHooks.openGui((EntityPlayerMP) player, new RandomizerBagGuiHandler());
} else {
//Use item
//Get bag inventory
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return new ActionResult<>(EnumActionResult.FAIL, bag);
ItemStack toUse = pickRandomStack(bagInventory);
if (toUse.isEmpty()) return new ActionResult<>(EnumActionResult.FAIL, bag);
return toUse.useItemRightClick(world, player, hand);
}
return new ActionResult<>(EnumActionResult.PASS, bag);
}
/**
* Get the inventory of a randomizer bag by checking the capability.
*
* @param bag
* @return
*/
public static IItemHandler getBagInventory(ItemStack bag) {
return bag.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).orElse(null);
}
/**
* Pick a random slot from the bag. Empty slots will never get chosen.
*
* @param bagInventory
* @return
*/
public static ItemStack pickRandomStack(IItemHandler bagInventory) {
//Find how many stacks are non-empty, and save them in a list
int nonempty = 0;
List<ItemStack> nonEmptyStacks = new ArrayList<>(INV_SIZE);
List<Integer> originalSlots = new ArrayList<>(INV_SIZE);
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty()) {
nonempty++;
nonEmptyStacks.add(stack);
originalSlots.add(i);
}
}
if (nonEmptyStacks.size() != originalSlots.size())
throw new Error("NonEmptyStacks and OriginalSlots not same size");
if (nonempty == 0) return ItemStack.EMPTY;
//Pick random slot
int randomSlot = rand.nextInt(nonempty);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
int originalSlot = originalSlots.get(randomSlot);
if (originalSlot < 0 || originalSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
return bagInventory.getStackInSlot(originalSlot);
}
public static ItemStack findStack(IItemHandler bagInventory, Item item) {
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == item) {
return stack;
}
}
return ItemStack.EMPTY;
}
@Override
public int getUseDuration(ItemStack p_77626_1_) {
return 1;
}
@Nullable
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable NBTTagCompound nbt) {
return new ItemHandlerCapabilityProvider();
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.BLUE + "Rightclick" + TextFormatting.GRAY + " to place a random block"));
tooltip.add(new TextComponentString(TextFormatting.BLUE + "Sneak + rightclick" + TextFormatting.GRAY + " to open inventory"));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
public static void resetRandomness() {
rand.setSeed(currentSeed);
}
public static void renewRandomness() {
currentSeed = Calendar.getInstance().getTimeInMillis();
rand.setSeed(currentSeed);
}
}

View File

@@ -1,65 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade1 extends Item {
public ItemReachUpgrade1() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 0) {
modifierSettings.setReachUpgrade(1);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 0) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel1.get()));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
}

View File

@@ -1,70 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade2 extends Item {
public ItemReachUpgrade2() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 1) {
modifierSettings.setReachUpgrade(2);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 1) {
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 1 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 1) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel2.get()));
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
}

View File

@@ -1,73 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade3 extends Item {
public ItemReachUpgrade3() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 2) {
modifierSettings.setReachUpgrade(3);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 2) {
if (currentLevel == 0)
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 1 and 2 first.");
if (currentLevel == 1)
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 2 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 2) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel3.get()));
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
}

View File

@@ -0,0 +1,46 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import javax.annotation.Nullable;
public class RandomizerBagItem extends AbstractRandomizerBagItem {
public static final int INV_SIZE = 5;
@Override
public int getInventorySize() {
return 5;
}
@Override
public MenuProvider getContainerProvider(ItemStack bag) {
return new ContainerProvider(bag);
}
public static class ContainerProvider implements MenuProvider {
private final ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public Component getDisplayName() {
return new TranslatableComponent("effortlessbuilding:randomizer_bag");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new RandomizerBagContainer(containerId, playerInventory, ((AbstractRandomizerBagItem)bag.getItem()).getBagInventory(bag));
}
}
}

View File

@@ -0,0 +1,74 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ReachUpgrade1Item extends Item {
public ReachUpgrade1Item() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 0) {
modifierSettings.setReachUpgrade(1);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 0) {
if (world.isClientSide)
EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(new TextComponent(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel1.get()));
}
@Override
public String getDescriptionId() {
return this.getRegistryName().toString();
}
}

View File

@@ -0,0 +1,79 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ReachUpgrade2Item extends Item {
public ReachUpgrade2Item() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 1) {
modifierSettings.setReachUpgrade(2);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 1) {
if (world.isClientSide) EffortlessBuilding.log(player, "Use Reach Upgrade 1 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 1) {
if (world.isClientSide)
EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(new TextComponent(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel2.get()));
tooltip.add(new TextComponent(ChatFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
@Override
public String getDescriptionId() {
return this.getRegistryName().toString();
}
}

View File

@@ -0,0 +1,82 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ReachUpgrade3Item extends Item {
public ReachUpgrade3Item() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 2) {
modifierSettings.setReachUpgrade(3);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 2) {
if (currentLevel == 0)
if (world.isClientSide) EffortlessBuilding.log(player, "Use Reach Upgrade 1 and 2 first.");
if (currentLevel == 1)
if (world.isClientSide) EffortlessBuilding.log(player, "Use Reach Upgrade 2 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 2) {
if (world.isClientSide)
EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(new TextComponent(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel3.get()));
tooltip.add(new TextComponent(ChatFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
@Override
public String getDescriptionId() {
return this.getRegistryName().toString();
}
}

View File

@@ -1,13 +1,13 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
@@ -19,68 +19,73 @@ import java.util.function.Supplier;
* Sends a message to the client asking to add a block to the undo stack.
*/
public class AddUndoMessage {
private BlockPos coordinate;
private IBlockState previousBlockState;
private IBlockState newBlockState;
private final BlockPos coordinate;
private final BlockState previousBlockState;
private final BlockState newBlockState;
public AddUndoMessage() {
coordinate = BlockPos.ORIGIN;
previousBlockState = null;
newBlockState = null;
}
public AddUndoMessage() {
coordinate = BlockPos.ZERO;
previousBlockState = null;
newBlockState = null;
}
public AddUndoMessage(BlockPos coordinate, IBlockState previousBlockState, IBlockState newBlockState) {
this.coordinate = coordinate;
this.previousBlockState = previousBlockState;
this.newBlockState = newBlockState;
}
public AddUndoMessage(BlockPos coordinate, BlockState previousBlockState, BlockState newBlockState) {
this.coordinate = coordinate;
this.previousBlockState = previousBlockState;
this.newBlockState = newBlockState;
}
public BlockPos getCoordinate() {
return coordinate;
}
public static void encode(AddUndoMessage message, FriendlyByteBuf buf) {
buf.writeInt(message.coordinate.getX());
buf.writeInt(message.coordinate.getY());
buf.writeInt(message.coordinate.getZ());
buf.writeInt(Block.getId(message.previousBlockState));
buf.writeInt(Block.getId(message.newBlockState));
}
public IBlockState getPreviousBlockState() {
return previousBlockState;
}
public static AddUndoMessage decode(FriendlyByteBuf buf) {
BlockPos coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
BlockState previousBlockState = Block.stateById(buf.readInt());
BlockState newBlockState = Block.stateById(buf.readInt());
return new AddUndoMessage(coordinate, previousBlockState, newBlockState);
}
public IBlockState getNewBlockState() {
return newBlockState;
}
public BlockPos getCoordinate() {
return coordinate;
}
public static void encode(AddUndoMessage message, PacketBuffer buf) {
buf.writeInt(message.coordinate.getX());
buf.writeInt(message.coordinate.getY());
buf.writeInt(message.coordinate.getZ());
buf.writeInt(Block.getStateId(message.previousBlockState));
buf.writeInt(Block.getStateId(message.newBlockState));
}
public BlockState getPreviousBlockState() {
return previousBlockState;
}
public static AddUndoMessage decode(PacketBuffer buf) {
BlockPos coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
IBlockState previousBlockState = Block.getStateById(buf.readInt());
IBlockState newBlockState = Block.getStateById(buf.readInt());
return new AddUndoMessage(coordinate, previousBlockState, newBlockState);
}
public BlockState getNewBlockState() {
return newBlockState;
}
public static class Handler
{
public static void handle(AddUndoMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
public static class Handler {
public static void handle(AddUndoMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
UndoRedo.addUndo(ctx.get().getSender(), new BlockSet(
new ArrayList<BlockPos>() {{add(message.getCoordinate());}},
new ArrayList<IBlockState>() {{add(message.getPreviousBlockState());}},
new ArrayList<IBlockState>() {{add(message.getNewBlockState());}},
new Vec3d(0,0,0),
message.getCoordinate(), message.getCoordinate()));
}
});
ctx.get().setPacketHandled(true);
}
}
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
//Only the appropriate player that needs to add this to the undo stack gets this message
UndoRedo.addUndo(player, new BlockSet(
new ArrayList<BlockPos>() {{
add(message.getCoordinate());
}},
new ArrayList<BlockState>() {{
add(message.getPreviousBlockState());
}},
new ArrayList<BlockState>() {{
add(message.getNewBlockState());
}},
new Vec3(0, 0, 0),
message.getCoordinate(), message.getCoordinate()));
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,13 +1,13 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import java.util.function.Supplier;
@@ -17,78 +17,76 @@ import java.util.function.Supplier;
*/
public class BlockBrokenMessage {
private boolean blockHit;
private BlockPos blockPos;
private EnumFacing sideHit;
private Vec3d hitVec;
private final boolean blockHit;
private final BlockPos blockPos;
private final Direction sideHit;
private final Vec3 hitVec;
public BlockBrokenMessage() {
this.blockHit = false;
this.blockPos = BlockPos.ORIGIN;
this.sideHit = EnumFacing.UP;
this.hitVec = new Vec3d(0, 0, 0);
}
public BlockBrokenMessage() {
this.blockHit = false;
this.blockPos = BlockPos.ZERO;
this.sideHit = Direction.UP;
this.hitVec = new Vec3(0, 0, 0);
}
public BlockBrokenMessage(RayTraceResult result) {
this.blockHit = result.type == RayTraceResult.Type.BLOCK;
this.blockPos = result.getBlockPos();
this.sideHit = result.sideHit;
this.hitVec = result.hitVec;
}
public BlockBrokenMessage(BlockHitResult result) {
this.blockHit = result.getType() == HitResult.Type.BLOCK;
this.blockPos = result.getBlockPos();
this.sideHit = result.getDirection();
this.hitVec = result.getLocation();
}
public BlockBrokenMessage(boolean blockHit, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) {
this.blockHit = blockHit;
this.blockPos = blockPos;
this.sideHit = sideHit;
this.hitVec = hitVec;
}
public BlockBrokenMessage(boolean blockHit, BlockPos blockPos, Direction sideHit, Vec3 hitVec) {
this.blockHit = blockHit;
this.blockPos = blockPos;
this.sideHit = sideHit;
this.hitVec = hitVec;
}
public boolean isBlockHit() {
return blockHit;
}
public static void encode(BlockBrokenMessage message, FriendlyByteBuf buf) {
buf.writeBoolean(message.blockHit);
buf.writeInt(message.blockPos.getX());
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.get3DDataValue());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
}
public BlockPos getBlockPos() {
return blockPos;
}
public static BlockBrokenMessage decode(FriendlyByteBuf buf) {
boolean blockHit = buf.readBoolean();
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
Direction sideHit = Direction.from3DDataValue(buf.readInt());
Vec3 hitVec = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
return new BlockBrokenMessage(blockHit, blockPos, sideHit, hitVec);
}
public EnumFacing getSideHit() {
return sideHit;
}
public boolean isBlockHit() {
return blockHit;
}
public Vec3d getHitVec() {
return hitVec;
}
public BlockPos getBlockPos() {
return blockPos;
}
public static void encode(BlockBrokenMessage message, PacketBuffer buf) {
buf.writeBoolean(message.blockHit);
buf.writeInt(message.blockPos.getX());
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.getIndex());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
}
public Direction getSideHit() {
return sideHit;
}
public static BlockBrokenMessage decode(PacketBuffer buf) {
boolean blockHit = buf.readBoolean();
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
EnumFacing sideHit = EnumFacing.byIndex(buf.readInt());
Vec3d hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
return new BlockBrokenMessage(blockHit, blockPos, sideHit, hitVec);
}
public Vec3 getHitVec() {
return hitVec;
}
public static class Handler
{
public static void handle(BlockBrokenMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.SERVER) {
//Received serverside
BuildModes.onBlockBrokenMessage(ctx.get().getSender(), message);
}
});
ctx.get().setPacketHandled(true);
}
}
public static class Handler {
public static void handle(BlockBrokenMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.SERVER) {
//Received serverside
BuildModes.onBlockBrokenMessage(ctx.get().getSender(), message);
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,13 +1,13 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
@@ -19,92 +19,90 @@ import java.util.function.Supplier;
*/
public class BlockPlacedMessage {
private boolean blockHit;
private BlockPos blockPos;
private EnumFacing sideHit;
private Vec3d hitVec;
private boolean placeStartPos; //prevent double placing in normal mode
private final boolean blockHit;
private final BlockPos blockPos;
private final Direction sideHit;
private final Vec3 hitVec;
private final boolean placeStartPos; //prevent double placing in normal mode
public BlockPlacedMessage() {
this.blockHit = false;
this.blockPos = BlockPos.ORIGIN;
this.sideHit = EnumFacing.UP;
this.hitVec = new Vec3d(0, 0, 0);
this.placeStartPos = true;
}
public BlockPlacedMessage() {
this.blockHit = false;
this.blockPos = BlockPos.ZERO;
this.sideHit = Direction.UP;
this.hitVec = new Vec3(0, 0, 0);
this.placeStartPos = true;
}
public BlockPlacedMessage(RayTraceResult result, boolean placeStartPos) {
this.blockHit = result.type == RayTraceResult.Type.BLOCK;
this.blockPos = result.getBlockPos();
this.sideHit = result.sideHit;
this.hitVec = result.hitVec;
this.placeStartPos = placeStartPos;
}
public BlockPlacedMessage(BlockHitResult result, boolean placeStartPos) {
this.blockHit = result.getType() == HitResult.Type.BLOCK;
this.blockPos = result.getBlockPos();
this.sideHit = result.getDirection();
this.hitVec = result.getLocation();
this.placeStartPos = placeStartPos;
}
public BlockPlacedMessage(boolean blockHit, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean placeStartPos) {
this.blockHit = blockHit;
this.blockPos = blockPos;
this.sideHit = sideHit;
this.hitVec = hitVec;
this.placeStartPos = placeStartPos;
}
public BlockPlacedMessage(boolean blockHit, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean placeStartPos) {
this.blockHit = blockHit;
this.blockPos = blockPos;
this.sideHit = sideHit;
this.hitVec = hitVec;
this.placeStartPos = placeStartPos;
}
public boolean isBlockHit() {
return blockHit;
}
public static void encode(BlockPlacedMessage message, FriendlyByteBuf buf) {
buf.writeBoolean(message.blockHit);
buf.writeInt(message.blockPos.getX());
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.get3DDataValue());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
buf.writeBoolean(message.placeStartPos);
}
public BlockPos getBlockPos() {
return blockPos;
}
public static BlockPlacedMessage decode(FriendlyByteBuf buf) {
boolean blockHit = buf.readBoolean();
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
Direction sideHit = Direction.from3DDataValue(buf.readInt());
Vec3 hitVec = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean placeStartPos = buf.readBoolean();
return new BlockPlacedMessage(blockHit, blockPos, sideHit, hitVec, placeStartPos);
}
public EnumFacing getSideHit() {
return sideHit;
}
public boolean isBlockHit() {
return blockHit;
}
public Vec3d getHitVec() {
return hitVec;
}
public BlockPos getBlockPos() {
return blockPos;
}
public boolean getPlaceStartPos() {
return placeStartPos;
}
public Direction getSideHit() {
return sideHit;
}
public static void encode(BlockPlacedMessage message, PacketBuffer buf) {
buf.writeBoolean(message.blockHit);
buf.writeInt(message.blockPos.getX());
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.getIndex());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
buf.writeBoolean(message.placeStartPos);
}
public Vec3 getHitVec() {
return hitVec;
}
public static BlockPlacedMessage decode(PacketBuffer buf) {
boolean blockHit = buf.readBoolean();
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
EnumFacing sideHit = EnumFacing.byIndex(buf.readInt());
Vec3d hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean placeStartPos = buf.readBoolean();
return new BlockPlacedMessage(blockHit, blockPos, sideHit, hitVec, placeStartPos);
}
public boolean getPlaceStartPos() {
return placeStartPos;
}
public static class Handler
{
public static void handle(BlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
//Nod RenderHandler to do the dissolve shader effect
BlockPreviewRenderer.onBlocksPlaced();
} else {
//Received serverside
BuildModes.onBlockPlacedMessage(ctx.get().getSender(), message);
}
});
ctx.get().setPacketHandled(true);
}
}
public static class Handler {
public static void handle(BlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
//Nod RenderHandler to do the dissolve shader effect
BlockPreviewRenderer.onBlocksPlaced();
} else {
//Received serverside
BuildModes.onBlockPlacedMessage(ctx.get().getSender(), message);
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
@@ -13,23 +13,21 @@ import java.util.function.Supplier;
*/
public class CancelModeMessage {
public static void encode(CancelModeMessage message, PacketBuffer buf) {
}
public static void encode(CancelModeMessage message, FriendlyByteBuf buf) {
}
public static CancelModeMessage decode(PacketBuffer buf) {
return new CancelModeMessage();
}
public static CancelModeMessage decode(FriendlyByteBuf buf) {
return new CancelModeMessage();
}
public static class Handler
{
public static void handle(CancelModeMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
public static class Handler {
public static void handle(CancelModeMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
BuildModes.initializeMode(player);
});
ctx.get().setPacketHandled(true);
}
}
BuildModes.initializeMode(player);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,9 +1,9 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
@@ -14,31 +14,29 @@ import java.util.function.Supplier;
*/
public class ClearUndoMessage {
public ClearUndoMessage() {
}
public ClearUndoMessage() {
}
public static void encode(ClearUndoMessage message, PacketBuffer buf) {
public static void encode(ClearUndoMessage message, FriendlyByteBuf buf) {
}
}
public static ClearUndoMessage decode(PacketBuffer buf) {
return new ClearUndoMessage();
}
public static ClearUndoMessage decode(FriendlyByteBuf buf) {
return new ClearUndoMessage();
}
public static class Handler
{
public static void handle(ClearUndoMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
public static class Handler {
public static void handle(ClearUndoMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
UndoRedo.clear(player);
}
});
ctx.get().setPacketHandled(true);
}
}
//Add to undo stack clientside
UndoRedo.clear(player);
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
@@ -13,34 +13,32 @@ import java.util.function.Supplier;
*/
public class ModeActionMessage {
private ModeOptions.ActionEnum action;
private ModeOptions.ActionEnum action;
public ModeActionMessage() {
}
public ModeActionMessage() {
}
public ModeActionMessage(ModeOptions.ActionEnum action) {
this.action = action;
}
public ModeActionMessage(ModeOptions.ActionEnum action) {
this.action = action;
}
public static void encode(ModeActionMessage message, PacketBuffer buf) {
buf.writeInt(message.action.ordinal());
}
public static void encode(ModeActionMessage message, FriendlyByteBuf buf) {
buf.writeInt(message.action.ordinal());
}
public static ModeActionMessage decode(PacketBuffer buf) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.values()[buf.readInt()];
return new ModeActionMessage(action);
}
public static ModeActionMessage decode(FriendlyByteBuf buf) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.values()[buf.readInt()];
return new ModeActionMessage(action);
}
public static class Handler
{
public static void handle(ModeActionMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
public static class Handler {
public static void handle(ModeActionMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ModeOptions.performAction(player, message.action);
});
ctx.get().setPacketHandled(true);
}
}
ModeOptions.performAction(player, message.action);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,10 +1,8 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
@@ -17,38 +15,36 @@ import java.util.function.Supplier;
*/
public class ModeSettingsMessage {
private ModeSettings modeSettings;
private ModeSettings modeSettings;
public ModeSettingsMessage() {
}
public ModeSettingsMessage() {
}
public ModeSettingsMessage(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
public ModeSettingsMessage(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
public static void encode(ModeSettingsMessage message, PacketBuffer buf) {
buf.writeInt(message.modeSettings.getBuildMode().ordinal());
}
public static void encode(ModeSettingsMessage message, FriendlyByteBuf buf) {
buf.writeInt(message.modeSettings.getBuildMode().ordinal());
}
public static ModeSettingsMessage decode(PacketBuffer buf) {
BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()];
public static ModeSettingsMessage decode(FriendlyByteBuf buf) {
BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()];
return new ModeSettingsMessage(new ModeSettings(buildMode));
}
return new ModeSettingsMessage(new ModeSettings(buildMode));
}
public static class Handler
{
public static void handle(ModeSettingsMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
public static class Handler {
public static void handle(ModeSettingsMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize
ModeSettingsManager.sanitize(message.modeSettings, player);
// Sanitize
ModeSettingsManager.sanitize(message.modeSettings, player);
ModeSettingsManager.setModeSettings(player, message.modeSettings);
});
ctx.get().setPacketHandled(true);
}
}
ModeSettingsManager.setModeSettings(player, message.modeSettings);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
@@ -15,128 +15,128 @@ import java.util.function.Supplier;
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
/**
* Shares modifier settings (see ModifierSettingsManager) between server and client
*/
public class ModifierSettingsMessage {
private ModifierSettings modifierSettings;
private ModifierSettings modifierSettings;
public ModifierSettingsMessage() {
}
public ModifierSettingsMessage() {
}
public ModifierSettingsMessage(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
public ModifierSettingsMessage(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
public static void encode(ModifierSettingsMessage message, PacketBuffer buf) {
//MIRROR
Mirror.MirrorSettings m = message.modifierSettings.getMirrorSettings();
buf.writeBoolean(m != null);
if (m != null) {
buf.writeBoolean(m.enabled);
buf.writeDouble(m.position.x);
buf.writeDouble(m.position.y);
buf.writeDouble(m.position.z);
buf.writeBoolean(m.mirrorX);
buf.writeBoolean(m.mirrorY);
buf.writeBoolean(m.mirrorZ);
buf.writeInt(m.radius);
buf.writeBoolean(m.drawLines);
buf.writeBoolean(m.drawPlanes);
}
public static void encode(ModifierSettingsMessage message, FriendlyByteBuf buf) {
//MIRROR
Mirror.MirrorSettings m = message.modifierSettings.getMirrorSettings();
buf.writeBoolean(m != null);
if (m != null) {
buf.writeBoolean(m.enabled);
buf.writeDouble(m.position.x);
buf.writeDouble(m.position.y);
buf.writeDouble(m.position.z);
buf.writeBoolean(m.mirrorX);
buf.writeBoolean(m.mirrorY);
buf.writeBoolean(m.mirrorZ);
buf.writeInt(m.radius);
buf.writeBoolean(m.drawLines);
buf.writeBoolean(m.drawPlanes);
}
//ARRAY
Array.ArraySettings a = message.modifierSettings.getArraySettings();
buf.writeBoolean(a != null);
if (a != null) {
buf.writeBoolean(a.enabled);
buf.writeInt(a.offset.getX());
buf.writeInt(a.offset.getY());
buf.writeInt(a.offset.getZ());
buf.writeInt(a.count);
}
//ARRAY
Array.ArraySettings a = message.modifierSettings.getArraySettings();
buf.writeBoolean(a != null);
if (a != null) {
buf.writeBoolean(a.enabled);
buf.writeInt(a.offset.getX());
buf.writeInt(a.offset.getY());
buf.writeInt(a.offset.getZ());
buf.writeInt(a.count);
}
buf.writeBoolean(message.modifierSettings.doQuickReplace());
buf.writeBoolean(message.modifierSettings.doQuickReplace());
buf.writeInt(message.modifierSettings.getReachUpgrade());
buf.writeInt(message.modifierSettings.getReachUpgrade());
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null);
if (r != null) {
buf.writeBoolean(r.enabled);
buf.writeDouble(r.position.x);
buf.writeDouble(r.position.y);
buf.writeDouble(r.position.z);
buf.writeInt(r.slices);
buf.writeBoolean(r.alternate);
buf.writeInt(r.radius);
buf.writeBoolean(r.drawLines);
buf.writeBoolean(r.drawPlanes);
}
}
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null);
if (r != null) {
buf.writeBoolean(r.enabled);
buf.writeDouble(r.position.x);
buf.writeDouble(r.position.y);
buf.writeDouble(r.position.z);
buf.writeInt(r.slices);
buf.writeBoolean(r.alternate);
buf.writeInt(r.radius);
buf.writeBoolean(r.drawLines);
buf.writeBoolean(r.drawPlanes);
}
}
public static ModifierSettingsMessage decode(PacketBuffer buf) {
//MIRROR
Mirror.MirrorSettings m = new Mirror.MirrorSettings();
if (buf.readBoolean()) {
boolean mirrorEnabled = buf.readBoolean();
Vec3d mirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean mirrorX = buf.readBoolean();
boolean mirrorY = buf.readBoolean();
boolean mirrorZ = buf.readBoolean();
int mirrorRadius = buf.readInt();
boolean mirrorDrawLines = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean();
m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius,
mirrorDrawLines, mirrorDrawPlanes);
}
public static ModifierSettingsMessage decode(FriendlyByteBuf buf) {
//MIRROR
Mirror.MirrorSettings m = new Mirror.MirrorSettings();
if (buf.readBoolean()) {
boolean mirrorEnabled = buf.readBoolean();
Vec3 mirrorPosition = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean mirrorX = buf.readBoolean();
boolean mirrorY = buf.readBoolean();
boolean mirrorZ = buf.readBoolean();
int mirrorRadius = buf.readInt();
boolean mirrorDrawLines = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean();
m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius,
mirrorDrawLines, mirrorDrawPlanes);
}
//ARRAY
Array.ArraySettings a = new Array.ArraySettings();
if (buf.readBoolean()) {
boolean arrayEnabled = buf.readBoolean();
BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
int arrayCount = buf.readInt();
a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
}
//ARRAY
Array.ArraySettings a = new Array.ArraySettings();
if (buf.readBoolean()) {
boolean arrayEnabled = buf.readBoolean();
BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
int arrayCount = buf.readInt();
a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
}
boolean quickReplace = buf.readBoolean();
boolean quickReplace = buf.readBoolean();
int reachUpgrade = buf.readInt();
int reachUpgrade = buf.readInt();
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings();
if (buf.readBoolean()) {
boolean radialMirrorEnabled = buf.readBoolean();
Vec3d radialMirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
int radialMirrorSlices = buf.readInt();
boolean radialMirrorAlternate = buf.readBoolean();
int radialMirrorRadius = buf.readInt();
boolean radialMirrorDrawLines = buf.readBoolean();
boolean radialMirrorDrawPlanes = buf.readBoolean();
r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices,
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
}
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings();
if (buf.readBoolean()) {
boolean radialMirrorEnabled = buf.readBoolean();
Vec3 radialMirrorPosition = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
int radialMirrorSlices = buf.readInt();
boolean radialMirrorAlternate = buf.readBoolean();
int radialMirrorRadius = buf.readInt();
boolean radialMirrorDrawLines = buf.readBoolean();
boolean radialMirrorDrawPlanes = buf.readBoolean();
r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices,
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
}
ModifierSettings modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade);
return new ModifierSettingsMessage(modifierSettings);
}
ModifierSettings modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade);
return new ModifierSettingsMessage(modifierSettings);
}
public static class Handler
{
public static void handle(ModifierSettingsMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
public static class Handler {
public static void handle(ModifierSettingsMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize
ModifierSettingsManager.sanitize(message.modifierSettings, player);
// Sanitize
ModifierSettingsManager.sanitize(message.modifierSettings, player);
ModifierSettingsManager.setModifierSettings(player, message.modifierSettings);
});
ctx.get().setPacketHandled(true);
}
}
ModifierSettingsManager.setModifierSettings(player, message.modifierSettings);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,32 +1,32 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fmllegacy.network.NetworkRegistry;
import net.minecraftforge.fmllegacy.network.simple.SimpleChannel;
import nl.requios.effortlessbuilding.EffortlessBuilding;
public class PacketHandler {
private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.ChannelBuilder
.named(new ResourceLocation(EffortlessBuilding.MODID, "main_channel"))
.clientAcceptedVersions(PROTOCOL_VERSION::equals)
.serverAcceptedVersions(PROTOCOL_VERSION::equals)
.networkProtocolVersion(() -> PROTOCOL_VERSION)
.simpleChannel();
private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation(EffortlessBuilding.MODID, "main_channel"),
() -> PROTOCOL_VERSION,
PROTOCOL_VERSION::equals,
PROTOCOL_VERSION::equals
);
public static void register() {
int id = 0;
public static void register() {
int id = 0;
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode, ModifierSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeSettingsMessage.class, ModeSettingsMessage::encode, ModeSettingsMessage::decode, ModeSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode, ModeActionMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockPlacedMessage.class, BlockPlacedMessage::encode, BlockPlacedMessage::decode, BlockPlacedMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockBrokenMessage.class, BlockBrokenMessage::encode, BlockBrokenMessage::decode, BlockBrokenMessage.Handler::handle);
INSTANCE.registerMessage(id++, CancelModeMessage.class, CancelModeMessage::encode, CancelModeMessage::decode, CancelModeMessage.Handler::handle);
INSTANCE.registerMessage(id++, RequestLookAtMessage.class, RequestLookAtMessage::encode, RequestLookAtMessage::decode, RequestLookAtMessage.Handler::handle);
INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode, AddUndoMessage.Handler::handle);
INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode, ClearUndoMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode, ModifierSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeSettingsMessage.class, ModeSettingsMessage::encode, ModeSettingsMessage::decode, ModeSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode, ModeActionMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockPlacedMessage.class, BlockPlacedMessage::encode, BlockPlacedMessage::decode, BlockPlacedMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockBrokenMessage.class, BlockBrokenMessage::encode, BlockBrokenMessage::decode, BlockBrokenMessage.Handler::handle);
INSTANCE.registerMessage(id++, CancelModeMessage.class, CancelModeMessage::encode, CancelModeMessage::decode, CancelModeMessage.Handler::handle);
INSTANCE.registerMessage(id++, RequestLookAtMessage.class, RequestLookAtMessage::encode, RequestLookAtMessage::decode, RequestLookAtMessage.Handler::handle);
INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode, AddUndoMessage.Handler::handle);
INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode, ClearUndoMessage.Handler::handle);
}
}
}

View File

@@ -1,19 +1,14 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.util.ArrayList;
import java.util.function.Supplier;
/***
@@ -21,45 +16,47 @@ import java.util.function.Supplier;
* This is then sent back with a BlockPlacedMessage.
*/
public class RequestLookAtMessage {
private boolean placeStartPos;
private final boolean placeStartPos;
public RequestLookAtMessage() {
placeStartPos = false;
}
public RequestLookAtMessage() {
placeStartPos = false;
}
public RequestLookAtMessage(boolean placeStartPos) {
this.placeStartPos = placeStartPos;
}
public RequestLookAtMessage(boolean placeStartPos) {
this.placeStartPos = placeStartPos;
}
public boolean getPlaceStartPos() {
return placeStartPos;
}
public static void encode(RequestLookAtMessage message, FriendlyByteBuf buf) {
buf.writeBoolean(message.placeStartPos);
}
public static void encode(RequestLookAtMessage message, PacketBuffer buf) {
buf.writeBoolean(message.placeStartPos);
}
public static RequestLookAtMessage decode(FriendlyByteBuf buf) {
boolean placeStartPos = buf.readBoolean();
return new RequestLookAtMessage(placeStartPos);
}
public static RequestLookAtMessage decode(PacketBuffer buf) {
boolean placeStartPos = buf.readBoolean();
return new RequestLookAtMessage(placeStartPos);
}
public boolean getPlaceStartPos() {
return placeStartPos;
}
public static class Handler
{
public static void handle(RequestLookAtMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
//Send back your info
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
public static class Handler {
public static void handle(RequestLookAtMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
//Send back your info
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Prevent double placing in normal mode with placeStartPos false
//Unless QuickReplace is on, then we do need to place start pos.
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage(ClientProxy.previousLookAt, message.getPlaceStartPos()));
}
});
ctx.get().setPacketHandled(true);
}
}
//Prevent double placing in normal mode with placeStartPos false
//Unless QuickReplace is on, then we do need to place start pos.
if (ClientProxy.previousLookAt.getType() == HitResult.Type.BLOCK) {
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage((BlockHitResult) ClientProxy.previousLookAt, message.getPlaceStartPos()));
} else {
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage());
}
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -0,0 +1,71 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import java.util.function.Supplier;
public class TranslatedLogMessage {
private final String prefix;
private final String translationKey;
private final String suffix;
private final boolean actionBar;
public TranslatedLogMessage() {
prefix = "";
translationKey = "";
suffix = "";
actionBar = false;
}
public TranslatedLogMessage(String prefix, String translationKey, String suffix, boolean actionBar) {
this.prefix = prefix;
this.translationKey = translationKey;
this.suffix = suffix;
this.actionBar = actionBar;
}
public static void encode(TranslatedLogMessage message, FriendlyByteBuf buf) {
buf.writeUtf(message.prefix);
buf.writeUtf(message.translationKey);
buf.writeUtf(message.suffix);
buf.writeBoolean(message.actionBar);
}
public static TranslatedLogMessage decode(FriendlyByteBuf buf) {
return new TranslatedLogMessage(buf.readUtf(), buf.readUtf(), buf.readUtf(), buf.readBoolean());
}
public String getPrefix() {
return prefix;
}
public String getTranslationKey() {
return translationKey;
}
public String getSuffix() {
return suffix;
}
public boolean isActionBar() {
return actionBar;
}
public static class Handler {
public static void handle(TranslatedLogMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
EffortlessBuilding.logTranslate(player, message.prefix, message.translationKey, message.suffix, message.actionBar);
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,393 +1,354 @@
package nl.requios.effortlessbuilding.proxy;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.KeyboardListener;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceFluidMode;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.KeyMapping;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.InteractionHand;
import net.minecraft.sounds.SoundSource;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.settings.KeyConflictContext;
import net.minecraftforge.client.settings.KeyModifier;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fmlclient.registry.ClientRegistry;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagScreen;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagScreen;
import nl.requios.effortlessbuilding.gui.RandomizerBagScreen;
import nl.requios.effortlessbuilding.gui.buildmode.PlayerSettingsGui;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.*;
import nl.requios.effortlessbuilding.render.RenderHandler;
import nl.requios.effortlessbuilding.render.ShaderHandler;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import java.util.HashMap;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.function.Supplier;
@Mod.EventBusSubscriber(value = {Dist.CLIENT})
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ClientProxy implements IProxy {
public static KeyBinding[] keyBindings;
public static RayTraceResult previousLookAt;
public static RayTraceResult currentLookAt;
private static int placeCooldown = 0;
private static int breakCooldown = 0;
private static boolean shadersInitialized = false;
public static KeyMapping[] keyBindings;
public static HitResult previousLookAt;
public static HitResult currentLookAt;
public static int ticksInGame = 0;
private static int placeCooldown = 0;
private static int breakCooldown = 0;
public static int ticksInGame = 0;
@Override
public void setup(FMLCommonSetupEvent event) {
}
private static final HashMap<BuildModes.BuildModeEnum, ResourceLocation> buildModeIcons = new HashMap<>();
private static final HashMap<ModeOptions.ActionEnum, ResourceLocation> modeOptionIcons = new HashMap<>();
@Override
public void clientSetup(FMLClientSetupEvent event) {
// register key bindings
keyBindings = new KeyMapping[6];
@Override
public void setup(FMLCommonSetupEvent event) {}
// instantiate the key bindings
keyBindings[0] = new KeyMapping("key.effortlessbuilding.hud.desc", KeyConflictContext.UNIVERSAL, InputConstants.getKey(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category");
keyBindings[1] = new KeyMapping("key.effortlessbuilding.replace.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_KP_SUBTRACT, 0), "key.effortlessbuilding.category");
keyBindings[2] = new KeyMapping("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category");
keyBindings[3] = new KeyMapping("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category");
keyBindings[4] = new KeyMapping("key.effortlessbuilding.redo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Y, 0), "key.effortlessbuilding.category");
keyBindings[5] = new KeyMapping("key.effortlessbuilding.altplacement.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_CONTROL, 0), "key.effortlessbuilding.category");
@Override
public void clientSetup(FMLClientSetupEvent event) {
//Crashes in 1.13, do it elsewhere
// ShaderHandler.init();
// register all the key bindings
for (KeyMapping keyBinding : keyBindings) {
ClientRegistry.registerKeyBinding(keyBinding);
}
// register key bindings
keyBindings = new KeyBinding[7];
MenuScreens.register(EffortlessBuilding.RANDOMIZER_BAG_CONTAINER.get(), RandomizerBagScreen::new);
MenuScreens.register(EffortlessBuilding.GOLDEN_RANDOMIZER_BAG_CONTAINER.get(), GoldenRandomizerBagScreen::new);
MenuScreens.register(EffortlessBuilding.DIAMOND_RANDOMIZER_BAG_CONTAINER.get(), DiamondRandomizerBagScreen::new);
}
// instantiate the key bindings
keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", KeyConflictContext.UNIVERSAL, InputMappings.getInputByCode(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_KP_SUBTRACT, 0), "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_F4, 0), "key.effortlessbuilding.category");
keyBindings[3] = new KeyBinding("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category") {
@Override
public boolean func_197983_b(KeyBinding other) {
//Does not conflict with Chisels and Bits radial menu
if (other.getKey().getKeyCode() == getKey().getKeyCode() && other.getKeyDescription().equals("mod.chiselsandbits.other.mode")) return false;
return super.func_197983_b(other);
}
};
keyBindings[4] = new KeyBinding("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputMappings.getInputByCode(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category");
keyBindings[5] = new KeyBinding("key.effortlessbuilding.redo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputMappings.getInputByCode(GLFW.GLFW_KEY_Y, 0), "key.effortlessbuilding.category");
keyBindings[6] = new KeyBinding("key.effortlessbuilding.altplacement.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_LEFT_CONTROL, 0), "key.effortlessbuilding.category");
//keyBindings[7] = new KeyBinding("Reload shaders", KeyConflictContext.UNIVERSAL, InputMappings.getInputByCode(GLFW.GLFW_KEY_TAB, 0), "key.effortlessbuilding.category");
@SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) {
// register all the key bindings
for (int i = 0; i < keyBindings.length; ++i) {
ClientRegistry.registerKeyBinding(keyBindings[i]);
}
if (event.phase == TickEvent.Phase.START) {
onMouseInput();
}
//Update previousLookAt
HitResult objectMouseOver = Minecraft.getInstance().hitResult;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return;
public EntityPlayer getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx){
return (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT ? Minecraft.getInstance().player : ctx.get().getSender());
}
if (currentLookAt == null) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
return;
}
@SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getEntity() == Minecraft.getInstance().player) {
event.getWorld().addEventListener(new RenderHandler());
}
}
if (objectMouseOver.getType() == HitResult.Type.BLOCK) {
if (currentLookAt.getType() != HitResult.Type.BLOCK) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (((BlockHitResult) currentLookAt).getBlockPos() != ((BlockHitResult) objectMouseOver).getBlockPos()) {
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
}
}
} else if (event.phase == TickEvent.Phase.END) {
Screen gui = Minecraft.getInstance().screen;
if (gui == null || !gui.isPauseScreen()) {
ticksInGame++;
}
}
@SubscribeEvent
public static void onTextureStitch(final TextureStitchEvent.Pre event) {
//register icon textures
final TextureMap map = event.getMap();
}
for ( final BuildModes.BuildModeEnum mode : BuildModes.BuildModeEnum.values() )
{
final ResourceLocation sprite = new ResourceLocation(EffortlessBuilding.MODID, "icons/" + mode.name().toLowerCase());
map.registerSprite(Minecraft.getInstance().getResourceManager(), sprite);
buildModeIcons.put(mode, sprite);
}
private static void onMouseInput() {
Minecraft mc = Minecraft.getInstance();
LocalPlayer player = mc.player;
if (player == null) return;
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
for ( final ModeOptions.ActionEnum action : ModeOptions.ActionEnum.values() )
{
final ResourceLocation sprite = new ResourceLocation(EffortlessBuilding.MODID, "icons/" + action.name().toLowerCase());
map.registerSprite(Minecraft.getInstance().getResourceManager(), sprite);
modeOptionIcons.put(action, sprite);
}
}
if (Minecraft.getInstance().screen != null ||
buildMode == BuildModes.BuildModeEnum.NORMAL ||
RadialMenu.instance.isVisible()) {
return;
}
public static TextureAtlasSprite getBuildModeIcon(BuildModes.BuildModeEnum mode) {
return Minecraft.getInstance().getTextureMap().getSprite(buildModeIcons.get(mode));
}
if (mc.options.keyUse.isDown()) {
public static TextureAtlasSprite getModeOptionIcon(ModeOptions.ActionEnum action) {
return Minecraft.getInstance().getTextureMap().getSprite(modeOptionIcons.get(action));
}
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
@SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) {
if (placeCooldown <= 0) {
placeCooldown = 4;
if (event.phase == TickEvent.Phase.START) {
onMouseInput();
ItemStack currentItemStack = player.getItemInHand(InteractionHand.MAIN_HAND);
if (currentItemStack.getItem() instanceof BlockItem ||
(CompatHelper.isItemBlockProxy(currentItemStack) && !player.isShiftKeyDown())) {
//Update previousLookAt
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return;
ItemStack itemStack = CompatHelper.getItemBlockFromStack(currentItemStack);
if (currentLookAt == null) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
return;
}
//find position in distance
HitResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
if (objectMouseOver.type == RayTraceResult.Type.BLOCK) {
if (currentLookAt.type != RayTraceResult.Type.BLOCK) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()) {
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
}
}
BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage(blockLookingAt, true));
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage(blockLookingAt, true));
} else if (event.phase == TickEvent.Phase.END){
GuiScreen gui = Minecraft.getInstance().currentScreen;
if(gui == null || !gui.doesGuiPauseGame()) {
ticksInGame++;
}
//play sound if further than normal
if ((blockLookingAt.getLocation().subtract(player.getEyePosition(1f))).lengthSqr() > 25f &&
itemStack.getItem() instanceof BlockItem) {
//Init shaders in the first tick. Doing it anywhere before this seems to crash the game.
if (!shadersInitialized) {
ShaderHandler.init();
shadersInitialized = true;
}
}
BlockState state = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
BlockPos blockPos = blockLookingAt.getBlockPos();
SoundType soundType = state.getBlock().getSoundType(state, player.level, blockPos, player);
player.level.playSound(player, player.blockPosition(), soundType.getPlaceSound(), SoundSource.BLOCKS,
0.4f, soundType.getPitch());
player.swing(InteractionHand.MAIN_HAND);
}
} else {
BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage());
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage());
}
}
} else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
placeCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0;
}
} else {
placeCooldown = 0;
}
}
if (mc.options.keyAttack.isDown()) {
private static void onMouseInput() {
Minecraft mc = Minecraft.getInstance();
EntityPlayerSP player = mc.player;
if (player == null) return;
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
//Break block in distance in creative (or survival if enabled in config)
if (breakCooldown <= 0) {
breakCooldown = 4;
if (Minecraft.getInstance().currentScreen != null ||
buildMode == BuildModes.BuildModeEnum.NORMAL ||
RadialMenu.instance.isVisible()) {
return;
}
//Early out if cant break far, coming from own mouse event (not block broken event)
//To make breaking blocks in survival possible like array
//TODO this causes not being able to cancel placement in survival
// moving it to after buildmodes fixes that, but introduces this bug
if (!ReachHelper.canBreakFar(player)) return;
if (mc.gameSettings.keyBindUseItem.isKeyDown()) {
HitResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage(blockLookingAt));
PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage(blockLookingAt));
if (placeCooldown <= 0) {
placeCooldown = 4;
//play sound if further than normal
if ((blockLookingAt.getLocation().subtract(player.getEyePosition(1f))).lengthSqr() > 25f) {
ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (currentItemStack.getItem() instanceof ItemBlock ||
(CompatHelper.isItemBlockProxy(currentItemStack) && !player.isSneaking())) {
BlockPos blockPos = blockLookingAt.getBlockPos();
BlockState state = player.level.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.level, blockPos, player);
player.level.playSound(player, player.blockPosition(), soundtype.getBreakSound(), SoundSource.BLOCKS,
0.4f, soundtype.getPitch());
player.swing(InteractionHand.MAIN_HAND);
}
} else {
BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage());
PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage());
}
} else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
breakCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0;
}
ItemStack itemStack = CompatHelper.getItemBlockFromStack(currentItemStack);
//EffortlessBuilding.packetHandler.sendToServer(new CancelModeMessage());
//find position in distance
RayTraceResult lookingAt = getLookingAt(player);
BuildModes.onBlockPlacedMessage(player, lookingAt == null ? new BlockPlacedMessage() : new BlockPlacedMessage(lookingAt, true));
PacketHandler.INSTANCE.sendToServer(lookingAt == null ? new BlockPlacedMessage() : new BlockPlacedMessage(lookingAt, true));
} else {
breakCooldown = 0;
}
}
//play sound if further than normal
if (lookingAt != null && lookingAt.type == RayTraceResult.Type.BLOCK &&
(lookingAt.hitVec.subtract(player.getEyePosition(1f))).lengthSquared() > 25f &&
itemStack.getItem() instanceof ItemBlock) {
@SubscribeEvent(receiveCanceled = true)
public static void onKeyPress(InputEvent.KeyInputEvent event) {
LocalPlayer player = Minecraft.getInstance().player;
if (player == null)
return;
IBlockState state = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
BlockPos blockPos = lookingAt.getBlockPos();
SoundType soundType = state.getBlock().getSoundType(state, player.world, blockPos, player);
player.world.playSound(player, player.getPosition(), soundType.getPlaceSound(), SoundCategory.BLOCKS,
0.4f, soundType.getPitch() * 1f);
player.swingArm(EnumHand.MAIN_HAND);
}
}
}
else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
placeCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0;
}
} else {
placeCooldown = 0;
}
//Remember to send packet to server if necessary
//Show Modifier Settings GUI
if (keyBindings[0].consumeClick()) {
openModifierSettings();
}
if (mc.gameSettings.keyBindAttack.isKeyDown()) {
//QuickReplace toggle
if (keyBindings[1].consumeClick()) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + ChatFormatting.GOLD + "Quick Replace " + ChatFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"));
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
}
//Break block in distance in creative (or survival if enabled in config)
if (breakCooldown <= 0) {
breakCooldown = 4;
//Radial menu
if (keyBindings[2].isDown()) {
if (ReachHelper.getMaxReach(player) > 0) {
if (!RadialMenu.instance.isVisible()) {
Minecraft.getInstance().setScreen(RadialMenu.instance);
}
} else {
EffortlessBuilding.log(player, "Build modes are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
}
}
//Early out if cant break far, coming from own mouse event (not block broken event)
//To make breaking blocks in survival possible like array
//TODO this causes not being able to cancel placement in survival
// moving it to after buildmodes fixes that, but introduces this bug
if (!ReachHelper.canBreakFar(player)) return;
//Undo (Ctrl+Z)
if (keyBindings[3].consumeClick()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.UNDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
RayTraceResult lookingAt = getLookingAt(player);
BuildModes.onBlockBrokenMessage(player, lookingAt == null ? new BlockBrokenMessage() : new BlockBrokenMessage(lookingAt));
PacketHandler.INSTANCE.sendToServer(lookingAt == null ? new BlockBrokenMessage() : new BlockBrokenMessage(lookingAt));
//Redo (Ctrl+Y)
if (keyBindings[4].consumeClick()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.REDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
//play sound if further than normal
if (lookingAt != null && lookingAt.type == RayTraceResult.Type.BLOCK &&
(lookingAt.hitVec.subtract(player.getEyePosition(1f))).lengthSquared() > 25f) {
//Change placement mode
if (keyBindings[5].consumeClick()) {
//Toggle between first two actions of the first option of the current build mode
BuildModes.BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (currentBuildMode.options.length > 0) {
ModeOptions.OptionEnum option = currentBuildMode.options[0];
if (option.actions.length >= 2) {
if (ModeOptions.getOptionSetting(option) == option.actions[0]) {
ModeOptions.performAction(player, option.actions[1]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[1]));
} else {
ModeOptions.performAction(player, option.actions[0]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[0]));
}
}
}
}
BlockPos blockPos = lookingAt.getBlockPos();
IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
player.world.playSound(player, player.getPosition(), soundtype.getBreakSound(), SoundCategory.BLOCKS,
0.4f, soundtype.getPitch() * 1f);
player.swingArm(EnumHand.MAIN_HAND);
}
}
else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
breakCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0;
}
}
//EffortlessBuilding.packetHandler.sendToServer(new CancelModeMessage());
public static void openModifierSettings() {
Minecraft mc = Minecraft.getInstance();
LocalPlayer player = mc.player;
if (player == null) return;
} else {
breakCooldown = 0;
}
}
//Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Build modifiers are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else {
mc.setScreen(new ModifierSettingsGui());
}
}
@SubscribeEvent(receiveCanceled = true)
public static void onKeyPress(InputEvent.KeyInputEvent event) {
EntityPlayerSP player = Minecraft.getInstance().player;
public static void openPlayerSettings() {
Minecraft mc = Minecraft.getInstance();
mc.setScreen(new PlayerSettingsGui());
}
//Remember to send packet to server if necessary
//Show Modifier Settings GUI
if (keyBindings[0].isPressed()) {
openModifierSettings();
}
@SubscribeEvent
public static void onGuiOpen(GuiOpenEvent event) {
Player player = Minecraft.getInstance().player;
if (player != null) {
BuildModes.initializeMode(player);
}
}
//QuickReplace toggle
if (keyBindings[1].isPressed()) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"));
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
}
public static boolean isKeybindDown(int keybindIndex) {
return InputConstants.isKeyDown(
Minecraft.getInstance().getWindow().getWindow(),
ClientProxy.keyBindings[2].getKey().getValue());
}
//Creative/survival mode toggle
if (keyBindings[2].isPressed()) {
if (player.isCreative()) {
player.sendChatMessage("/gamemode survival");
} else {
player.sendChatMessage("/gamemode creative");
}
}
public static HitResult getLookingAt(Player player) {
Level world = player.level;
//Undo (Ctrl+Z)
if (keyBindings[4].isPressed()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.UNDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
//base distance off of player ability (config)
float raytraceRange = ReachHelper.getPlacementReach(player);
//Redo (Ctrl+Y)
if (keyBindings[5].isPressed()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.REDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
Vec3 look = player.getLookAngle();
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Vec3 end = new Vec3(player.getX() + look.x * raytraceRange, player.getY() + player.getEyeHeight() + look.y * raytraceRange, player.getZ() + look.z * raytraceRange);
// return player.rayTrace(raytraceRange, 1f, RayTraceFluidMode.NEVER);
//TODO 1.14 check if correct
return world.clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player));
}
//Change placement mode
if (keyBindings[6].isPressed()) {
//Toggle between first two actions of the first option of the current build mode
BuildModes.BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (currentBuildMode.options.length > 0) {
ModeOptions.OptionEnum option = currentBuildMode.options[0];
if (option.actions.length >= 2) {
if (ModeOptions.getOptionSetting(option) == option.actions[0]) {
ModeOptions.performAction(player, option.actions[1]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[1]));
} else {
ModeOptions.performAction(player, option.actions[0]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[0]));
}
}
}
}
public Player getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx) {
return (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT ? Minecraft.getInstance().player : ctx.get().getSender());
}
//For shader development
if (keyBindings.length >= 8 && keyBindings[7].isPressed()) {
ShaderHandler.init();
EffortlessBuilding.log(player, "Reloaded shaders");
}
}
public static void openModifierSettings() {
Minecraft mc = Minecraft.getInstance();
EntityPlayerSP player = mc.player;
RadialMenu.instance.setVisibility(0f);
//Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Build modifiers are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else {
if (mc.currentScreen == null) {
mc.displayGuiScreen(new ModifierSettingsGui());
} else {
player.closeScreen();
}
}
}
@SubscribeEvent
public static void onGuiOpen(GuiOpenEvent event) {
EntityPlayer player = Minecraft.getInstance().player;
if (player != null) {
BuildModes.initializeMode(player);
}
}
@Nullable
public static RayTraceResult getLookingAt(EntityPlayer player) {
// World world = player.world;
//base distance off of player ability (config)
float raytraceRange = ReachHelper.getPlacementReach(player);
// Vec3d look = player.getLookVec();
// Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
// Vec3d end = new Vec3d(player.posX + look.x * raytraceRange, player.posY + player.getEyeHeight() + look.y * raytraceRange, player.posZ + look.z * raytraceRange);
return player.rayTrace(raytraceRange, 1f, RayTraceFluidMode.NEVER);
// return world.rayTraceBlocks(start, end, false, false, false);
}
public static void logTranslate(String key) {
EffortlessBuilding.log(Minecraft.getInstance().player, I18n.format(key), true);
}
@Override
public void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
EffortlessBuilding.log(Minecraft.getInstance().player, prefix + I18n.get(translationKey) + suffix, actionBar);
}
}

View File

@@ -1,16 +1,18 @@
package nl.requios.effortlessbuilding.proxy;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import java.util.function.Supplier;
public interface IProxy {
void setup(final FMLCommonSetupEvent event);
void setup(final FMLCommonSetupEvent event);
void clientSetup(final FMLClientSetupEvent event);
void clientSetup(final FMLClientSetupEvent event);
EntityPlayer getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx);
Player getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx);
void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar);
}

View File

@@ -1,23 +1,33 @@
package nl.requios.effortlessbuilding.proxy;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.TranslatedLogMessage;
import java.util.function.Supplier;
public class ServerProxy implements IProxy {
//Only physical server! Singleplayer server is seen as clientproxy
@Override
public void setup(FMLCommonSetupEvent event) {
//Only physical server! Singleplayer server is seen as clientproxy
@Override
public void setup(FMLCommonSetupEvent event) {
}
}
@Override
public void clientSetup(FMLClientSetupEvent event) {}
@Override
public void clientSetup(FMLClientSetupEvent event) {
}
public EntityPlayer getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx){
return ctx.get().getSender();
}
public Player getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx) {
return ctx.get().getSender();
}
@Override
public void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new TranslatedLogMessage(prefix, translationKey, suffix, actionBar));
}
}

View File

@@ -1,22 +1,23 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundSource;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.BuildConfig;
@@ -31,409 +32,352 @@ import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.Modif
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
@OnlyIn(Dist.CLIENT)
public class BlockPreviewRenderer {
private static List<BlockPos> previousCoordinates;
private static List<IBlockState> previousBlockStates;
private static List<ItemStack> previousItemStacks;
private static BlockPos previousFirstPos;
private static BlockPos previousSecondPos;
private static int soundTime = 0;
static class PlacedData {
float time;
List<BlockPos> coordinates;
List<IBlockState> blockStates;
List<ItemStack> itemStacks;
BlockPos firstPos;
BlockPos secondPos;
boolean breaking;
public PlacedData(float time, List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
this.time = time;
this.coordinates = coordinates;
this.blockStates = blockStates;
this.itemStacks = itemStacks;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.breaking = breaking;
}
}
private static List<PlacedData> placedDataList = new ArrayList<>();
private static final int primaryTextureUnit = 0;
private static final int secondaryTextureUnit = 2;
public static void render(EntityPlayer player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
//Render placed blocks with dissolve effect
//Use fancy shader if config allows, otherwise no dissolve
if (BuildConfig.visuals.useShaders.get()) {
RenderHandler.beginBlockPreviews();
for (int i = 0; i < placedDataList.size(); i++) {
PlacedData placed = placedDataList.get(i);
if (placed.coordinates != null && !placed.coordinates.isEmpty()) {
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) totalTime;
renderBlockPreviews(placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
}
}
RenderHandler.endBlockPreviews();
}
//Expire
placedDataList.removeIf(placed -> {
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
return placed.time + totalTime < ClientProxy.ticksInGame;
});
//Render block previews
RayTraceResult lookingAt = ClientProxy.getLookingAt(player);
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.NORMAL) lookingAt = Minecraft.getInstance().objectMouseOver;
ItemStack mainhand = player.getHeldItemMainhand();
boolean toolInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
BlockPos startPos = null;
EnumFacing sideHit = null;
Vec3d hitVec = null;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (lookingAt != null && lookingAt.type == RayTraceResult.Type.BLOCK) {
startPos = lookingAt.getBlockPos();
//Check if tool (or none) in hand
//TODO 1.13 replaceable
boolean replaceable = player.world.getBlockState(startPos).getBlock().getMaterial(player.world.getBlockState(startPos)).isReplaceable();
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, lookingAt.sideHit);
if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable && !becomesDoubleSlab) {
startPos = startPos.offset(lookingAt.sideHit);
}
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down();
}
sideHit = lookingAt.sideHit;
hitVec = lookingAt.hitVec;
}
//Dont render if in normal mode and modifiers are disabled
//Unless alwaysShowBlockPreview is true in config
if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) {
//Keep blockstate the same for every block in the buildmode
//So dont rotate blocks when in the middle of placing wall etc.
if (BuildModes.isActive(player)) {
IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
}
if (sideHit != null) {
//Should be red?
boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
//get coordinates
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
//Remember first and last point for the shader
BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN;
if (!startCoordinates.isEmpty()) {
firstPos = startCoordinates.get(0);
secondPos = startCoordinates.get(startCoordinates.size() - 1);
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (startCoordinates.size() > limit) {
startCoordinates = startCoordinates.subList(0, limit);
}
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
sortOnDistanceToPlayer(newCoordinates, player);
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z)));
//Get blockstates
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = new ArrayList<>();
if (breaking) {
//Find blockstate of world
for (BlockPos coordinate : newCoordinates) {
blockStates.add(player.world.getBlockState(coordinate));
}
} else {
blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
}
//Check if they are different from previous
//TODO fix triggering when moving player
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates;
//remember the rest for placed blocks
previousBlockStates = blockStates;
previousItemStacks = itemStacks;
previousFirstPos = firstPos;
previousSecondPos = secondPos;
//if so, renew randomness of randomizer bag
ItemRandomizerBag.renewRandomness();
//and play sound (max once every tick)
if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) {
soundTime = ClientProxy.ticksInGame;
if (blockStates.get(0) != null) {
SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world,
newCoordinates.get(0), player);
player.world.playSound(player, player.getPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(),
SoundCategory.BLOCKS, 0.3f, 0.8f);
}
}
}
//Render block previews
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
int blockCount;
//Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderTreshold.get()) {
RenderHandler.beginBlockPreviews();
blockCount = renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
RenderHandler.endBlockPreviews();
} else {
RenderHandler.beginLines();
Vec3d color = new Vec3d(1f, 1f, 1f);
if (breaking) color = new Vec3d(1f, 0f, 0f);
for (int i = newCoordinates.size() - 1; i >= 0; i--) {
VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.world, newCoordinates.get(i));
RenderHandler.renderBlockOutline(newCoordinates.get(i), collisionShape, color);
}
RenderHandler.endLines();
blockCount = newCoordinates.size();
}
//Display block count and dimensions in actionbar
if (BuildModes.isActive(player)) {
//Find min and max values (not simply firstPos and secondPos because that doesn't work with circles)
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
for (BlockPos pos : startCoordinates) {
if (pos.getX() < minX) minX = pos.getX();
if (pos.getX() > maxX) maxX = pos.getX();
if (pos.getY() < minY) minY = pos.getY();
if (pos.getY() > maxY) maxY = pos.getY();
if (pos.getZ() < minZ) minZ = pos.getZ();
if (pos.getZ() > maxZ) maxZ = pos.getZ();
}
BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
String dimensions = "(";
if (dim.getX() > 1) dimensions += dim.getX() + "x";
if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
if (dim.getY() > 1) dimensions += dim.getY() + "x";
dimensions = dimensions.substring(0, dimensions.length() - 1);
if (dimensions.length() > 1) dimensions += ")";
EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
}
}
}
RenderHandler.beginLines();
//Draw outlines if tool in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver;
RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
if (toolInHand && breakingRaytrace != null && breakingRaytrace.type == RayTraceResult.Type.BLOCK) {
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, breakingRaytrace.getBlockPos());
//Only render first outline if further than normal reach
boolean excludeFirst = objectMouseOver != null && objectMouseOver.type == RayTraceResult.Type.BLOCK;
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i);
IBlockState blockState = player.world.getBlockState(coordinate);
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) {
if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) {
VoxelShape collisionShape = blockState.getCollisionShape(player.world, coordinate);
RenderHandler.renderBlockOutline(coordinate, collisionShape, new Vec3d(0f, 0f, 0f));
}
}
}
}
RenderHandler.endLines();
}
}
//Whether to draw any block previews or outlines
public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.NORMAL ||
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
BuildConfig.visuals.alwaysShowBlockPreview.get();
}
protected static int renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace, boolean red) {
EntityPlayer player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
int blocksValid = 0;
if (coordinates.isEmpty()) return blocksValid;
for (int i = coordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
//Check if can place
//If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks breaking shader)
SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), EnumFacing.UP)) {
ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve,
new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos),
blockPos == secondPos, red));
RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState);
blocksValid++;
}
}
return blocksValid;
}
public static void onBlocksPlaced() {
onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<IBlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
EntityPlayerSP player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold.get()) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, false));
}
}
}
public static void onBlocksBroken() {
onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<IBlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
EntityPlayerSP player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold.get()) {
sortOnDistanceToPlayer(coordinates, player);
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, true));
}
}
}
private static Consumer<Integer> generateShaderCallback(final float dissolve, final Vec3d blockpos,
final Vec3d firstpos, final Vec3d secondpos,
final boolean highlight, final boolean red) {
Minecraft mc = Minecraft.getInstance();
return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve");
int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight");
int redUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "red");
int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos");
int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos");
int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos");
int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image");
int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask");
GlStateManager.enableTexture2D();
GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
//mask
ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit);
OpenGlHelper.glActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getTextureManager().getTexture(ShaderHandler.shaderMaskTextureLocation).getGlTextureId());
//image
ARBShaderObjects.glUniform1iARB(imageUniform, primaryTextureUnit);
OpenGlHelper.glActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + primaryTextureUnit);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getTextureManager().getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).getGlTextureId());
//blockpos
ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z);
ARBShaderObjects.glUniform3fARB(firstposUniform, (float) firstpos.x, (float) firstpos.y, (float) firstpos.z);
ARBShaderObjects.glUniform3fARB(secondposUniform, (float) secondpos.x, (float) secondpos.y, (float) secondpos.z);
//dissolve
ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve);
//highlight
ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0);
//red
ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0);
};
}
private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, EntityPlayer player) {
Collections.sort(coordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getEyePosition(1f)).lengthSquared();
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getEyePosition(1f)).lengthSquared();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
}
private static final List<PlacedData> placedDataList = new ArrayList<>();
private static List<BlockPos> previousCoordinates;
private static List<BlockState> previousBlockStates;
private static List<ItemStack> previousItemStacks;
private static BlockPos previousFirstPos;
private static BlockPos previousSecondPos;
private static int soundTime = 0;
public static void render(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Player player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
//Render placed blocks with dissolve effect
//Use fancy shader if config allows, otherwise no dissolve
if (BuildConfig.visuals.useShaders.get()) {
for (int i = 0; i < placedDataList.size(); i++) {
PlacedData placed = placedDataList.get(i);
if (placed.coordinates != null && !placed.coordinates.isEmpty()) {
double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) totalTime;
renderBlockPreviews(matrixStack, renderTypeBuffer, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
}
}
}
//Expire
placedDataList.removeIf(placed -> {
double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
return placed.time + totalTime < ClientProxy.ticksInGame;
});
//Render block previews
HitResult lookingAt = ClientProxy.getLookingAt(player);
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.NORMAL)
lookingAt = Minecraft.getInstance().hitResult;
ItemStack mainhand = player.getMainHandItem();
boolean toolInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
BlockPos startPos = null;
Direction sideHit = null;
Vec3 hitVec = null;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
startPos = blockLookingAt.getBlockPos();
//Check if tool (or none) in hand
//TODO 1.13 replaceable
boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable();
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, blockLookingAt.getDirection());
if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable && !becomesDoubleSlab) {
startPos = startPos.relative(blockLookingAt.getDirection());
}
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.below();
}
sideHit = blockLookingAt.getDirection();
hitVec = blockLookingAt.getLocation();
}
//Dont render if in normal mode and modifiers are disabled
//Unless alwaysShowBlockPreview is true in config
if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) {
//Keep blockstate the same for every block in the buildmode
//So dont rotate blocks when in the middle of placing wall etc.
if (BuildModes.isActive(player)) {
IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
}
if (sideHit != null) {
//Should be red?
boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
//get coordinates
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
//Remember first and last point for the shader
BlockPos firstPos = BlockPos.ZERO, secondPos = BlockPos.ZERO;
if (!startCoordinates.isEmpty()) {
firstPos = startCoordinates.get(0);
secondPos = startCoordinates.get(startCoordinates.size() - 1);
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (startCoordinates.size() > limit) {
startCoordinates = startCoordinates.subList(0, limit);
}
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
sortOnDistanceToPlayer(newCoordinates, player);
hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z)));
//Get blockstates
List<ItemStack> itemStacks = new ArrayList<>();
List<BlockState> blockStates = new ArrayList<>();
if (breaking) {
//Find blockstate of world
for (BlockPos coordinate : newCoordinates) {
blockStates.add(player.level.getBlockState(coordinate));
}
} else {
blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
}
//Check if they are different from previous
//TODO fix triggering when moving player
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates;
//remember the rest for placed blocks
previousBlockStates = blockStates;
previousItemStacks = itemStacks;
previousFirstPos = firstPos;
previousSecondPos = secondPos;
//if so, renew randomness of randomizer bag
AbstractRandomizerBagItem.renewRandomness();
//and play sound (max once every tick)
if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) {
soundTime = ClientProxy.ticksInGame;
if (blockStates.get(0) != null) {
SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.level,
newCoordinates.get(0), player);
player.level.playSound(player, player.blockPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(),
SoundSource.BLOCKS, 0.3f, 0.8f);
}
}
}
//Render block previews
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
int blockCount;
//Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
blockCount = renderBlockPreviews(matrixStack, renderTypeBuffer, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
} else {
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
Vec3 color = new Vec3(1f, 1f, 1f);
if (breaking) color = new Vec3(1f, 0f, 0f);
for (int i = newCoordinates.size() - 1; i >= 0; i--) {
VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.level, newCoordinates.get(i));
RenderHandler.renderBlockOutline(matrixStack, buffer, newCoordinates.get(i), collisionShape, color);
}
RenderHandler.endLines(renderTypeBuffer);
blockCount = newCoordinates.size();
}
//Display block count and dimensions in actionbar
if (BuildModes.isActive(player)) {
//Find min and max values (not simply firstPos and secondPos because that doesn't work with circles)
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
for (BlockPos pos : startCoordinates) {
if (pos.getX() < minX) minX = pos.getX();
if (pos.getX() > maxX) maxX = pos.getX();
if (pos.getY() < minY) minY = pos.getY();
if (pos.getY() > maxY) maxY = pos.getY();
if (pos.getZ() < minZ) minZ = pos.getZ();
if (pos.getZ() > maxZ) maxZ = pos.getZ();
}
BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
String dimensions = "(";
if (dim.getX() > 1) dimensions += dim.getX() + "x";
if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
if (dim.getY() > 1) dimensions += dim.getY() + "x";
dimensions = dimensions.substring(0, dimensions.length() - 1);
if (dimensions.length() > 1) dimensions += ")";
EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
}
}
}
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
//Draw outlines if tool in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar
HitResult objectMouseOver = Minecraft.getInstance().hitResult;
HitResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
if (toolInHand && breakingRaytrace != null && breakingRaytrace.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockBreakingRaytrace = (BlockHitResult) breakingRaytrace;
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getBlockPos());
//Only render first outline if further than normal reach
boolean excludeFirst = objectMouseOver != null && objectMouseOver.getType() == HitResult.Type.BLOCK;
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i);
BlockState blockState = player.level.getBlockState(coordinate);
if (!blockState.isAir()) {
if (SurvivalHelper.canBreak(player.level, player, coordinate) || i == 0) {
VoxelShape collisionShape = blockState.getCollisionShape(player.level, coordinate);
RenderHandler.renderBlockOutline(matrixStack, buffer, coordinate, collisionShape, new Vec3(0f, 0f, 0f));
}
}
}
}
RenderHandler.endLines(renderTypeBuffer);
}
}
//Whether to draw any block previews or outlines
public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.NORMAL ||
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
BuildConfig.visuals.alwaysShowBlockPreview.get();
}
protected static int renderBlockPreviews(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, List<BlockPos> coordinates, List<BlockState> blockStates,
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace, boolean red) {
Player player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
int blocksValid = 0;
if (coordinates.isEmpty()) return blocksValid;
for (int i = coordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = coordinates.get(i);
BlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
//Check if can place
//If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks the breaking shader)
SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP)) {
RenderHandler.renderBlockPreview(matrixStack, renderTypeBuffer, dispatcher, blockPos, blockState, dissolve, firstPos, secondPos, red);
blocksValid++;
}
}
return blocksValid;
}
public static void onBlocksPlaced() {
onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
LocalPlayer player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, false));
}
}
}
public static void onBlocksBroken() {
onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
LocalPlayer player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
sortOnDistanceToPlayer(coordinates, player);
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, true));
}
}
}
private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, Player player) {
Collections.sort(coordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = Vec3.atLowerCornerOf(lhs).subtract(player.getEyePosition(1f)).lengthSqr();
double rhsDistanceToPlayer = Vec3.atLowerCornerOf(rhs).subtract(player.getEyePosition(1f)).lengthSqr();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
}
static class PlacedData {
float time;
List<BlockPos> coordinates;
List<BlockState> blockStates;
List<ItemStack> itemStacks;
BlockPos firstPos;
BlockPos secondPos;
boolean breaking;
public PlacedData(float time, List<BlockPos> coordinates, List<BlockState> blockStates,
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
this.time = time;
this.coordinates = coordinates;
this.blockStates = blockStates;
this.itemStacks = itemStacks;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.breaking = breaking;
}
}
}

View File

@@ -0,0 +1,138 @@
package nl.requios.effortlessbuilding.render;
import com.mojang.blaze3d.shaders.Uniform;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.texture.TextureAtlas;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import org.lwjgl.opengl.*;
import java.util.OptionalDouble;
import java.util.function.Consumer;
import java.util.function.Function;
public class BuildRenderTypes extends RenderType {
public static ResourceLocation shaderMaskTextureLocation = new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png");
public static final RenderType LINES;
public static final RenderType PLANES;
public static ShaderInstance dissolveShaderInstance;
private static final ShaderStateShard RENDERTYPE_DISSOLVE_SHADER = new ShaderStateShard(() -> dissolveShaderInstance);
//Between 0 and 7, but dont override vanilla textures
//Also update dissolve.fsh SamplerX
private static final int maskTextureIndex = 2;
static {
final LineStateShard LINE = new LineStateShard(OptionalDouble.of(2.0));
final int INITIAL_BUFFER_SIZE = 128;
RenderType.CompositeState renderState;
//LINES
renderState = CompositeState.builder()
.setLineState(LINE)
.setShaderState(RenderStateShard.RENDERTYPE_LINES_SHADER)
.setLayeringState(VIEW_OFFSET_Z_LAYERING)
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
.setTextureState(RenderStateShard.NO_TEXTURE)
.setDepthTestState(RenderStateShard.NO_DEPTH_TEST)
.setLightmapState(RenderStateShard.NO_LIGHTMAP)
.setWriteMaskState(COLOR_DEPTH_WRITE)
.setCullState(RenderStateShard.NO_CULL)
.createCompositeState(false);
LINES = RenderType.create("eb_lines",
DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.LINES, INITIAL_BUFFER_SIZE, false, false, renderState);
//PLANES
renderState = CompositeState.builder()
.setLineState(LINE)
.setShaderState(RenderStateShard.RENDERTYPE_LINES_SHADER)
.setLayeringState(VIEW_OFFSET_Z_LAYERING)
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
.setTextureState(RenderStateShard.NO_TEXTURE)
.setDepthTestState(RenderStateShard.NO_DEPTH_TEST)
.setLightmapState(RenderStateShard.NO_LIGHTMAP)
.setWriteMaskState(COLOR_WRITE)
.setCullState(RenderStateShard.NO_CULL)
.createCompositeState(false);
PLANES = RenderType.create("eb_planes",
DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP, INITIAL_BUFFER_SIZE, false, false, renderState);
}
// Dummy constructor needed to make java happy
public BuildRenderTypes(String p_173178_, VertexFormat p_173179_, VertexFormat.Mode p_173180_, int p_173181_, boolean p_173182_, boolean p_173183_, Runnable p_173184_, Runnable p_173185_) {
super(p_173178_, p_173179_, p_173180_, p_173181_, p_173182_, p_173183_, p_173184_, p_173185_);
}
public static RenderType getBlockPreviewRenderType(float dissolve, BlockPos blockPos, BlockPos firstPos, BlockPos secondPos, boolean red) {
String stateName = "eb_texturing_" + dissolve + "_" + blockPos + "_" + firstPos + "_" + secondPos + "_" + red;
TexturingStateShard MY_TEXTURING = new TexturingStateShard(stateName, () -> {
setShaderParameters(dissolveShaderInstance, dissolve, Vec3.atLowerCornerOf(blockPos), Vec3.atLowerCornerOf(firstPos), Vec3.atLowerCornerOf(secondPos), blockPos == secondPos, red);
RenderSystem.setShaderColor(1f, 1f, 1f, 0.8f);
}, () -> {});
RenderType.CompositeState renderState = RenderType.CompositeState.builder()
.setShaderState(RENDERTYPE_DISSOLVE_SHADER)
.setTexturingState(MY_TEXTURING)
.setTextureState(RenderStateShard.BLOCK_SHEET_MIPPED)
.setTransparencyState(TRANSLUCENT_TRANSPARENCY)
.setLightmapState(RenderStateShard.NO_LIGHTMAP)
.setCullState(RenderStateShard.CULL)
.setOutputState(RenderStateShard.TRANSLUCENT_TARGET)
.createCompositeState(true);
//Unique name for every combination, otherwise it will reuse the previous one
String name = "eb_block_previews_" + dissolve + "_" + blockPos + "_" + firstPos + "_" + secondPos + "_" + red;
return RenderType.create(name,
DefaultVertexFormat.BLOCK, VertexFormat.Mode.QUADS, 2097152, true, true, renderState);
}
private static void setShaderParameters(ShaderInstance shader, final float dissolve, final Vec3 blockpos,
final Vec3 firstpos, final Vec3 secondpos,
final boolean highlight, final boolean red) {
Uniform percentileUniform = shader.getUniform("dissolve");
Uniform highlightUniform = shader.getUniform("highlight");
Uniform redUniform = shader.getUniform("red");
Uniform blockposUniform = shader.getUniform("blockpos");
Uniform firstposUniform = shader.getUniform("firstpos");
Uniform secondposUniform = shader.getUniform("secondpos");
RenderSystem.setShaderTexture(maskTextureIndex, shaderMaskTextureLocation);
if (percentileUniform != null) percentileUniform.set(dissolve); else EffortlessBuilding.log("percentileUniform is null");
if (highlightUniform != null) highlightUniform.set(highlight ? 1 : 0); else EffortlessBuilding.log("highlightUniform is null");
if (redUniform != null) redUniform.set(red ? 1 : 0); else EffortlessBuilding.log("redUniform is null");
if (blockposUniform != null) blockposUniform.set((float) blockpos.x, (float) blockpos.y, (float) blockpos.z); else EffortlessBuilding.log("blockposUniform is null");
if (firstposUniform != null) firstposUniform.set((float) firstpos.x, (float) firstpos.y, (float) firstpos.z); else EffortlessBuilding.log("firstposUniform is null");
if (secondposUniform != null) secondposUniform.set((float) secondpos.x, (float) secondpos.y, (float) secondpos.z); else EffortlessBuilding.log("secondposUniform is null");
}
private class ShaderInfo {
float dissolve;
Vec3 blockPos;
Vec3 firstPos;
Vec3 secondPos;
boolean red;
public ShaderInfo(float dissolve, Vec3 blockPos, Vec3 firstPos, Vec3 secondPos, boolean red) {
this.dissolve = dissolve;
this.blockPos = blockPos;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.red = red;
}
}
}

View File

@@ -1,176 +1,167 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.Vec3d;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import com.mojang.math.Matrix4f;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import org.lwjgl.opengl.GL11;
import java.awt.*;
@OnlyIn(Dist.CLIENT)
public class ModifierRenderer {
protected static final Color colorX = new Color(255, 72, 52);
protected static final Color colorY = new Color(67, 204, 51);
protected static final Color colorZ = new Color(52, 247, 255);
protected static final Color colorRadial = new Color(52, 247, 255);
protected static final int lineAlpha = 200;
protected static final int planeAlpha = 75;
protected static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
protected static final Color colorX = new Color(255, 72, 52);
protected static final Color colorY = new Color(67, 204, 51);
protected static final Color colorZ = new Color(52, 247, 255);
protected static final Color colorRadial = new Color(52, 247, 255);
protected static final int lineAlpha = 200;
protected static final int planeAlpha = 50;
protected static final Vec3 epsilon = new Vec3(0.001, 0.001, 0.001); //prevents z-fighting
public static void render(ModifierSettingsManager.ModifierSettings modifierSettings) {
RenderHandler.beginLines();
public static void render(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, ModifierSettingsManager.ModifierSettings modifierSettings) {
//Mirror lines and areas
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ)) {
Vec3 pos = m.position.add(epsilon);
int radius = m.radius;
//Mirror lines and areas
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ))
{
Vec3d pos = m.position.add(epsilon);
int radius = m.radius;
if (m.mirrorX) {
Vec3 posA = new Vec3(pos.x, pos.y - radius, pos.z - radius);
Vec3 posB = new Vec3(pos.x, pos.y + radius, pos.z + radius);
if (m.mirrorX)
{
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorX, m.drawLines, m.drawPlanes, true);
}
if (m.mirrorY) {
Vec3 posA = new Vec3(pos.x - radius, pos.y, pos.z - radius);
Vec3 posB = new Vec3(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes, true);
}
if (m.mirrorY)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(matrixStack, renderTypeBuffer, posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ) {
Vec3 posA = new Vec3(pos.x - radius, pos.y - radius, pos.z);
Vec3 posB = new Vec3(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorZ, m.drawLines, m.drawPlanes, true);
}
drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes, true);
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) {
drawMirrorLines(matrixStack, renderTypeBuffer, m);
}
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ)))
{
drawMirrorLines(m);
}
}
//Radial mirror lines and areas
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r != null && r.enabled) {
Vec3 pos = r.position.add(epsilon);
int radius = r.radius;
//Radial mirror lines and areas
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r != null && r.enabled)
{
Vec3d pos = r.position.add(epsilon);
int radius = r.radius;
float angle = 2f * ((float) Math.PI) / r.slices;
Vec3 relStartVec = new Vec3(radius, 0, 0);
if (r.slices % 4 == 2) relStartVec = relStartVec.yRot(angle / 2f);
float angle = 2f * ((float) Math.PI) / r.slices;
Vec3d relStartVec = new Vec3d(radius, 0, 0);
if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f);
for (int i = 0; i < r.slices; i++) {
Vec3 relNewVec = relStartVec.yRot(angle * i);
Vec3 newVec = pos.add(relNewVec);
for (int i = 0; i < r.slices; i++) {
Vec3d relNewVec = relStartVec.rotateYaw(angle * i);
Vec3d newVec = pos.add(relNewVec);
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z);
drawMirrorPlane(posA, posB, colorRadial, r.drawLines, r.drawPlanes, false);
}
}
RenderHandler.endLines();
}
Vec3 posA = new Vec3(pos.x, pos.y - radius, pos.z);
Vec3 posB = new Vec3(newVec.x, pos.y + radius, newVec.z);
drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorRadial, r.drawLines, r.drawPlanes, false);
}
}
}
//----Mirror----
//----Mirror----
protected static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) {
protected static void drawMirrorPlane(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Vec3 posA, Vec3 posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
// GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Matrix4f matrixPos = matrixStack.last().pose();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
if (drawPlanes) {
VertexConsumer buffer = RenderHandler.beginPlanes(renderTypeBuffer);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) posB.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posB.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posB.x, (float) posB.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
//backface (using triangle strip)
buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) posB.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
RenderHandler.endPlanes(renderTypeBuffer);
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
if (drawLines) {
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
if (drawVerticalLines) {
bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
}
Vec3 middle = posA.add(posB).scale(0.5);
buffer.vertex(matrixPos, (float) posA.x, (float) middle.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) posB.x, (float) middle.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
if (drawVerticalLines) {
buffer.vertex(matrixPos, (float) middle.x, (float) posA.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) middle.x, (float) posB.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
}
tessellator.draw();
}
}
RenderHandler.endLines(renderTypeBuffer);
}
}
protected static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
protected static void drawMirrorPlaneY(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Vec3 posA, Vec3 posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
// GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Matrix4f matrixPos = matrixStack.last().pose();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
if (drawPlanes) {
VertexConsumer buffer = RenderHandler.beginPlanes(renderTypeBuffer);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posB.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posB.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
//backface (using triangle strip)
buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
RenderHandler.endPlanes(renderTypeBuffer);
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
if (drawLines) {
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
Vec3 middle = posA.add(posB).scale(0.5);
buffer.vertex(matrixPos, (float) middle.x, (float) middle.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) middle.x, (float) middle.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) posA.x, (float) middle.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) posB.x, (float) middle.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
RenderHandler.endLines(renderTypeBuffer);
}
}
protected static void drawMirrorLines(Mirror.MirrorSettings m) {
protected static void drawMirrorLines(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Mirror.MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
// GL11.glColor4d(100, 100, 100, 255);
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
Matrix4f matrixPos = matrixStack.last().pose();
GL11.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
Vec3 pos = m.position.add(epsilon);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
buffer.vertex(matrixPos, (float) pos.x - m.radius, (float) pos.y, (float) pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) pos.x + m.radius, (float) pos.y, (float) pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) pos.x, (float) pos.y - m.radius, (float) pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) pos.x, (float) pos.y + m.radius, (float) pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) pos.x, (float) pos.y, (float) pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
buffer.vertex(matrixPos, (float) pos.x, (float) pos.y, (float) pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
RenderHandler.endLines(renderTypeBuffer);
}
}

View File

@@ -1,331 +1,158 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.block.state.IBlockState;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SimpleSound;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.particles.IParticleData;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldEventListener;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.ModeActionMessage;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import javax.annotation.Nullable;
import java.util.List;
/***
* Main render class for Effortless Building
*/
@Mod.EventBusSubscriber(value = Dist.CLIENT)
public class RenderHandler implements IWorldEventListener {
public class RenderHandler {
@SubscribeEvent
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getInstance().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
@SubscribeEvent
public static void onRender(RenderWorldLastEvent event) {
if (event.getPhase() != EventPriority.NORMAL)
return;
begin(event.getPartialTicks());
PoseStack matrixStack = event.getMatrixStack();
BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder();
MultiBufferSource.BufferSource renderTypeBuffer = MultiBufferSource.immediate(bufferBuilder);
//Mirror and radial mirror lines and areas
ModifierRenderer.render(modifierSettings);
Player player = Minecraft.getInstance().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
//Render block previews
BlockPreviewRenderer.render(player, modifierSettings, modeSettings);
Vec3 projectedView = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
end();
}
matrixStack.pushPose();
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
@SubscribeEvent
//Display Radial Menu
public static void onRenderGameOverlay(final RenderGameOverlayEvent.Post event) {
Minecraft mc = Minecraft.getInstance();
EntityPlayerSP player = mc.player;
//Mirror and radial mirror lines and areas
ModifierRenderer.render(matrixStack, renderTypeBuffer, modifierSettings);
//check if chisel and bits tool in hand (and has menu)
// final boolean hasChiselInHand = CompatHelper.chiselsAndBitsProxy.isHoldingChiselTool(EnumHand.MAIN_HAND);
//Render block previews
BlockPreviewRenderer.render(matrixStack, renderTypeBuffer, player, modifierSettings, modeSettings);
final RenderGameOverlayEvent.ElementType type = event.getType();
//TODO 1.13 compatibility
if (type == RenderGameOverlayEvent.ElementType.ALL /*&& !hasChiselInHand*/) {
final boolean wasVisible = RadialMenu.instance.isVisible();
matrixStack.popPose();
}
if (ClientProxy.keyBindings[3].isKeyDown()) {
if (ReachHelper.getMaxReach(player) > 0) {
RadialMenu.instance.actionUsed = false;
RadialMenu.instance.raiseVisibility();
} else if (ClientProxy.keyBindings[3].isPressed()) {
EffortlessBuilding.log(player, "Build modes are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
}
} else {
if (!RadialMenu.instance.actionUsed) {
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
protected static VertexConsumer beginLines(MultiBufferSource.BufferSource renderTypeBuffer) {
return renderTypeBuffer.getBuffer(BuildRenderTypes.LINES);
}
if (RadialMenu.instance.switchTo != null) {
playRadialMenuSound();
modeSettings.setBuildMode(RadialMenu.instance.switchTo);
ModeSettingsManager.setModeSettings(player, modeSettings);
PacketHandler.INSTANCE.sendToServer(new ModeSettingsMessage(modeSettings));
protected static void endLines(MultiBufferSource.BufferSource renderTypeBuffer) {
renderTypeBuffer.endBatch();
}
EffortlessBuilding.log(player, I18n.format(modeSettings.getBuildMode().name), true);
}
protected static VertexConsumer beginPlanes(MultiBufferSource.BufferSource renderTypeBuffer) {
return renderTypeBuffer.getBuffer(BuildRenderTypes.PLANES);
}
//Perform button action
ModeOptions.ActionEnum action = RadialMenu.instance.doAction;
if (action != null) {
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
protected static void endPlanes(MultiBufferSource.BufferSource renderTypeBuffer) {
renderTypeBuffer.endBatch();
}
playRadialMenuSound();
}
protected static void renderBlockPreview(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, BlockRenderDispatcher dispatcher,
BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean red) {
if (blockState == null) return;
RadialMenu.instance.actionUsed = true;
RadialMenu.instance.decreaseVisibility();
}
matrixStack.pushPose();
matrixStack.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ());
// matrixStack.rotate(Vector3f.YP.rotationDegrees(-90f));
matrixStack.translate(-0.01f, -0.01f, -0.01f);
matrixStack.scale(1.02f, 1.02f, 1.02f);
if (RadialMenu.instance.isVisible()) {
//Begin block preview rendering
RenderType blockPreviewRenderType = BuildRenderTypes.getBlockPreviewRenderType(dissolve, blockPos, firstPos, secondPos, red);
VertexConsumer buffer = renderTypeBuffer.getBuffer(blockPreviewRenderType);
int scaledWidth = mc.mainWindow.getScaledWidth();
int scaledHeight = mc.mainWindow.getScaledHeight();
RadialMenu.instance.configure(scaledWidth, scaledHeight);
// MinecraftServer server = Minecraft.getInstance().getIntegratedServer();
// World world = DimensionManager.getWorld(server, DimensionType.OVERWORLD, false, true);
if (!wasVisible) {
mc.mouseHelper.ungrabMouse();
}
try {
BakedModel model = dispatcher.getBlockModel(blockState);
dispatcher.getModelRenderer().renderModel(matrixStack.last(), buffer, blockState, model,
1f, 1f, 1f, 0, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
// blockRendererDispatcher.getBlockModelRenderer().renderModel(world, blockRendererDispatcher.getModelForState(blockState),
// blockState, logicPos, matrixStack, renderTypeBuffer.getBuffer(renderType), true, new Random(), blockState.getPositionRandom(logicPos), i);
} catch (NullPointerException e) {
EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString());
if (mc.mouseHelper.isMouseGrabbed()) {
KeyBinding.unPressAllKeys();
}
//Render outline as backup, escape out of the current renderstack
matrixStack.popPose();
renderTypeBuffer.endBatch();
VertexConsumer lineBuffer = beginLines(renderTypeBuffer);
renderBlockOutline(matrixStack, lineBuffer, blockPos, new Vec3(1f, 1f, 1f));
endLines(renderTypeBuffer);
buffer = renderTypeBuffer.getBuffer(Sheets.translucentCullBlockSheet()); //any type will do, as long as we have something on the stack
matrixStack.pushPose();
}
final int mouseX = ((int) mc.mouseHelper.getMouseX()) * scaledWidth / mc.mainWindow.getFramebufferWidth();
final int mouseY = scaledHeight - ((int) mc.mouseHelper.getMouseY()) * scaledHeight / mc.mainWindow.getFramebufferHeight() - 1;
renderTypeBuffer.endBatch();
matrixStack.popPose();
}
net.minecraftforge.client.ForgeHooksClient.drawScreen(RadialMenu.instance, mouseX, mouseY, event.getPartialTicks());
} else {
if (wasVisible && RadialMenu.instance.doAction != ModeOptions.ActionEnum.OPEN_MODIFIER_SETTINGS) {
mc.mouseHelper.grabMouse();
}
}
}
}
protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, Vec3 color) {
renderBlockOutline(matrixStack, buffer, pos, pos, color);
}
public static void playRadialMenuSound() {
final float volume = 0.1f;
if (volume >= 0.0001f) {
SimpleSound sound = new SimpleSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.MASTER, volume, 1.0f, Minecraft.getInstance().player.getPosition());
Minecraft.getInstance().getSoundHandler().play(sound);
}
}
private static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getInstance().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
GL11.glPushMatrix();
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glDepthMask(false);
}
protected static void beginLines() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glLineWidth(2);
}
protected static void endLines() {
GL11.glPopAttrib();
}
protected static void beginBlockPreviews() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_TEXTURE_2D);
// Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
Minecraft.getInstance().textureManager.bindTexture(ShaderHandler.shaderMaskTextureLocation);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL14.glBlendColor(1F, 1F, 1F, 0.8f);
}
protected static void endBlockPreviews() {
ShaderHandler.releaseShader();
GlStateManager.disableBlend();
GL11.glPopAttrib();
}
private static void end() {
GL11.glDepthMask(true);
GL11.glPopMatrix();
}
protected static void renderBlockPreview(BlockRendererDispatcher dispatcher, BlockPos blockPos, IBlockState blockState) {
if (blockState == null) return;
GlStateManager.pushMatrix();
GlStateManager.translatef(blockPos.getX(), blockPos.getY(), blockPos.getZ());
GlStateManager.rotatef(-90.0F, 0.0F, 1.0F, 0.0F);
GlStateManager.translatef(-0.01f, -0.01f, 0.01f);
GlStateManager.scalef(1.02f, 1.02f, 1.02f);
try {
dispatcher.renderBlockBrightness(blockState, 0.85f);
} catch (NullPointerException e) {
EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString());
//Render outline as backup
GlStateManager.popMatrix();
// ShaderHandler.releaseShader();
GL11.glDisable(GL11.GL_LIGHTING);
renderBlockOutline(blockPos, new Vec3d(1f, 1f, 1f));
GL11.glEnable(GL11.GL_LIGHTING);
GlStateManager.pushMatrix();
}
GlStateManager.popMatrix();
}
protected static void renderBlockOutline(BlockPos pos, Vec3d color) {
renderBlockOutline(pos, pos, color);
}
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
protected static void renderBlockOutline(BlockPos pos1, BlockPos pos2, Vec3d color) {
GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
}
//Renders outline with given bounding box
protected static void renderBlockOutline(BlockPos pos, VoxelShape collisionShape, Vec3d color) {
GL11.glLineWidth(2);
// AxisAlignedBB aabb = boundingBox.offset(pos).grow(0.0020000000949949026);
// VoxelShape voxelShape = collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ());
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos1, BlockPos pos2, Vec3 color) {
AABB aabb = new AABB(pos1, pos2.offset(1, 1, 1)).inflate(0.0020000000949949026);
LevelRenderer.renderLineBox(matrixStack, buffer, aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
// WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
WorldRenderer.drawShape(collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f);
}
}
//IWORLDEVENTLISTENER IMPLEMENTATION
@Override
public void notifyBlockUpdate(IBlockReader worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {
//Renders outline with given bounding box
protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, VoxelShape collisionShape, Vec3 color) {
// WorldRenderer.drawShape(collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f);
LevelRenderer.renderVoxelShape(matrixStack, buffer, collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f);
}
}
@Override
public void notifyLightSet(BlockPos pos) {
}
@Override
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
}
@Override
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category,
double x, double y, double z, float volume, float pitch) {
}
@Override
public void playRecord(SoundEvent soundIn, BlockPos pos) {
}
@Override
public void addParticle(IParticleData particleData, boolean alwaysRender, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
}
@Override
public void addParticle(IParticleData particleData, boolean ignoreRange, boolean minimizeLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
}
@Override
public void onEntityAdded(Entity entityIn) {
}
@Override
public void onEntityRemoved(Entity entityIn) {
}
@Override
public void broadcastSound(int soundID, BlockPos pos, int data) {
}
@Override
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) {
}
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
Minecraft mc = Minecraft.getInstance();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (!BuildModifiers.isEnabled(modifierSettings, pos)) return;
List<BlockPos> coordinates = BuildModifiers.findCoordinates(mc.player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) {
//Send i as entity id because only one block can be broken per id
//Unless i happens to be the player id, then take something else
int fakeId = mc.player.getEntityId() != i ? i : coordinates.size();
mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress);
}
}
}
//TODO
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
// @Override
// public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
// Minecraft mc = Minecraft.getInstance();
//
// ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
// if (!BuildModifiers.isEnabled(modifierSettings, pos)) return;
//
// List<BlockPos> coordinates = BuildModifiers.findCoordinates(mc.player, pos);
// for (int i = 1; i < coordinates.size(); i++) {
// BlockPos coordinate = coordinates.get(i);
// if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) {
// //Send i as entity id because only one block can be broken per id
// //Unless i happens to be the player id, then take something else
// int fakeId = mc.player.getEntityId() != i ? i : coordinates.size();
// mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress);
// }
// }
// }
}

View File

@@ -1,195 +0,0 @@
/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Modified by Requios
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Apr 9, 2014, 11:20:26 PM (GMT)]
*/
package nl.requios.effortlessbuilding.render;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.util.ResourceLocation;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.logging.log4j.Level;
import org.lwjgl.opengl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public final class ShaderHandler {
private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
private static final int VERT = 1;
private static final int FRAG = 2;
private static final String VERT_EXTENSION = ".vert";
private static final String FRAG_EXTENSION = ".frag";
public static int rawColor;
public static int dissolve;
public static ResourceLocation shaderMaskTextureLocation = new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png");
public static void init() {
if(!doUseShaders())
return;
// rawColor = createProgram("/assets/effortlessbuilding/shaders/raw_color", FRAG);
dissolve = createProgram("/assets/effortlessbuilding/shaders/dissolve", VERT + FRAG);
}
public static void useShader(int shader, Consumer<Integer> callback) {
if(!doUseShaders())
return;
ARBShaderObjects.glUseProgramObjectARB(shader);
if(shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1iARB(time, ClientProxy.ticksInGame);
if(callback != null)
callback.accept(shader);
}
}
public static void useShader(int shader) {
useShader(shader, null);
}
public static void releaseShader() {
useShader(0);
}
public static boolean doUseShaders() {
return BuildConfig.visuals.useShaders.get() && OpenGlHelper.shadersSupported;
}
private static int createProgram(String s, int sides) {
boolean vert = (sides & VERT) != 0;
boolean frag = (sides & FRAG) != 0;
return createProgram(vert ? s + VERT_EXTENSION : null, frag ? s + FRAG_EXTENSION : null);
}
// Most of the code taken from the LWJGL wiki
// http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL
private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if(vert != null)
vertId = createShader(vert, VERT_ST);
if(frag != null)
fragId = createShader(frag, FRAG_ST);
program = ARBShaderObjects.glCreateProgramObjectARB();
if(program == 0)
return 0;
if(vert != null)
ARBShaderObjects.glAttachObjectARB(program, vertId);
if(frag != null)
ARBShaderObjects.glAttachObjectARB(program, fragId);
ARBShaderObjects.glLinkProgramARB(program);
if(ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
return program;
}
private static int createShader(String filename, int shaderType){
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);
if(shader == 0)
return 0;
ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);
if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE)
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
return shader;
}
catch(Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}
private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}
private static String readFileAsString(String filename) throws Exception {
StringBuilder source = new StringBuilder();
InputStream in = ShaderHandler.class.getResourceAsStream(filename);
Exception exception = null;
BufferedReader reader;
if(in == null)
return "";
try {
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
Exception innerExc= null;
try {
String line;
while((line = reader.readLine()) != null)
source.append(line).append('\n');
} catch(Exception exc) {
exception = exc;
} finally {
try {
reader.close();
} catch(Exception exc) {
innerExc = exc;
}
}
if(innerExc != null)
throw innerExc;
} catch(Exception exc) {
exception = exc;
} finally {
try {
in.close();
} catch(Exception exc) {
if(exception == null)
exception = exc;
else exc.printStackTrace();
}
if(exception != null)
throw exception;
}
return source.toString();
}
}

View File

@@ -0,0 +1,3 @@
public net.minecraft.client.gui.components.AbstractSelectionList f_93398_ # renderHeader
public net.minecraft.client.gui.Font m_92803_(Ljava/lang/String;FFILcom/mojang/math/Matrix4f;ZZ)I # renderString
public net.minecraft.world.inventory.MenuType m_39988_(Ljava/lang/String;Lnet/minecraft/world/inventory/MenuType$MenuSupplier;)Lnet/minecraft/world/inventory/MenuType; # register

Some files were not shown because too many files have changed in this diff Show More