diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..8000a6fa --- /dev/null +++ b/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random + Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/VoxelSniperCore/build.gradle.kts b/VoxelSniperCore/build.gradle.kts index 9377b52d..646aab6a 100644 --- a/VoxelSniperCore/build.gradle.kts +++ b/VoxelSniperCore/build.gradle.kts @@ -1,5 +1,4 @@ plugins { id("voxel-core") } - description = "VoxelSniperCore" diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java index cca96c1f..f9aa92c4 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java @@ -1,10 +1,11 @@ package com.github.kevindagame; -import com.google.common.base.Preconditions; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Multimap; import com.github.kevindagame.brush.*; +import com.github.kevindagame.brush.multiBlock.*; +import com.github.kevindagame.brush.shell.ShellBallBrush; +import com.github.kevindagame.brush.shell.ShellSetBrush; +import com.github.kevindagame.brush.shell.ShellVoxelBrush; +import com.google.common.base.Preconditions; import java.util.*; @@ -15,8 +16,7 @@ public class VoxelBrushManager { private static VoxelBrushManager instance = null; - private final Multimap, String> brushes = HashMultimap.create(); - private final List brushHandles = new ArrayList<>(); + private final Map> brushes = new HashMap<>(); public static VoxelBrushManager getInstance() { return instance; @@ -72,31 +72,23 @@ public static VoxelBrushManager initialize() { brushManager.registerSniperBrush(OverlayBrush.class, "over", "overlay"); brushManager.registerSniperBrush(PaintingBrush.class, "painting"); brushManager.registerSniperBrush(PullBrush.class, "pull"); - //brushManager.registerSniperBrush(RandomErodeBrush.class, "re", "randomerode"); brushManager.registerSniperBrush(RegenerateChunkBrush.class, "rc", "regeneratechunk"); brushManager.registerSniperBrush(RingBrush.class, "ri", "ring"); - brushManager.registerSniperBrush(Rot2DBrush.class, "rot2", "rotation2d"); - brushManager.registerSniperBrush(Rot2DvertBrush.class, "rot2v", "rotation2dvertical"); - brushManager.registerSniperBrush(Rot3DBrush.class, "rot3", "rotation3d"); brushManager.registerSniperBrush(RulerBrush.class, "r", "ruler"); brushManager.registerSniperBrush(ScannerBrush.class, "sc", "scanner"); brushManager.registerSniperBrush(SetBrush.class, "set"); - //brushManager.registerSniperBrush(SetRedstoneFlipBrush.class, "setrf", "setredstoneflip"); brushManager.registerSniperBrush(ShellBallBrush.class, "shb", "shellball"); brushManager.registerSniperBrush(ShellSetBrush.class, "shs", "shellset"); brushManager.registerSniperBrush(ShellVoxelBrush.class, "shv", "shellvoxel"); brushManager.registerSniperBrush(SignOverwriteBrush.class, "sio", "signoverwriter"); brushManager.registerSniperBrush(SnipeBrush.class, "s", "snipe"); - //brushManager.registerSniperBrush(SnowConeBrush.class, "snow", "snowcone"); - //brushManager.registerSniperBrush(SpiralStaircaseBrush.class, "sstair", "spiralstaircase"); brushManager.registerSniperBrush(SplatterBallBrush.class, "sb", "splatball"); brushManager.registerSniperBrush(SplatterDiscBrush.class, "sd", "splatdisc"); brushManager.registerSniperBrush(SplatterOverlayBrush.class, "sover", "splatteroverlay"); + brushManager.registerSniperBrush(SplineBrush.class, "sp", "spline"); brushManager.registerSniperBrush(SplatterVoxelBrush.class, "sv", "splattervoxel"); brushManager.registerSniperBrush(SplatterDiscBrush.class, "svd", "splatvoxeldisc"); brushManager.registerSniperBrush(SplineBrush.class, "sp", "spline"); - //brushManager.registerSniperBrush(StencilBrush.class, "st", "stencil"); - //brushManager.registerSniperBrush(StencilListBrush.class, "sl", "stencillist"); brushManager.registerSniperBrush(ThreePointCircleBrush.class, "tpc", "threepointcircle"); brushManager.registerSniperBrush(TreeSnipeBrush.class, "t", "tree", "treesnipe"); brushManager.registerSniperBrush(TriangleBrush.class, "tri", "triangle"); @@ -107,6 +99,19 @@ public static VoxelBrushManager initialize() { brushManager.registerSniperBrush(VoxelDiscFaceBrush.class, "vdf", "voxeldiscface"); brushManager.registerSniperBrush(WarpBrush.class, "w", "warp"); + //these brushes are currently removed/broken + //brushManager.registerSniperBrush(StencilBrush.class, "st", "stencil"); + //brushManager.registerSniperBrush(StencilListBrush.class, "sl", "stencillist"); + + //brushManager.registerSniperBrush(Rot2DBrush.class, "rot2", "rotation2d"); + //brushManager.registerSniperBrush(Rot2DvertBrush.class, "rot2v", "rotation2dvertical"); + //brushManager.registerSniperBrush(Rot3DBrush.class, "rot3", "rotation3d"); + + + //these brushes have an unknown status + //brushManager.registerSniperBrush(SnowConeBrush.class, "snow", "snowcone"); + //brushManager.registerSniperBrush(SpiralStaircaseBrush.class, "sstair", "spiralstaircase"); + return getInstance(); } @@ -119,43 +124,34 @@ public static VoxelBrushManager initialize() { public void registerSniperBrush(Class clazz, String... handles) { Preconditions.checkNotNull(clazz, "Cannot register null as a class."); for (String handle : handles) { - brushes.put(clazz, handle.toLowerCase()); - brushHandles.add(handle.toLowerCase()); + brushes.put(handle.toLowerCase(), clazz); } } /** * Retrieve Brush class via handle Lookup. * - * @param handle Case insensitive brush handle + * @param handle Case-insensitive brush handle * @return Brush class */ public Class getBrushForHandle(String handle) { Preconditions.checkNotNull(handle, "Brushhandle can not be null."); - if (!brushes.containsValue(handle.toLowerCase())) { - return null; - } - for (Map.Entry, String> entry : brushes.entries()) { - if (entry.getValue().equalsIgnoreCase(handle)) { - return entry.getKey(); - } - } - return null; + return brushes.get(handle.toLowerCase()); } /** * @return Amount of IBrush classes registered with the system under Sniper visibility. */ public int registeredSniperBrushes() { - return brushes.keySet().size(); + return (int) brushes.values().stream().distinct().count(); } /** * @return Amount of handles registered with the system under Sniper visibility. */ public int registeredSniperBrushHandles() { - return brushes.size(); + return brushes.values().size(); } /** @@ -163,17 +159,23 @@ public int registeredSniperBrushHandles() { * @return All Sniper registered handles for the brush. */ public Set getSniperBrushHandles(Class clazz) { - return new HashSet<>(brushes.get(clazz)); + Set handles = new HashSet<>(); + for (String key : brushes.keySet()) { + if (brushes.get(key).equals(clazz)) { + handles.add(key); + } + } + return handles; } /** - * @return Immutable Multimap copy of all the registered brushes + * @return Immutable Map copy of all the registered brushes */ - public Multimap, String> getRegisteredBrushesMultimap() { - return ImmutableMultimap.copyOf(brushes); + public Map> getRegisteredBrushesMap() { + return Map.copyOf(brushes); } public List getBrushHandles() { - return brushHandles; + return new ArrayList<>(brushes.keySet()); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelProfileManager.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelProfileManager.java index 5e19cd7e..46def28a 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelProfileManager.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelProfileManager.java @@ -1,8 +1,8 @@ package com.github.kevindagame; -import com.google.common.collect.Maps; import com.github.kevindagame.snipe.Sniper; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.google.common.collect.Maps; import java.util.Map; import java.util.UUID; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/AbstractBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/AbstractBrush.java deleted file mode 100644 index 2e7c83ad..00000000 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/AbstractBrush.java +++ /dev/null @@ -1,340 +0,0 @@ -package com.github.kevindagame.brush; - -import com.github.kevindagame.brush.perform.PerformerBrush; -import com.github.kevindagame.snipe.SnipeAction; -import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; -import com.github.kevindagame.util.BlockHelper; -import com.github.kevindagame.util.BlockWrapper; -import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.BlockFace; -import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.blockdata.IBlockData; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; -import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import com.github.kevindagame.voxelsniper.world.IWorld; - -import java.util.*; - - -/** - * Abstract implementation of the {@link IBrush} interface. - */ -public abstract class AbstractBrush implements IBrush { - - protected static final int CHUNK_SIZE = 16; - /** - * Targeted Block. - */ - private IBlock targetBlock; - /** - * Last Block before targeted Block. - */ - private IBlock lastBlock; - /** - * Brush name. - */ - private String name = "Undefined"; - - /** - * @param x - * @param y - * @param z - * @return {@link IBlock} - */ - public final IBlock clampY(final int x, final int y, final int z) { - int clampedY = this.clampWorldHeight(y); - return this.getWorld().getBlock(x, clampedY, z); - } - - private boolean preparePerform(final SnipeData v, final IBlock clickedBlock, final BlockFace clickedFace) { - if (this.getTarget(v, clickedBlock, clickedFace)) { - if (this instanceof PerformerBrush) { - ((PerformerBrush) this).initP(v); - } - return true; - } - - return false; - } - - protected Set sphere(VoxelLocation location, double radius, boolean smooth) { - Set circleBlocks = new HashSet<>(); - double SMOOTH_SPHERE_VALUE = 0.5; - int VOXEL_SPHERE_VALUE = 0; - - int bx = location.getBlockX(); - int by = location.getBlockY(); - int bz = location.getBlockZ(); - var radiusSquared = Math.pow(radius + (smooth ? SMOOTH_SPHERE_VALUE : VOXEL_SPHERE_VALUE), 2); - for(int x = (int) (bx - radius); x <= bx + radius; x++) { - for(int y = (int) (by - radius); y <= by + radius; y++) { - for(int z = (int) (bz - radius); z <= bz + radius; z++) { - - double distance = ((bx-x) * (bx-x) + ((bz-z) * (bz-z)) + ((by-y) * (by-y))); - if(distance <= radiusSquared) { - circleBlocks.add(new VoxelLocation(location.getWorld(), x, y, z)); - } - } - } - } - - return circleBlocks; - } - - @Override - public boolean perform(SnipeAction action, SnipeData data, IBlock targetBlock, IBlock lastBlock) { - this.setTargetBlock(targetBlock); - this.setLastBlock(lastBlock); - switch (action) { - case ARROW: - this.arrow(data); - return true; - case GUNPOWDER: - this.powder(data); - return true; - default: - return false; - } - } - - /** - * The arrow action. Executed when a player RightClicks with an Arrow - * - * @param v Sniper caller - */ - protected void arrow(final SnipeData v) { - } - - /** - * The powder action. Executed when a player RightClicks with Gunpowder - * - * @param v Sniper caller - */ - protected void powder(final SnipeData v) { - } - - @Override - public abstract void info(VoxelMessage vm); - - @Override - public void parseParameters(String triggerHandle, final String[] params, final SnipeData v) { - v.sendMessage(Messages.BRUSH_NO_PARAMS_ACCEPTED); - } - - // TODO: make abstract - @Override - public List registerArguments() { - // Return empty list if not overridden; i.e. no arguments to add. - return new ArrayList<>(); - } - - @Override - public HashMap> registerArgumentValues() { - // Do nothing because not all brushes have arguments that have values - return new HashMap<>(); - } - - /** - * Overridable getTarget method. - * - * @param v - * @param clickedBlock - * @param clickedFace - * @return boolean - */ - protected final boolean getTarget(final SnipeData v, final IBlock clickedBlock, final BlockFace clickedFace) { - if (clickedBlock != null) { - this.setTargetBlock(clickedBlock); - this.setLastBlock(clickedBlock.getRelative(clickedFace)); - if (this.getLastBlock() == null) { - v.sendMessage(Messages.TARGET_MUST_BE_VISIBLE); - return false; - } - if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isLightningEnabled()) { - this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); - } - return true; - } else { - BlockHelper rangeBlockHelper; - if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isRanged()) { - rangeBlockHelper = new BlockHelper(v.owner().getPlayer(), v.owner().getSnipeData(v.owner().getCurrentToolId()).getRange()); - this.setTargetBlock(rangeBlockHelper.getRangeBlock()); - } else { - rangeBlockHelper = new BlockHelper(v.owner().getPlayer()); - this.setTargetBlock(rangeBlockHelper.getTargetBlock()); - } - if (this.getTargetBlock() != null) { - this.setLastBlock(rangeBlockHelper.getLastBlock()); - if (this.getLastBlock() == null) { - v.sendMessage(Messages.TARGET_MUST_BE_VISIBLE); - return false; - } - if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isLightningEnabled()) { - this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); - } - return true; - } else { - v.sendMessage(Messages.TARGET_MUST_BE_VISIBLE); - return false; - } - } - } - - @Override - public final String getName() { - return this.name; - } - - @Override - public final void setName(final String name) { - this.name = name; - } - - @Override - public String getBrushCategory() { - return "General"; - } - - /** - * @return the targetBlock - */ - protected final IBlock getTargetBlock() { - return this.targetBlock; - } - - /** - * @param targetBlock the targetBlock to set - */ - protected final void setTargetBlock(final IBlock targetBlock) { - this.targetBlock = targetBlock; - } - - /** - * @return the world - */ - protected final IWorld getWorld() { - return targetBlock.getWorld(); - } - - protected final int getMinHeight() { - return getWorld().getMinWorldHeight(); - } - - protected final int getMaxHeight() { - return getWorld().getMaxWorldHeight(); - } - - protected final int clampWorldHeight(int height) { - return Math.max(getMinHeight(), Math.min(getMaxHeight(), height)); - } - - /** - * Looks up Type ID of Block at given coordinates in the world of the targeted Block. - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @return Type ID of Block at given coordinates in the world of the targeted Block. - */ - protected VoxelMaterial getBlockMaterialAt(int x, int y, int z) { - return clampY(x, y, z).getMaterial(); - } - - /** - * Looks up Block Data Value of Block at given coordinates in the world of the targeted Block. - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @return Block Data Value of Block at given coordinates in the world of the targeted Block. - */ - protected IBlockData getBlockDataAt(int x, int y, int z) { - return this.clampY(x, y, z).getBlockData(); - } - - /** - * @return Block before target Block. - */ - protected final IBlock getLastBlock() { - return this.lastBlock; - } - - /** - * @param lastBlock Last Block before target Block. - */ - protected final void setLastBlock(IBlock lastBlock) { - this.lastBlock = lastBlock; - } - - /** - * Set block data with supplied data over BlockWrapper. - * - * @param blockWrapper Block data wrapper - */ - @Deprecated - protected final void setBlock(BlockWrapper blockWrapper) { - this.clampY(blockWrapper.getX(), blockWrapper.getY(), blockWrapper.getZ()).setBlockData(blockWrapper.getBlockData()); - } - - /** - * Sets the VoxelMaterial of the block at the passed coordinate. This function will automatically create use the default BlockData for that Material. - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @param material the material to set this block to - */ - protected final void setBlockMaterialAt(int x, int y, int z, VoxelMaterial material) { - this.clampY(x, y, z).setBlockData(material.createBlockData()); - } - - /** - * Sets the BlockData value of the block at the passed coordinate. Will use the exact BlockData that is passed into the function and NOT the default - * BlockData of the Material. - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @param blockData The blockData to set this block to - */ - protected final void setBlockMaterialAndDataAt(int x, int y, int z, IBlockData blockData) { - this.clampY(x, y, z).setBlockData(blockData, true); - } - - /** - * Sets the type of the passed block, and appends the block to the Undo container. This function will automatically create use the default BlockData for the passed Material. - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @param material the material to set this block to - * @param undo The Undo container to store the change - */ - protected final void setBlockMaterialAt(int x, int y, int z, VoxelMaterial material, Undo undo) { - IBlock b = this.clampY(x, y, z); - if (b.getMaterial() != material) { - undo.put(b); - } - b.setMaterial(material); - } - - /** - * Sets the type of the passed block, and adds the block to the Undo container. This function will automatically create use the default BlockData for the passed Material. - * - * @param b The block to change - * @param material the material to set this block to - * @param undo The Undo container to store the change - */ - protected final void setBlockType(IBlock b, VoxelMaterial material, Undo undo) { - int clampedY = this.clampWorldHeight(b.getY()); - if (clampedY != b.getY()) { - b = getWorld().getBlock(b.getX(), clampedY, b.getX()); - } - if (b.getMaterial() != material) { - undo.put(b); - } - b.setMaterial(material); - } -} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/AbstractBrush.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/AbstractBrush.kt new file mode 100644 index 00000000..682c9a5b --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/AbstractBrush.kt @@ -0,0 +1,292 @@ +package com.github.kevindagame.brush + +import com.github.kevindagame.brush.perform.PerformerBrush +import com.github.kevindagame.snipe.SnipeAction +import com.github.kevindagame.snipe.SnipeData +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.util.BlockHelper +import com.github.kevindagame.util.Messages +import com.github.kevindagame.util.VoxelMessage +import com.github.kevindagame.util.brushOperation.BrushOperation +import com.github.kevindagame.util.brushOperation.CustomOperation +import com.github.kevindagame.voxelsniper.block.BlockFace +import com.github.kevindagame.voxelsniper.block.IBlock +import com.github.kevindagame.voxelsniper.blockdata.IBlockData +import com.github.kevindagame.voxelsniper.events.player.PlayerSnipeEvent +import com.github.kevindagame.voxelsniper.material.VoxelMaterial +import com.github.kevindagame.voxelsniper.world.IWorld +import com.google.common.collect.ImmutableList +import java.util.* + +/** + * Abstract implementation of the [IBrush] interface. + */ +abstract class AbstractBrush : IBrush { + /** + * @return the targetBlock + */ + /** + * @param targetBlock the targetBlock to set + */ + /** + * Targeted Block. + */ + protected lateinit var targetBlock: IBlock + /** + * @return Block before target Block. + */ + /** + * @param lastBlock Last Block before target Block. + */ + /** + * Last Block before targeted Block. + */ + protected lateinit var lastBlock: IBlock + + /** + * The operations this brush performs + */ + private val operations: MutableList = ArrayList() + + /** + * Brush name. + */ + private var name = "Undefined" + protected var snipeAction: SnipeAction? = null + + private fun preparePerform(v: SnipeData, clickedBlock: IBlock, clickedFace: BlockFace): Boolean { + if (getTarget(v, clickedBlock, clickedFace)) { + if (this is PerformerBrush) { + this.initP(v) + } + return true + } + return false + } + + protected fun addOperation(operation: BrushOperation) { + if (isInWorldHeight(operation.location.blockY)) { + operations.add(operation) + } + } + + protected fun addOperations(operations: Collection) { + this.operations.addAll(operations.filter { o -> isInWorldHeight(o.location.blockY) }) + } + + protected fun getOperationsCount(): Int { + return operations.size + } + + override fun perform(action: SnipeAction, data: SnipeData, targetBlock: IBlock, lastBlock: IBlock): Boolean { + operations.clear() + this.targetBlock = targetBlock + this.lastBlock = lastBlock + snipeAction = action + when (action) { + SnipeAction.ARROW -> arrow(data) + SnipeAction.GUNPOWDER -> powder(data) + } + return performOperations(data) + } + + protected fun performOperations(data: SnipeData): Boolean { + if (operations.size == 0) return false + val event = PlayerSnipeEvent( + data.owner().player, + this, + ImmutableList.copyOf(operations), + operations.any { o -> o is CustomOperation }).callEvent() + if (!event.isCancelled) { + val undo = Undo() + var reloadArea = false + if (event.isCustom && this is CustomBrush) { + this.perform(event.operations.stream().filter { o -> !o.isCancelled && o is CustomOperation } + .map { o -> o as CustomOperation }.collect(ImmutableList.toImmutableList()), data, undo) + } else { + for (operation in event.operations) { + if (!operation.isCancelled) { + if (executeOperation(operation, undo)) { + reloadArea = true + } + } + } + } + data.owner().storeUndo(undo) + if (reloadArea) { + reloadBrushArea(data) + } + } + return false + } + + private fun reloadBrushArea(v: SnipeData) { + val brushSize = v.brushSize + val block1 = world.getBlock(targetBlock.x - brushSize, 0, targetBlock.z - brushSize) + val block2 = world.getBlock(targetBlock.x + brushSize, 0, targetBlock.z + brushSize) + val lowChunkX = if (block1.x <= block2.x) block1.chunk.x else block2.chunk.x + val lowChunkZ = if (block1.z <= block2.z) block1.chunk.z else block2.chunk.z + val highChunkX = if (block1.x >= block2.x) block1.chunk.x else block2.chunk.x + val highChunkZ = if (block1.z >= block2.z) block1.chunk.z else block2.chunk.z + for (x in lowChunkX..highChunkX) { + for (z in lowChunkZ..highChunkZ) { + world.refreshChunk(x, z) + } + } + } + + /** + * + * @param operation + * @param undo + * @return whether to reload the area + */ + private fun executeOperation(operation: BrushOperation, undo: Undo): Boolean { + return operation.perform(undo) + } + + /** + * The arrow action. Executed when a player RightClicks with an Arrow + * + * @param v Sniper caller + */ + protected open fun arrow(v: SnipeData?) {} + + /** + * The powder action. Executed when a player RightClicks with Gunpowder + * + * @param v Sniper caller + */ + protected open fun powder(v: SnipeData?) {} + abstract override fun info(vm: VoxelMessage) + override fun parseParameters(triggerHandle: String, params: Array, v: SnipeData) { + v.sendMessage(Messages.BRUSH_NO_PARAMS_ACCEPTED) + } + + override fun registerArguments(): List { + // Return empty list if not overridden; i.e. no arguments to add. + return ArrayList() + } + + override fun registerArgumentValues(): HashMap> { + // Do nothing because not all brushes have arguments that have values + return HashMap() + } + + /** + * Overridable getTarget method. + * + * @param v + * @param clickedBlock + * @param clickedFace + * @return boolean + */ + protected fun getTarget(v: SnipeData, clickedBlock: IBlock?, clickedFace: BlockFace?): Boolean { + return if (clickedBlock != null) { + targetBlock = clickedBlock + lastBlock = clickedBlock.getRelative(clickedFace) + if (lastBlock == null) { + v.sendMessage(Messages.TARGET_MUST_BE_VISIBLE) + return false + } + if (v.owner().getSnipeData(v.owner().currentToolId).isLightningEnabled) { + world.strikeLightning(targetBlock.location) + } + true + } else { + val rangeBlockHelper: BlockHelper + if (v.owner().getSnipeData(v.owner().currentToolId).isRanged) { + rangeBlockHelper = BlockHelper( + v.owner().player, v.owner().getSnipeData(v.owner().currentToolId).range + .toDouble() + ) + targetBlock = rangeBlockHelper.rangeBlock + } else { + rangeBlockHelper = BlockHelper(v.owner().player) + targetBlock = rangeBlockHelper.targetBlock + } + if (targetBlock != null) { + lastBlock = rangeBlockHelper.lastBlock + if (lastBlock == null) { + v.sendMessage(Messages.TARGET_MUST_BE_VISIBLE) + return false + } + if (v.owner().getSnipeData(v.owner().currentToolId).isLightningEnabled) { + world.strikeLightning(targetBlock.location) + } + true + } else { + v.sendMessage(Messages.TARGET_MUST_BE_VISIBLE) + false + } + } + } + + override fun getName(): String { + return name + } + + override fun setName(name: String) { + this.name = name + } + + override fun getBrushCategory(): String { + return "General" + } + + /** + * @return the world + */ + protected val world: IWorld + protected get() = targetBlock.world + protected val minHeight: Int + protected get() = world.minWorldHeight + protected val maxHeight: Int + protected get() = world.maxWorldHeight + + protected fun isInWorldHeight(height: Int): Boolean { + return minHeight <= height && maxHeight > height + } + + /** + * Looks up Type ID of Block at given coordinates in the world of the targeted Block. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * @return Type ID of Block at given coordinates in the world of the targeted Block. + */ + protected fun getBlockMaterialAt(x: Int, y: Int, z: Int): VoxelMaterial { + return if (isInWorldHeight(y)) world.getBlock(x, y, z).material else VoxelMaterial.AIR + } + + /** + * Looks up Block Data Value of Block at given coordinates in the world of the targeted Block. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * @return Block Data Value of Block at given coordinates in the world of the targeted Block. + */ + protected fun getBlockDataAt(x: Int, y: Int, z: Int): IBlockData { + return if (isInWorldHeight(y)) world.getBlock(x, y, z).blockData else VoxelMaterial.AIR.createBlockData() + } + + /** + * Sets the VoxelMaterial of the block at the passed coordinate. This function will automatically create use the default BlockData for that Material. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * @param material the material to set this block to + */ + protected fun setBlockMaterialAt(x: Int, y: Int, z: Int, material: VoxelMaterial) { + if (isInWorldHeight(y)) { + world.getBlock(x, y, z).blockData = material.createBlockData() + } + } + + companion object { + protected const val CHUNK_SIZE = 16 + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BallBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BallBrush.java index e06e60da..8bd0b7ec 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BallBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BallBrush.java @@ -3,15 +3,17 @@ import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * A brush that creates a solid ball. http://www.voxelwiki.com/minecraft/Voxelsniper#The_Ball_Brush + * A brush that creates a solid ball. ... * * @author Piotr */ @@ -25,20 +27,17 @@ public BallBrush() { } private void ball(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - var positions = this.sphere(targetBlock.getLocation(), brushSize, this.smoothSphere); - positions.forEach(position -> this.currentPerformer.perform(position.getBlock())); - v.owner().storeUndo(this.currentPerformer.getUndo()); + this.positions = Shapes.ball(targetBlock.getLocation(), v.getBrushSize(), this.smoothSphere); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.ball(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.ball(v, this.getLastBlock()); } @@ -64,6 +63,8 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -72,6 +73,7 @@ public List registerArguments() { arguments.addAll(super.registerArguments()); return arguments; } + @Override public String getPermissionNode() { return "voxelsniper.brush.ball"; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBallBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBallBrush.java index bf70cbed..1f400978 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBallBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBallBrush.java @@ -2,17 +2,27 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BiomeOperation; import com.github.kevindagame.voxelsniper.biome.VoxelBiome; -import com.github.kevindagame.voxelsniper.block.IBlock; +import org.jetbrains.annotations.NotNull; import java.util.List; -import java.util.stream.Collectors; +import static java.util.stream.Collectors.toList; + +/** + * ... + */ public class BiomeBallBrush extends AbstractBrush { private VoxelBiome selectedBiome = VoxelBiome.PLAINS; + public BiomeBallBrush() { + this.setName("Biome ball"); + } + @Override public void info(VoxelMessage vm) { vm.brushName(this.getName()); @@ -25,6 +35,7 @@ public String getPermissionNode() { return "voxelsniper.brush.biomeball"; } + @Override public void arrow(SnipeData v) { this.biome(v); @@ -36,28 +47,12 @@ protected void powder(SnipeData v) { } private void biome(final SnipeData v) { - final int brushSize = v.getBrushSize(); - var blocks = this.sphere(this.getTargetBlock().getLocation(), brushSize, true); - blocks.forEach(block -> block.getWorld().setBiome(block.getBlockX(), block.getBlockY(), block.getBlockZ(), selectedBiome)); - - //refresh chunks - final IBlock block1 = this.getWorld().getBlock(this.getTargetBlock().getX() - brushSize, 0, this.getTargetBlock().getZ() - brushSize); - final IBlock block2 = this.getWorld().getBlock(this.getTargetBlock().getX() + brushSize, 0, this.getTargetBlock().getZ() + brushSize); - - final int lowChunkX = (block1.getX() <= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX(); - final int lowChunkZ = (block1.getZ() <= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ(); - final int highChunkX = (block1.getX() >= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX(); - final int highChunkZ = (block1.getZ() >= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ(); - - for (int x = lowChunkX; x <= highChunkX; x++) { - for (int z = lowChunkZ; z <= highChunkZ; z++) { - this.getWorld().refreshChunk(x, z); - } - } + this.addOperations(Shapes.ball(this.getTargetBlock().getLocation(), v.getBrushSize(), true).stream().map(location -> new BiomeOperation(location, getWorld().getBiome(location), this.selectedBiome)).collect(toList())); + } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.BIOMEBALL_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -71,9 +66,10 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { - return VoxelBiome.BIOMES.values().stream().map(VoxelBiome::getKey).collect(Collectors.toList()); + return VoxelBiome.BIOMES.values().stream().map(VoxelBiome::getKey).collect(toList()); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBrush.java index d00706ba..417d59e2 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BiomeBrush.java @@ -3,14 +3,16 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BiomeOperation; import com.github.kevindagame.voxelsniper.biome.VoxelBiome; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.stream.Collectors; /** - * + * ... */ public class BiomeBrush extends AbstractBrush { @@ -26,27 +28,15 @@ private void biome(final SnipeData v) { for (int x = -brushSize; x <= brushSize; x++) { final double xSquared = Math.pow(x, 2); - for (int z = -brushSize; z <= brushSize; z++) { if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared) { - this.getWorld().setBiome(this.getTargetBlock().getX() + x, this.getTargetBlock().getZ() + z, this.selectedBiome); + var location = new BaseLocation(this.getWorld(), this.getTargetBlock().getX() + x, 0, this.getTargetBlock().getZ() + z); + this.addOperation(new BiomeOperation(location, getWorld().getBiome(location), this.selectedBiome)); } } } - final IBlock block1 = this.getWorld().getBlock(this.getTargetBlock().getX() - brushSize, 0, this.getTargetBlock().getZ() - brushSize); - final IBlock block2 = this.getWorld().getBlock(this.getTargetBlock().getX() + brushSize, 0, this.getTargetBlock().getZ() + brushSize); - - final int lowChunkX = (block1.getX() <= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX(); - final int lowChunkZ = (block1.getZ() <= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ(); - final int highChunkX = (block1.getX() >= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX(); - final int highChunkZ = (block1.getZ() >= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ(); - for (int x = lowChunkX; x <= highChunkX; x++) { - for (int z = lowChunkZ; z <= highChunkZ; z++) { - this.getWorld().refreshChunk(x, z); - } - } } @Override @@ -67,7 +57,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.BIOME_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -81,6 +71,7 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBallBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBallBrush.java index 40f8f3d5..3157ba45 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBallBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBallBrush.java @@ -1,121 +1,30 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + * ... */ public class BlendBallBrush extends BlendBrushBase { - - /** - * TODO: NEEDS TO CHECK AFTER REWRITE - */ public BlendBallBrush() { this.setName("Blend Ball"); } @Override protected final void blend(final SnipeData v) { - final int brushSize = v.getBrushSize(); - final int brushSizeDoubled = 2 * brushSize; - // Array that holds the original materials plus a buffer - final VoxelMaterial[][][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; - // Array that holds the blended materials - final VoxelMaterial[][][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; - - // Log current materials into oldmats - for (int x = 0; x <= 2 * (brushSize + 1); x++) { - for (int y = 0; y <= 2 * (brushSize + 1); y++) { - for (int z = 0; z <= 2 * (brushSize + 1); z++) { - oldMaterials[x][y][z] = this.getBlockMaterialAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z); - } - } - } - - // Log current materials into newmats - for (int x = 0; x <= brushSizeDoubled; x++) { - for (int y = 0; y <= brushSizeDoubled; y++) { - System.arraycopy(oldMaterials[x + 1][y + 1], 1, newMaterials[x][y], 0, brushSizeDoubled + 1); - } - } - - // Blend materials - for (int x = 0; x <= brushSizeDoubled; x++) { - for (int y = 0; y <= brushSizeDoubled; y++) { - for (int z = 0; z <= brushSizeDoubled; z++) { - Map materialFrequency = new HashMap<>(); - - boolean tiecheck = true; - - for (int m = -1; m <= 1; m++) { - for (int n = -1; n <= 1; n++) { - for (int o = -1; o <= 1; o++) { - if (!(m == 0 && n == 0 && o == 0)) { - VoxelMaterial currentMaterial = oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]; - int currentFrequency = materialFrequency.getOrDefault(currentMaterial, 0) + 1; - - materialFrequency.put(currentMaterial, currentFrequency); - } - } - } - } - - int highestMaterialCount = 0; - VoxelMaterial highestMaterial = VoxelMaterial.AIR; - - // Find most common neighbouring material - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() > highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - highestMaterialCount = e.getValue(); - highestMaterial = e.getKey(); - } - } - - // Make sure that there's no tie in highest material - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() == highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - if (e.getKey() == highestMaterial) { - continue; - } - tiecheck = false; - } - } - - // Record most common neighbor material for this block - if (tiecheck) { - newMaterials[x][y][z] = highestMaterial; - } - } - } - } - - final Undo undo = new Undo(); - final double rSquared = Math.pow(brushSize + 1, 2); - - // Make the changes - for (int x = brushSizeDoubled; x >= 0; x--) { - final double xSquared = Math.pow(x - brushSize - 1, 2); - - for (int y = 0; y <= brushSizeDoubled; y++) { - final double ySquared = Math.pow(y - brushSize - 1, 2); - - for (int z = brushSizeDoubled; z >= 0; z--) { - if (xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared) { - if (!(this.excludeAir && newMaterials[x][y][z].isAir()) && !(this.excludeWater && (newMaterials[x][y][z] == VoxelMaterial.WATER))) { - this.setBlockMaterialAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z, newMaterials[x][y][z], undo); - } - } - } + var brushSize = v.getBrushSize(); + var positions = Shapes.ball(this.getTargetBlock().getLocation(), v.getBrushSize(), false); + var newMaterials = this.blend3D(brushSize); + for (var position : positions) { + var material = newMaterials[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockY() - this.getTargetBlock().getY() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (!(this.excludeAir && material.isAir()) && !(this.excludeWater && (material == VoxelMaterial.WATER))) { + addOperation(new BlockOperation(position, position.getBlock().getBlockData(), material.createBlockData())); } } - v.owner().storeUndo(undo); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBrushBase.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBrushBase.java index 6d68ba25..38bbc8b0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBrushBase.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendBrushBase.java @@ -1,13 +1,16 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @author Monofraps @@ -17,10 +20,147 @@ public abstract class BlendBrushBase extends AbstractBrush { protected boolean excludeAir = true; protected boolean excludeWater = true; - /** - * @param v - */ - protected abstract void blend(final SnipeData v); + protected abstract void blend(SnipeData v); + + protected VoxelMaterial[][][] blend3D(int brushSize) { + final int brushSizeDoubled = 2 * brushSize; + // Array that holds the original materials plus a buffer + final VoxelMaterial[][][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; + // Array that holds the blended materials + final VoxelMaterial[][][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) { + for (int y = 0; y <= 2 * (brushSize + 1); y++) { + for (int z = 0; z <= 2 * (brushSize + 1); z++) { + oldMaterials[x][y][z] = this.getBlockMaterialAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z); + } + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) { + for (int y = 0; y <= brushSizeDoubled; y++) { + System.arraycopy(oldMaterials[x + 1][y + 1], 1, newMaterials[x][y], 0, brushSizeDoubled + 1); + } + } + + // Blend materials + for (int x = 0; x <= brushSizeDoubled; x++) { + for (int y = 0; y <= brushSizeDoubled; y++) { + for (int z = 0; z <= brushSizeDoubled; z++) { + Map materialFrequency = new HashMap<>(); + + boolean tiecheck = true; + + for (int m = -1; m <= 1; m++) { + for (int n = -1; n <= 1; n++) { + for (int o = -1; o <= 1; o++) { + if (!(m == 0 && n == 0 && o == 0)) { + VoxelMaterial currentMaterial = oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]; + int currentFrequency = materialFrequency.getOrDefault(currentMaterial, 0) + 1; + + materialFrequency.put(currentMaterial, currentFrequency); + } + } + } + } + + int highestMaterialCount = 0; + VoxelMaterial highestMaterial = VoxelMaterial.AIR; + + // Find most common neighbouring material + for (Map.Entry e : materialFrequency.entrySet()) { + if (e.getValue() > highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { + highestMaterialCount = e.getValue(); + highestMaterial = e.getKey(); + } + } + + // Make sure that there's no tie in highest material + for (Map.Entry e : materialFrequency.entrySet()) { + if (e.getValue() == highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { + if (e.getKey() == highestMaterial) { + continue; + } + tiecheck = false; + } + } + + // Record most common neighbor material for this block + if (tiecheck) { + newMaterials[x][y][z] = highestMaterial; + } + } + } + } + return newMaterials; + } + + protected VoxelMaterial[][] blend2D(int brushSize) { + final int brushSizeDoubled = 2 * brushSize; + final VoxelMaterial[][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer + final VoxelMaterial[][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials + + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) { + for (int z = 0; z <= 2 * (brushSize + 1); z++) { + oldMaterials[x][z] = this.getBlockMaterialAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z); + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) { + System.arraycopy(oldMaterials[x + 1], 1, newMaterials[x], 0, brushSizeDoubled + 1); + } + + // Blend materials + for (int x = 0; x <= brushSizeDoubled; x++) { + for (int z = 0; z <= brushSizeDoubled; z++) { + Map materialFrequency = new HashMap<>(); + + boolean tiecheck = true; + + for (int m = -1; m <= 1; m++) { + for (int n = -1; n <= 1; n++) { + if (!(m == 0 && n == 0)) { + VoxelMaterial currentMaterial = oldMaterials[x + 1 + m][z + 1 + n]; + int currentFrequency = materialFrequency.getOrDefault(currentMaterial, 0) + 1; + + materialFrequency.put(currentMaterial, currentFrequency); + } + } + } + + int highestMaterialCount = 0; + VoxelMaterial highestMaterial = VoxelMaterial.AIR; + + // Find most common neighboring material. + for (Map.Entry e : materialFrequency.entrySet()) { + if (e.getValue() > highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { + highestMaterialCount = e.getValue(); + highestMaterial = e.getKey(); + } + } + + // Make sure that there's no tie in highest material + for (Map.Entry e : materialFrequency.entrySet()) { + if (e.getValue() == highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { + if (e.getKey() == highestMaterial) { + continue; + } + tiecheck = false; + } + } + + // Record most common neighbor material for this block + if (tiecheck) { + newMaterials[x][z] = highestMaterial; + } + } + } + return newMaterials; + } @Override protected final void arrow(final SnipeData v) { @@ -43,7 +183,7 @@ public final void info(final VoxelMessage vm) { } @Override - public void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("water")) { if (params.length >= 2) { this.excludeWater = !Boolean.parseBoolean(params[1].toLowerCase()); @@ -57,11 +197,13 @@ public void parseParameters(final String triggerHandle, final String[] params, f v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("water")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); @@ -71,32 +213,4 @@ public HashMap> registerArgumentValues() { return argumentValues; } - - /** - * @return - */ - protected final boolean isExcludeAir() { - return excludeAir; - } - - /** - * @param excludeAir - */ - protected final void setExcludeAir(boolean excludeAir) { - this.excludeAir = excludeAir; - } - - /** - * @return - */ - protected final boolean isExcludeWater() { - return excludeWater; - } - - /** - * @param excludeWater - */ - protected final void setExcludeWater(boolean excludeWater) { - this.excludeWater = excludeWater; - } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendDiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendDiscBrush.java index 5c735077..fbf11bca 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendDiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendDiscBrush.java @@ -1,16 +1,13 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + * ... */ public class BlendDiscBrush extends BlendBrushBase { @@ -23,85 +20,16 @@ public BlendDiscBrush() { @Override protected final void blend(final SnipeData v) { - final int brushSize = v.getBrushSize(); - final int brushSizeDoubled = 2 * brushSize; - final VoxelMaterial[][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer - final VoxelMaterial[][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials - - // Log current materials into oldmats - for (int x = 0; x <= 2 * (brushSize + 1); x++) { - for (int z = 0; z <= 2 * (brushSize + 1); z++) { - oldMaterials[x][z] = this.getBlockMaterialAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z); - } - } - - // Log current materials into newmats - for (int x = 0; x <= brushSizeDoubled; x++) { - System.arraycopy(oldMaterials[x + 1], 1, newMaterials[x], 0, brushSizeDoubled + 1); - } - - // Blend materials - for (int x = 0; x <= brushSizeDoubled; x++) { - for (int z = 0; z <= brushSizeDoubled; z++) { - Map materialFrequency = new HashMap<>(); - - boolean tiecheck = true; - - for (int m = -1; m <= 1; m++) { - for (int n = -1; n <= 1; n++) { - if (!(m == 0 && n == 0)) { - VoxelMaterial currentMaterial = oldMaterials[x + 1 + m][z + 1 + n]; - int currentFrequency = materialFrequency.getOrDefault(currentMaterial, 0) + 1; - - materialFrequency.put(currentMaterial, currentFrequency); - } - } - } - - int highestMaterialCount = 0; - VoxelMaterial highestMaterial = VoxelMaterial.AIR; - - // Find most common neighboring material. - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() > highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - highestMaterialCount = e.getValue(); - highestMaterial = e.getKey(); - } - } - - // Make sure that there's no tie in highest material - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() == highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - if (e.getKey() == highestMaterial) { - continue; - } - tiecheck = false; - } - } - - // Record most common neighbor material for this block - if (tiecheck) { - newMaterials[x][z] = highestMaterial; - } - } - } - - final Undo undo = new Undo(); - final double rSquared = Math.pow(brushSize + 1, 2); - - // Make the changes - for (int x = brushSizeDoubled; x >= 0; x--) { - final double xSquared = Math.pow(x - brushSize - 1, 2); - - for (int z = brushSizeDoubled; z >= 0; z--) { - if (xSquared + Math.pow(z - brushSize - 1, 2) <= rSquared) { - if (!(this.excludeAir && newMaterials[x][z].isAir()) && !(this.excludeWater && newMaterials[x][z] == VoxelMaterial.WATER)) { - this.setBlockMaterialAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z, newMaterials[x][z], undo); - } - } + var positions = Shapes.disc(this.getTargetBlock().getLocation(), v.getBrushSize(), false); + var brushSize = v.getBrushSize(); + var newMaterials = this.blend2D(brushSize); + + for (var position : positions) { + var material = newMaterials[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (!(this.excludeAir && material.isAir()) && !(this.excludeWater && (material == VoxelMaterial.WATER))) { + addOperation(new BlockOperation(position, position.getBlock().getBlockData(), material.createBlockData())); } } - v.owner().storeUndo(undo); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelBrush.java index 055ffafb..3ad5a107 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelBrush.java @@ -1,16 +1,13 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + * ... */ public class BlendVoxelBrush extends BlendBrushBase { @@ -23,92 +20,15 @@ public BlendVoxelBrush() { @Override protected final void blend(final SnipeData v) { - final int brushSize = v.getBrushSize(); - final int brushSizeDoubled = 2 * brushSize; - // Array that holds the original materials plus a buffer - final VoxelMaterial[][][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; - // Array that holds the blended materials - final VoxelMaterial[][][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; - - // Log current materials into oldmats - for (int x = 0; x <= 2 * (brushSize + 1); x++) { - for (int y = 0; y <= 2 * (brushSize + 1); y++) { - for (int z = 0; z <= 2 * (brushSize + 1); z++) { - oldMaterials[x][y][z] = this.getBlockMaterialAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z); - } - } - } - - // Log current materials into newmats - for (int x = 0; x <= brushSizeDoubled; x++) { - for (int y = 0; y <= brushSizeDoubled; y++) { - System.arraycopy(oldMaterials[x + 1][y + 1], 1, newMaterials[x][y], 0, brushSizeDoubled + 1); - } - } - - // Blend materials - for (int x = 0; x <= brushSizeDoubled; x++) { - for (int y = 0; y <= brushSizeDoubled; y++) { - for (int z = 0; z <= brushSizeDoubled; z++) { - Map materialFrequency = new HashMap<>(); - - boolean tiecheck = true; - - for (int m = -1; m <= 1; m++) { - for (int n = -1; n <= 1; n++) { - for (int o = -1; o <= 1; o++) { - if (!(m == 0 && n == 0 && o == 0)) { - VoxelMaterial currentMaterial = oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]; - int currentFrequency = materialFrequency.getOrDefault(currentMaterial, 0) + 1; - - materialFrequency.put(currentMaterial, currentFrequency); - } - } - } - } - - int highestMaterialCount = 0; - VoxelMaterial highestMaterial = VoxelMaterial.AIR; - - // Find most common neighbouring material - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() > highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - highestMaterialCount = e.getValue(); - highestMaterial = e.getKey(); - } - } - - // Make sure that there's no tie in highest material - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() == highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - if (e.getKey() == highestMaterial) { - continue; - } - tiecheck = false; - } - } - - // Record most common neighbor material for this block - if (tiecheck) { - newMaterials[x][y][z] = highestMaterial; - } - } - } - } - - final Undo undo = new Undo(); - - // Make the changes - for (int x = brushSizeDoubled; x >= 0; x--) { - for (int y = 0; y <= brushSizeDoubled; y++) { - for (int z = brushSizeDoubled; z >= 0; z--) { - if (!(this.excludeAir && newMaterials[x][y][z].isAir()) && !(this.excludeWater && newMaterials[x][y][z] == VoxelMaterial.WATER)) { - setBlockMaterialAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z, newMaterials[x][y][z], undo); - } - } + var brushSize = v.getBrushSize(); + var positions = Shapes.voxel(this.getTargetBlock().getLocation(), v.getBrushSize()); + var newMaterials = this.blend3D(brushSize); + for (var position : positions) { + var material = newMaterials[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockY() - this.getTargetBlock().getY() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (!(this.excludeAir && material.isAir()) && !(this.excludeWater && (material == VoxelMaterial.WATER))) { + addOperation(new BlockOperation(position, position.getBlock().getBlockData(), material.createBlockData())); } } - v.owner().storeUndo(undo); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelDiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelDiscBrush.java index ae27df3b..5ecb5571 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelDiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlendVoxelDiscBrush.java @@ -1,16 +1,13 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + * ... */ public class BlendVoxelDiscBrush extends BlendBrushBase { @@ -23,81 +20,16 @@ public BlendVoxelDiscBrush() { @Override protected final void blend(final SnipeData v) { - final int brushSize = v.getBrushSize(); - final int brushSizeDoubled = 2 * brushSize; - final VoxelMaterial[][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer - final VoxelMaterial[][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials - - // Log current materials into oldmats - for (int x = 0; x <= 2 * (brushSize + 1); x++) { - for (int z = 0; z <= 2 * (brushSize + 1); z++) { - oldMaterials[x][z] = this.getBlockMaterialAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z); + var positions = Shapes.voxelDisc(this.getTargetBlock().getLocation(), v.getBrushSize()); + var brushSize = v.getBrushSize(); + var newMaterials = this.blend2D(brushSize); + + for (var position : positions) { + var material = newMaterials[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (!(this.excludeAir && material.isAir()) && !(this.excludeWater && (material == VoxelMaterial.WATER))) { + addOperation(new BlockOperation(position, position.getBlock().getBlockData(), material.createBlockData())); } } - - // Log current materials into newmats - for (int x = 0; x <= brushSizeDoubled; x++) { - System.arraycopy(oldMaterials[x + 1], 1, newMaterials[x], 0, brushSizeDoubled + 1); - } - - // Blend materials - for (int x = 0; x <= brushSizeDoubled; x++) { - for (int z = 0; z <= brushSizeDoubled; z++) { - Map materialFrequency = new HashMap<>(); - - boolean tiecheck = true; - - for (int m = -1; m <= 1; m++) { - for (int n = -1; n <= 1; n++) { - if (!(m == 0 && n == 0)) { - VoxelMaterial currentMaterial = oldMaterials[x + 1 + m][z + 1 + n]; - int currentFrequency = materialFrequency.getOrDefault(currentMaterial, 0) + 1; - - materialFrequency.put(currentMaterial, currentFrequency); - } - } - } - - int highestMaterialCount = 0; - VoxelMaterial highestMaterial = VoxelMaterial.AIR; - - // Find most common neighboring material. - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() > highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - highestMaterialCount = e.getValue(); - highestMaterial = e.getKey(); - } - } - - // Make sure that there's no tie in highest material - for (Entry e : materialFrequency.entrySet()) { - if (e.getValue() == highestMaterialCount && !(this.excludeAir && e.getKey().isAir()) && !(this.excludeWater && e.getKey() == VoxelMaterial.WATER)) { - if (e.getKey() == highestMaterial) { - continue; - } - tiecheck = false; - } - } - - // Record most common neighbor material for this block - if (tiecheck) { - newMaterials[x][z] = highestMaterial; - } - } - } - - final Undo undo = new Undo(); - - // Make the changes - for (int x = brushSizeDoubled; x >= 0; x--) { - for (int z = brushSizeDoubled; z >= 0; z--) { - if (!(this.excludeAir && newMaterials[x][z].isAir()) && !(this.excludeWater && newMaterials[x][z] == VoxelMaterial.WATER)) { - this.setBlockMaterialAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z, newMaterials[x][z], undo); - } - } - } - - v.owner().storeUndo(undo); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlobBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlobBrush.java index c06ceaa4..062e779f 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlobBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlobBrush.java @@ -1,10 +1,12 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -12,7 +14,7 @@ import java.util.Random; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Blob_Brush + * ... * * @author Giltwist */ @@ -112,13 +114,11 @@ private void digBlob(final SnipeData v) { for (int z = brushSizeDoubled; z >= 0; z--) { if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y)); + positions.add(new BaseLocation(this.getWorld(), this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y)); } } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private void growBlob(final SnipeData v) { @@ -188,22 +188,20 @@ private void growBlob(final SnipeData v) { for (int z = brushSizeDoubled; z >= 0; z--) { if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y)); + positions.add(new BaseLocation(getWorld(), this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y)); } } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.growBlob(v); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.digBlob(v); } @@ -255,6 +253,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -264,6 +263,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetBrush.java index bac12b47..f889fd6e 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetBrush.java @@ -1,14 +1,18 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.util.brushOperation.BlockOperation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import java.util.ArrayList; +import java.util.stream.Collectors; /** * @author MikeMatrix + * ... */ public class BlockResetBrush extends AbstractBrush { @@ -52,22 +56,8 @@ public BlockResetBrush() { } private void applyBrush(final SnipeData v) { - for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) { - for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) { - for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++) { - final IBlock block = this.getWorld().getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); - if (BlockResetBrush.DENIED_UPDATES.contains(block.getMaterial())) { - continue; - } - - // Resets the block state to initial state by creating a new BlockData with default values. - block.setBlockData(block.getBlockData().getMaterial().createBlockData(), true); - - // Do we need this??? - // block.setBlockData(MagicValues.getBlockDataFor(MagicValues.getIdFor(block.getMaterial()), oldData), true); - } - } - } + addOperations(Shapes.voxel(this.getTargetBlock().getLocation(), v.getBrushSize()).stream().map(BaseLocation::getBlock) + .filter(block -> BlockResetBrush.DENIED_UPDATES.contains(block.getMaterial())).map(b -> new BlockOperation(b.getLocation(), b.getBlockData(), b.getBlockData().getMaterial().createBlockData())).collect(Collectors.toList())); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetSurfaceBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetSurfaceBrush.java index 1d51ef39..3d34b3c3 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetSurfaceBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/BlockResetSurfaceBrush.java @@ -2,7 +2,9 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; @@ -20,6 +22,8 @@ * typical terrain, blockPositionY my calculations, overall speed increase is about a factor of 5-6 for a size 20 brush. For a complicated city or ship, etc., * this may be only a factor of about 2. In a hypothetical worst case scenario of a 3d checkerboard of stone and air every other block, this brush should only * be about 1.5x slower than the original brush. Savings increase for larger brushes. + *
+ * ... * * @author GavJenks */ @@ -66,69 +70,49 @@ public BlockResetSurfaceBrush() { this.setName("Block Reset Brush Surface Only"); } - @SuppressWarnings("deprecation") private void applyBrush(final SnipeData v) { final IWorld world = this.getWorld(); for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) { for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) { for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++) { - // TODO clampY IBlock block = world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); if (BlockResetSurfaceBrush.DENIED_UPDATES.contains(block.getMaterial())) { continue; } - boolean airFound = false; + boolean airFound; - if (world.getBlock(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { - block = world.getBlock(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); - resetBlock(block); - airFound = true; - } - - if (world.getBlock(this.getTargetBlock().getX() + x - 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { - block = world.getBlock(this.getTargetBlock().getX() + x - 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); - resetBlock(block); - airFound = true; - } - - if (world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y + 1, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { - block = world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y + 1, this.getTargetBlock().getZ() + z); - resetBlock(block); - airFound = true; - } - - if (world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y - 1, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { - block = world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y - 1, this.getTargetBlock().getZ() + z); - resetBlock(block); - airFound = true; - } - - if (world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z + 1).getMaterial().isAir()) { - block = world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z + 1); - resetBlock(block); - airFound = true; - } - - if (world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z - 1).getMaterial().isAir()) { - block = world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z - 1); - resetBlock(block); - airFound = true; - } + airFound = checkBlock(world, x + 1, y, z); + airFound = checkBlock(world, x - 1, y, z) || airFound; + airFound = checkBlock(world, x, y + 1, z) || airFound; + airFound = checkBlock(world, x, y - 1, z) || airFound; + airFound = checkBlock(world, x, y, z + 1) || airFound; + airFound = checkBlock(world, x, y, z - 1) || airFound; if (airFound) { - block = world.getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); - resetBlock(block); + var location = new BaseLocation(getWorld(), this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + + resetBlock(location); } } } } } - private void resetBlock(IBlock block) { - // Resets the block state to initial state by creating a new BlockData with default values. - block.setBlockData(block.getBlockData().getMaterial().createBlockData(), true); + private boolean checkBlock(IWorld world, int x, int y, int z) { + IBlock block = world.getBlock(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + if (block.getMaterial().isAir()) { + resetBlock(block.getLocation()); + return true; + } + return false; + } + + private void resetBlock(BaseLocation location) { + // create an operation to reset the block + var block = location.getBlock(); + addOperation(new BlockOperation(location, block.getBlockData(), block.getMaterial().createBlockData())); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CheckerVoxelDiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CheckerVoxelDiscBrush.java index 9a558f71..399812eb 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CheckerVoxelDiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CheckerVoxelDiscBrush.java @@ -1,17 +1,20 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Actions; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** * @author MikeMatrix + * ... */ public class CheckerVoxelDiscBrush extends PerformerBrush { @@ -26,28 +29,19 @@ public CheckerVoxelDiscBrush() { /** * @param v - * @param target */ - private void applyBrush(final SnipeData v, final IBlock target) { - for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { - for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) { - final int sum = this.useWorldCoordinates ? target.getX() + x + target.getZ() + y : x + y; - if (sum % 2 != 0) { - this.currentPerformer.perform(this.clampY(target.getX() + x, target.getY(), target.getZ() + y)); - } - } - } - v.owner().storeUndo(this.currentPerformer.getUndo()); + private void applyBrush(final SnipeData v) { + this.positions = Actions.checker(Shapes.voxelDisc(this.getTargetBlock().getLocation(), v.getBrushSize()), this.useWorldCoordinates); } @Override - protected final void arrow(final SnipeData v) { - this.applyBrush(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.applyBrush(v); } @Override - protected final void powder(final SnipeData v) { - this.applyBrush(v, this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + this.applyBrush(v); } @Override @@ -74,6 +68,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CleanSnowBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CleanSnowBrush.java index 7e0ddc73..0e6a0014 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CleanSnowBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CleanSnowBrush.java @@ -1,26 +1,26 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; +import com.github.kevindagame.voxelsniper.block.BlockFace; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Clean_Snow_Brush + * ... * * @author psanker */ public class CleanSnowBrush extends AbstractBrush { - public static final double SMOOTH_SPHERE_VALUE = 0.5; - public static final int VOXEL_SPHERE_VALUE = 0; - private boolean smoothSphere = false; /** @@ -31,29 +31,14 @@ public CleanSnowBrush() { } private void cleanSnow(final SnipeData v) { - final int brushSize = v.getBrushSize(); - final double brushSizeSquared = Math.pow(brushSize + (this.smoothSphere ? SMOOTH_SPHERE_VALUE : VOXEL_SPHERE_VALUE), 2); - final Undo undo = new Undo(); - - for (int x = (brushSize + 1) * 2; x >= 0; x--) { - final double xSquared = Math.pow(x - brushSize, 2); - for (int z = (brushSize + 1) * 2; z >= 0; z--) { - final double zSquared = Math.pow(z - brushSize, 2); - - for (int y = (brushSize + 1) * 2; y >= 0; y--) { - if ((xSquared + Math.pow(y - brushSize, 2) + zSquared) <= brushSizeSquared) { - IBlock b = this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + y - brushSize, this.getTargetBlock().getZ() + z - brushSize); - IBlock blockDown = this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + y - brushSize - 1, this.getTargetBlock().getZ() + z - brushSize); - if ((b.getMaterial() == VoxelMaterial.SNOW) && ((blockDown.getMaterial() == VoxelMaterial.SNOW) || (blockDown.getMaterial().isAir()))) { - setBlockType(b, VoxelMaterial.AIR, undo); - } - - } - } + var positions = Shapes.ball(this.getTargetBlock().getLocation(), v.getBrushSize(), smoothSphere); + for (var position : positions) { + IBlock b = position.getBlock(); + IBlock blockDown = b.getRelative(BlockFace.DOWN); + if ((b.getMaterial() == VoxelMaterial.SNOW) && ((blockDown.getMaterial() == VoxelMaterial.SNOW) || (blockDown.getMaterial().isAir()))) { + addOperation(new BlockOperation(position, b.getBlockData(), VoxelMaterial.AIR.createBlockData())); } } - - v.owner().storeUndo(undo); } @Override @@ -73,7 +58,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.CLEAN_SNOW_BURSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -88,6 +73,7 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CloneStampBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CloneStampBrush.java index 5ea8aaf6..f6822e20 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CloneStampBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CloneStampBrush.java @@ -1,21 +1,28 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** * The CloneStamp class is used to create a collection of blocks in a cylinder shape according to the selection the player has set. - * http://www.voxelwiki.com/minecraft/Voxelsniper#Clone_and_CopyPasta_Brushes + * ... * * @author Voxel */ public class CloneStampBrush extends StampBrush { + private BaseLocation startingPoint; + /** * */ @@ -32,55 +39,18 @@ public CloneStampBrush() { * @param v the caller */ private void clone(final SnipeData v) { - final int brushSize = v.getBrushSize(); + VoxelLocation point = getTargetBlock().getLocation().makeMutable(); + point.add(0, v.getcCen(), 0); + this.startingPoint = point.makeImmutable(); + var positions = Shapes.cylinder(startingPoint, v.getBrushSize(), v.getVoxelHeight(), 0, false); this.clone.clear(); - this.fall.clear(); - this.drop.clear(); - this.solid.clear(); + this.toStamp.clear(); this.sorted = false; - - int yStartingPoint = this.getTargetBlock().getY() + v.getcCen(); - int yEndPoint = this.getTargetBlock().getY() + v.getVoxelHeight() + v.getcCen(); - - if (yStartingPoint < this.getMinHeight()) { - yStartingPoint = this.getMinHeight(); - v.sendMessage(Messages.OFF_WORLD_START_POS); - } else if (yStartingPoint > this.getMaxHeight() - 1) { - yStartingPoint = this.getMaxHeight() - 1; - v.sendMessage(Messages.OFF_WORLD_START_POS); - } - - if (yEndPoint < this.getMinHeight()) { - yEndPoint = this.getMinHeight(); - v.sendMessage(Messages.OFF_WORLD_END_POS); - } else if (yEndPoint > this.getMaxHeight() - 1) { - yEndPoint = this.getMaxHeight() - 1; - v.sendMessage(Messages.OFF_WORLD_END_POS); - } - - final double bSquared = Math.pow(brushSize, 2); - - for (int z = yStartingPoint; z < yEndPoint; z++) { - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ()), 0, z - yStartingPoint, 0, v.getWorld())); - for (int y = 1; y <= brushSize; y++) { - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ() + y), 0, z - yStartingPoint, y, v.getWorld())); - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ() - y), 0, z - yStartingPoint, -y, v.getWorld())); - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + y, z, this.getTargetBlock().getZ()), y, z - yStartingPoint, 0, v.getWorld())); - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - y, z, this.getTargetBlock().getZ()), -y, z - yStartingPoint, 0, v.getWorld())); - } - for (int x = 1; x <= brushSize; x++) { - final double xSquared = Math.pow(x, 2); - for (int y = 1; y <= brushSize; y++) { - if ((xSquared + Math.pow(y, 2)) <= bSquared) { - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + x, z, this.getTargetBlock().getZ() + y), x, z - yStartingPoint, y, v.getWorld())); - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + x, z, this.getTargetBlock().getZ() - y), x, z - yStartingPoint, -y, v.getWorld())); - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - x, z, this.getTargetBlock().getZ() + y), -x, z - yStartingPoint, y, v.getWorld())); - this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - x, z, this.getTargetBlock().getZ() - y), -x, z - yStartingPoint, -y, v.getWorld())); - } - } - } + for (var p : positions) { + this.clone.add(new BlockWrapper(p.getBlock(), p.getBlockX() - startingPoint.getBlockX(), p.getBlockY() - startingPoint.getBlockY(), p.getBlockZ() - startingPoint.getBlockZ(), getWorld())); } v.sendMessage(Messages.BLOCKS_COPIED_SUCCESSFULLY.replace("%amount%", String.valueOf(this.clone.size()))); + } @Override @@ -114,7 +84,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.CLONE_STAMP_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -141,13 +111,12 @@ public final void parseParameters(final String triggerHandle, final String[] par return; } - /** - * TODO: Implement if (params[0].startsWith("centre")) { v.setcCen(Integer.parseInt(params[0].replace("c", ""))); v.sendMessage(ChatColor.BLUE + "Center - * set to " + v.getcCen()); return; } - */ + // TODO: Implement if (params[0].startsWith("centre")) { v.setcCen(Integer.parseInt(params[0].replace("c", ""))); v.sendMessage(ChatColor.BLUE + "Center + // set to " + v.getcCen()); return; } v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CometBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CometBrush.java index 59dc55ae..2448d543 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CometBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CometBrush.java @@ -1,12 +1,16 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -15,8 +19,9 @@ * @author Gavjenks Heavily revamped from ruler brush blockPositionY * @author Giltwist * @author Monofraps (Merged Meteor brush) + * ... */ -public class CometBrush extends AbstractBrush { +public class CometBrush extends CustomBrush { private boolean useBigBalls = false; @@ -29,15 +34,13 @@ public CometBrush() { private void doFireball(final SnipeData v) { final VoxelVector targetCoords = new VoxelVector(this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()), this.getTargetBlock().getY() + .5, this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ())); - final VoxelLocation playerLocation = v.owner().getPlayer().getEyeLocation(); - final VoxelVector slope = targetCoords.subtract(playerLocation.toVector()); + addOperation(new CustomOperation(targetCoords.getLocation(getWorld()), this, v, CustomOperationContext.TARGETLOCATION)); + addOperation(new CustomOperation(v.owner().getPlayer().getEyeLocation(), this, v, CustomOperationContext.PLAYERLOCATION)); - final VoxelEntityType type = (useBigBalls ? VoxelEntityType.FIREBALL : VoxelEntityType.SMALL_FIREBALL); - v.owner().getPlayer().launchProjectile(type, slope.normalize()); } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.COMET_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -58,6 +61,7 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { @@ -86,4 +90,20 @@ public final void info(final VoxelMessage vm) { public String getPermissionNode() { return "voxelsniper.brush.comet"; } + + @Override + public boolean perform(ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + if (operations.size() != 2) { + return false; + } + final var targetCoords = operations.stream().filter(operation -> operation.getContext() == CustomOperationContext.TARGETLOCATION).findFirst(); + final var playerCoords = operations.stream().filter(operation -> operation.getContext() == CustomOperationContext.PLAYERLOCATION).findFirst(); + if (targetCoords.isEmpty() || playerCoords.isEmpty()) return false; + final VoxelVector slope = targetCoords.get().getLocation().toVector().subtract(playerCoords.get().getLocation().toVector()); + + final VoxelEntityType type = (useBigBalls ? VoxelEntityType.FIREBALL : VoxelEntityType.SMALL_FIREBALL); + snipeData.owner().getPlayer().launchProjectile(type, slope.normalize()); + return true; + + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CustomBrush.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CustomBrush.kt new file mode 100644 index 00000000..67f8c13f --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CustomBrush.kt @@ -0,0 +1,10 @@ +package com.github.kevindagame.brush + +import com.github.kevindagame.snipe.SnipeData +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.util.brushOperation.CustomOperation +import com.google.common.collect.ImmutableList + +abstract class CustomBrush : AbstractBrush() { + abstract fun perform(operations: ImmutableList, snipeData: SnipeData, undo: Undo): Boolean +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CylinderBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CylinderBrush.java index 941153e1..8d69c310 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CylinderBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CylinderBrush.java @@ -1,11 +1,12 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -13,12 +14,10 @@ /** * @author Kavutop + * ... */ public class CylinderBrush extends PerformerBrush { - private static final double SMOOTH_CIRCLE_VALUE = 0.5; - private static final double VOXEL_CIRCLE_VALUE = 0.0; - private boolean smoothCircle = false; /** @@ -28,56 +27,18 @@ public CylinderBrush() { this.setName("Cylinder"); } - private void cylinder(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - int yStartingPoint = targetBlock.getY() + v.getcCen(); - int yEndPoint = targetBlock.getY() + v.getVoxelHeight() + v.getcCen(); - - if (yEndPoint < yStartingPoint) { - yEndPoint = yStartingPoint; - } - if (yStartingPoint < this.getMinHeight()) { - yStartingPoint = this.getMinHeight(); - v.sendMessage(Messages.OFF_WORLD_START_POS); - } else if (yStartingPoint > this.getMaxHeight() - 1) { - yStartingPoint = this.getMaxHeight() - 1; - v.sendMessage(Messages.OFF_WORLD_START_POS); - } - if (yEndPoint < this.getMinHeight()) { - yEndPoint = this.getMinHeight(); - v.sendMessage(Messages.OFF_WORLD_START_POS); - } else if (yEndPoint > this.getMaxHeight() - 1) { - yEndPoint = this.getMaxHeight() - 1; - v.sendMessage(Messages.OFF_WORLD_START_POS); - } - - final double bSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - - for (int y = yEndPoint; y >= yStartingPoint; y--) { - for (int x = brushSize; x >= 0; x--) { - final double xSquared = Math.pow(x, 2); - - for (int z = brushSize; z >= 0; z--) { - if ((xSquared + Math.pow(z, 2)) <= bSquared) { - this.currentPerformer.perform(this.clampY(targetBlock.getX() + x, y, targetBlock.getZ() + z)); - this.currentPerformer.perform(this.clampY(targetBlock.getX() + x, y, targetBlock.getZ() - z)); - this.currentPerformer.perform(this.clampY(targetBlock.getX() - x, y, targetBlock.getZ() + z)); - this.currentPerformer.perform(this.clampY(targetBlock.getX() - x, y, targetBlock.getZ() - z)); - } - } - } - } - v.owner().storeUndo(this.currentPerformer.getUndo()); + private void cylinder(final SnipeData v) { + this.positions = Shapes.cylinder(this.getTargetBlock().getLocation(), v.getBrushSize(), v.getVoxelHeight(), v.getcCen(), this.smoothCircle); } @Override - protected final void arrow(final SnipeData v) { - this.cylinder(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.cylinder(v); } @Override - protected final void powder(final SnipeData v) { - this.cylinder(v, this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + this.cylinder(v); } @Override @@ -125,6 +86,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -134,6 +96,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscBrush.java index e6db8645..5e23ab7f 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscBrush.java @@ -1,25 +1,24 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Disc_Brush + * ... * * @author Voxel */ public class DiscBrush extends PerformerBrush { - private static final double SMOOTH_CIRCLE_VALUE = 0.5; - private static final double VOXEL_CIRCLE_VALUE = 0.0; private boolean smoothCircle = false; @@ -33,32 +32,19 @@ public DiscBrush() { /** * Disc executor. * - * @param v + * @param v SnipeData */ private void disc(final SnipeData v, final IBlock targetBlock) { - final double radiusSquared = (v.getBrushSize() + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE)) * (v.getBrushSize() + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE)); - final VoxelVector centerPoint = targetBlock.getLocation().toVector(); - final VoxelVector currentPoint = centerPoint.clone(); - - for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) { - currentPoint.setX(centerPoint.getX() + x); - for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) { - currentPoint.setZ(centerPoint.getZ() + z); - if (centerPoint.distanceSquared(currentPoint) <= radiusSquared) { - this.currentPerformer.perform(this.clampY(currentPoint.getBlockX(), currentPoint.getBlockY(), currentPoint.getBlockZ())); - } - } - } - v.owner().storeUndo(this.currentPerformer.getUndo()); + this.positions = Shapes.disc(targetBlock.getLocation(), v.getBrushSize(), this.smoothCircle); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.disc(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.disc(v, this.getLastBlock()); } @@ -85,6 +71,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscFaceBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscFaceBrush.java index 1c640866..c5735942 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscFaceBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DiscFaceBrush.java @@ -1,18 +1,18 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.BlockFace; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Disc_Face_Brush + * ... * * @author Voxel */ @@ -30,98 +30,18 @@ public DiscFaceBrush() { this.setName("Disc Face"); } - private void discUD(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - final double brushSizeSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - - for (int x = brushSize; x >= 0; x--) { - final double xSquared = Math.pow(x, 2); - - for (int z = brushSize; z >= 0; z--) { - if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared) { - currentPerformer.perform(targetBlock.getRelative(x, 0, z)); - currentPerformer.perform(targetBlock.getRelative(x, 0, -z)); - currentPerformer.perform(targetBlock.getRelative(-x, 0, z)); - currentPerformer.perform(targetBlock.getRelative(-x, 0, -z)); - } - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private void discNS(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - final double brushSizeSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - - for (int x = brushSize; x >= 0; x--) { - final double xSquared = Math.pow(x, 2); - for (int y = brushSize; y >= 0; y--) { - if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared) { - currentPerformer.perform(targetBlock.getRelative(x, y, 0)); - currentPerformer.perform(targetBlock.getRelative(x, -y, 0)); - currentPerformer.perform(targetBlock.getRelative(-x, y, 0)); - currentPerformer.perform(targetBlock.getRelative(-x, -y, 0)); - } - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private void discEW(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - final double brushSizeSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - - for (int x = brushSize; x >= 0; x--) { - final double xSquared = Math.pow(x, 2); - for (int y = brushSize; y >= 0; y--) { - if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared) { - currentPerformer.perform(targetBlock.getRelative(0, x, y)); - currentPerformer.perform(targetBlock.getRelative(0, x, -y)); - currentPerformer.perform(targetBlock.getRelative(0, -x, y)); - currentPerformer.perform(targetBlock.getRelative(0, -x, -y)); - } - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private void pre(final SnipeData v, IBlock targetBlock) { - BlockFace blockFace = getTargetBlock().getFace(this.getLastBlock()); - if (blockFace == null) { - return; - } - switch (blockFace) { - case NORTH: - case SOUTH: - this.discNS(v, targetBlock); - break; - - case EAST: - case WEST: - this.discEW(v, targetBlock); - break; - - case UP: - case DOWN: - this.discUD(v, targetBlock); - break; - - default: - break; - } + private void discFace(final SnipeData v) { + this.positions = Shapes.discFace(this.getTargetBlock().getLocation(), v.getBrushSize(), this.smoothCircle, this.getTargetBlock().getFace(this.getLastBlock())); } @Override - protected final void arrow(final SnipeData v) { - this.pre(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.discFace(v); } @Override - protected final void powder(final SnipeData v) { - this.pre(v, this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + this.discFace(v); } @Override @@ -147,6 +67,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DomeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DomeBrush.java index 52af9d30..043436c7 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DomeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DomeBrush.java @@ -1,22 +1,18 @@ package com.github.kevindagame.brush; +import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.vector.VoxelVector; - -import java.util.HashSet; -import java.util.Set; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Dome_Brush + * ... * * @author Gavjenks * @author MikeMatrix */ -public class DomeBrush extends AbstractBrush { +public class DomeBrush extends PerformerBrush { /** * @@ -25,80 +21,35 @@ public DomeBrush() { this.setName("Dome"); } - @Override - public final void info(final VoxelMessage vm) { - vm.brushName(this.getName()); - vm.size(); - vm.voxel(); - vm.height(); - } - /** * @param v - * @param targetBlock */ - @SuppressWarnings("deprecation") - private void generateDome(final SnipeData v, final IBlock targetBlock) { + private void generateDome(final SnipeData v) { if (v.getVoxelHeight() == 0) { v.sendMessage(Messages.VOXEL_HEIGHT_MUST_NOT_BE_0); return; } - final int absoluteHeight = Math.abs(v.getVoxelHeight()); - final boolean negative = v.getVoxelHeight() < 0; - - final Set changeablePositions = new HashSet<>(); - - final Undo undo = new Undo(); - - final int brushSizeTimesVoxelHeight = v.getBrushSize() * absoluteHeight; - final double stepScale = ((v.getBrushSize() * v.getBrushSize()) + brushSizeTimesVoxelHeight + brushSizeTimesVoxelHeight) / 5; - - final double stepSize = 1 / stepScale; - - for (double u = 0; u <= Math.PI / 2; u += stepSize) { - final double y = absoluteHeight * Math.sin(u); - for (double stepV = -Math.PI; stepV <= -(Math.PI / 2); stepV += stepSize) { - final double x = v.getBrushSize() * Math.cos(u) * Math.cos(stepV); - final double z = v.getBrushSize() * Math.cos(u) * Math.sin(stepV); - - final double targetBlockX = targetBlock.getX() + 0.5; - final double targetBlockZ = targetBlock.getZ() + 0.5; - final int targetY = ((int) Math.floor(targetBlock.getY() + (negative ? -y : y))); - final int currentBlockXAdd = ((int) Math.floor(targetBlockX + x)); - final int currentBlockZAdd = ((int) Math.floor(targetBlockZ + z)); - final int currentBlockXSubtract = ((int) Math.floor(targetBlockX - x)); - final int currentBlockZSubtract = ((int) Math.floor(targetBlockZ - z)); - changeablePositions.add(new VoxelVector(currentBlockXAdd, targetY, currentBlockZAdd)); - changeablePositions.add(new VoxelVector(currentBlockXSubtract, targetY, currentBlockZAdd)); - changeablePositions.add(new VoxelVector(currentBlockXAdd, targetY, currentBlockZSubtract)); - changeablePositions.add(new VoxelVector(currentBlockXSubtract, targetY, currentBlockZSubtract)); - - } - } - - for (final VoxelVector vector : changeablePositions) { - final IBlock currentTargetBlock = vector.getLocation(this.getTargetBlock().getWorld()).getBlock(); - // TODO: Check whether BlockData omission affects this or not. - // if (currentTargetBlock.getMaterial() != v.getVoxelMaterial() || currentTargetBlock.getBlockData().matches(v.getVoxelSubstance())) { - if (currentTargetBlock.getMaterial() != v.getVoxelMaterial()) { - undo.put(currentTargetBlock); - currentTargetBlock.setBlockData(v.getVoxelMaterial().createBlockData(), true); - } - } + this.positions = Shapes.dome(this.getTargetBlock().getLocation(), v.getBrushSize(), v.getVoxelHeight()); + } - v.owner().storeUndo(undo); + @Override + public final void info(final VoxelMessage vm) { + vm.brushName(this.getName()); + vm.size(); + vm.voxel(); + vm.height(); } @Override - protected final void arrow(final SnipeData v) { - this.generateDome(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.generateDome(v); } @Override - protected final void powder(final SnipeData v) { - this.generateDome(v, this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + this.generateDome(v); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DrainBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DrainBrush.java index 99fc600e..887b2be9 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DrainBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/DrainBrush.java @@ -1,25 +1,26 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Drain_Brush + * ... * * @author Gavjenks * @author psanker */ public class DrainBrush extends AbstractBrush { - private final double trueCircle = 0.5; + private final boolean smooth = true; private boolean disc = false; /** @@ -29,50 +30,14 @@ public DrainBrush() { this.setName("Drain"); } - @SuppressWarnings("deprecation") private void drain(final SnipeData v) { - final int brushSize = v.getBrushSize(); - final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); - final Undo undo = new Undo(); - if (this.disc) { - for (int x = brushSize; x >= 0; x--) { - final double xSquared = Math.pow(x, 2); - - for (int z = brushSize; z >= 0; z--) { - if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared) { - for (int dx : new int[]{-1, 1}) { - for (int dz : new int[]{-1, 1}) { - IBlock b = this.clampY(this.getTargetBlock().getX() + (x * dx), this.getTargetBlock().getY(), this.getTargetBlock().getZ() + (z * dz)); - if (b.getMaterial().isFluid()) { - undo.put(b); - b.setMaterial(VoxelMaterial.AIR); - } - } - } - } - } - } - } else { - for (int x = (brushSize + 1) * 2; x >= 0; x--) { - final double xSquared = Math.pow(x - brushSize, 2); - - for (int z = (brushSize + 1) * 2; z >= 0; z--) { - final double zSquared = Math.pow(z - brushSize, 2); - - for (int y = (brushSize + 1) * 2; y >= 0; y--) { - if ((xSquared + Math.pow(y - brushSize, 2) + zSquared) <= brushSizeSquared) { - IBlock b = this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + y - brushSize, this.getTargetBlock().getZ() + z - brushSize); - if (b.getMaterial().isFluid()) { - undo.put(b); - b.setMaterial(VoxelMaterial.AIR); - } - } - } - } + var positions = this.disc ? Shapes.disc(getTargetBlock().getLocation(), v.getBrushSize(), smooth) : Shapes.ball(getTargetBlock().getLocation(), v.getBrushSize(), smooth); + for (var pos : positions) { + var block = pos.getBlock(); + if (block.getMaterial().isFluid()) { + addOperation(new BlockOperation(pos, block.getBlockData(), VoxelMaterial.AIR.createBlockData())); } } - - v.owner().storeUndo(undo); } @Override @@ -90,12 +55,12 @@ public final void info(final VoxelMessage vm) { vm.brushName(this.getName()); vm.size(); - vm.custom(Messages.DRAIN_TRUE_CIRCLE_MODE.replace("%state%", (this.trueCircle == 0.5) ? "ON" : "OFF")); + vm.custom(Messages.DRAIN_TRUE_CIRCLE_MODE.replace("%state%", this.smooth ? "ON" : "OFF")); vm.custom(Messages.DISC_DRAIN_MODE.replace("%state%", (this.disc) ? "ON" : "OFF")); } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.DRAIN_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -109,6 +74,7 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipseBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipseBrush.java index 2384f123..6d89e9c0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipseBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipseBrush.java @@ -1,18 +1,20 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Objects; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Ellipse_Brush + * ... * * @author psanker */ @@ -44,18 +46,18 @@ private void ellipse(final SnipeData v, IBlock targetBlock) { final int x = (int) Math.round(this.xscl * Math.cos(steps)); final int y = (int) Math.round(this.yscl * Math.sin(steps)); - switch (getTargetBlock().getFace(this.getLastBlock())) { + switch (Objects.requireNonNull(getTargetBlock().getFace(this.getLastBlock()))) { case NORTH: case SOUTH: - currentPerformer.perform(targetBlock.getRelative(0, x, y)); + positions.add(targetBlock.getRelative(0, x, y).getLocation()); break; case EAST: case WEST: - currentPerformer.perform(targetBlock.getRelative(x, y, 0)); + positions.add(targetBlock.getRelative(x, y, 0).getLocation()); break; case UP: case DOWN: - currentPerformer.perform(targetBlock.getRelative(x, 0, y)); + positions.add(targetBlock.getRelative(x, 0, y).getLocation()); default: break; } @@ -67,15 +69,13 @@ private void ellipse(final SnipeData v, IBlock targetBlock) { } catch (final Exception exception) { v.sendMessage(Messages.INVALID_TARGET); } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private void ellipsefill(final SnipeData v, IBlock targetBlock) { int ix = this.xscl; int iy = this.yscl; - currentPerformer.perform(targetBlock); + positions.add(targetBlock.getLocation()); try { if (ix >= iy) { // Need this unless you want weird holes @@ -84,18 +84,18 @@ private void ellipsefill(final SnipeData v, IBlock targetBlock) { final int x = (int) Math.round(ix * Math.cos(steps)); final int y = (int) Math.round(iy * Math.sin(steps)); - switch (getTargetBlock().getFace(this.getLastBlock())) { + switch (Objects.requireNonNull(getTargetBlock().getFace(this.getLastBlock()))) { case NORTH: case SOUTH: - currentPerformer.perform(targetBlock.getRelative(0, x, y)); + positions.add(targetBlock.getRelative(0, x, y).getLocation()); break; case EAST: case WEST: - currentPerformer.perform(targetBlock.getRelative(x, y, 0)); + positions.add(targetBlock.getRelative(x, y, 0).getLocation()); break; case UP: case DOWN: - currentPerformer.perform(targetBlock.getRelative(x, 0, y)); + positions.add(targetBlock.getRelative(x, 0, y).getLocation()); default: break; } @@ -112,18 +112,18 @@ private void ellipsefill(final SnipeData v, IBlock targetBlock) { final int x = (int) Math.round(ix * Math.cos(steps)); final int y = (int) Math.round(iy * Math.sin(steps)); - switch (getTargetBlock().getFace(this.getLastBlock())) { + switch (Objects.requireNonNull(getTargetBlock().getFace(this.getLastBlock()))) { case NORTH: case SOUTH: - currentPerformer.perform(targetBlock.getRelative(0, x, y)); + positions.add(targetBlock.getRelative(0, x, y).getLocation()); break; case EAST: case WEST: - currentPerformer.perform(targetBlock.getRelative(x, y, 0)); + positions.add(targetBlock.getRelative(x, y, 0).getLocation()); break; case UP: case DOWN: - currentPerformer.perform(targetBlock.getRelative(x, 0, y)); + positions.add(targetBlock.getRelative(x, 0, y).getLocation()); default: break; } @@ -138,8 +138,6 @@ private void ellipsefill(final SnipeData v, IBlock targetBlock) { } catch (final Exception exception) { v.sendMessage(Messages.INVALID_TARGET); } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private void execute(final SnipeData v, IBlock targetBlock) { @@ -153,17 +151,17 @@ private void execute(final SnipeData v, IBlock targetBlock) { } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.execute(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.execute(v, this.getLastBlock()); } @Override - public final void info(final VoxelMessage vm) { + public final void info(@NotNull final VoxelMessage vm) { if (this.xscl < SCL_MIN || this.xscl > SCL_MAX) { this.xscl = SCL_DEFAULT; } @@ -243,6 +241,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -252,6 +251,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipsoidBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipsoidBrush.java index e5772a57..a04e21c3 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipsoidBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EllipsoidBrush.java @@ -1,18 +1,19 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Ellipsoid_Brush + * ... */ public class EllipsoidBrush extends PerformerBrush { @@ -28,12 +29,12 @@ public EllipsoidBrush() { this.setName("Ellipsoid"); } - private void execute(final SnipeData v, IBlock targetBlock) { - this.currentPerformer.perform(targetBlock); + private void execute(final SnipeData v) { + positions.add(getTargetBlock().getLocation()); double istrueoffset = istrue ? 0.5 : 0; - int blockPositionX = targetBlock.getX(); - int blockPositionY = targetBlock.getY(); - int blockPositionZ = targetBlock.getZ(); + int blockPositionX = getTargetBlock().getX(); + int blockPositionY = getTargetBlock().getY(); + int blockPositionZ = getTargetBlock().getZ(); for (double x = 0; x <= xRad; x++) { @@ -48,31 +49,29 @@ private void execute(final SnipeData v, IBlock targetBlock) { final double ySquared = (y / (yRad + istrueoffset)) * (y / (yRad + istrueoffset)); if (xSquared + ySquared + zSquared <= 1) { - this.currentPerformer.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ + z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ - z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ + z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ - z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ + z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ - z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ + z))); - this.currentPerformer.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ - z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ + z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ - z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ + z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ - z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ + z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ - z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ + z))); + positions.add(new BaseLocation(getWorld(), (int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ - z))); } } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { - this.execute(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.execute(v); } @Override - protected final void powder(final SnipeData v) { - this.execute(v, this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + this.execute(v); } @Override @@ -115,6 +114,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -124,6 +124,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityBrush.java index bae2e7b1..7d6368bc 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityBrush.java @@ -3,13 +3,15 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.EntitySpawnOperation; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Entity_Brush + * ... * * @author Piotr */ @@ -27,7 +29,7 @@ public EntityBrush() { private void spawn(final SnipeData v) { for (int x = 0; x < v.getBrushSize(); x++) { try { - this.getWorld().spawn(this.getLastBlock().getLocation(), this.entityType); + addOperation(new EntitySpawnOperation(this.getLastBlock().getLocation(), entityType)); } catch (final IllegalArgumentException exception) { v.sendMessage(Messages.ENTITYBRUSH_SPAWN_FAIL); } @@ -36,12 +38,12 @@ private void spawn(final SnipeData v) { @Override protected final void arrow(final SnipeData v) { - this.spawn(v); + spawn(v); } @Override protected final void powder(final SnipeData v) { - this.spawn(v); + spawn(v); } @Override @@ -51,7 +53,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.ENTITYBRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -73,6 +75,7 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { List entities = new ArrayList<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityRemovalBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityRemovalBrush.java index 2a07869a..1ba178ea 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityRemovalBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EntityRemovalBrush.java @@ -1,12 +1,14 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.EntityRemoveOperation; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.entity.IEntity; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -15,7 +17,7 @@ import java.util.stream.Collectors; /** - * + * ... */ public class EntityRemovalBrush extends AbstractBrush { @@ -83,7 +85,7 @@ private int removeEntities(IChunk chunk) throws PatternSyntaxException { continue; } - entity.remove(); + addOperation(new EntityRemoveOperation(entity.getLocation(), entity)); entityCount++; } @@ -92,12 +94,12 @@ private int removeEntities(IChunk chunk) throws PatternSyntaxException { @Override protected void arrow(SnipeData v) { - this.radialRemoval(v); + radialRemoval(v); } @Override protected void powder(SnipeData v) { - this.radialRemoval(v); + radialRemoval(v); } @Override @@ -109,7 +111,7 @@ public void info(VoxelMessage vm) { } @Override - public void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.ENTITY_REMOVAL_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -159,12 +161,14 @@ public void parseParameters(final String triggerHandle, final String[] params, f v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("+", "-", "reset", "clear", "list")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EraserBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EraserBrush.java index 17374362..9f1b34f0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EraserBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/EraserBrush.java @@ -1,35 +1,25 @@ package com.github.kevindagame.brush; +import com.github.kevindagame.snipe.SnipeAction; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import com.github.kevindagame.voxelsniper.world.IWorld; import java.util.Set; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Eraser_Brush + * ... * * @author Voxel */ public class EraserBrush extends AbstractBrush { - //todo This was enumset, should it still be? private static final Set EXCLUSIVE_MATERIALS = Set.of( - VoxelMaterial.AIR, VoxelMaterial.CAVE_AIR, VoxelMaterial.VOID_AIR, VoxelMaterial.STONE, VoxelMaterial.GRASS_BLOCK, VoxelMaterial.DIRT, VoxelMaterial.SAND, VoxelMaterial.GRAVEL, VoxelMaterial.SANDSTONE); + VoxelMaterial.AIR, VoxelMaterial.CAVE_AIR, VoxelMaterial.VOID_AIR, VoxelMaterial.STONE, VoxelMaterial.GRASS_BLOCK, VoxelMaterial.DIRT, VoxelMaterial.SAND, VoxelMaterial.GRAVEL, VoxelMaterial.SANDSTONE, VoxelMaterial.DEEPSLATE); private static final Set EXCLUSIVE_LIQUIDS = Set.of( VoxelMaterial.WATER, VoxelMaterial.LAVA); - static { - try { - // 1.17+ - EXCLUSIVE_MATERIALS.add(VoxelMaterial.DEEPSLATE); - } catch (Throwable ignore) { - // Don't add for older versions - } - } - /** * */ @@ -37,39 +27,27 @@ public EraserBrush() { this.setName("Eraser"); } - private void doErase(final SnipeData v, final boolean keepWater) { - final int brushSize = v.getBrushSize(); - final int brushSizeDoubled = 2 * brushSize; - IWorld world = this.getTargetBlock().getWorld(); - final Undo undo = new Undo(); + private void doErase(final SnipeData v) { - for (int x = brushSizeDoubled; x >= 0; x--) { - int currentX = this.getTargetBlock().getX() - brushSize + x; - for (int y = 0; y <= brushSizeDoubled; y++) { - int currentY = this.getTargetBlock().getY() - brushSize + y; - for (int z = brushSizeDoubled; z >= 0; z--) { - int currentZ = this.getTargetBlock().getZ() - brushSize + z; - IBlock currentBlock = world.getBlock(currentX, currentY, currentZ); - if (EXCLUSIVE_MATERIALS.contains(currentBlock.getMaterial()) - || (keepWater && EXCLUSIVE_LIQUIDS.contains(currentBlock.getMaterial()))) { - continue; - } - undo.put(currentBlock); - currentBlock.setMaterial(VoxelMaterial.AIR); - } + var positions = Shapes.voxel(this.getTargetBlock().getLocation(), v.getBrushSize()); + for (var pos : positions) { + var currentBlock = pos.getBlock(); + if (EXCLUSIVE_MATERIALS.contains(currentBlock.getMaterial()) + || (getSnipeAction() == SnipeAction.GUNPOWDER && EXCLUSIVE_LIQUIDS.contains(currentBlock.getMaterial()))) { + continue; } + addOperation(new BlockOperation(pos, currentBlock.getBlockData(), VoxelMaterial.AIR.createBlockData())); } - v.owner().storeUndo(undo); } @Override protected final void arrow(final SnipeData v) { - this.doErase(v, false); + this.doErase(v); } @Override protected final void powder(final SnipeData v) { - this.doErase(v, true); + this.doErase(v); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ErodeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ErodeBrush.java index 5a4a5bde..90b74ac8 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ErodeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ErodeBrush.java @@ -1,21 +1,22 @@ package com.github.kevindagame.brush; -import com.google.common.base.Objects; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.vector.VoxelVector; import com.github.kevindagame.voxelsniper.world.IWorld; +import com.google.common.base.Objects; +import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.stream.Collectors; /** - * http://www.voxelwiki.com/minecraft/VoxelSniper#The_Erosion_Brush + * ... * * @author Piotr * @author MikeMatrix @@ -25,6 +26,7 @@ public class ErodeBrush extends AbstractBrush { private static final VoxelVector[] FACES_TO_CHECK = {new VoxelVector(0, 0, 1), new VoxelVector(0, 0, -1), new VoxelVector(0, 1, 0), new VoxelVector(0, -1, 0), new VoxelVector(1, 0, 0), new VoxelVector(-1, 0, 0)}; private String presetName = "NONE"; private ErosionPreset currentPreset = new ErosionPreset(0, 1, 0, 1); + private BlockChangeTracker blockTracker; /** * @@ -33,6 +35,7 @@ public ErodeBrush() { this.setName("Erode"); } + @Override protected final void arrow(final SnipeData v) { this.erosion(v, this.currentPreset); @@ -43,7 +46,6 @@ protected final void powder(final SnipeData v) { this.erosion(v, this.currentPreset.getInverted()); } - @SuppressWarnings("deprecation") private void erosion(final SnipeData v, final ErosionPreset erosionPreset) { final BlockChangeTracker blockChangeTracker = new BlockChangeTracker(this.getTargetBlock().getWorld()); @@ -56,14 +58,8 @@ private void erosion(final SnipeData v, final ErosionPreset erosionPreset) { for (int i = 0; i < erosionPreset.getFillRecursion(); ++i) { fillIteration(v, erosionPreset, blockChangeTracker, targetBlockVector); } - - final Undo undo = new Undo(); - for (final BlockWrapper blockWrapper : blockChangeTracker.getAll()) { - undo.put(blockWrapper.getBlock()); - blockWrapper.getBlock().setBlockData(blockWrapper.getBlockData(), true); - } - - v.owner().storeUndo(undo); + blockChangeTracker.getAll().forEach(block -> addOperation(new BlockOperation(block.block.getLocation(), block.block.getBlockData(), block.blockData))); + this.blockTracker = blockChangeTracker; } private void erosionIteration(final SnipeData v, final ErosionPreset erosionPreset, final BlockChangeTracker blockChangeTracker, final VoxelVector targetBlockVector) { @@ -159,7 +155,7 @@ public final void info(final VoxelMessage vm) { @Override // TODO: Implement changing of individual variables | fill erode fillrecursion eroderecursion - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.ERODE_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -175,10 +171,11 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { - return new ArrayList<>(Arrays.stream(Preset.values()).map(e -> e.name()).collect(Collectors.toList())); + return Arrays.stream(Preset.values()).map(Enum::name).collect(Collectors.toList()); } @Override @@ -286,7 +283,6 @@ private static final class BlockWrapper { private final IBlock block; private final IBlockData blockData; - @SuppressWarnings("deprecation") public BlockWrapper(final IBlock block) { this.block = block; this.blockData = block.getBlockData(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FillDownBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FillDownBrush.java index e949e695..1a30c0ae 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FillDownBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FillDownBrush.java @@ -1,17 +1,19 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** * @author Voxel + * ... */ public class FillDownBrush extends PerformerBrush { @@ -63,7 +65,7 @@ private void fillDown(final SnipeData v, final IBlock b) { targetBlock.getY() + y, targetBlock.getZ() + z); if (currentBlock.isEmpty() || (fillLiquid && currentBlock.isLiquid())) { - this.currentPerformer.perform(currentBlock); + this.positions.add(currentBlock.getLocation()); } else { break; } @@ -71,17 +73,15 @@ private void fillDown(final SnipeData v, final IBlock b) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.fillDown(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.fillDown(v, this.getLastBlock()); } @@ -122,6 +122,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JaggedLineBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JaggedLineBrush.java index 52967aef..1474c731 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JaggedLineBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JaggedLineBrush.java @@ -1,17 +1,19 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.*; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Jagged_Line_Brush + * ... * * @author Giltwist * @author Monofraps @@ -47,21 +49,19 @@ private void jaggedP(final SnipeData v) { final double length = this.targetCoords.distance(this.originCoords); if (length == 0) { - this.currentPerformer.perform(this.targetCoords.getLocation(this.getWorld()).getBlock()); + this.positions.add(this.targetCoords.getLocation(this.getWorld())); } else { for (final Iterator iterator = getWorld().getBlockIterator(originClone, direction, 0, ((int) Math.round(length))); iterator.hasNext(); ) { final IBlock block = iterator.next(); for (int i = 0; i < recursion; i++) { - this.currentPerformer.perform(this.clampY(Math.round(block.getX() + this.random.nextInt(spread * 2) - spread), Math.round(block.getY() + this.random.nextInt(spread * 2) - spread), Math.round(block.getZ() + this.random.nextInt(spread * 2) - spread))); + this.positions.add(new BaseLocation(getWorld(), Math.round(block.getX() + this.random.nextInt(spread * 2) - spread), Math.round(block.getY() + this.random.nextInt(spread * 2) - spread), Math.round(block.getZ() + this.random.nextInt(spread * 2) - spread))); } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - public final void arrow(final SnipeData v) { + public final void doArrow(final SnipeData v) { if (originCoords == null) { originCoords = new VoxelVector(); } @@ -70,7 +70,7 @@ public final void arrow(final SnipeData v) { } @Override - public final void powder(final SnipeData v) { + public final void doPowder(final SnipeData v) { if (originCoords == null) { v.sendMessage(Messages.FIRST_COORDINATE_NOT_SET); } else { @@ -121,6 +121,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -130,6 +131,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JockeyBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JockeyBrush.java index 3cd0adb0..be364da8 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JockeyBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/JockeyBrush.java @@ -1,24 +1,27 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.entity.IEntity; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author Voxel * @author Monofraps + * ... */ -public class JockeyBrush extends AbstractBrush { +public class JockeyBrush extends CustomBrush { private static final int ENTITY_STACK_LIMIT = 50; private JockeyType jockeyType = JockeyType.NORMAL; @@ -34,7 +37,7 @@ public JockeyBrush() { } private void sitOn(final SnipeData v) { - VoxelLocation location = this.getLastBlock().getLocation(); + BaseLocation location = this.getLastBlock().getLocation(); IChunk targetChunk = location.getChunk(); final int targetChunkX = targetChunk.getX(); final int targetChunkZ = targetChunk.getZ(); @@ -114,67 +117,26 @@ private void stack(final SnipeData v) { @Override protected final void arrow(final SnipeData v) { - if (jockeyType == JockeyType.STACK) { - stack(v); - } else { - this.sitOn(v); - } + addOperation(new CustomOperation(getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override protected final void powder(final SnipeData v) { - // invers || stack: remove passenger(s) from player - // normal: remove player from pasenger (jockeyedEntity) - if (jockeyType == JockeyType.INVERSE || jockeyType == JockeyType.STACK) { - Set foundPassengers = new HashSet<>(); - foundPassengers.add(v.owner().getPlayer()); - while (foundPassengers.size() > 0) { - Set entities = foundPassengers; - foundPassengers = new HashSet<>(); - for (IEntity e : entities) { - List passengers = e.getPassengers(); - if (passengers.size() > 0) { - foundPassengers.addAll(passengers); - e.eject(); - } - } - } - } else { - if (jockeyedEntity != null) { - jockeyedEntity.eject(); - jockeyedEntity = null; - v.sendMessage(Messages.YOU_HAVE_BEEN_EJECTED); - } - } - + addOperation(new CustomOperation(getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override public final void info(final VoxelMessage vm) { vm.brushName(this.getName()); - vm.custom(Messages.CURRENT_JOCKEY_MODE.replace("%mode%", jockeyType.getName(this.playerOnly))); + vm.custom(Messages.CURRENT_JOCKEY_MODE.replace("%mode%", jockeyType.getName())); } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.JOCKEY_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; } - - if (params[0].equalsIgnoreCase("player")) { - this.playerOnly = !this.playerOnly; - - if (playerOnly) { - jockeyType = JockeyType.valueOf(this.jockeyType.name().split("_")[0] + "_PLAYER_ONLY"); - v.sendMessage(Messages.JOCKEY_TARGETING_PLAYERS); - } else { - jockeyType = JockeyType.valueOf(this.jockeyType.name().split("_")[0] + "_ALL_ENTITIES"); - v.sendMessage(Messages.JOCKEY_TARGETING_ENTITIES); - } - return; - } - try { if (params[0].equalsIgnoreCase("inverse")) { jockeyType = JockeyType.INVERSE; @@ -183,16 +145,17 @@ public final void parseParameters(final String triggerHandle, final String[] par } else if (params[0].equalsIgnoreCase("normal")) { jockeyType = JockeyType.NORMAL; } - v.sendMessage(Messages.CURRENT_JOCKEY_MODE.replace("%mode%", jockeyType.getName(this.playerOnly))); + v.sendMessage(Messages.CURRENT_JOCKEY_MODE.replace("%mode%", jockeyType.getName())); } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } } + @NotNull @Override public List registerArguments() { - return new ArrayList<>(Lists.newArrayList("inverse", "stack", "normal", "player")); + return new ArrayList<>(Lists.newArrayList("inverse", "stack", "normal")); } @Override @@ -200,6 +163,47 @@ public String getPermissionNode() { return "voxelsniper.brush.jockey"; } + @Override + public boolean perform(@NotNull ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + if (operations.size() != 1) return false; + switch (Objects.requireNonNull(getSnipeAction())) { + case GUNPOWDER: + // invers || stack: remove passenger(s) from player + // normal: remove player from pasenger (jockeyedEntity) + if (jockeyType == JockeyType.INVERSE || jockeyType == JockeyType.STACK) { + Set foundPassengers = new HashSet<>(); + foundPassengers.add(snipeData.owner().getPlayer()); + while (foundPassengers.size() > 0) { + Set entities = foundPassengers; + foundPassengers = new HashSet<>(); + for (IEntity e : entities) { + List passengers = e.getPassengers(); + if (passengers.size() > 0) { + foundPassengers.addAll(passengers); + e.eject(); + } + } + } + } else { + if (jockeyedEntity != null) { + jockeyedEntity.eject(); + jockeyedEntity = null; + snipeData.sendMessage(Messages.YOU_HAVE_BEEN_EJECTED); + } + } + return true; + case ARROW: + if (jockeyType == JockeyType.STACK) { + stack(snipeData); + } else { + this.sitOn(snipeData); + } + return true; + default: + return false; + } + } + /** * Available types of jockey modes. */ @@ -219,8 +223,8 @@ public String toString() { return this.name; } - public String getName(boolean playerOnly) { - return this.name + (playerOnly ? " (Player only)" : " (All)"); + public String getName() { + return this.name; } } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LightningBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LightningBrush.java index b8b7d9d6..83aaef95 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LightningBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LightningBrush.java @@ -1,13 +1,19 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; /** * @author Gavjenks + * ... */ -public class LightningBrush extends AbstractBrush { +public class LightningBrush extends CustomBrush { /** * @@ -24,16 +30,22 @@ public final void info(final VoxelMessage vm) { @Override protected final void arrow(final SnipeData v) { - this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); + addOperation(new CustomOperation(this.getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override protected final void powder(final SnipeData v) { - this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); + addOperation(new CustomOperation(this.getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override public String getPermissionNode() { return "voxelsniper.brush.lightning"; } + + @Override + public boolean perform(@NotNull ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + operations.forEach(operation -> operation.getLocation().getWorld().strikeLightning(operation.getLocation())); + return true; + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LineBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LineBrush.java index 723ef182..c7ee9b3a 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LineBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/LineBrush.java @@ -3,23 +3,19 @@ import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.vector.VoxelVector; import com.github.kevindagame.voxelsniper.world.IWorld; -import java.util.Iterator; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Line_Brush + * ... * * @author Gavjenks * @author giltwist * @author MikeMatrix */ public class LineBrush extends PerformerBrush { - - private static final VoxelVector HALF_BLOCK_OFFSET = new VoxelVector(0.5, 0.5, 0.5); private VoxelVector originCoords = null; private VoxelVector targetCoords = new VoxelVector(); private IWorld targetWorld; @@ -48,33 +44,18 @@ public final void parseParameters(final String triggerHandle, final String[] par } private void linePowder(final SnipeData v) { - final VoxelVector originClone = this.originCoords.clone().add(LineBrush.HALF_BLOCK_OFFSET); - final VoxelVector targetClone = this.targetCoords.clone().add(LineBrush.HALF_BLOCK_OFFSET); - - final VoxelVector direction = targetClone.clone().subtract(originClone); - final double length = this.targetCoords.distance(this.originCoords); - - if (length == 0) { - this.currentPerformer.perform(this.targetCoords.getLocation(this.targetWorld).getBlock()); - } else { - for (final Iterator blockIterator = getWorld().getBlockIterator(originClone, direction, 0, (int) Math.round(length)); blockIterator.hasNext(); ) { - final IBlock currentBlock = blockIterator.next(); - this.currentPerformer.perform(currentBlock); - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); + this.positions = Shapes.line(this.originCoords, this.targetCoords, this.getWorld()); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.originCoords = this.getTargetBlock().getLocation().toVector(); this.targetWorld = this.getTargetBlock().getWorld(); v.sendMessage(Messages.FIRST_POINT_SELECTED); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { if (this.originCoords == null || !this.getTargetBlock().getWorld().equals(this.targetWorld)) { v.sendMessage(Messages.FIRST_COORDINATE_NOT_SET); } else { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OverlayBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OverlayBrush.java index 34f421ae..dc296c12 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OverlayBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OverlayBrush.java @@ -1,19 +1,21 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelList; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Overlay_.2F_Topsoil_Brush + * ... * * @author Gavjenks */ @@ -47,7 +49,7 @@ private void overlay(final SnipeData v) { for (int currentDepth = y; y - currentDepth < depth; currentDepth--) { final VoxelMaterial currentBlock = this.getBlockMaterialAt(this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z); if (isOverrideableMaterial(v.getVoxelList(), currentBlock)) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z)); + positions.add(new BaseLocation(getWorld(), this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z)); } } break; @@ -57,8 +59,6 @@ private void overlay(final SnipeData v) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private void overlayTwo(final SnipeData v) { @@ -78,7 +78,7 @@ private void overlayTwo(final SnipeData v) { final VoxelMaterial currentBlock = this.getBlockMaterialAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z); if (this.isOverrideableMaterial(v.getVoxelList(), currentBlock)) { for (int d = 1; (d < this.depth + 1); d++) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify + positions.add(new BaseLocation(getWorld(), this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify // in parameters memory[x + brushSize][z + brushSize] = 1; // stop it from checking any other blocks in this vertical 1x1 column. } @@ -91,8 +91,6 @@ private void overlayTwo(final SnipeData v) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private boolean isIgnoredBlock(VoxelMaterial material) { @@ -111,7 +109,7 @@ private boolean isOverrideableMaterial(VoxelList list, VoxelMaterial material) { } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { if (this.useVoxelList && v.getVoxelList().isEmpty()) { v.sendMessage(Messages.OVERLAY_BRUSH_VOXELLIST_EMPTY); return; @@ -120,7 +118,7 @@ protected final void arrow(final SnipeData v) { } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.overlayTwo(v); } @@ -174,6 +172,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -183,6 +182,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PaintingBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PaintingBrush.java index 3015c346..11527710 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PaintingBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PaintingBrush.java @@ -1,15 +1,22 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.BlockHelper; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; /** - * Painting scrolling Brush. http://www.voxelwiki.com/minecraft/Voxelsniper#The_Painting_Picker_Brush + * Painting scrolling Brush. ... * * @author Voxel */ -public class PaintingBrush extends AbstractBrush { +public class PaintingBrush extends CustomBrush { /** * @@ -25,7 +32,7 @@ public PaintingBrush() { */ @Override protected final void arrow(final SnipeData v) { - BlockHelper.painting(v.owner().getPlayer(), true, false, 0); + addOperation(new CustomOperation(getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } /** @@ -35,7 +42,7 @@ protected final void arrow(final SnipeData v) { */ @Override protected final void powder(final SnipeData v) { - BlockHelper.painting(v.owner().getPlayer(), true, true, 0); + addOperation(new CustomOperation(getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override @@ -47,4 +54,18 @@ public final void info(final VoxelMessage vm) { public String getPermissionNode() { return "voxelsniper.brush.painting"; } + + @Override + public boolean perform(@NotNull ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + switch (Objects.requireNonNull(getSnipeAction())) { + case ARROW: + BlockHelper.painting(snipeData.owner().getPlayer(), true, false, 0); + return true; + case GUNPOWDER: + BlockHelper.painting(snipeData.owner().getPlayer(), true, true, 0); + return true; + default: + return false; + } + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RegenerateChunkBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RegenerateChunkBrush.java index 9d8d53bc..9cc84da5 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RegenerateChunkBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RegenerateChunkBrush.java @@ -4,38 +4,36 @@ import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.chunk.IChunk; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; /** * Regenerates the target chunk. + * ... * * @author Mick */ -public class RegenerateChunkBrush extends AbstractBrush { +public class RegenerateChunkBrush extends CustomBrush { + private int originalSize; - /** - * - */ public RegenerateChunkBrush() { this.setName("Chunk Generator 40k"); } private void generateChunk(final SnipeData v) { final IChunk chunk = this.getTargetBlock().getChunk(); - final Undo undo = new Undo(); - for (int z = CHUNK_SIZE; z >= 0; z--) { for (int x = CHUNK_SIZE; x >= 0; x--) { for (int y = this.getMaxHeight(); y >= this.getMinHeight(); y--) { - undo.put(chunk.getBlock(x, y, z)); + addOperation(new CustomOperation(new BaseLocation(this.getWorld(), chunk.getX() * 16 + x, y, chunk.getZ() * 16 + z), this, v, CustomOperationContext.OTHER)); } } } - v.owner().storeUndo(undo); - - v.sendMessage(Messages.GENERATED_CHUNK.replace("%chunk.getX%", Integer.toString(chunk.getX())).replace("%chunk.getZ%", Integer.toString(chunk.getZ()))); - this.getWorld().regenerateChunk(chunk.getX(), chunk.getZ()); - this.getWorld().refreshChunk(chunk.getX(), chunk.getZ()); + originalSize = this.getOperationsCount(); } @Override @@ -58,4 +56,24 @@ public final void info(final VoxelMessage vm) { public String getPermissionNode() { return "voxelsniper.brush.regeneratechunk"; } + + @Override + public boolean perform(@NotNull ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + final IChunk chunk = this.getTargetBlock().getChunk(); + //check if no operation has been cancelled by comparing the size to the amount of loops + if (operations.stream().filter(o -> !o.isCancelled()).count() != originalSize) { + return false; + } + for (int z = CHUNK_SIZE; z >= 0; z--) { + for (int x = CHUNK_SIZE; x >= 0; x--) { + for (int y = this.getMaxHeight(); y >= this.getMinHeight(); y--) { + undo.put(chunk.getBlock(x, y, z)); + } + } + } + snipeData.sendMessage(Messages.GENERATED_CHUNK.replace("%chunk.getX%", Integer.toString(chunk.getX())).replace("%chunk.getZ%", Integer.toString(chunk.getZ()))); + this.getWorld().regenerateChunk(chunk.getX(), chunk.getZ()); + this.getWorld().refreshChunk(chunk.getX(), chunk.getZ()); + return true; + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RingBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RingBrush.java index 492b3d82..f148b9a3 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RingBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RingBrush.java @@ -1,18 +1,20 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Ring_Brush + * ... * * @author Voxel */ @@ -33,33 +35,16 @@ public RingBrush() { } private void ring(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - final double outerSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - final double innerSquared = Math.pow(this.innerSize, 2); - - for (int x = brushSize; x >= 0; x--) { - final double xSquared = Math.pow(x, 2); - for (int z = brushSize; z >= 0; z--) { - final double ySquared = Math.pow(z, 2); - if ((xSquared + ySquared) <= outerSquared && (xSquared + ySquared) >= innerSquared) { - currentPerformer.perform(targetBlock.getRelative(x, 0, z)); - currentPerformer.perform(targetBlock.getRelative(x, 0, -z)); - currentPerformer.perform(targetBlock.getRelative(-x, 0, z)); - currentPerformer.perform(targetBlock.getRelative(-x, 0, -z)); - } - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); + this.positions = Shapes.ring(this.getTargetBlock().getLocation(), v.getBrushSize(), this.innerSize, this.smoothCircle); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.ring(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.ring(v, this.getLastBlock()); } @@ -97,6 +82,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -106,6 +92,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { // Number variables diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DBrush.java index aa7d14e9..bdaaca09 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DBrush.java @@ -1,19 +1,23 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; + import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** * @author Piotr + * ... */ public class Rot2DBrush extends AbstractBrush { private BlockWrapper[][][] snap; @@ -43,9 +47,9 @@ private void getMatrix(final int bSize) { sy = this.getTargetBlock().getY() - bSize; if (xSquared + Math.pow(y - bSize, 2) <= brushSizeSquared) { for (int z = 0; z < this.snap.length; z++) { - final IBlock block = this.clampY(sx, sy, sz); // why is this not sx + x, sy + y sz + z? + final IBlock block = getWorld().getBlock(sx, sy, sz); this.snap[x][z][y] = new BlockWrapper(block); - block.setMaterial(VoxelMaterial.AIR); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), VoxelMaterial.AIR.createBlockData())); sy++; } } @@ -84,7 +88,9 @@ private void rotate(final int bSize, final SnipeData v) { if (block.getMaterial().isAir()) { continue; } - this.setBlockMaterialAndDataAt(this.getTargetBlock().getX() + (int) newX, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + (int) newZ, block.getBlockData()); + var b = getWorld().getBlock(this.getTargetBlock().getX() + (int) newX, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + (int) newZ); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), block.getBlockData())); + } } } @@ -119,8 +125,8 @@ private void rotate(final int bSize, final SnipeData v) { } else { winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C; } - - this.setBlockMaterialAndDataAt(fx, fy, fz, winner); + var block = getWorld().getBlock(fx, fy, fz); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), winner)); } } } @@ -149,7 +155,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.ROTATE_2D_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -164,6 +170,7 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DvertBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DvertBrush.java index 9a11124a..b699403c 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DvertBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot2DvertBrush.java @@ -1,6 +1,5 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; @@ -8,6 +7,8 @@ import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -47,7 +48,7 @@ private void getMatrix(final int bSize) { sy = this.getTargetBlock().getY() - bSize; for (int y = 0; y < this.snap.length; y++) { - final IBlock block = this.clampY(sx, sy, sz); // why is this not sx + x, sy + y sz + z? + final IBlock block = this.getWorld().getBlock(sx, sy, sz); // why is this not sx + x, sy + y sz + z? this.snap[x][y][z] = new BlockWrapper(block); block.setMaterial(VoxelMaterial.AIR); sy++; @@ -88,7 +89,7 @@ private void rotate(final int bSize, final SnipeData v) { if (block.getMaterial().isAir()) { continue; } - this.setBlockMaterialAndDataAt(this.getTargetBlock().getX() + yy, this.getTargetBlock().getY() + (int) newX, this.getTargetBlock().getZ() + (int) newZ, block.getBlockData()); + this.getWorld().getBlock(this.getTargetBlock().getX() + yy, this.getTargetBlock().getY() + (int) newX, this.getTargetBlock().getZ() + (int) newZ).setBlockData(block.getBlockData()); } } } @@ -124,7 +125,7 @@ private void rotate(final int bSize, final SnipeData v) { winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C; } - this.setBlockMaterialAndDataAt(fy, fx, fz, winner); + this.getWorld().getBlock(fy, fx, fz).setBlockData(winner); } } } @@ -152,7 +153,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.ROTATE_2D_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -167,6 +168,7 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot3DBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot3DBrush.java index af19359c..05f460f3 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot3DBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/Rot3DBrush.java @@ -1,6 +1,5 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.BlockWrapper; @@ -9,13 +8,15 @@ import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * + * ... */ public class Rot3DBrush extends AbstractBrush { @@ -41,7 +42,7 @@ public final void info(final VoxelMessage vm) { // --> agreed. Do what erode does and store one snapshot with Block pointers and int id of what the block started with, afterwards simply go thru that // matrix and compare Block.getId with 'id' if different undo.add( new BlockWrapper ( Block, oldId ) ) @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { // which way is clockwise is less obvious for roll and pitch... should probably fix that / make it clear if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.ROTATION_3D_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); @@ -81,12 +82,14 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("pitch", "roll", "yaw")); } + @NotNull @Override public HashMap> registerArgumentValues() { // Number variables @@ -118,7 +121,7 @@ private void getMatrix(final int bSize) { // only need to do once. But y needs t for (int y = 0; y < this.snap.length; y++) { if (xSquared + zSquared + Math.pow(y - bSize, 2) <= brushSizeSquared) { - final IBlock block = this.clampY(sx, sz, sz); + final IBlock block = this.getWorld().getBlock(sx, sz, sz); this.snap[x][y][z] = new BlockWrapper(block); block.setMaterial(VoxelMaterial.AIR); sz++; @@ -164,7 +167,7 @@ private void rotate(final int bSize, final SnipeData v) { for (int y = 0; y < this.snap.length; y++) { final int yy = y - bSize; if (xSquared + zSquared + Math.pow(yy, 2) <= brushSizeSquared) { - undo.put(this.clampY(this.getTargetBlock().getX() + xx, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + zz)); // just store + undo.put(this.getWorld().getBlock(this.getTargetBlock().getX() + xx, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + zz)); // just store // whole sphere in undo, too complicated otherwise, since this brush both adds and remos things unpredictably. final double newxyX = (newxzX * cosPitch) - (yy * sinPitch); @@ -180,7 +183,7 @@ private void rotate(final int bSize, final SnipeData v) { if (block.getMaterial().isAir()) { continue; } - this.setBlockMaterialAndDataAt(this.getTargetBlock().getX() + (int) newxyX, this.getTargetBlock().getY() + (int) newyzY, this.getTargetBlock().getZ() + (int) newyzZ, block.getBlockData()); + this.getWorld().getBlock(this.getTargetBlock().getX() + (int) newxyX, this.getTargetBlock().getY() + (int) newyzY, this.getTargetBlock().getZ() + (int) newyzZ).setBlockData(block.getBlockData()); } } } @@ -216,7 +219,7 @@ private void rotate(final int bSize, final SnipeData v) { winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C; } - this.setBlockMaterialAndDataAt(fx, fy, fz, winner); + this.getWorld().getBlock(fx, fy, fz).setBlockData(winner); } } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RulerBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RulerBrush.java index 30de4fa0..1e49e8fa 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RulerBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/RulerBrush.java @@ -4,15 +4,20 @@ import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Ruler_Brush + * ... * * @author Gavjenks */ -public class RulerBrush extends AbstractBrush { +public class RulerBrush extends CustomBrush { private final int xOff = 0; private final int yOff = 0; @@ -29,33 +34,17 @@ public RulerBrush() { @Override protected final void arrow(final SnipeData v) { - final VoxelMaterial voxelMaterial = v.getVoxelMaterial(); - this.coords = this.getTargetBlock().getLocation().toVector(); - - if (this.xOff == 0 && this.yOff == 0 && this.zOff == 0) { - v.sendMessage(Messages.FIRST_POINT_SELECTED); - this.first = !this.first; - } else { - final Undo undo = new Undo(); - setBlockMaterialAt(this.getTargetBlock().getX() + this.xOff, this.getTargetBlock().getY() + this.yOff, this.getTargetBlock().getZ() + this.zOff, voxelMaterial, undo); - v.owner().storeUndo(undo); - } + addOperation(new CustomOperation(this.getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } + @Override protected final void powder(final SnipeData v) { if (this.coords == null || this.coords.lengthSquared() == 0) { v.sendMessage(Messages.FIRST_COORDINATE_NOT_SET); return; } - - double x = this.getTargetBlock().getX() - this.coords.getX(); - double y = this.getTargetBlock().getY() - this.coords.getY(); - double z = this.getTargetBlock().getZ() - this.coords.getZ(); - final double distance = (double) (Math.round(this.getTargetBlock().getLocation().toVector().subtract(this.coords).length() * 100) / 100); - final double blockDistance = (double) (Math.round((Math.abs(Math.max(Math.max(Math.abs(x), Math.abs(y)), Math.abs(z))) + 1) * 100) / 100); - - v.sendMessage(Messages.RULER_BRUSH_POWDER.replace("%x%", String.valueOf(x)).replace("%y%", String.valueOf(y)).replace("%z%", String.valueOf(z)).replace("%distance%", String.valueOf(distance)).replace("%blockDistance%", String.valueOf(blockDistance))); + addOperation(new CustomOperation(this.getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override @@ -65,8 +54,7 @@ public final void info(final VoxelMessage vm) { } @Override - // TODO: Implement block placing - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.RULER_BRUSH_USAGE); return; @@ -79,4 +67,31 @@ public final void parseParameters(final String triggerHandle, final String[] par public String getPermissionNode() { return "voxelsniper.brush.ruler"; } + + @Override + public boolean perform(ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + if (operations.size() != 1) { + return false; + } + switch (Objects.requireNonNull(getSnipeAction())) { + case ARROW -> { + if (operations.size() == 1) { + this.coords = operations.stream().findFirst().get().getLocation().toVector(); + snipeData.sendMessage(Messages.FIRST_POINT_SELECTED); + this.first = !this.first; + } + } + case GUNPOWDER -> { + var target = operations.stream().findFirst().get().getLocation(); + double x = target.getX() - this.coords.getX(); + double y = target.getY() - this.coords.getY(); + double z = target.getZ() - this.coords.getZ(); + final double distance = (double) (Math.round(target.toVector().subtract(this.coords).length() * 100) / 100); + final double blockDistance = (double) (Math.round((Math.abs(Math.max(Math.max(Math.abs(x), Math.abs(y)), Math.abs(z))) + 1) * 100) / 100); + + snipeData.sendMessage(Messages.RULER_BRUSH_POWDER.replace("%x%", String.valueOf(x)).replace("%y%", String.valueOf(y)).replace("%z%", String.valueOf(z)).replace("%distance%", String.valueOf(distance)).replace("%blockDistance%", String.valueOf(blockDistance))); + } + } + return true; + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ScannerBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ScannerBrush.java index 0be1f2a4..97e5a6e7 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ScannerBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ScannerBrush.java @@ -1,11 +1,16 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.block.BlockFace; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -13,8 +18,9 @@ /** * @author DivineRage + * ... */ -public class ScannerBrush extends AbstractBrush { +public class ScannerBrush extends CustomBrush { private static final int DEPTH_MIN = 1; private static final int DEPTH_DEFAULT = 24; @@ -46,7 +52,7 @@ private void scan(final SnipeData v, final BlockFace bf) { if (y >= this.getMaxHeight() || y < this.getMinHeight()) { break; } - VoxelMaterial mat = this.clampY(this.getTargetBlock().getX() + (bf.getModX() * i * -1), y, this.getTargetBlock().getZ() + (bf.getModZ() * i * -1)).getMaterial(); + VoxelMaterial mat = getWorld().getBlock(this.getTargetBlock().getX() + (bf.getModX() * i * -1), y, this.getTargetBlock().getZ() + (bf.getModZ() * i * -1)).getMaterial(); if (mat == checkFor) { v.sendMessage(Messages.SCANNER_FOUND_BLOCKS.replace("%checkFor%", checkFor.getName()).replace("%i%", Integer.toString(i))); return; @@ -57,7 +63,7 @@ private void scan(final SnipeData v, final BlockFace bf) { @Override protected final void arrow(final SnipeData v) { - this.scan(v, this.getTargetBlock().getFace(this.getLastBlock())); + addOperation(new CustomOperation(getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override @@ -67,7 +73,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.SCANNER_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -85,12 +91,14 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("depth")); } + @NotNull @Override public HashMap> registerArgumentValues() { // Number variables @@ -105,4 +113,13 @@ public HashMap> registerArgumentValues() { public String getPermissionNode() { return "voxelsniper.brush.scanner"; } + + @Override + public boolean perform(ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + if (operations.size() != 1) { + return false; + } + this.scan(snipeData, this.getTargetBlock().getFace(this.getLastBlock())); + return true; + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SetBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SetBrush.java index 73010ece..03ee26e6 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SetBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SetBrush.java @@ -5,9 +5,10 @@ import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Set_Brush + * ... * * @author Voxel */ @@ -30,15 +31,16 @@ public SetBrush() { * @param v data * @return TRUE when first point was selected, or second point is in different world */ - private boolean set(final IBlock bl, final SnipeData v) { + private void set(final IBlock bl, final SnipeData v) { if (this.block == null) { this.block = bl; - return true; + v.sendMessage(Messages.FIRST_POINT_SELECTED); + return; } else { if (!this.block.getWorld().getName().equals(bl.getWorld().getName())) { v.sendMessage(Messages.SELECTED_POINTS_DIFFERENT_WORLD); this.block = bl; - return true; + return; } final int lowX = Math.min(this.block.getX(), bl.getX()); final int lowY = Math.min(this.block.getY(), bl.getY()); @@ -53,33 +55,24 @@ private boolean set(final IBlock bl, final SnipeData v) { for (int y = lowY; y <= highY; y++) { for (int x = lowX; x <= highX; x++) { for (int z = lowZ; z <= highZ; z++) { - this.currentPerformer.perform(this.clampY(x, y, z)); + this.positions.add(new BaseLocation(getWorld(), x, y, z)); } } } } this.block = null; - return false; } } @Override - protected final void arrow(final SnipeData v) { - if (this.set(this.getTargetBlock(), v)) { - v.sendMessage(Messages.FIRST_POINT_SELECTED); - } else { - v.owner().storeUndo(this.currentPerformer.getUndo()); - } + protected final void doArrow(final SnipeData v) { + this.set(this.getTargetBlock(), v); } @Override - protected final void powder(final SnipeData v) { - if (this.set(this.getLastBlock(), v)) { - v.sendMessage(Messages.FIRST_POINT_SELECTED); - } else { - v.owner().storeUndo(this.currentPerformer.getUndo()); - } + protected final void doPowder(final SnipeData v) { + this.set(this.getLastBlock(), v); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellVoxelBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellVoxelBrush.java deleted file mode 100644 index af8c2539..00000000 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellVoxelBrush.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.github.kevindagame.brush; - -import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; -import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.material.VoxelMaterial; - -/** - * THIS BRUSH SHOULD NOT USE PERFORMERS. http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes - * - * @author Voxel - */ -public class ShellVoxelBrush extends AbstractBrush { - - /** - * - */ - public ShellVoxelBrush() { - this.setName("Shell Voxel"); - } - - private void vShell(final SnipeData v, IBlock targetBlock) { - final int brushSize = v.getBrushSize(); - final int brushSizeSquared = 2 * brushSize; - final VoxelMaterial[][][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer - final VoxelMaterial[][][] newMaterials = new VoxelMaterial[2 * brushSize + 1][2 * brushSize + 1][2 * brushSize + 1]; // Array that holds the hollowed materials - - int blockPositionX = targetBlock.getX(); - int blockPositionY = targetBlock.getY(); - int blockPositionZ = targetBlock.getZ(); - // Log current materials into oldmats - for (int x = 0; x <= 2 * (brushSize + 1); x++) { - for (int y = 0; y <= 2 * (brushSize + 1); y++) { - for (int z = 0; z <= 2 * (brushSize + 1); z++) { - oldMaterials[x][y][z] = this.getBlockMaterialAt(blockPositionX - brushSize - 1 + x, blockPositionY - brushSize - 1 + y, blockPositionZ - brushSize - 1 + z); - } - } - } - - // Log current materials into newmats - for (int x = 0; x <= brushSizeSquared; x++) { - for (int y = 0; y <= brushSizeSquared; y++) { - System.arraycopy(oldMaterials[x + 1][y + 1], 1, newMaterials[x][y], 0, brushSizeSquared + 1); - } - } - int temp; - - // Hollow Brush Area - for (int x = 0; x <= brushSizeSquared; x++) { - for (int z = 0; z <= brushSizeSquared; z++) { - for (int y = 0; y <= brushSizeSquared; y++) { - temp = 0; - - if (oldMaterials[x + 1 + 1][z + 1][y + 1] == v.getReplaceMaterial()) { - temp++; - } - if (oldMaterials[x + 1 - 1][z + 1][y + 1] == v.getReplaceMaterial()) { - temp++; - } - if (oldMaterials[x + 1][z + 1 + 1][y + 1] == v.getReplaceMaterial()) { - temp++; - } - if (oldMaterials[x + 1][z + 1 - 1][y + 1] == v.getReplaceMaterial()) { - temp++; - } - if (oldMaterials[x + 1][z + 1][y + 1 + 1] == v.getReplaceMaterial()) { - temp++; - } - if (oldMaterials[x + 1][z + 1][y + 1 - 1] == v.getReplaceMaterial()) { - temp++; - } - - if (temp == 0) { - newMaterials[x][z][y] = v.getVoxelMaterial(); - } - } - } - } - - // Make the changes - final Undo undo = new Undo(); - - for (int x = brushSizeSquared; x >= 0; x--) { - for (int y = 0; y <= brushSizeSquared; y++) { - for (int z = brushSizeSquared; z >= 0; z--) { - setBlockMaterialAt(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z, newMaterials[x][y][z], undo); - } - } - } - v.owner().storeUndo(undo); - - v.sendMessage(Messages.SHELL_BRUSH_COMPLETE); - } - - @Override - protected final void arrow(final SnipeData v) { - this.vShell(v, this.getTargetBlock()); - } - - @Override - protected final void powder(final SnipeData v) { - this.vShell(v, this.getLastBlock()); - } - - @Override - public final void info(final VoxelMessage vm) { - vm.brushName(this.getName()); - vm.size(); - vm.voxel(); - vm.replace(); - } - - @Override - public String getPermissionNode() { - return "voxelsniper.brush.shellvoxel"; - } -} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java index c10e6e7f..dafabbcf 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java @@ -2,22 +2,29 @@ import com.github.kevindagame.VoxelSniper; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockStateOperation; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.blockstate.IBlockState; import com.github.kevindagame.voxelsniper.blockstate.sign.ISign; +import com.google.common.collect.ImmutableList; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.jetbrains.annotations.NotNull; import java.io.*; import java.util.Arrays; +import java.util.Objects; /** - * Overwrites signs. (Wiki: http://www.voxelwiki.com/minecraft/VoxelSniper#Sign_Overwrite_Brush) + * Overwrites signs. ... * * @author Monofraps */ -public class SignOverwriteBrush extends AbstractBrush { +public class SignOverwriteBrush extends CustomBrush { private static final int MAX_SIGN_LINE_LENGTH = 15; private static final int NUM_SIGN_LINES = 4; @@ -46,13 +53,13 @@ public SignOverwriteBrush() { * @param sign */ private void setSignText(final ISign sign) { + var oldState = sign.getBlock().getState(); for (int i = 0; i < this.signTextLines.length; i++) { if (this.signLinesEnabled[i]) { sign.setLine(i, this.signTextLines[i]); } } - - sign.update(); + addOperation(new BlockStateOperation(sign.getLocation(), oldState, sign)); } /** @@ -87,8 +94,8 @@ private void setRanged(final SnipeData v) { for (int y = minY; y <= maxY; y++) { for (int z = minZ; z <= maxZ; z++) { IBlockState blockState = this.getWorld().getBlock(x, y, z).getState(); - if (blockState instanceof ISign) { - setSignText((ISign) blockState); + if (blockState instanceof ISign sign) { + setSignText(sign); signFound = true; } } @@ -111,23 +118,12 @@ protected final void arrow(final SnipeData v) { @Override protected final void powder(final SnipeData v) { - if (this.getTargetBlock().getState() instanceof ISign sign) { - - for (int i = 0; i < this.signTextLines.length; i++) { - if (this.signLinesEnabled[i]) { - this.signTextLines[i] = sign.getLine(i); - } - } - - displayBuffer(v); - } else { - v.sendMessage(Messages.TARGET_BLOCK_NO_SIGN); - } + if (this.getTargetBlock().getState() instanceof ISign) + addOperation(new CustomOperation(getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override - // TODO: Rewrite this - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { boolean textChanged = false; for (int i = 0; i < params.length; i++) { @@ -244,7 +240,6 @@ private int parseSignLineFromParam(final String[] params, final int lineNumber, } } - // TODO not entirely sure what to do here newText = new StringBuilder(newText.toString()); // remove last space or return if the string is empty and the user just wanted to set the status @@ -384,4 +379,29 @@ public final void info(final VoxelMessage vm) { public String getPermissionNode() { return "voxelsniper.brush.signoverwrite"; } + + @Override + public boolean perform(@NotNull ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + switch (Objects.requireNonNull(getSnipeAction())) { + case ARROW -> { + return false; + } + case GUNPOWDER -> { + if (this.getTargetBlock().getState() instanceof ISign sign) { + + for (int i = 0; i < this.signTextLines.length; i++) { + if (this.signLinesEnabled[i]) { + this.signTextLines[i] = sign.getLine(i); + } + } + + displayBuffer(snipeData); + } else { + snipeData.sendMessage(Messages.TARGET_BLOCK_NO_SIGN); + } + return true; + } + } + return false; + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SnipeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SnipeBrush.java index 86edadc7..9c75fe89 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SnipeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SnipeBrush.java @@ -5,7 +5,7 @@ import com.github.kevindagame.util.VoxelMessage; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Snipe_Brush + * ... * * @author Voxel */ @@ -19,15 +19,13 @@ public SnipeBrush() { } @Override - protected final void arrow(final SnipeData v) { - this.currentPerformer.perform(this.getTargetBlock()); - v.owner().storeUndo(this.currentPerformer.getUndo()); + protected final void doArrow(final SnipeData v) { + this.positions.add(this.getTargetBlock().getLocation()); } @Override - protected final void powder(final SnipeData v) { - this.currentPerformer.perform(this.getLastBlock()); - v.owner().storeUndo(this.currentPerformer.getUndo()); + protected final void doPowder(final SnipeData v) { + this.positions.add(this.getTargetBlock().getLocation()); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBallBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBallBrush.java index 9459a8cb..bfcd99c2 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBallBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBallBrush.java @@ -1,240 +1,62 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; -import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.util.Shapes; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Random; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * ... * * @author Voxel */ -public class SplatterBallBrush extends PerformerBrush { - - private static final int GROW_PERCENT_MIN = 1; - private static final int GROW_PERCENT_DEFAULT = 1000; - private static final int GROW_PERCENT_MAX = 9999; - private static final int SEED_PERCENT_MIN = 1; - private static final int SEED_PERCENT_DEFAULT = 1000; - private static final int SEED_PERCENT_MAX = 9999; - private static final int SPLATREC_PERCENT_MIN = 1; - private static final int SPLATREC_PERCENT_DEFAULT = 3; - private static final int SPLATREC_PERCENT_MAX = 10; - private final Random generator = new Random(); - private int seedPercent; // Chance block on first pass is made active - private int growPercent; // chance block on recursion pass is made active - private int splatterRecursions; // How many times you grow the seeds +public class SplatterBallBrush extends SplatterBrushBase { - /** - * - */ public SplatterBallBrush() { this.setName("Splatter Ball"); } - private void splatterBall(final SnipeData v, IBlock targetBlock) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", "10")); - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", "10")); - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", "3")); - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - - final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - - // Seed the array - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { - splat[x][y][z] = 1; - } - } - } - } - // Grow the seeds - final int gref = this.growPercent; - final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - int growcheck; - - for (int r = 0; r < this.splatterRecursions; r++) { - this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat - - growcheck = 0; - if (splat[x][y][z] == 0) { - if (x != 0 && splat[x - 1][y][z] == 1) { - growcheck++; - } - if (y != 0 && splat[x][y - 1][z] == 1) { - growcheck++; - } - if (z != 0 && splat[x][y][z - 1] == 1) { - growcheck++; - } - if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1) { - growcheck++; - } - if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1) { - growcheck++; - } - if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1) { - growcheck++; - } - } - - if (growcheck >= GROW_PERCENT_MIN && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { - tempSplat[x][y][z] = 1; // prevent bleed into splat - } - - } - } - } - // integrate tempsplat back into splat at end of iteration - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (2 * v.getBrushSize() + 1 >= 0) - System.arraycopy(tempSplat[x][y], 0, splat[x][y], 0, 2 * v.getBrushSize() + 1); - } - } - } - this.growPercent = gref; - // Fill 1x1x1 holes - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1) { - splat[x][y][z] = 1; - } - } + private void splatterBall(final SnipeData v) { + final int brushSize = v.getBrushSize(); + var positions = Shapes.ball(this.getTargetBlock().getLocation(), brushSize, false); + var splat = this.splatter3D(v); + for (var position : positions) { + var val = splat[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockY() - this.getTargetBlock().getY() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (val == 1) { + this.positions.add(position); } } - - // Make the changes - final double rSquared = Math.pow(v.getBrushSize() + 1, 2); - - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - final double xSquared = Math.pow(x - v.getBrushSize() - 1, 2); - - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - final double ySquared = Math.pow(y - v.getBrushSize() - 1, 2); - - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - v.getBrushSize() - 1, 2) <= rSquared) { - currentPerformer.perform(targetBlock.getRelative(-v.getBrushSize() + x, -v.getBrushSize() + y, -v.getBrushSize() + z)); - } - } - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { - this.splatterBall(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.splatterBall(v); } @Override - protected final void powder(final SnipeData v) { - this.splatterBall(v, this.getLastBlock()); - } - - @Override - public final void info(final VoxelMessage vm) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - vm.brushName("Splatter Ball"); - vm.size(); - vm.custom(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(this.seedPercent / 100))); - vm.custom(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(this.growPercent / 100))); - vm.custom(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(this.splatterRecursions))); - + protected final void doPowder(final SnipeData v) { + this.splatterBall(v); } @Override public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + if (super.parseParams(triggerHandle, params, v)) return; if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.SPLATTER_BALL_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; } - if (params[0].equalsIgnoreCase("reset")) { - this.seedPercent = SEED_PERCENT_DEFAULT; - this.growPercent = GROW_PERCENT_DEFAULT; - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - v.sendMessage(Messages.BRUSH_RESET_DEFAULT); - return; - } - - try { - if (params[0].startsWith("seed")) { - final int seedPercentage = ((int) Double.parseDouble(params[1]) * 100); - - if (seedPercentage >= SEED_PERCENT_MIN && seedPercentage <= SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(seedPercentage / 100))); - this.seedPercent = seedPercentage; - } else { - v.sendMessage(Messages.SEED_PERCENT_RANGE); - } - return; - } - - if (params[0].startsWith("growth")) { - final int growthPercentage = ((int) Double.parseDouble(params[1]) * 100); - - if (growthPercentage >= GROW_PERCENT_MIN && growthPercentage <= GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(growthPercentage / 100))); - this.growPercent = growthPercentage; - } else { - v.sendMessage(Messages.GROWTH_PERCENT_RANGE.replace("%min%", "0.01").replace("%max%", "99.99")); - } - return; - } - - if (params[0].startsWith("recursion")) { - final int recursionValue = Integer.parseInt(params[1]); - - if (recursionValue >= SPLATREC_PERCENT_MIN && recursionValue <= SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(recursionValue))); - this.splatterRecursions = recursionValue; - } else { - v.sendMessage(Messages.SPLATTER_BALL_BRUSH_RECURSION_RANGE); - } - return; - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -244,6 +66,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBrushBase.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBrushBase.java new file mode 100644 index 00000000..e9c57c67 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterBrushBase.java @@ -0,0 +1,298 @@ +package com.github.kevindagame.brush; + +import com.github.kevindagame.brush.perform.PerformerBrush; +import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.VoxelMessage; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +public abstract class SplatterBrushBase extends PerformerBrush { + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MAX = 9999; + private static final int SEED_PERCENT_MIN = 1; + private static final int SEED_PERCENT_DEFAULT = 1000; + private static final int SEED_PERCENT_MAX = 9999; + private static final int SPLATREC_PERCENT_MIN = 1; + private static final int SPLATREC_PERCENT_DEFAULT = 3; + private static final int SPLATREC_PERCENT_MAX = 10; + protected final Random generator = new Random(); + private int seedPercent; // Chance block on first pass is made active + private int growPercent; // chance block on recursion pass is made active + private int splatterRecursions; // How many times you grow the seeds + + protected int[][] splatter2D(SnipeData v) { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { + v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", "10")); + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { + v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", "10")); + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { + v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", "3")); + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { + splat[x][y] = 1; + + } + } + } + // Grow the seeds + final int gref = this.growPercent; + int growcheck; + final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + for (int r = 0; r < this.splatterRecursions; r++) { + + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + tempSplat[x][y] = splat[x][y]; // prime tempsplat + + growcheck = 0; + if (splat[x][y] == 0) { + if (x != 0 && splat[x - 1][y] == 1) { + growcheck++; + } + if (y != 0 && splat[x][y - 1] == 1) { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) { + growcheck++; + } + } + + if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { + tempSplat[x][y] = 1; // prevent bleed into splat + } + } + } + + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + if (2 * v.getBrushSize() + 1 >= 0) + System.arraycopy(tempSplat[x], 0, splat[x], 0, 2 * v.getBrushSize() + 1); + } + } + this.growPercent = gref; + // Fill 1x1 holes + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1) { + splat[x][y] = 1; + } + } + } + return splat; + + } + + protected int[][][] splatter3D(SnipeData v) { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { + v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", "10")); + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { + v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", "10")); + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { + v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", "3")); + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + + final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) { + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { + splat[x][y][z] = 1; + } + } + } + } + // Grow the seeds + final int gref = this.growPercent; + final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + int growcheck; + + for (int r = 0; r < this.splatterRecursions; r++) { + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) { + tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat + + growcheck = 0; + if (splat[x][y][z] == 0) { + if (x != 0 && splat[x - 1][y][z] == 1) { + growcheck++; + } + if (y != 0 && splat[x][y - 1][z] == 1) { + growcheck++; + } + if (z != 0 && splat[x][y][z - 1] == 1) { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1) { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1) { + growcheck++; + } + if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1) { + growcheck++; + } + } + + if (growcheck >= GROW_PERCENT_MIN && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { + tempSplat[x][y][z] = 1; // prevent bleed into splat + } + + } + } + } + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + if (2 * v.getBrushSize() + 1 >= 0) + System.arraycopy(tempSplat[x][y], 0, splat[x][y], 0, 2 * v.getBrushSize() + 1); + } + } + } + this.growPercent = gref; + // Fill 1x1x1 holes + for (int x = 2 * v.getBrushSize(); x >= 0; x--) { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) { + if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1) { + splat[x][y][z] = 1; + } + } + } + } + return splat; + } + + @Override + public final void info(@NotNull final VoxelMessage vm) { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + vm.brushName("Splatter Ball"); + vm.size(); + vm.custom(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(this.seedPercent / 100))); + vm.custom(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(this.growPercent / 100))); + vm.custom(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(this.splatterRecursions))); + + } + + + protected void resetBrush(SnipeData v) { + this.seedPercent = SEED_PERCENT_DEFAULT; + this.growPercent = GROW_PERCENT_DEFAULT; + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + v.sendMessage(Messages.BRUSH_RESET_DEFAULT); + } + + + public boolean parseParams(final String triggerHandle, final String[] params, final SnipeData v) { + if (params[0].equalsIgnoreCase("reset")) { + this.resetBrush(v); + return true; + } + + try { + if (params[0].startsWith("seed")) { + final int seedPercentage = ((int) Double.parseDouble(params[1]) * 100); + + if (seedPercentage >= SEED_PERCENT_MIN && seedPercentage <= SEED_PERCENT_MAX) { + v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(seedPercentage / 100))); + this.seedPercent = seedPercentage; + } else { + v.sendMessage(Messages.SEED_PERCENT_RANGE); + } + return true; + } + + if (params[0].startsWith("growth")) { + final int growthPercentage = ((int) Double.parseDouble(params[1]) * 100); + + if (growthPercentage >= GROW_PERCENT_MIN && growthPercentage <= GROW_PERCENT_MAX) { + v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(growthPercentage / 100))); + this.growPercent = growthPercentage; + } else { + v.sendMessage(Messages.GROWTH_PERCENT_RANGE.replace("%min%", "0.01").replace("%max%", "99.99")); + } + return true; + } + + if (params[0].startsWith("recursion")) { + final int recursionValue = Integer.parseInt(params[1]); + + if (recursionValue >= SPLATREC_PERCENT_MIN && recursionValue <= SPLATREC_PERCENT_MAX) { + v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(recursionValue))); + this.splatterRecursions = recursionValue; + } else { + v.sendMessage(Messages.SPLATTER_BALL_BRUSH_RECURSION_RANGE); + } + return true; + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + + return false; + } + + @NotNull + @Override + public List registerArguments() { + List arguments = new ArrayList<>(); + arguments.addAll(Lists.newArrayList("recursion", "growth", "seed", "reset")); + + arguments.addAll(super.registerArguments()); + return arguments; + } + + @NotNull + @Override + public HashMap> registerArgumentValues() { + HashMap> argumentValues = new HashMap<>(); + + // Number variables + argumentValues.put("recursion", Lists.newArrayList("[number]")); + + // Decimal variables + argumentValues.put("seed", Lists.newArrayList("[decimal]")); + argumentValues.put("growth", Lists.newArrayList("[decimal]")); + + argumentValues.putAll(super.registerArgumentValues()); + return argumentValues; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterDiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterDiscBrush.java index 3b0b949b..c0f55b75 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterDiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterDiscBrush.java @@ -1,243 +1,54 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; -import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Random; +import com.github.kevindagame.util.Shapes; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * ... * * @author Voxel */ -public class SplatterDiscBrush extends PerformerBrush { +public class SplatterDiscBrush extends SplatterBrushBase { - private static final int GROW_PERCENT_MIN = 1; - private static final int GROW_PERCENT_DEFAULT = 1000; - private static final int GROW_PERCENT_MAX = 9999; - private static final int SEED_PERCENT_MIN = 1; - private static final int SEED_PERCENT_DEFAULT = 1000; - private static final int SEED_PERCENT_MAX = 9999; - private static final int SPLATREC_PERCENT_MIN = 1; - private static final int SPLATREC_PERCENT_DEFAULT = 3; - private static final int SPLATREC_PERCENT_MAX = 10; - private final Random generator = new Random(); - private int seedPercent; // Chance block on first pass is made active - private int growPercent; // chance block on recursion pass is made active - private int splatterRecursions; // How many times you grow the seeds - /** - * - */ public SplatterDiscBrush() { this.setName("Splatter Disc"); } - private void splatterDisc(final SnipeData v, IBlock targetBlock) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", "10")); - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", "10")); - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", "3")); - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - - // Seed the array - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - - if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { - splat[x][y] = 1; - - } + private void splatterDisc(final SnipeData v) { + var positions = Shapes.disc(this.getTargetBlock().getLocation(), v.getBrushSize(), false); + var splat = splatter2D(v); + final int brushSize = v.getBrushSize(); + for (var position : positions) { + var val = splat[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (val == 1) { + this.positions.add(position); } } - // Grow the seeds - final int gref = this.growPercent; - int growcheck; - final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - for (int r = 0; r < this.splatterRecursions; r++) { - - this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - tempSplat[x][y] = splat[x][y]; // prime tempsplat - - growcheck = 0; - if (splat[x][y] == 0) { - if (x != 0 && splat[x - 1][y] == 1) { - growcheck++; - } - if (y != 0 && splat[x][y - 1] == 1) { - growcheck++; - } - if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) { - growcheck++; - } - if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) { - growcheck++; - } - } - - if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { - tempSplat[x][y] = 1; // prevent bleed into splat - } - } - } - - // integrate tempsplat back into splat at end of iteration - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - if (2 * v.getBrushSize() + 1 >= 0) - System.arraycopy(tempSplat[x], 0, splat[x], 0, 2 * v.getBrushSize() + 1); - } - } - this.growPercent = gref; - // Fill 1x1 holes - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1) { - splat[x][y] = 1; - } - } - } - - // Make the changes - final double rSquared = Math.pow(v.getBrushSize() + 1, 2); - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - final double xSquared = Math.pow(x - v.getBrushSize() - 1, 2); - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (splat[x][y] == 1 && xSquared + Math.pow(y - v.getBrushSize() - 1, 2) <= rSquared) { - currentPerformer.perform(targetBlock.getRelative(x - v.getBrushSize(), 0, y - v.getBrushSize())); - } - } - } - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { - this.splatterDisc(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.splatterDisc(v); } @Override - protected final void powder(final SnipeData v) { - this.splatterDisc(v, this.getLastBlock()); - } - - @Override - public final void info(final VoxelMessage vm) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - vm.brushName("Splatter Disc"); - vm.size(); - vm.custom(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(this.seedPercent / 100))); - vm.custom(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(this.growPercent / 100))); - vm.custom(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(this.splatterRecursions))); + protected final void doPowder(final SnipeData v) { + this.splatterDisc(v); } @Override public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + if (super.parseParams(triggerHandle, params, v)) return; if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.SPLATTER_DISC_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; } - - if (params[0].equalsIgnoreCase("reset")) { - this.seedPercent = SEED_PERCENT_DEFAULT; - this.growPercent = GROW_PERCENT_DEFAULT; - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - v.sendMessage(Messages.BRUSH_RESET_DEFAULT); - return; - } - - try { - if (params[0].startsWith("seed")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(temp / 100))); - this.seedPercent = temp; - } else { - v.sendMessage(Messages.SEED_PERCENT_RANGE); - } - return; - } - - if (params[0].startsWith("growth")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(temp / 100))); - this.growPercent = temp; - } else { - v.sendMessage(Messages.GROWTH_PERCENT_RANGE.replace("%min%", "0.01").replace("%max%", "99.99")); - } - return; - } - - if (params[0].startsWith("recursion")) { - final int temp = Integer.parseInt(params[1]); - - if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(temp))); - this.splatterRecursions = temp; - } else { - v.sendMessage(Messages.SPLATTER_BALL_BRUSH_RECURSION_RANGE); - } - return; - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); sendPerformerMessage(triggerHandle, v); } - @Override - public List registerArguments() { - List arguments = new ArrayList<>(); - arguments.addAll(Lists.newArrayList("recursion", "growth", "seed", "reset")); - - arguments.addAll(super.registerArguments()); - return arguments; - } - - @Override - public HashMap> registerArgumentValues() { - HashMap> argumentValues = new HashMap<>(); - - // Number variables - argumentValues.put("recursion", Lists.newArrayList("[number]")); - - // Decimal variables - argumentValues.put("seed", Lists.newArrayList("[decimal]")); - argumentValues.put("growth", Lists.newArrayList("[decimal]")); - - argumentValues.putAll(super.registerArgumentValues()); - return argumentValues; - } - @Override public String getPermissionNode() { return "voxelsniper.brush.splatterdisc"; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterOverlayBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterOverlayBrush.java index 6023af3c..13dc3d52 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterOverlayBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterOverlayBrush.java @@ -1,107 +1,38 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; -import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelList; -import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Random; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Overlay_Brush + * ... * * @author Gavjenks Splatterized blockPositionY Giltwist */ -public class SplatterOverlayBrush extends PerformerBrush { +public class SplatterOverlayBrush extends SplatterBrushBase { - private static final int GROW_PERCENT_MIN = 1; - private static final int GROW_PERCENT_DEFAULT = 1000; - private static final int GROW_PERCENT_MAX = 9999; - private static final int SEED_PERCENT_MIN = 1; - private static final int SEED_PERCENT_DEFAULT = 1000; - private static final int SEED_PERCENT_MAX = 9999; - private static final int SPLATREC_PERCENT_MIN = 1; - private static final int SPLATREC_PERCENT_DEFAULT = 3; - private static final int SPLATREC_PERCENT_MAX = 10; - private final int yOffset = 0; private final boolean randomizeHeight = false; - private final Random generator = new Random(); - private int seedPercent; // Chance block on first pass is made active - private int growPercent; // chance block on recursion pass is made active - private int splatterRecursions; // How many times you grow the seeds + private final int yOffset = 0; private int depth = 3; - private boolean allBlocks = false; private boolean useVoxelList = false; - - /** - * - */ public SplatterOverlayBrush() { this.setName("Splatter Overlay"); } private void sOverlay(final SnipeData v) { - // Splatter Time - final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - // Seed the array - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { - splat[x][y] = 1; - } - } - } - // Grow the seeds - final int gref = this.growPercent; - final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - int growcheck; - - for (int r = 0; r < this.splatterRecursions; r++) { - this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - tempSplat[x][y] = splat[x][y]; // prime tempsplat - - growcheck = 0; - if (splat[x][y] == 0) { - if (x != 0 && splat[x - 1][y] == 1) { - growcheck++; - } - if (y != 0 && splat[x][y - 1] == 1) { - growcheck++; - } - if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) { - growcheck++; - } - if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) { - growcheck++; - } - } - - if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { - tempSplat[x][y] = 1; // prevent bleed into splat - } - } - } - // integrate tempsplat back into splat at end of iteration - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - if (2 * v.getBrushSize() + 1 >= 0) - System.arraycopy(tempSplat[x], 0, splat[x], 0, 2 * v.getBrushSize() + 1); - } - } - this.growPercent = gref; - - final int[][] memory = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + var splat = splatter2D(v); final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); - + final int[][] memory = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) { for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { for (int y = this.getTargetBlock().getY(); y > this.getMinHeight(); y--) { @@ -119,9 +50,10 @@ private void sOverlay(final SnipeData v) { final int depth = this.randomizeHeight ? generator.nextInt(this.depth) : this.depth; for (int d = this.depth - 1; ((this.depth - d) <= depth); d--) { - if (!this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { + if (!this.getWorld().getBlock(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { // fills down as many layers as you specify in parameters - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, y - d + yOffset, this.getTargetBlock().getZ() + z)); + var block = v.getWorld().getBlock(getTargetBlock().getX() + x, y - d + yOffset, this.getTargetBlock().getZ() + z); + this.positions.add(block.getLocation()); // stop it from checking any other blocks in this vertical 1x1 column. memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; } @@ -133,71 +65,17 @@ private void sOverlay(final SnipeData v) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private void soverlayTwo(final SnipeData v) { - // Splatter Time - final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - // Seed the array - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { - splat[x][y] = 1; - } - } - } - // Grow the seeds - final int gref = this.growPercent; - final int[][] tempsplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - int growcheck; - - for (int r = 0; r < this.splatterRecursions; r++) { - this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); - - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - tempsplat[x][y] = splat[x][y]; // prime tempsplat - - growcheck = 0; - if (splat[x][y] == 0) { - if (x != 0 && splat[x - 1][y] == 1) { - growcheck++; - } - if (y != 0 && splat[x][y - 1] == 1) { - growcheck++; - } - if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) { - growcheck++; - } - if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) { - growcheck++; - } - } - - if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { - tempsplat[x][y] = 1; // prevent bleed into splat - } - - } - - } - // integrate tempsplat back into splat at end of iteration - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - if (2 * v.getBrushSize() + 1 >= 0) - System.arraycopy(tempsplat[x], 0, splat[x], 0, 2 * v.getBrushSize() + 1); - } - } - this.growPercent = gref; - - final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1]; + var splat = splatter2D(v); final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) { for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { + var checked = false; for (int y = this.getTargetBlock().getY(); y > this.getMinHeight(); y--) { // start scanning from the height you clicked at - if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1) { // if haven't already found the surface in this column + if (!checked) { // if haven't already found the surface in this column if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared && splat[x + v.getBrushSize()][z + v.getBrushSize()] == 1) { // if inside of the column...&& if to be splattered if (!this.getBlockMaterialAt(this.getTargetBlock().getX() + x, y - 1, this.getTargetBlock().getZ() + z).isAir()) { // if not a floating block (like one of Notch'world pools) if (this.getBlockMaterialAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z).isAir()) { // must start at surface... this prevents it filling stuff in if @@ -205,10 +83,9 @@ private void soverlayTwo(final SnipeData v) { if (this.isOverrideableMaterial(v.getVoxelList(), currentBlock)) { final int depth = this.randomizeHeight ? generator.nextInt(this.depth) : this.depth; for (int d = 1; (d < depth + 1); d++) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, y + d + yOffset, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify - // in parameters - memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + this.positions.add(new BaseLocation(this.getWorld(), this.getTargetBlock().getX() + x, y + d + yOffset, this.getTargetBlock().getZ() + z)); } + checked = true; // stop it from checking any other blocks in this vertical 1x1 column. } } } @@ -217,12 +94,6 @@ private void soverlayTwo(final SnipeData v) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private boolean isIgnoredBlock(VoxelMaterial material) { - return material.equals(VoxelMaterial.WATER) || material.isTransparent() || material.equals(VoxelMaterial.CACTUS); } private boolean isOverrideableMaterial(VoxelList list, VoxelMaterial material) { @@ -238,51 +109,30 @@ private boolean isOverrideableMaterial(VoxelList list, VoxelMaterial material) { } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.sOverlay(v); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.soverlayTwo(v); } @Override - public final void info(final VoxelMessage vm) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - vm.brushName(this.getName()); - vm.size(); - vm.custom(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(this.seedPercent / 100))); - vm.custom(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(this.growPercent / 100))); - vm.custom(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(this.splatterRecursions))); - vm.custom(Messages.Y_OFFSET_SET.replace("%yOffset%", String.valueOf(this.yOffset))); + protected void resetBrush(SnipeData v) { + super.resetBrush(v); + this.depth = 3; + this.allBlocks = false; } @Override public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + if (super.parseParams(triggerHandle, params, v)) return; if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.SPLATTER_OVERLAY_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; } - if (params[0].equalsIgnoreCase("reset")) { - this.seedPercent = SEED_PERCENT_DEFAULT; - this.growPercent = GROW_PERCENT_DEFAULT; - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - this.depth = 3; - this.allBlocks = false; - v.sendMessage(Messages.BRUSH_RESET_DEFAULT); - return; - } - if (params[0].startsWith("mode")) { if (!this.useVoxelList) { if (!this.allBlocks) { @@ -310,42 +160,6 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.OVERLAY_DEPTH_SET.replace("%depth%", String.valueOf(this.depth))); return; } - - if (params[0].startsWith("seed")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(temp / 100))); - this.seedPercent = temp; - } else { - v.sendMessage(Messages.SEED_PERCENT_RANGE); - } - return; - } - - if (params[0].startsWith("growth")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(temp / 100))); - this.growPercent = temp; - } else { - v.sendMessage(Messages.GROWTH_PERCENT_RANGE.replace("%min%", "0.01").replace("%max%", "99.99")); - } - return; - } - - if (params[0].startsWith("recursion")) { - final int temp = Integer.parseInt(params[1]); - - if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(temp))); - this.splatterRecursions = temp; - } else { - v.sendMessage(Messages.SPLATTER_BALL_BRUSH_RECURSION_RANGE); - } - return; - } } catch (NumberFormatException e) { e.printStackTrace(); } @@ -354,6 +168,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -363,6 +178,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelBrush.java index 76fb1aa3..3a7cda35 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelBrush.java @@ -1,256 +1,55 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; -import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.voxelsniper.block.IBlock; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * ... * * @author Voxel */ -public class SplatterVoxelBrush extends PerformerBrush { - - private static final int GROW_PERCENT_MIN = 1; - private static final int GROW_PERCENT_DEFAULT = 1000; - private static final int GROW_PERCENT_MAX = 9999; - private static final int SEED_PERCENT_MIN = 1; - private static final int SEED_PERCENT_DEFAULT = 1000; - private static final int SEED_PERCENT_MAX = 9999; - private static final int SPLATREC_PERCENT_MIN = 1; - private static final int SPLATREC_PERCENT_DEFAULT = 3; - private static final int SPLATREC_PERCENT_MAX = 10; - private final Random generator = new Random(); - private int seedPercent; // Chance block on first pass is made active - private int growPercent; // chance block on recursion pass is made active - private int splatterRecursions; // How many times you grow the seeds +public class SplatterVoxelBrush extends SplatterBrushBase { - /** - * - */ public SplatterVoxelBrush() { this.setName("Splatter Voxel"); } private void vSplatterBall(final SnipeData v, IBlock targetBlock) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", "10")); - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", "10")); - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", "3")); - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - - // Seed the array - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { - splat[x][y][z] = 1; - } - } - } - } - // Grow the seeds - final int gref = this.growPercent; - final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - int growcheck; - - for (int r = 0; r < this.splatterRecursions; r++) { - this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); - - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat - - growcheck = 0; - if (splat[x][y][z] == 0) { - if (x != 0 && splat[x - 1][y][z] == 1) { - growcheck++; - } - if (y != 0 && splat[x][y - 1][z] == 1) { - growcheck++; - } - if (z != 0 && splat[x][y][z - 1] == 1) { - growcheck++; - } - if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1) { - growcheck++; - } - if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1) { - growcheck++; - } - if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1) { - growcheck++; - } - } - - if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { - tempSplat[x][y][z] = 1; // prevent bleed into splat - } - - } - } - } - // integrate tempsplat back into splat at end of iteration - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (2 * v.getBrushSize() + 1 >= 0) - System.arraycopy(tempSplat[x][y], 0, splat[x][y], 0, 2 * v.getBrushSize() + 1); - } - } - } - this.growPercent = gref; - // Fill 1x1x1 holes - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1) { - splat[x][y][z] = 1; - } - } - } - } - - // Make the changes - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - for (int z = 2 * v.getBrushSize(); z >= 0; z--) { - if (splat[x][y][z] == 1) { - currentPerformer.perform(targetBlock.getRelative(-v.getBrushSize() + x, -v.getBrushSize() + z, -v.getBrushSize() + y)); - } - } + final int brushSize = v.getBrushSize(); + var positions = Shapes.voxel(this.getTargetBlock().getLocation(), brushSize); + var splat = this.splatter3D(v); + for (var position : positions) { + var val = splat[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockY() - this.getTargetBlock().getY() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (val == 1) { + this.positions.add(position); } } - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.vSplatterBall(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.vSplatterBall(v, this.getLastBlock()); } - @Override - public final void info(final VoxelMessage vm) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - vm.brushName("Splatter Voxel"); - vm.size(); - vm.custom(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(this.seedPercent / 100))); - vm.custom(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(this.growPercent / 100))); - vm.custom(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(this.splatterRecursions))); - } - @Override public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + if (super.parseParams(triggerHandle, params, v)) return; if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.SPLATTER_FOXEL_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; } - if (params[0].equalsIgnoreCase("reset")) { - this.seedPercent = SEED_PERCENT_DEFAULT; - this.growPercent = GROW_PERCENT_DEFAULT; - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - v.sendMessage(Messages.BRUSH_RESET_DEFAULT); - return; - } - - try { - if (params[0].startsWith("seed")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(temp / 100))); - this.seedPercent = temp; - } else { - v.sendMessage(Messages.SEED_PERCENT_RANGE); - } - return; - } - - if (params[0].startsWith("growth")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(temp / 100))); - this.growPercent = temp; - } else { - v.sendMessage(Messages.GROWTH_PERCENT_RANGE.replace("%min%", "0.01").replace("%max%", "99.99")); - } - return; - } - - if (params[0].startsWith("recursion")) { - final int temp = Integer.parseInt(params[1]); - - if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(temp))); - this.splatterRecursions = temp; - } else { - v.sendMessage(Messages.SPLATTER_BALL_BRUSH_RECURSION_RANGE); - } - return; - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); sendPerformerMessage(triggerHandle, v); } - @Override - public List registerArguments() { - List arguments = new ArrayList<>(); - arguments.addAll(Lists.newArrayList("recursion", "growth", "seed", "reset")); - - arguments.addAll(super.registerArguments()); - return arguments; - } - - @Override - public HashMap> registerArgumentValues() { - HashMap> argumentValues = new HashMap<>(); - - // Number variables - argumentValues.put("recursion", Lists.newArrayList("[number]")); - - // Decimal variables - argumentValues.put("seed", Lists.newArrayList("[decimal]")); - argumentValues.put("growth", Lists.newArrayList("[decimal]")); - - argumentValues.putAll(super.registerArgumentValues()); - return argumentValues; - } - @Override public String getPermissionNode() { return "voxelsniper.brush.splattervoxel"; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelDiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelDiscBrush.java index 725b745e..cf42049e 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelDiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplatterVoxelDiscBrush.java @@ -1,37 +1,15 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; -import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.voxelsniper.block.IBlock; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes - * * @author Voxel */ -public class SplatterVoxelDiscBrush extends PerformerBrush { +public class SplatterVoxelDiscBrush extends SplatterBrushBase { - private static final int GROW_PERCENT_MIN = 1; - private static final int GROW_PERCENT_DEFAULT = 1000; - private static final int GROW_PERCENT_MAX = 9999; - private static final int SEED_PERCENT_MIN = 1; - private static final int SEED_PERCENT_DEFAULT = 1000; - private static final int SEED_PERCENT_MAX = 9999; - private static final int SPLATREC_PERCENT_MIN = 1; - private static final int SPLATREC_PERCENT_DEFAULT = 3; - private static final int SPLATREC_PERCENT_MAX = 10; - private final Random generator = new Random(); - private int seedPercent; // Chance block on first pass is made active - private int growPercent; // chance block on recursion pass is made active - private int splatterRecursions; // How many times you grow the seeds /** * @@ -41,199 +19,38 @@ public SplatterVoxelDiscBrush() { } private void vSplatterDisc(final SnipeData v, IBlock targetBlock) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", "10")); - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", "10")); - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", "3")); - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - - // Seed the array - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) { - splat[x][y] = 1; - } - } - } - // Grow the seeds - final int gref = this.growPercent; - final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; - int growcheck; - - for (int r = 0; r < this.splatterRecursions; r++) { - this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - tempSplat[x][y] = splat[x][y]; // prime tempsplat - - growcheck = 0; - if (splat[x][y] == 0) { - if (x != 0 && splat[x - 1][y] == 1) { - growcheck++; - } - if (y != 0 && splat[x][y - 1] == 1) { - growcheck++; - } - if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) { - growcheck++; - } - if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) { - growcheck++; - } - } - - if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) { - tempSplat[x][y] = 1; // prevent bleed into splat - } - } - } - // integrate tempsplat back into splat at end of iteration - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - if (2 * v.getBrushSize() + 1 >= 0) - System.arraycopy(tempSplat[x], 0, splat[x], 0, 2 * v.getBrushSize() + 1); - } - } - this.growPercent = gref; - // Fill 1x1 holes - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1) { - splat[x][y] = 1; - } - } - } - - // Make the changes - for (int x = 2 * v.getBrushSize(); x >= 0; x--) { - for (int y = 2 * v.getBrushSize(); y >= 0; y--) { - if (splat[x][y] == 1) { - this.currentPerformer.perform(this.clampY(targetBlock.getX() - v.getBrushSize() + x, targetBlock.getY(), targetBlock.getZ() - v.getBrushSize() + y)); - } + var positions = Shapes.voxelDisc(this.getTargetBlock().getLocation(), v.getBrushSize()); + var splat = splatter2D(v); + final int brushSize = v.getBrushSize(); + for (var position : positions) { + var val = splat[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + if (val == 1) { + this.positions.add(position); } } - v.owner().storeUndo(this.currentPerformer.getUndo()); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.vSplatterDisc(v, this.getTargetBlock()); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.vSplatterDisc(v, this.getLastBlock()); } - @Override - public final void info(final VoxelMessage vm) { - if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) { - this.seedPercent = SEED_PERCENT_DEFAULT; - } - if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) { - this.growPercent = GROW_PERCENT_DEFAULT; - } - if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) { - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - } - vm.brushName("Splatter Voxel Disc"); - vm.size(); - vm.custom(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(this.seedPercent / 100))); - vm.custom(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(this.growPercent / 100))); - vm.custom(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(this.splatterRecursions))); - - } - @Override public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + if (super.parseParams(triggerHandle, params, v)) return; if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.SPLATTER_VOXEL_DISC_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; } - - if (params[0].equalsIgnoreCase("reset")) { - this.seedPercent = SEED_PERCENT_DEFAULT; - this.growPercent = GROW_PERCENT_DEFAULT; - this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; - v.sendMessage(Messages.BRUSH_RESET_DEFAULT); - return; - } - - try { - if (params[0].startsWith("seed")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_SEED_PERCENT_SET.replace("%val%", String.valueOf(temp / 100))); - this.seedPercent = temp; - } else { - v.sendMessage(Messages.SEED_PERCENT_RANGE); - } - return; - } - - if (params[0].startsWith("growth")) { - final int temp = ((int) Double.parseDouble(params[1]) * 100); - - if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) { - v.sendMessage(Messages.GROWTH_PERCENT_SET.replace("%growPercent%", String.valueOf(temp / 100))); - this.growPercent = temp; - } else { - v.sendMessage(Messages.GROWTH_PERCENT_RANGE.replace("%min%", "0.01").replace("%max%", "99.99")); - } - return; - } - - if (params[0].startsWith("recursion")) { - final int temp = Integer.parseInt(params[1]); - - if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) { - v.sendMessage(Messages.BRUSH_RECURSION_SET.replace("%val%", String.valueOf(temp))); - this.splatterRecursions = temp; - } else { - v.sendMessage(Messages.SPLATTER_BALL_BRUSH_RECURSION_RANGE); - } - return; - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); sendPerformerMessage(triggerHandle, v); } - @Override - public List registerArguments() { - List arguments = new ArrayList<>(); - arguments.addAll(Lists.newArrayList("recursion", "growth", "seed", "reset")); - - arguments.addAll(super.registerArguments()); - return arguments; - } - - @Override - public HashMap> registerArgumentValues() { - HashMap> argumentValues = new HashMap<>(); - - // Number variables - argumentValues.put("recursion", Lists.newArrayList("[number]")); - - // Decimal variables - argumentValues.put("seed", Lists.newArrayList("[decimal]")); - argumentValues.put("growth", Lists.newArrayList("[decimal]")); - - argumentValues.putAll(super.registerArgumentValues()); - return argumentValues; - } - @Override public String getPermissionNode() { return "voxelsniper.brush.splattervoxeldisc"; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplineBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplineBrush.java index d43505b3..342ae4a7 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplineBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SplineBrush.java @@ -1,11 +1,13 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -14,6 +16,7 @@ /** * FOR ANY BRUSH THAT USES A SPLINE, EXTEND THAT BRUSH FROM THIS BRUSH!!! That way, the spline calculations are already there. Also, the UI for the splines will * be included. + * ... * * @author psanker */ @@ -21,7 +24,6 @@ public class SplineBrush extends PerformerBrush { private final ArrayList endPts = new ArrayList<>(); private final ArrayList ctrlPts = new ArrayList<>(); - protected ArrayList spline = new ArrayList<>(); protected boolean set; protected boolean ctrl; @@ -84,7 +86,7 @@ public final void removeFromSet(final SnipeData v, final boolean ep, IBlock targ } public final boolean spline(final Point start, final Point end, final Point c1, final Point c2, final SnipeData v) { - this.spline.clear(); + this.positions.clear(); try { final Point c = (c1.subtract(start)).multiply(3); @@ -95,12 +97,10 @@ public final boolean spline(final Point start, final Point end, final Point c1, final int px = (int) Math.round((a.getX() * (t * t * t)) + (b.getX() * (t * t)) + (c.getX() * t) + start.getX()); final int py = (int) Math.round((a.getY() * (t * t * t)) + (b.getY() * (t * t)) + (c.getY() * t) + start.getY()); final int pz = (int) Math.round((a.getZ() * (t * t * t)) + (b.getZ() * (t * t)) + (c.getZ() * t) + start.getZ()); - - if (!this.spline.contains(new Point(px, py, pz))) { - this.spline.add(new Point(px, py, pz)); - } + positions.add(new BaseLocation(getWorld(), px, py, pz)); } - + //manually add operations because the performer logic is not called here + addOperations(currentPerformer.perform(positions)); return true; } catch (final Exception exception) { v.sendMessage(Messages.SPLINE_BRUSH_NOT_ENOUGH_POINTS.replace("%endPts%", String.valueOf(this.endPts.size())).replace("%ctrlPts%", String.valueOf(this.ctrlPts.size()))); @@ -108,43 +108,32 @@ public final boolean spline(final Point start, final Point end, final Point c1, } } - protected final void render(final SnipeData v) { - if (this.spline.isEmpty()) { - return; - } - - this.initP(v); - for (final Point point : this.spline) { - this.currentPerformer.perform(this.clampY(point.getX(), point.getY(), point.getZ())); - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { if (this.set) { this.removeFromSet(v, true, this.getTargetBlock()); } else if (this.ctrl) { this.removeFromSet(v, false, this.getTargetBlock()); } + this.positions.clear(); } protected final void clear(final SnipeData v) { - this.spline.clear(); + this.positions.clear(); this.ctrlPts.clear(); this.endPts.clear(); v.sendMessage(Messages.BEZIER_CURVE_CLEARED); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { if (this.set) { this.addToSet(v, true, this.getTargetBlock()); } if (this.ctrl) { this.addToSet(v, false, this.getTargetBlock()); } + this.positions.clear(); } @Override @@ -202,7 +191,8 @@ public final void parseParameters(final String triggerHandle, final String[] par return; } if (this.spline(this.endPts.get(0), this.endPts.get(1), this.ctrlPts.get(0), this.ctrlPts.get(1), v)) { - this.render(v); + this.initP(v); + this.performOperations(v); } return; } @@ -211,6 +201,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/StampBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/StampBrush.java index 51b0dc42..1724c9b8 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/StampBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/StampBrush.java @@ -1,13 +1,13 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import com.github.kevindagame.voxelsniper.world.IWorld; +import org.jetbrains.annotations.NotNull; import java.util.HashSet; @@ -17,12 +17,10 @@ public class StampBrush extends AbstractBrush { protected HashSet clone = new HashSet<>(); - protected HashSet fall = new HashSet<>(); - protected HashSet drop = new HashSet<>(); - protected HashSet solid = new HashSet<>(); - protected Undo undo; + protected HashSet toStamp = new HashSet<>(); protected boolean sorted = false; protected StampType stamp = StampType.DEFAULT; + /** * */ @@ -37,185 +35,96 @@ public final void reSort() { this.sorted = false; } + /** + * @param material + * @return whether this material falls or is a fluid + */ protected final boolean falling(final VoxelMaterial material) { - // TODO: Translate this - // return (id > 7 && id < 14); return material.hasGravity() || material.isFluid(); } /** + * Sets block at location of cb to the block in cb. + * * @param cb */ protected final void setBlock(final BlockWrapper cb) { - final IBlock block = this.clampY(this.getTargetBlock().getX() + cb.x, this.getTargetBlock().getY() + cb.y, this.getTargetBlock().getZ() + cb.z); - this.undo.put(block); - block.setBlockData(cb.blockData); + final IBlock block = getWorld().getBlock(this.getTargetBlock().getX() + cb.getX(), this.getTargetBlock().getY() + cb.getY(), this.getTargetBlock().getZ() + cb.getZ()); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), cb.getBlockData())); } /** + * Sets the block at location of cb to the block in cb, only if the block at the location of cb is air. + * * @param cb */ protected final void setBlockFill(final BlockWrapper cb) { - final IBlock block = this.clampY(this.getTargetBlock().getX() + cb.x, this.getTargetBlock().getY() + cb.y, this.getTargetBlock().getZ() + cb.z); + final IBlock block = getWorld().getBlock(this.getTargetBlock().getX() + cb.getX(), this.getTargetBlock().getY() + cb.getY(), this.getTargetBlock().getZ() + cb.getZ()); if (block.getMaterial().isAir()) { - this.undo.put(block); - block.setBlockData(cb.blockData); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), cb.getBlockData())); } } /** - * @param type + * Set the stamp type */ protected final void setStamp(final StampType type) { this.stamp = type; } /** + * stamps the terrain. This will replace all old blocks in the stamp area + * * @param v */ protected final void stamp(final SnipeData v) { - this.undo = new Undo(); - - if (this.sorted) { - for (final BlockWrapper block : this.solid) { - this.setBlock(block); - } - for (final BlockWrapper block : this.drop) { - this.setBlock(block); - } - for (final BlockWrapper block : this.fall) { - this.setBlock(block); - } - } else { - this.fall.clear(); - this.drop.clear(); - this.solid.clear(); - for (final BlockWrapper block : this.clone) { - if (block.blockData.getMaterial().fallsOff()) { - this.fall.add(block); - } else if (this.falling(block.blockData.getMaterial())) { - this.drop.add(block); - } else { - this.solid.add(block); - this.setBlock(block); - } - } - for (final BlockWrapper block : this.drop) { - this.setBlock(block); - } - for (final BlockWrapper block : this.fall) { - this.setBlock(block); - } + if (!this.sorted) { + this.toStamp.clear(); + this.toStamp.addAll(this.clone); this.sorted = true; } - - v.owner().storeUndo(this.undo); + for (final BlockWrapper block : this.toStamp) { + this.setBlock(block); + } } /** - * @param v + * Stamp the terrain. This will only replace a block, if the existing block is air. */ protected final void stampFill(final SnipeData v) { - - this.undo = new Undo(); - - if (this.sorted) { - for (final BlockWrapper block : this.solid) { - this.setBlockFill(block); - } - for (final BlockWrapper block : this.drop) { - this.setBlockFill(block); - } - for (final BlockWrapper block : this.fall) { - this.setBlockFill(block); - } - } else { - this.fall.clear(); - this.drop.clear(); - this.solid.clear(); - for (final BlockWrapper block : this.clone) { - if (block.blockData.getMaterial().fallsOff()) { - this.fall.add(block); - } else if (this.falling(block.blockData.getMaterial())) { - this.drop.add(block); - } else { - this.solid.add(block); - this.setBlockFill(block); - } - } - for (final BlockWrapper block : this.drop) { - this.setBlockFill(block); - } - for (final BlockWrapper block : this.fall) { - this.setBlockFill(block); - } + if (!this.sorted) { + this.toStamp.clear(); + this.toStamp.addAll(this.clone); this.sorted = true; } - - v.owner().storeUndo(this.undo); + for (final BlockWrapper block : this.toStamp) { + this.setBlockFill(block); + } } /** - * @param v + * Stamps the terrain, if the replace block is air, it won't remove the old block */ protected final void stampNoAir(final SnipeData v) { - - this.undo = new Undo(); - - if (this.sorted) { - for (final BlockWrapper block : this.solid) { - this.setBlock(block); - } - for (final BlockWrapper block : this.drop) { - this.setBlock(block); - } - for (final BlockWrapper block : this.fall) { - this.setBlock(block); - } - } else { - this.fall.clear(); - this.drop.clear(); - this.solid.clear(); + if (!this.sorted) { + this.toStamp.clear(); for (final BlockWrapper block : this.clone) { - if (block.blockData.getMaterial().fallsOff()) { - this.fall.add(block); - } else if (this.falling(block.blockData.getMaterial())) { - this.drop.add(block); - } else if (!block.blockData.getMaterial().isAir()) { - this.solid.add(block); - this.setBlock(block); + if (!block.getMaterial().isAir()) { + this.toStamp.add(block); } } - for (final BlockWrapper block : this.drop) { - this.setBlock(block); - } - for (final BlockWrapper block : this.fall) { - this.setBlock(block); - } this.sorted = true; } - - v.owner().storeUndo(this.undo); + stamp(v); } @Override protected final void arrow(final SnipeData v) { switch (this.stamp) { - case DEFAULT: - this.stamp(v); - break; - - case NO_AIR: - this.stampNoAir(v); - break; - - case FILL: - this.stampFill(v); - break; - - default: - v.sendMessage(Messages.STAMP_ERROR); - break; + case DEFAULT -> this.stamp(v); + case NO_AIR -> this.stampNoAir(v); + case FILL -> this.stampFill(v); + default -> v.sendMessage(Messages.STAMP_ERROR); } } @@ -225,7 +134,7 @@ protected void powder(final SnipeData v) { } @Override - public void info(final VoxelMessage vm) { + public void info(@NotNull final VoxelMessage vm) { throw new UnsupportedOperationException("Not supported yet."); } @@ -240,30 +149,4 @@ public String getPermissionNode() { protected enum StampType { NO_AIR, FILL, DEFAULT } - - /** - * @author Voxel - */ - protected class BlockWrapper { - - private final IWorld world; - public IBlockData blockData; - public int x; - public int y; - public int z; - - /** - * @param b - * @param blx - * @param bly - * @param blz - */ - public BlockWrapper(final IBlock b, final int blx, final int bly, final int blz, final IWorld world) { - this.blockData = b.getBlockData(); - this.x = blx; - this.y = bly; - this.z = blz; - this.world = world; - } - } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ThreePointCircleBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ThreePointCircleBrush.java index 49349c6c..7509f897 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ThreePointCircleBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ThreePointCircleBrush.java @@ -4,15 +4,16 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Three-Point_Circle_Brush + * ... * * @author Giltwist */ @@ -31,7 +32,7 @@ public ThreePointCircleBrush() { } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { if (this.coordsOne == null) { this.coordsOne = this.getTargetBlock().getLocation().toVector(); v.sendMessage(Messages.FIRST_POINT_SELECTED); @@ -50,7 +51,7 @@ protected final void arrow(final SnipeData v) { } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { if (this.coordsOne == null || this.coordsTwo == null || this.coordsThree == null) { return; } @@ -123,16 +124,13 @@ protected final void powder(final SnipeData v) { // Check if point is within sphere and on plane (some tolerance given) if (tempDistance <= radius && (Math.abs(cornerConstant - planeConstant) < this.tolerance.getValue() || Math.abs(centerConstant - planeConstant) < this.tolerance.getValue())) { - this.currentPerformer.perform(this.clampY(brushCenter.getBlockX() + x, brushCenter.getBlockY() + y, brushCenter.getBlockZ() + z)); + this.positions.add(new BaseLocation(getWorld(), brushCenter.getBlockX() + x, brushCenter.getBlockY() + y, brushCenter.getBlockZ() + z)); } } } } - v.sendMessage(Messages.TRI_POINT_CIRCLE_DONE); - v.owner().storeUndo(this.currentPerformer.getUndo()); - // Reset Brush this.coordsOne = null; this.coordsTwo = null; @@ -144,18 +142,10 @@ protected final void powder(final SnipeData v) { public final void info(final VoxelMessage vm) { vm.brushName(this.getName()); switch (this.tolerance) { - case ACCURATE: - vm.custom(Messages.TRI_POINT_CIRCLE_MODE_ACCURATE); - break; - case DEFAULT: - vm.custom(Messages.TRI_POINT_CIRCLE_MODE_DEFAULT); - break; - case SMOOTH: - vm.custom(Messages.TRI_POINT_CIRCLE_MODE_SMOOTH); - break; - default: - vm.custom(Messages.TRI_POINT_CIRCLE_MODE_UNKNOWN); - break; + case ACCURATE -> vm.custom(Messages.TRI_POINT_CIRCLE_MODE_ACCURATE); + case DEFAULT -> vm.custom(Messages.TRI_POINT_CIRCLE_MODE_DEFAULT); + case SMOOTH -> vm.custom(Messages.TRI_POINT_CIRCLE_MODE_SMOOTH); + default -> vm.custom(Messages.TRI_POINT_CIRCLE_MODE_UNKNOWN); } } @@ -176,11 +166,12 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); - arguments.addAll(Arrays.stream(Tolerance.values()).map(e -> e.name()).collect(Collectors.toList())); + arguments.addAll(Arrays.stream(Tolerance.values()).map(Enum::name).toList()); arguments.addAll(super.registerArguments()); return arguments; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TreeSnipeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TreeSnipeBrush.java index d72f57b0..1d4e8cc4 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TreeSnipeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TreeSnipeBrush.java @@ -1,23 +1,22 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.block.BlockFace; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.blockstate.IBlockState; -import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.treeType.VoxelTreeType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Tree_Brush + * ... * * @author Mick */ @@ -33,18 +32,12 @@ public TreeSnipeBrush() { } private void single(final SnipeData v, IBlock targetBlock) { - Undo undo = new Undo(); - - IBlock blockBelow = targetBlock.getRelative(BlockFace.DOWN); - IBlockState currentState = blockBelow.getState(); - undo.put(currentState); - blockBelow.setMaterial(VoxelMaterial.GRASS_BLOCK, false); - - this.getWorld().generateTree(targetBlock.getLocation(), this.treeType, undo); - - blockBelow.setBlockData(currentState.getBlockData(), false); - - v.owner().storeUndo(undo); + var result = this.getWorld().generateTree(targetBlock.getLocation(), this.treeType, false); + if (result != null) { + // don't include the clicked block + BaseLocation targetLocation = targetBlock.getRelative(BlockFace.DOWN).getLocation(); + addOperations(result.stream().filter((o) -> !o.getLocation().equals(targetLocation)).toList()); + } } private int getYOffset() { @@ -93,7 +86,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.TREESNIPE_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -110,6 +103,7 @@ public final void parseParameters(final String triggerHandle, final String[] par } } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TriangleBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TriangleBrush.java index e6e408a0..4f5f139e 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TriangleBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/TriangleBrush.java @@ -4,9 +4,10 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Triangle_Brush + * https://github.com/KevinDaGame/VoxelSniper-Reimagined/wiki/Brushes#triangle-brush * * @author Giltwist */ @@ -146,7 +147,7 @@ private void triangleP(final SnipeData v) { if (barycentric <= 1.1) { - this.currentPerformer.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); + this.positions.add(new BaseLocation(getWorld(), (int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); } @@ -197,7 +198,7 @@ private void triangleP(final SnipeData v) { if (barycentric <= 1.1) { - this.currentPerformer.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); + this.positions.add(new BaseLocation(getWorld(), (int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); } @@ -247,13 +248,11 @@ private void triangleP(final SnipeData v) { // VoxelSniper.log.info("Bary: "+barycentric+", hb: "+heronbig+", h1: "+heronone+", h2: "+herontwo+", h3: "+heronthree); if (barycentric <= 1.1) { - this.currentPerformer.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); + this.positions.add(new BaseLocation(getWorld(), (int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); } } } // END Z DEPENDENT - v.owner().storeUndo(this.currentPerformer.getUndo()); - } // RESET BRUSH @@ -272,12 +271,12 @@ private void triangleP(final SnipeData v) { } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.triangleA(v); } @Override - protected final void powder(final SnipeData v) { // Add a point + protected final void doPowder(final SnipeData v) { // Add a point this.triangleP(v); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/UnderlayBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/UnderlayBrush.java index 6be5393d..ccc40e1c 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/UnderlayBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/UnderlayBrush.java @@ -1,19 +1,21 @@ package com.github.kevindagame.brush; -import com.google.common.collect.Lists; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelList; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Underlay_Brush + * ... * * @author jmck95 Credit to GavJenks for framework and 95 of code. Big Thank you * to GavJenks @@ -45,8 +47,9 @@ private void underlay(final SnipeData v) { final VoxelMaterial currentBlock = this.getBlockMaterialAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z); if (this.isOverrideableMaterial(v.getVoxelList(), currentBlock)) { for (int d = 0; (d < this.depth); d++) { - if (!this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z).getMaterial().isAir()) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + var mat = getBlockMaterialAt(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z); + if (!mat.isAir()) { + positions.add(new BaseLocation(getWorld(), this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in // parameters memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. } @@ -58,8 +61,6 @@ private void underlay(final SnipeData v) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private void underlay2(final SnipeData v) { @@ -74,7 +75,7 @@ private void underlay2(final SnipeData v) { final VoxelMaterial currentBlock = this.getBlockMaterialAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z); if (this.isOverrideableMaterial(v.getVoxelList(), currentBlock)) { for (int d = -1; (d < this.depth - 1); d++) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + positions.add(new BaseLocation(getWorld(), this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in // parameters memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. } @@ -84,8 +85,6 @@ private void underlay2(final SnipeData v) { } } } - - v.owner().storeUndo(this.currentPerformer.getUndo()); } private boolean isOverrideableMaterial(VoxelList list, VoxelMaterial material) { @@ -101,12 +100,12 @@ private boolean isOverrideableMaterial(VoxelList list, VoxelMaterial material) { } @Override - public final void arrow(final SnipeData v) { + public final void doArrow(final SnipeData v) { this.underlay(v); } @Override - public final void powder(final SnipeData v) { + public final void doPowder(final SnipeData v) { this.underlay2(v); } @@ -161,6 +160,7 @@ public final void parseParameters(final String triggerHandle, final String[] par sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { List arguments = new ArrayList<>(); @@ -170,6 +170,7 @@ public List registerArguments() { return arguments; } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoltMeterBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoltMeterBrush.java index 99a0b1d0..3ca9c2c4 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoltMeterBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoltMeterBrush.java @@ -1,19 +1,25 @@ package com.github.kevindagame.brush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.CustomOperation; +import com.github.kevindagame.util.brushOperation.CustomOperationContext; import com.github.kevindagame.voxelsniper.block.BlockFace; -import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.blockdata.redstoneWire.IRedstoneWire; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Volt-Meter_Brush + * ... * * @author Gavjenks */ -public class VoltMeterBrush extends AbstractBrush { +public class VoltMeterBrush extends CustomBrush { /** * @@ -23,15 +29,14 @@ public VoltMeterBrush() { } private void data(final SnipeData v) { - final IBlock block = this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ()); - final IBlockData data = block.getBlockData(); + final IBlockData data = getTargetBlock().getBlockData(); if (data instanceof IRedstoneWire redstone) { v.sendMessage(Messages.REDSTONE_POWER_LEVEL.replace("%blocks%", String.valueOf(redstone.getPower()))); } } private void volt(final SnipeData v) { - final IBlock block = this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ()); + var block = getTargetBlock(); final boolean indirect = block.isBlockIndirectlyPowered(); final boolean direct = block.isBlockPowered(); v.sendMessage(Messages.BLOCK_POWER_MESSAGE.replace("%direct%", String.valueOf(direct)).replace("%indirect%", String.valueOf(indirect))); @@ -45,12 +50,12 @@ private void volt(final SnipeData v) { @Override protected final void arrow(final SnipeData v) { - this.volt(v); + addOperation(new CustomOperation(this.getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override protected final void powder(final SnipeData v) { - this.data(v); + addOperation(new CustomOperation(this.getTargetBlock().getLocation(), this, v, CustomOperationContext.TARGETLOCATION)); } @Override @@ -63,4 +68,18 @@ public final void info(final VoxelMessage vm) { public String getPermissionNode() { return "voxelsniper.brush.voltmeter"; } + + @Override + public boolean perform(@NotNull ImmutableList operations, @NotNull SnipeData snipeData, @NotNull Undo undo) { + switch (Objects.requireNonNull(this.getSnipeAction())) { + case ARROW: + volt(snipeData); + return true; + case GUNPOWDER: + data(snipeData); + return true; + default: + return false; + } + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelBrush.java index c6e48c90..7ae1ef77 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelBrush.java @@ -2,10 +2,11 @@ import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Brush + * ... * * @author Piotr */ @@ -19,23 +20,16 @@ public VoxelBrush() { } private void voxel(final SnipeData v) { - for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) { - for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { - for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) { - this.currentPerformer.perform(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y)); - } - } - } - v.owner().storeUndo(this.currentPerformer.getUndo()); + this.positions = Shapes.voxel(this.getTargetBlock().getLocation(), v.getBrushSize()); } @Override - protected final void arrow(final SnipeData v) { + protected final void doArrow(final SnipeData v) { this.voxel(v); } @Override - protected final void powder(final SnipeData v) { + protected final void doPowder(final SnipeData v) { this.voxel(v); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscBrush.java index 8965a072..94d78c76 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscBrush.java @@ -2,11 +2,11 @@ import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Disc_Brush + * ... * * @author Voxel */ @@ -19,23 +19,18 @@ public VoxelDiscBrush() { this.setName("Voxel Disc"); } - private void disc(final SnipeData v, IBlock targetBlock) { - for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { - for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) { - currentPerformer.perform(targetBlock.getRelative(x, 0, z)); - } - } - v.owner().storeUndo(this.currentPerformer.getUndo()); + private void voxelDisc(final SnipeData v) { + this.positions = Shapes.voxelDisc(this.getTargetBlock().getLocation(), v.getBrushSize()); } @Override - protected final void arrow(final SnipeData v) { - this.disc(v, this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + this.voxelDisc(v); } @Override - protected final void powder(final SnipeData v) { - this.disc(v, this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + this.voxelDisc(v); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscFaceBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscFaceBrush.java index ac673431..ff50aadf 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscFaceBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/VoxelDiscFaceBrush.java @@ -2,12 +2,11 @@ import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Shapes; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.BlockFace; -import com.github.kevindagame.voxelsniper.block.IBlock; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Disc_Face_Brush + * ... * * @author Voxel */ @@ -20,69 +19,18 @@ public VoxelDiscFaceBrush() { this.setName("Voxel Disc Face"); } - private void disc(final SnipeData v, IBlock targetBlock) { - for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { - for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) { - this.currentPerformer.perform(this.clampY(targetBlock.getX() + x, targetBlock.getY(), targetBlock.getZ() + y)); - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private void discNS(final SnipeData v, IBlock targetBlock) { - for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { - for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) { - this.currentPerformer.perform(this.clampY(targetBlock.getX() + x, targetBlock.getY() + y, targetBlock.getZ())); - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private void discEW(final SnipeData v, IBlock targetBlock) { - for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) { - for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) { - this.currentPerformer.perform(this.clampY(targetBlock.getX(), targetBlock.getY() + x, targetBlock.getZ() + y)); - } - } - - v.owner().storeUndo(this.currentPerformer.getUndo()); - } - - private void pre(final SnipeData v, final BlockFace bf, IBlock targetBlock) { - if (bf == null) { - return; - } - switch (bf) { - case NORTH: - case SOUTH: - this.discNS(v, targetBlock); - break; - - case EAST: - case WEST: - this.discEW(v, targetBlock); - break; - - case UP: - case DOWN: - this.disc(v, targetBlock); - break; - - default: - break; - } + private void voxelDiscFace(final SnipeData v) { + this.positions = Shapes.voxelDiscFace(this.getTargetBlock().getLocation(), v.getBrushSize(), this.getTargetBlock().getFace(this.getLastBlock())); } @Override - protected final void arrow(final SnipeData v) { - this.pre(v, this.getTargetBlock().getFace(this.getLastBlock()), this.getTargetBlock()); + protected final void doArrow(final SnipeData v) { + voxelDiscFace(v); } @Override - protected final void powder(final SnipeData v) { - this.pre(v, this.getTargetBlock().getFace(this.getLastBlock()), this.getLastBlock()); + protected final void doPowder(final SnipeData v) { + voxelDiscFace(v); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/WarpBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/WarpBrush.java index 7c66c933..5f013d3b 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/WarpBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/WarpBrush.java @@ -3,10 +3,11 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; /** * @author MikeMatrix + * ... */ public class WarpBrush extends AbstractBrush { @@ -25,8 +26,8 @@ public final void info(final VoxelMessage vm) { @Override protected final void arrow(final SnipeData v) { IPlayer player = v.owner().getPlayer(); - VoxelLocation location = this.getLastBlock().getLocation(); - VoxelLocation playerLocation = player.getLocation(); + BaseLocation location = this.getLastBlock().getLocation(); + BaseLocation playerLocation = player.getLocation(); location.setPitch(playerLocation.getPitch()); location.setYaw(playerLocation.getYaw()); @@ -36,14 +37,11 @@ protected final void arrow(final SnipeData v) { @Override protected final void powder(final SnipeData v) { IPlayer player = v.owner().getPlayer(); - VoxelLocation location = this.getLastBlock().getLocation(); - VoxelLocation playerLocation = player.getLocation(); + BaseLocation location = this.getLastBlock().getLocation(); + BaseLocation playerLocation = player.getLocation(); location.setPitch(playerLocation.getPitch()); location.setYaw(playerLocation.getYaw()); - - getWorld().strikeLightning(location); player.teleport(location); - getWorld().strikeLightning(location); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CanyonBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CanyonBrush.java similarity index 74% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CanyonBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CanyonBrush.java index 97ed7751..63c77e46 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CanyonBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CanyonBrush.java @@ -1,20 +1,22 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_CANYONATOR + * ... * * @author Voxel */ @@ -33,56 +35,42 @@ public CanyonBrush() { /** * @param chunk - * @param undo */ - protected final void canyon(final IChunk chunk, final Undo undo) { + protected final void canyon(final IChunk chunk) { for (int x = 0; x < CHUNK_SIZE; x++) { for (int z = 0; z < CHUNK_SIZE; z++) { int currentYLevel = this.yLevel; + //TODO I don't think 63 is correct for (int y = 63; y < this.getMaxHeight(); y++) { final IBlock block = chunk.getBlock(x, y, z); final IBlock currentYLevelBlock = chunk.getBlock(x, currentYLevel, z); - - undo.put(block); - undo.put(currentYLevelBlock); - - currentYLevelBlock.setBlockData(block.getBlockData(), false); - + addOperation(new BlockOperation(currentYLevelBlock.getLocation(), currentYLevelBlock.getBlockData(), block.getBlockData())); currentYLevel++; } for (int y = currentYLevel; y < this.getMaxHeight(); y++) { - chunk.getBlock(x, y, z).setMaterial(VoxelMaterial.AIR); + var block = chunk.getBlock(x, y, z); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), VoxelMaterial.AIR.createBlockData())); } - - final IBlock block = chunk.getBlock(x, this.getMinHeight(), z); - undo.put(block); - block.setMaterial(VoxelMaterial.BEDROCK); + var block = chunk.getBlock(x, this.getMinHeight(), z); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), VoxelMaterial.BEDROCK.createBlockData())); } } } @Override protected void arrow(final SnipeData v) { - final Undo undo = new Undo(); - - canyon(getTargetBlock().getChunk(), undo); - - v.owner().storeUndo(undo); + canyon(getTargetBlock().getChunk()); } @Override protected void powder(final SnipeData v) { - final Undo undo = new Undo(); - IChunk targetChunk = getTargetBlock().getChunk(); for (int x = targetChunk.getX() - 1; x <= targetChunk.getX() + 1; x++) { for (int z = targetChunk.getZ() - 1; z <= targetChunk.getZ() + 1; z++) { - canyon(getWorld().getChunkAtLocation(x, z), undo); + canyon(getWorld().getChunkAtLocation(x, z)); } } - - v.owner().storeUndo(undo); } @Override @@ -92,7 +80,7 @@ public void info(final VoxelMessage vm) { } @Override - public final void parseParameters(String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.CANYON_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -120,11 +108,13 @@ public final void parseParameters(String triggerHandle, final String[] params, f v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("y")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CanyonSelectionBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CanyonSelectionBrush.java similarity index 89% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CanyonSelectionBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CanyonSelectionBrush.java index 92298e7a..a1b4878b 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CanyonSelectionBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CanyonSelectionBrush.java @@ -1,4 +1,4 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Undo; @@ -7,7 +7,7 @@ import com.github.kevindagame.voxelsniper.chunk.IChunk; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Canyon_Selection_Brush + * ... * * @author Voxel */ @@ -44,7 +44,7 @@ private void selection(final int lowX, final int lowZ, final int highX, final in for (int x = lowX; x <= highX; x++) { for (int z = lowZ; z <= highZ; z++) { - canyon(getWorld().getChunkAtLocation(x, z), undo); + canyon(getWorld().getChunkAtLocation(x, z)); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CopyPastaBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CopyPastaBrush.java similarity index 82% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CopyPastaBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CopyPastaBrush.java index 8aa5f276..f648e199 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/CopyPastaBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/CopyPastaBrush.java @@ -1,19 +1,22 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#CopyPasta_Brush + * ... * * @author giltwist */ @@ -39,7 +42,6 @@ public CopyPastaBrush() { this.setName("CopyPasta"); } - @SuppressWarnings("deprecation") private void doCopy(final SnipeData v) { for (int i = 0; i < 3; i++) { this.arraySize[i] = Math.abs(this.firstPoint[i] - this.secondPoint[i]) + 1; @@ -67,7 +69,6 @@ private void doCopy(final SnipeData v) { } } - @SuppressWarnings("deprecation") private void doPasta(final SnipeData v) { final Undo undo = new Undo(); @@ -79,24 +80,21 @@ private void doPasta(final SnipeData v) { switch (this.pivot) { case 180: - block = this.clampY(this.pastePoint[0] - this.offsetPoint[0] - i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[2] - k); + block = this.getWorld().getBlock(this.pastePoint[0] - this.offsetPoint[0] - i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[2] - k); break; case 270: - block = this.clampY(this.pastePoint[0] + this.offsetPoint[2] + k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[0] - i); + block = this.getWorld().getBlock(this.pastePoint[0] + this.offsetPoint[2] + k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[0] - i); break; case 90: - block = this.clampY(this.pastePoint[0] - this.offsetPoint[2] - k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[0] + i); + block = this.getWorld().getBlock(this.pastePoint[0] - this.offsetPoint[2] - k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[0] + i); break; default: // assume no rotation - block = this.clampY(this.pastePoint[0] + this.offsetPoint[0] + i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[2] + k); + block = this.getWorld().getBlock(this.pastePoint[0] + this.offsetPoint[0] + i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[2] + k); break; } - if (!(this.substanceArray[currentPosition].getMaterial().isAir() && !this.pasteAir)) { - if (block.getMaterial() != this.substanceArray[currentPosition].getMaterial() || !block.getBlockData().matches(this.substanceArray[currentPosition])) { - undo.put(block); - } - block.setBlockData(this.substanceArray[currentPosition], true); + if (!(!this.pasteAir && this.substanceArray[currentPosition].getMaterial().isAir())) { + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), this.substanceArray[currentPosition])); } } } @@ -160,7 +158,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.COPYPASTA_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -184,12 +182,14 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("rotate", "air")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ExtrudeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/ExtrudeBrush.java similarity index 70% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ExtrudeBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/ExtrudeBrush.java index cc774d64..215d36c2 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ExtrudeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/ExtrudeBrush.java @@ -1,18 +1,20 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.BlockFace; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Extrude_Brush + * ... * * @author psanker */ @@ -20,7 +22,6 @@ public class ExtrudeBrush extends AbstractBrush { private static final double SMOOTH_CIRCLE_VALUE = 0.5; private static final double VOXEL_CIRCLE_VALUE = 0.0; - private boolean smoothCircle = false; /** @@ -33,8 +34,6 @@ public ExtrudeBrush() { private void extrudeUpOrDown(final SnipeData v, boolean isUp) { final int brushSize = v.getBrushSize(); final double brushSizeSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - Undo undo = new Undo(); - for (int x = -brushSize; x <= brushSize; x++) { final double xSquared = Math.pow(x, 2); for (int z = -brushSize; z <= brushSize; z++) { @@ -42,23 +41,19 @@ private void extrudeUpOrDown(final SnipeData v, boolean isUp) { final int direction = (isUp ? 1 : -1); for (int y = 0; y < Math.abs(v.getVoxelHeight()); y++) { final int tempY = y * direction; - undo = this.perform( - this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY, this.getTargetBlock().getZ() + z), - this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY + direction, this.getTargetBlock().getZ() + z), - v, undo); + this.perform( + getWorld().getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY, this.getTargetBlock().getZ() + z), + getWorld().getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY + direction, this.getTargetBlock().getZ() + z), + v); } } } } - - v.owner().storeUndo(undo); } private void extrudeNorthOrSouth(final SnipeData v, boolean isSouth) { final int brushSize = v.getBrushSize(); final double brushSizeSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - Undo undo = new Undo(); - for (int x = -brushSize; x <= brushSize; x++) { final double xSquared = Math.pow(x, 2); for (int y = -brushSize; y <= brushSize; y++) { @@ -66,23 +61,20 @@ private void extrudeNorthOrSouth(final SnipeData v, boolean isSouth) { final int direction = (isSouth) ? 1 : -1; for (int z = 0; z < Math.abs(v.getVoxelHeight()); z++) { final int tempZ = z * direction; - undo = this.perform( - this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ), - this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ + direction), - v, undo); + this.perform( + getWorld().getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ), + getWorld().getBlock(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ + direction), + v); } } } } - - v.owner().storeUndo(undo); } private void extrudeEastOrWest(final SnipeData v, boolean isEast) { final int brushSize = v.getBrushSize(); final double brushSizeSquared = Math.pow(brushSize + (smoothCircle ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); - Undo undo = new Undo(); for (int y = -brushSize; y <= brushSize; y++) { final double ySquared = Math.pow(y, 2); @@ -91,27 +83,21 @@ private void extrudeEastOrWest(final SnipeData v, boolean isEast) { final int direction = (isEast) ? 1 : -1; for (int x = 0; x < Math.abs(v.getVoxelHeight()); x++) { final int tempX = x * direction; - undo = this.perform( - this.clampY(this.getTargetBlock().getX() + tempX, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z), - this.clampY(this.getTargetBlock().getX() + tempX + direction, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z), - v, undo); + this.perform( + getWorld().getBlock(this.getTargetBlock().getX() + tempX, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z), + getWorld().getBlock(this.getTargetBlock().getX() + tempX + direction, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z), + v); } } } } - v.owner().storeUndo(undo); } - private Undo perform(final IBlock b1, final IBlock b2, final SnipeData v, final Undo undo) { - IBlock clampedBlock1 = this.clampY(b1.getX(), b1.getY(), b1.getZ()); - IBlock clampedBlock2 = this.clampY(b2.getX(), b2.getY(), b2.getZ()); - if (v.getVoxelList().contains(clampedBlock1.getMaterial())) { - undo.put(clampedBlock2); - clampedBlock2.setBlockData(clampedBlock1.getBlockData()); + private void perform(final IBlock b1, final IBlock b2, final SnipeData v) { + if (v.getVoxelList().contains(b1.getMaterial())) { + addOperation(new BlockOperation(b2.getLocation(), b2.getBlockData(), b1.getBlockData())); } - - return undo; } private void selectExtrudeMethod(final SnipeData v, final BlockFace blockFace, final boolean towardsUser) { @@ -163,7 +149,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.EXTRUDE_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -178,6 +164,7 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FlatOceanBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/FlatOceanBrush.java similarity index 61% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FlatOceanBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/FlatOceanBrush.java index 539845e9..b1090d60 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/FlatOceanBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/FlatOceanBrush.java @@ -1,11 +1,15 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -13,6 +17,7 @@ /** * @author GavJenks + * ... */ public class FlatOceanBrush extends AbstractBrush { @@ -28,19 +33,21 @@ public FlatOceanBrush() { this.setName("FlatOcean"); } - @SuppressWarnings("deprecation") private void flatOcean(final IChunk chunk) { for (int x = 0; x < CHUNK_SIZE; x++) { for (int z = 0; z < CHUNK_SIZE; z++) { // chunk.getWorld() == getWorld() for (int y = this.getMinHeight(); y < this.getMaxHeight(); y++) { + var block = chunk.getBlock(x, y, z); + var blockWrapper = new BlockWrapper(block); if (y <= this.floorLevel) { - chunk.getBlock(x, y, z).setMaterial(VoxelMaterial.DIRT, false); + blockWrapper.setBlockData(VoxelMaterial.DIRT.createBlockData()); } else if (y <= this.waterLevel) { - chunk.getBlock(x, y, z).setMaterial(VoxelMaterial.WATER, false); + blockWrapper.setBlockData(VoxelMaterial.WATER.createBlockData()); } else { - chunk.getBlock(x, y, z).setMaterial(VoxelMaterial.AIR, false); + blockWrapper.setBlockData(VoxelMaterial.AIR.createBlockData()); } + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), blockWrapper.getBlockData())); } } } @@ -54,26 +61,25 @@ protected final void arrow(final SnipeData v) { @Override protected final void powder(final SnipeData v) { this.flatOcean(this.getWorld().getChunkAtLocation(this.getTargetBlock().getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ()).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() + CHUNK_SIZE).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ()).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() - CHUNK_SIZE).getLocation())); - this.flatOcean(this.getWorld().getChunkAtLocation(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ()).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() + CHUNK_SIZE).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ()).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() - CHUNK_SIZE).getLocation())); + this.flatOcean(this.getWorld().getChunkAtLocation(getWorld().getBlock(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE).getLocation())); } @Override public final void info(final VoxelMessage vm) { vm.brushName(this.getName()); - vm.custom(Messages.BRUSH_NO_UNDO); vm.custom(Messages.WATER_LEVEL_SET.replace("%waterLevel%", String.valueOf(waterLevel))); vm.custom(Messages.OCEAN_FLOOR_LEVEL_SET.replace("%floorLevel%", String.valueOf(this.floorLevel))); } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.FLAT_OCEAN_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); v.sendMessage(Messages.BRUSH_NO_UNDO); @@ -111,12 +117,14 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("water", "floor")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/GenerateTreeBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/GenerateTreeBrush.java similarity index 88% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/GenerateTreeBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/GenerateTreeBrush.java index e7977093..dac26877 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/GenerateTreeBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/GenerateTreeBrush.java @@ -1,20 +1,23 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.location.VoxelLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.*; // Proposal: Use /v and /vr for leave and wood material // or two more parameters -- Monofraps /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#VoxelTrees_Brush + * ... * * @author Ghost8700 @ Voxel */ @@ -24,7 +27,6 @@ public class GenerateTreeBrush extends AbstractBrush { private final Random random = new Random(); private final ArrayList branchBlocks = new ArrayList<>(); private final int twistChance = 5; // This is a hidden value not available through Parameters. Otherwise messy. - private Undo undo; // If these default values are edited. Remember to change default values in the default preset. private VoxelMaterial leavesMaterial = VoxelMaterial.OAK_LEAVES; private VoxelMaterial woodMaterial = VoxelMaterial.OAK_WOOD; @@ -49,8 +51,8 @@ public GenerateTreeBrush() { } // Branch Creation based on direction chosen from the parameters passed. - private void branchCreate(VoxelLocation location, final int xDirection, final int zDirection) { - location = location.clone(); + private void branchCreate(BaseLocation origin, final int xDirection, final int zDirection) { + VoxelLocation location = origin.makeMutable(); // Sets direction preference. final int xPreference = this.random.nextInt(60) + 20; @@ -72,18 +74,14 @@ private void branchCreate(VoxelLocation location, final int xDirection, final in location.addY(this.random.nextInt(2)); } - // Add block to undo function. - if (location.getBlock().getMaterial() != woodMaterial) { - this.undo.put(location.getClampedBlock()); - } - // Creates a branch block. - location.getBlock().setBlockData(woodMaterial.createBlockData(), false); - this.branchBlocks.add(location.getClampedBlock()); + addOperation(new BlockOperation(location, location.getBlock().getBlockData(), this.woodMaterial.createBlockData())); + this.branchBlocks.add(location.getBlock()); } } - private void leafNodeCreate(final VoxelLocation location) { + private void leafNodeCreate(final BaseLocation origin) { + VoxelLocation location = origin.makeMutable(); // Generates the node size. final int nodeRadius = this.random.nextInt(this.nodeMax - this.nodeMin + 1) + this.nodeMin; final double bSquared = Math.pow(nodeRadius + 0.5, 2); @@ -103,12 +101,8 @@ private void leafNodeCreate(final VoxelLocation location) { if (this.chance(70)) { // If block is Air, create a leaf block. if (location.getBlock().getRelative(x, y, z).getMaterial().isAir()) { - // Adds block to undo function. - if (location.getBlock().getRelative(x, y, z).getBlockData().getMaterial() != leavesMaterial) { - this.undo.put(location.getBlock().getRelative(x, y, z)); - } - // Creates block. - location.getClampedBlock().getRelative(x, y, z).setBlockData(leavesMaterial.createBlockData(), false); + var block = location.getBlock().getRelative(x, y, z); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), this.leavesMaterial.createBlockData())); } } for (int dx : new int[]{-1, 1}) { @@ -124,23 +118,23 @@ private void leafNodeCreate(final VoxelLocation location) { } } - private void createLeaf(final VoxelLocation location, int x, int y, int z) { + private void createLeaf(final BaseLocation location, int x, int y, int z) { if (location.getBlock().getRelative(x, y, z).getMaterial().isAir()) { - this.undo.put(location.getClampedBlock().getRelative(x, y, z)); - location.getBlock().getRelative(x, y, z).setBlockData(leavesMaterial.createBlockData(), false); + var block = location.getBlock().getRelative(x, y, z); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), this.leavesMaterial.createBlockData())); } } /** * Code Concerning Root Generation. * - * @param location + * @param origin * @param xDirection * @param zDirection */ - private void rootCreate(VoxelLocation location, final int xDirection, final int zDirection) { + private void rootCreate(BaseLocation origin, final int xDirection, final int zDirection) { // Sets Origin. - location = location.clone(); + VoxelLocation location = origin.makeMutable(); // Generates the number of roots to create. final int roots = this.random.nextInt(this.maxRoots - this.minRoots + 1) + this.minRoots; @@ -164,10 +158,9 @@ private void rootCreate(VoxelLocation location, final int xDirection, final int // If not solid then... // Save for undo function if (location.getBlock().getMaterial() != woodMaterial) { - this.undo.put(location.getClampedBlock()); // Place log block. - location.getClampedBlock().setBlockData(woodMaterial.createBlockData(), false); + addOperation(new BlockOperation(location, location.getBlock().getBlockData(), this.woodMaterial.createBlockData())); } else { // If solid then... // End loop @@ -175,7 +168,7 @@ private void rootCreate(VoxelLocation location, final int xDirection, final int } List blocks = Arrays.asList(VoxelMaterial.WATER, VoxelMaterial.SNOW, VoxelMaterial.OAK_LOG, VoxelMaterial.BIRCH_LOG, VoxelMaterial.ACACIA_LOG, VoxelMaterial.DARK_OAK_LOG, VoxelMaterial.SPRUCE_LOG, VoxelMaterial.JUNGLE_LOG); // Checks is block below is solid - if (blocks.contains(location.getClampedBlock().getRelative(0, -1, 0).getMaterial())) { + if (blocks.contains(location.getBlock().getRelative(0, -1, 0).getMaterial())) { // Move down if solid. location.addY(-1); if (this.rootFloat) { @@ -195,7 +188,7 @@ private void rootCreate(VoxelLocation location, final int xDirection, final int location.addZ(zDirection); } // Checks if new location is solid, if not then move down. - if (blocks.contains(location.getClampedBlock().getRelative(0, -1, 0).getMaterial())) { + if (blocks.contains(location.getBlock().getRelative(0, -1, 0).getMaterial())) { location.addY(-1); } } @@ -204,7 +197,7 @@ private void rootCreate(VoxelLocation location, final int xDirection, final int } } - private void rootGen(final VoxelLocation location) { + private void rootGen(final BaseLocation location) { // Quadrant 1 this.rootCreate(location, 1, 1); @@ -218,7 +211,7 @@ private void rootGen(final VoxelLocation location) { this.rootCreate(location, -1, -1); } - private void trunkCreate(final VoxelLocation location) { + private void trunkCreate(final BaseLocation location) { // Creates true circle discs of the set size using the wood type selected. final double bSquared = Math.pow(this.thickness + 0.5, 2); @@ -238,13 +231,12 @@ private void trunkCreate(final VoxelLocation location) { } } - private void createTrunk(final VoxelLocation location, int x, int z) { + private void createTrunk(final BaseLocation location, int x, int z) { // If block is air, then create a block. if (location.getBlock().getRelative(x, 0, z).getMaterial().isAir()) { - // Adds block to undo function. - this.undo.put(location.getClampedBlock().getRelative(x, 0, z)); // Creates block. - location.getClampedBlock().getRelative(x, 0, z).setBlockData(woodMaterial.createBlockData(), false); + var block = location.getBlock().getRelative(x, 0, z); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), this.woodMaterial.createBlockData())); } } @@ -252,9 +244,9 @@ private void createTrunk(final VoxelLocation location, int x, int z) { * * Code Concerning Trunk Generation */ - private void trunkGen(final VoxelLocation origin) { + private void trunkGen(final BaseLocation origin) { // Sets Origin - VoxelLocation location = origin.clone(); + VoxelLocation location = origin.makeMutable(); // ---------- // Main Trunk @@ -301,7 +293,7 @@ private void trunkGen(final VoxelLocation origin) { this.branchCreate(location, -1, -1); // Reset Origin for next trunk. - location = origin.clone(); + location = origin.makeMutable(); location.addY(4); // --------------- @@ -350,13 +342,12 @@ private void trunkGen(final VoxelLocation origin) { @Override protected final void arrow(final SnipeData v) { - this.undo = new Undo(); this.branchBlocks.clear(); // Sets the location variables. - VoxelLocation location = new VoxelLocation(this.getTargetBlock().getWorld(), this.getTargetBlock().getX(), this.getTargetBlock().getY() + this.startHeight, this.getTargetBlock().getZ()); + BaseLocation location = new BaseLocation(this.getTargetBlock().getWorld(), this.getTargetBlock().getX(), this.getTargetBlock().getY() + this.startHeight, this.getTargetBlock().getZ()); // Generates the roots. this.rootGen(location); @@ -368,9 +359,6 @@ protected final void arrow(final SnipeData v) { for (final IBlock block : this.branchBlocks) { this.leafNodeCreate(block.getLocation()); } - - // Ends the undo function and mos on. - v.owner().storeUndo(this.undo); } // The Powder currently does nothing extra. @@ -397,7 +385,7 @@ public boolean chance(int chance) { @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { if (params.length == 1 || params[1].equals("1")) { @@ -559,6 +547,7 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { @@ -566,6 +555,7 @@ public List registerArguments() { "rootFloat", "info", "rootMin", "rootMax", "minHeight", "maxHeight", "leavesMin", "leavesMax", "default")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/MoveBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/MoveBrush.java similarity index 79% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/MoveBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/MoveBrush.java index bfd228f4..27586261 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/MoveBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/MoveBrush.java @@ -1,15 +1,16 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.blockstate.IBlockState; +import com.github.kevindagame.util.brushOperation.BlockOperation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.location.VoxelLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; +import com.google.common.collect.Lists; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -17,11 +18,10 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; /** - * Moves a selection blockPositionY a certain amount. http://www.voxelwiki.com/minecraft/Voxelsniper#Move_Brush + * Moves a selection blockPositionY a certain amount. ... * * @author MikeMatrix */ @@ -35,6 +35,7 @@ public class MoveBrush extends AbstractBrush { * Saved selection. */ private Selection selection = null; + /** * */ @@ -49,18 +50,13 @@ public MoveBrush() { * @param selection * @param direction */ - @SuppressWarnings("deprecation") private void moveSelection(final SnipeData v, final Selection selection, final int[] direction) { - if (selection.getBlockStates().size() > 0) { - final IWorld world = selection.getBlockStates().get(0).getWorld(); - - final Undo undo = new Undo(); - final HashSet undoSet = new HashSet<>(); - + if (selection.getBlockWrappers().size() > 0) { + final IWorld world = selection.getBlockWrappers().get(0).getWorld(); final Selection newSelection = new Selection(); - final VoxelLocation movedLocation1 = selection.getLocation1(); + final VoxelLocation movedLocation1 = selection.getLocation1().makeMutable(); movedLocation1.add(direction[0], direction[1], direction[2]); - final VoxelLocation movedLocation2 = selection.getLocation2(); + final VoxelLocation movedLocation2 = selection.getLocation2().makeMutable(); movedLocation2.add(direction[0], direction[1], direction[2]); newSelection.setLocation1(movedLocation1); newSelection.setLocation2(movedLocation2); @@ -70,24 +66,12 @@ private void moveSelection(final SnipeData v, final Selection selection, final i v.sendMessage(exception); } - for (final IBlockState blockState : selection.getBlockStates()) { - undoSet.add(blockState.getBlock()); - } - for (final IBlockState blockState : newSelection.getBlockStates()) { - undoSet.add(blockState.getBlock()); - } - - for (final IBlock block : undoSet) { - undo.put(block); - } - v.owner().storeUndo(undo); - - for (final IBlockState blockState : selection.getBlockStates()) { - blockState.getBlock().setMaterial(VoxelMaterial.AIR); + for (final BlockWrapper blockWrapper : selection.getBlockWrappers()) { + addOperation(new BlockOperation(blockWrapper.getLocation(), blockWrapper.getLocation().getBlock().getBlockData(), VoxelMaterial.AIR.createBlockData())); } - for (final IBlockState blockState : selection.getBlockStates()) { - final IBlock affectedBlock = world.getBlock(blockState.getX() + direction[0], blockState.getY() + direction[1], blockState.getZ() + direction[2]); - affectedBlock.setBlockData(blockState.getBlockData(), !blockState.getMaterial().fallsOff()); + for (final BlockWrapper blockWrapper : selection.getBlockWrappers()) { + var block = world.getBlock(blockWrapper.getX() + direction[0], blockWrapper.getY() + direction[1], blockWrapper.getZ() + direction[2]); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), blockWrapper.getBlockData())); } } } @@ -135,7 +119,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.MOVE_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -174,12 +158,14 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("reset", "x", "y", "z")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); @@ -209,7 +195,8 @@ public String getMessage() { } @Override - public @NotNull Component asComponent() { + public @NotNull + Component asComponent() { return component.asComponent(); } } @@ -228,15 +215,15 @@ private class Selection { /** * Calculated BlockStates of the selection. */ - private final ArrayList blockStates = new ArrayList<>(); + private final ArrayList blockWrappers = new ArrayList<>(); /** * */ - private VoxelLocation location1 = null; + private BaseLocation location1 = null; /** * */ - private VoxelLocation location2 = null; + private BaseLocation location2 = null; /** * Calculates region, then saves all Blocks as BlockState. @@ -260,7 +247,7 @@ public boolean calculateRegion() throws ComponentException { for (int y = lowY; y <= highY; y++) { for (int x = lowX; x <= highX; x++) { for (int z = lowZ; z <= highZ; z++) { - this.blockStates.add(world.getBlock(x, y, z).getState()); + this.blockWrappers.add(new BlockWrapper(world.getBlock(x, y, z))); } } } @@ -273,35 +260,35 @@ public boolean calculateRegion() throws ComponentException { /** * @return ArrayList calculated BlockStates of defined region. */ - public ArrayList getBlockStates() { - return this.blockStates; + public ArrayList getBlockWrappers() { + return this.blockWrappers; } /** * @return Location */ - public VoxelLocation getLocation1() { + public BaseLocation getLocation1() { return this.location1; } /** * @param location1 */ - public void setLocation1(final VoxelLocation location1) { + public void setLocation1(final BaseLocation location1) { this.location1 = location1; } /** * @return Location */ - public VoxelLocation getLocation2() { + public BaseLocation getLocation2() { return this.location2; } /** * @param location2 */ - public void setLocation2(final VoxelLocation location2) { + public void setLocation2(final BaseLocation location2) { this.location2 = location2; } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OceanBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/OceanBrush.java similarity index 89% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OceanBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/OceanBrush.java index 12a73c4a..28279b1a 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/OceanBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/OceanBrush.java @@ -1,13 +1,16 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -15,11 +18,10 @@ import java.util.List; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#The_OCEANATOR_5000 + * ...s#ocean-brush * * @author Voxel */ -// TODO: FIX (not working?) public class OceanBrush extends AbstractBrush { private static final int WATER_LEVEL_DEFAULT = 62; // y=63 -- we are using array indices here @@ -94,7 +96,7 @@ public OceanBrush() { private int getHeight(final int bx, final int bz) { for (int y = this.getWorld().getHighestBlockYAt(bx, bz); y > this.getMinHeight(); y--) { - final VoxelMaterial material = this.clampY(bx, y, bz).getMaterial(); + final VoxelMaterial material = getWorld().getBlock(bx, y, bz).getMaterial(); if (!EXCLUDED_MATERIALS.contains(material)) { return y; } @@ -106,7 +108,6 @@ private int getHeight(final int bx, final int bz) { * @param v * @param undo */ - @SuppressWarnings("deprecation") protected final void oceanator(final SnipeData v, final Undo undo) { final IWorld world = this.getWorld(); @@ -127,8 +128,7 @@ protected final void oceanator(final SnipeData v, final Undo undo) { for (int y = highestY; y > newSeaFloorLevel; y--) { final IBlock block = world.getBlock(x, y, z); if (!block.getMaterial().isAir()) { - undo.put(block); - block.setMaterial(VoxelMaterial.AIR); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), VoxelMaterial.AIR.createBlockData())); } } @@ -136,11 +136,7 @@ protected final void oceanator(final SnipeData v, final Undo undo) { for (int y = this.waterLevel; y > newSeaFloorLevel; y--) { final IBlock block = world.getBlock(x, y, z); if (!block.getMaterial().equals(VoxelMaterial.WATER)) { - // do not put blocks into the undo we already put into - if (!block.getMaterial().isAir()) { - undo.put(block); - } - block.setMaterial(VoxelMaterial.WATER); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), VoxelMaterial.WATER.createBlockData())); } } @@ -148,8 +144,7 @@ protected final void oceanator(final SnipeData v, final Undo undo) { if (this.coverFloor && (newSeaFloorLevel < this.waterLevel)) { IBlock block = world.getBlock(x, newSeaFloorLevel, z); if (block.getMaterial() != v.getVoxelMaterial()) { - undo.put(block); - block.setBlockData(v.getVoxelMaterial().createBlockData()); + addOperation(new BlockOperation(block.getLocation(), block.getBlockData(), v.getVoxelMaterial().createBlockData())); } } } @@ -169,7 +164,7 @@ protected final void powder(final SnipeData v) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.OCEAN_BRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -200,12 +195,14 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.BRUSH_INVALID_PARAM.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("water", "floor")); } + @NotNull @Override public HashMap> registerArgumentValues() { HashMap> argumentValues = new HashMap<>(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PullBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/PullBrush.java similarity index 78% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PullBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/PullBrush.java index 98be1e1f..d2417a45 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/PullBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/multiBlock/PullBrush.java @@ -1,31 +1,34 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.multiBlock; -import com.google.common.collect.Lists; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.List; /** * @author Piotr + * ... */ -// TODO: Figure out what this does public class PullBrush extends AbstractBrush { private double pinch = 1; private double bubble = 0; + /** * Default Constructor. */ public PullBrush() { - this.setName("Soft Selection"); + this.setName("pull"); } @Override @@ -38,7 +41,7 @@ public final void info(final VoxelMessage vm) { } @Override - public final void parseParameters(final String triggerHandle, final String[] params, final SnipeData v) { + public final void parseParameters(@NotNull final String triggerHandle, final String[] params, @NotNull final SnipeData v) { if (params[0].equalsIgnoreCase("info")) { v.sendMessage(Messages.PULLBRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); return; @@ -73,6 +76,7 @@ public final void parseParameters(final String triggerHandle, final String[] par v.sendMessage(Messages.PULLBRUSH_USAGE.replace("%triggerHandle%", triggerHandle)); } + @NotNull @Override public List registerArguments() { return Lists.newArrayList("pinch", "bubble"); @@ -104,7 +108,7 @@ private HashSet getSurface(final SnipeData v) { final double volume = (xSquared + Math.pow(y, 2) + zSquared); if (volume <= bSquared) { if (this.isSurface(actualX, this.getTargetBlock().getY() + y, actualZ)) { - surface.add(new BlockWrapper(this.clampY(actualX, this.getTargetBlock().getY() + y, actualZ), this.getStr(((volume / bSquared))))); + surface.add(new BlockWrapper(getWorld().getBlock(actualX, this.getTargetBlock().getY() + y, actualZ), this.getStr(((volume / bSquared))))); } } } @@ -131,34 +135,28 @@ private boolean isSurface(final int x, final int y, final int z) { } - private void setBlock(final BlockWrapper block, Undo undo, int vh) { - final IBlock currentBlock = this.clampY(block.getX(), block.getY() + (int) (vh * block.getStr()), block.getZ()); - undo.put(currentBlock); - currentBlock.setBlockData(block.getBlockData()); - + private void setBlock(final BlockWrapper block, int vh) { + final IBlock currentBlock = this.getWorld().getBlock(block.getX(), block.getY() + (int) (vh * block.getStr()), block.getZ()); + addOperation(new BlockOperation(currentBlock.getLocation(), currentBlock.getBlockData(), block.getBlockData())); if (this.getBlockMaterialAt(block.getX(), block.getY() - 1, block.getZ()).isAir()) { for (int y = block.getY(); y < currentBlock.getY(); y++) { - IBlock b = this.clampY(block.getX(), y, block.getZ()); - undo.put(b); - b.setBlockData(VoxelMaterial.AIR.createBlockData()); + IBlock b = this.getWorld().getBlock(block.getX(), y, block.getZ()); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), VoxelMaterial.AIR.createBlockData())); } } else { for (int y = block.getY() - 1; y < currentBlock.getY(); y++) { - final IBlock current = this.clampY(block.getX(), y, block.getZ()); - undo.put(current); - current.setBlockData(block.getBlockData()); + final IBlock current = this.getWorld().getBlock(block.getX(), y, block.getZ()); + addOperation(new BlockOperation(current.getLocation(), current.getBlockData(), block.getBlockData())); } } } - private void setBlockDown(final BlockWrapper block, Undo undo, int vh) { - final IBlock currentBlock = this.clampY(block.getX(), block.getY() + (int) (vh * block.getStr()), block.getZ()); - undo.put(currentBlock); - currentBlock.setBlockData(block.getBlockData()); + private void setBlockDown(final BlockWrapper block, int vh) { + final IBlock currentBlock = this.getWorld().getBlock(block.getX(), block.getY() + (int) (vh * block.getStr()), block.getZ()); + addOperation(new BlockOperation(currentBlock.getLocation(), currentBlock.getBlockData(), block.getBlockData())); for (int y = block.getY(); y > currentBlock.getY(); y--) { - IBlock b = this.clampY(block.getX(), y, block.getZ()); - undo.put(b); - b.setBlockData(VoxelMaterial.AIR.createBlockData()); + IBlock b = this.getWorld().getBlock(block.getX(), y, block.getZ()); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), VoxelMaterial.AIR.createBlockData())); } } @@ -166,25 +164,20 @@ private void setBlockDown(final BlockWrapper block, Undo undo, int vh) { protected final void arrow(final SnipeData v) { int vh = v.getVoxelHeight(); HashSet surface = this.getSurface(v); - Undo undo = new Undo(); if (vh > 0) { for (final BlockWrapper block : surface) { - this.setBlock(block, undo, vh); + this.setBlock(block, vh); } } else if (vh < 0) { for (final BlockWrapper block : surface) { - this.setBlockDown(block, undo, vh); + this.setBlockDown(block, vh); } } - - if (undo.getSize() > 0) - v.owner().storeUndo(undo); } @Override protected final void powder(final SnipeData v) { - Undo undo = new Undo(); int vh = v.getVoxelHeight(); @@ -223,9 +216,8 @@ protected final void powder(final SnipeData v) { lastStr = (int) (vh * str); lastY = actualY + lastStr; - IBlock b = this.clampY(actualX, lastY, actualZ); - undo.put(b); - b.setMaterial(this.getWorld().getBlock(actualX, actualY, actualZ).getMaterial()); + IBlock b = this.getWorld().getBlock(actualX, lastY, actualZ); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), this.getWorld().getBlock(actualX, actualY, actualZ).getBlockData())); if (str == 1) { str = 0.8; @@ -239,9 +231,8 @@ protected final void powder(final SnipeData v) { int newY = actualY + lastStr; VoxelMaterial material = this.getWorld().getBlock(actualX, actualY, actualZ).getMaterial(); for (int i = newY; i < lastY; i++) { - b = this.clampY(actualX, i, actualZ); - undo.put(b); - b.setBlockData(material.createBlockData()); + b = this.getWorld().getBlock(actualX, i, actualZ); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), material.createBlockData())); } lastY = newY; actualY--; @@ -263,18 +254,16 @@ protected final void powder(final SnipeData v) { if (volume <= brushSizeSquared && !this.getWorld().getBlock(actualX, this.getTargetBlock().getY() + y, actualZ).getMaterial().isAir()) { final int actualY = this.getTargetBlock().getY() + y; lastY = actualY + (int) (vh * this.getStr(volume / brushSizeSquared)); - IBlock b = this.clampY(actualX, lastY, actualZ); - undo.put(b); - b.setMaterial(this.getWorld().getBlock(actualX, actualY, actualZ).getMaterial()); + IBlock b = this.getWorld().getBlock(actualX, lastY, actualZ); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), this.getWorld().getBlock(actualX, actualY, actualZ).getBlockData())); y++; volume = (xSquared + Math.pow(y, 2) + zSquared); while (volume <= brushSizeSquared) { final int blockY = this.getTargetBlock().getY() + y + (int) (vh * this.getStr(volume / brushSizeSquared)); final VoxelMaterial blockMaterial = this.getWorld().getBlock(actualX, this.getTargetBlock().getY() + y, actualZ).getMaterial(); for (int i = blockY; i < lastY; i++) { - b = this.clampY(actualX, i, actualZ); - undo.put(b); - b.setBlockData(blockMaterial.createBlockData()); + b = this.getWorld().getBlock(actualX, i, actualZ); + addOperation(new BlockOperation(b.getLocation(), b.getBlockData(), blockMaterial.createBlockData())); } lastY = blockY; y++; @@ -286,9 +275,6 @@ protected final void powder(final SnipeData v) { } } } - - if (undo.getSize() > 0) - v.owner().storeUndo(undo); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/vPerformer.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/BasePerformer.java similarity index 52% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/vPerformer.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/BasePerformer.java index 75defb16..fc2c7b64 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/vPerformer.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/BasePerformer.java @@ -7,13 +7,20 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; +import com.github.kevindagame.util.brushOperation.BrushOperation; import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.world.IWorld; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + /** * @author Voxel */ -public abstract class vPerformer { +public abstract class BasePerformer implements Predicate { public String name = "Performer"; protected Undo h; @@ -27,9 +34,16 @@ public void setUndo() { h = new Undo(); } - public abstract void perform(IBlock b); + @Override + public abstract boolean test(IBlock b); + + protected abstract BlockOperation perform(IBlock b); - public Undo getUndo() { + public List perform(List positions) { + return positions.stream().map(BaseLocation::getBlock).filter(this).map(this::perform).collect(Collectors.toList()); + } + + public Undo getAndClearUndo() { Undo temp = h; h = null; return temp; @@ -38,4 +52,5 @@ public Undo getUndo() { public boolean isUsingReplaceMaterial() { return false; } + } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/Performer.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/Performer.java index f460a7ba..964d79e0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/Performer.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/Performer.java @@ -72,7 +72,7 @@ public enum Performer { //COMBO_INK_NOPHYS_UPDATE( pComboInkNoPhysUpdate.class, "ciup", "combo-ink-update-nophys"), // place combo, replace ink, graphical update, no physics //COMBO_COMBO_UPDATE( pComboComboUpdate.class, "ccu", "combo-combo-update"), // place combo, replace combo, graphical update //COMBO_COMBO_NOPHYS_UPDATE(pComboComboNoPhysUpdate.class, "ccup", "combo-combo-update-nophys"),// place combo, replace combo, graphical update, no physics - private static final Map performers; + private static final Map performers; private static final Map long_names; static { @@ -99,19 +99,19 @@ public enum Performer { // performer_list_long = performer_list_long_builder.build(); } - private final Class pclass; + private final Class pclass; private final String short_name; -// public static final Component performer_list_short; + // public static final Component performer_list_short; // public static final Component performer_list_long; private final String long_name; - Performer(Class c, String s, String l) { + Performer(Class c, String s, String l) { pclass = c; short_name = s; long_name = l; } - public static vPerformer getPerformer(String s) { + public static BasePerformer getPerformer(String s) { if (performers.containsKey(s)) { return performers.get(s); } else { @@ -131,14 +131,14 @@ public static Collection getPerformerHandles() { return performers.keySet(); } - private vPerformer getPerformer() { - vPerformer p; + private BasePerformer getPerformer() { + BasePerformer p; try { try { p = pclass.getConstructor().newInstance(); return p; } catch (InstantiationException | InvocationTargetException | IllegalArgumentException | - IllegalAccessException ex) { + IllegalAccessException ex) { Logger.getLogger(Performer.class.getName()).log(Level.SEVERE, null, ex); } } catch (NoSuchMethodException | SecurityException ex) { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/PerformerBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/PerformerBrush.java index ffce1660..12cfaede 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/PerformerBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/PerformerBrush.java @@ -4,12 +4,14 @@ */ package com.github.kevindagame.brush.perform; -import com.google.common.collect.Lists; -import com.github.kevindagame.VoxelSniper; import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.voxelsniper.events.player.PlayerBrushChangedEvent; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; @@ -20,9 +22,10 @@ */ public abstract class PerformerBrush extends AbstractBrush implements IPerformerBrush { - protected vPerformer currentPerformer = new pMaterial(); + protected BasePerformer currentPerformer = new pMaterial(); + protected List positions = new ArrayList<>(); - public vPerformer getCurrentPerformer() { + public BasePerformer getCurrentPerformer() { return currentPerformer; } @@ -32,18 +35,16 @@ public void sendPerformerMessage(String triggerHandle, SnipeData v) { @Override public final boolean parsePerformer(String performerHandle, SnipeData v) { - vPerformer newPerfomer = Performer.getPerformer(performerHandle); - if (newPerfomer == null) { - return false; - } else { - currentPerformer = newPerfomer; - - VoxelSniper.voxelsniper.getEventManager().callSniperBrushChangedEvent(v.owner(), v.owner().getCurrentToolId(), this, this); - - info(v.getVoxelMessage()); - currentPerformer.info(v.getVoxelMessage()); - return true; + BasePerformer newPerfomer = Performer.getPerformer(performerHandle); + if (newPerfomer != null) { + if (!new PlayerBrushChangedEvent(v.owner().getPlayer(), v.owner().getCurrentToolId(), this, this).callEvent().isCancelled()) { + currentPerformer = newPerfomer; + info(v.getVoxelMessage()); + currentPerformer.info(v.getVoxelMessage()); + return true; + } } + return false; } @Override @@ -58,18 +59,20 @@ public final void parsePerformer(String triggerHandle, String[] args, SnipeData } @Override - public void parseParameters(String triggerHandle, String[] params, SnipeData v) { + public void parseParameters(@NotNull String triggerHandle, @NotNull String[] params, @NotNull SnipeData v) { super.parseParameters(triggerHandle, params, v); sendPerformerMessage(triggerHandle, v); } + @NotNull @Override public List registerArguments() { return new ArrayList<>(Lists.newArrayList("p")); } + @NotNull @Override public HashMap> registerArgumentValues() { // Number variables HashMap> argumentValues = new HashMap<>(); @@ -89,4 +92,19 @@ public void showInfo(VoxelMessage vm) { currentPerformer.info(vm); } + protected abstract void doArrow(SnipeData v); + + protected abstract void doPowder(SnipeData v); + + @Override + protected final void arrow(SnipeData v) { + doArrow(v); + addOperations(currentPerformer.perform(positions)); + } + + @Override + protected final void powder(SnipeData v) { + doPowder(v); + addOperations(currentPerformer.perform(positions)); + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pCombo.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pCombo.java index 86c9cfc7..43cd62f9 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pCombo.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pCombo.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; /** * @author Voxel */ -public class pCombo extends vPerformer { +public class pCombo extends BasePerformer { private IBlockData voxelSubstance; @@ -34,8 +35,12 @@ public void init(SnipeData v) { } @Override - public void perform(IBlock b) { - h.put(b); - b.setBlockData(voxelSubstance, true); + public boolean test(IBlock b) { + return true; + } + + @Override + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboCombo.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboCombo.java index 7d2884d8..2181f8af 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboCombo.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboCombo.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; /** * @author Voxel */ -public class pComboCombo extends vPerformer { +public class pComboCombo extends BasePerformer { private IBlockData voxelSubstance; private IBlockData targetSubstance; @@ -28,6 +29,11 @@ public void init(SnipeData v) { targetSubstance = v.getReplaceSubstance(); } + @Override + public boolean test(IBlock b) { + return b.getBlockData().matches(targetSubstance); + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -38,11 +44,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getBlockData().matches(targetSubstance)) { - h.put(b); - b.setBlockData(voxelSubstance, true); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboComboNoPhysics.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboComboNoPhysics.java index ce18da22..ce3f02b0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboComboNoPhysics.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboComboNoPhysics.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; /** * @author Voxel */ -public class pComboComboNoPhysics extends vPerformer { +public class pComboComboNoPhysics extends BasePerformer { private IBlockData voxelSubstance; private IBlockData targetSubstance; @@ -28,6 +29,11 @@ public void init(SnipeData v) { targetSubstance = v.getReplaceSubstance(); } + @Override + public boolean test(IBlock b) { + return b.getBlockData().matches(targetSubstance); + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -38,11 +44,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getBlockData().matches(targetSubstance)) { - h.put(b); - b.setBlockData(voxelSubstance, false); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance, false); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMat.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMat.java index 7348c809..0e1adb15 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMat.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMat.java @@ -6,6 +6,7 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; @@ -13,7 +14,7 @@ /** * @author Voxel */ -public class pComboMat extends vPerformer { +public class pComboMat extends BasePerformer { private IBlockData voxelSubstance; private VoxelMaterial targetMaterial; @@ -29,6 +30,11 @@ public void init(SnipeData v) { targetMaterial = v.getReplaceMaterial(); } + @Override + public boolean test(IBlock b) { + return b.getMaterial() == targetMaterial; + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -38,11 +44,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getMaterial() == targetMaterial) { - h.put(b); - b.setBlockData(voxelSubstance, true); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMatNoPhysics.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMatNoPhysics.java index 57f7d470..2a605b8f 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMatNoPhysics.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboMatNoPhysics.java @@ -6,6 +6,7 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; @@ -13,7 +14,7 @@ /** * @author Voxel */ -public class pComboMatNoPhysics extends vPerformer { +public class pComboMatNoPhysics extends BasePerformer { private IBlockData voxelSubstance; private VoxelMaterial targetMaterial; @@ -29,6 +30,11 @@ public void init(SnipeData v) { targetMaterial = v.getReplaceMaterial(); } + @Override + public boolean test(IBlock b) { + return b.getMaterial() == targetMaterial; + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -38,11 +44,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getMaterial() == targetMaterial) { - h.put(b); - b.setBlockData(voxelSubstance, false); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance, false); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboNoPhysics.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboNoPhysics.java index cd6950f2..d10bd89b 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboNoPhysics.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pComboNoPhysics.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; /** * @author Voxel */ -public class pComboNoPhysics extends vPerformer { +public class pComboNoPhysics extends BasePerformer { private IBlockData voxelSubstance; @@ -34,8 +35,12 @@ public void init(SnipeData v) { } @Override - public void perform(IBlock b) { - h.put(b); - b.setBlockData(voxelSubstance, false); + public boolean test(IBlock b) { + return true; + } + + @Override + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance, false); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeCombo.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeCombo.java index 7dada080..37ccfc69 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeCombo.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeCombo.java @@ -7,13 +7,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelList; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; /** * @author Voxel */ -public class pExcludeCombo extends vPerformer { +public class pExcludeCombo extends BasePerformer { private VoxelList excludeList; private IBlockData voxelSubstance; @@ -38,10 +39,12 @@ public void init(SnipeData v) { } @Override - public void perform(IBlock b) { - if (!excludeList.contains(b.getMaterial())) { - h.put(b); - b.setBlockData(voxelSubstance, true); - } + public boolean test(IBlock b) { + return !excludeList.contains(b.getMaterial()); + } + + @Override + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeMat.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeMat.java index a132f82f..6816a5fb 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeMat.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pExcludeMat.java @@ -7,13 +7,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelList; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** * @author Voxel */ -public class pExcludeMat extends vPerformer { +public class pExcludeMat extends BasePerformer { private VoxelList excludeList; private VoxelMaterial voxelMaterial; @@ -37,10 +38,12 @@ public void init(SnipeData v) { } @Override - public void perform(IBlock b) { - if (!excludeList.contains(b.getMaterial())) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData()); - } + public boolean test(IBlock b) { + return !excludeList.contains(b.getMaterial()); + } + + @Override + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData()); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeCombo.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeCombo.java index 37f79cc1..4fddbe29 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeCombo.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeCombo.java @@ -7,13 +7,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelList; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; /** * @author Voxel */ -public class pIncludeCombo extends vPerformer { +public class pIncludeCombo extends BasePerformer { private VoxelList includeList; private IBlockData voxelSubstance; @@ -38,10 +39,12 @@ public void init(SnipeData v) { } @Override - public void perform(IBlock b) { - if (includeList.contains(b.getMaterial())) { - h.put(b); - b.setBlockData(voxelSubstance, true); - } + public boolean test(IBlock b) { + return includeList.contains(b.getMaterial()); + } + + @Override + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelSubstance); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeMat.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeMat.java index e8e460a7..f7792326 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeMat.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pIncludeMat.java @@ -7,13 +7,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelList; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** * @author Voxel */ -public class pIncludeMat extends vPerformer { +public class pIncludeMat extends BasePerformer { private VoxelList includeList; private VoxelMaterial voxelMaterial; @@ -37,10 +38,12 @@ public void init(SnipeData v) { } @Override - public void perform(IBlock b) { - if (includeList.contains(b.getMaterial())) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData()); - } + public boolean test(IBlock b) { + return includeList.contains(b.getMaterial()); + } + + @Override + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData()); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatCombo.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatCombo.java index 2cffac64..6662232b 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatCombo.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatCombo.java @@ -6,6 +6,7 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; @@ -13,7 +14,7 @@ /** * @author Voxel */ -public class pMatCombo extends vPerformer { +public class pMatCombo extends BasePerformer { private VoxelMaterial voxelMaterial; private IBlockData targetSubstance; @@ -29,6 +30,11 @@ public void init(SnipeData v) { targetSubstance = v.getReplaceSubstance(); } + @Override + public boolean test(IBlock b) { + return b.getBlockData().matches(targetSubstance); + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -38,11 +44,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getBlockData().matches(targetSubstance)) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData(), true); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData()); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatComboNoPhysics.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatComboNoPhysics.java index 79da49da..f9be2a47 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatComboNoPhysics.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatComboNoPhysics.java @@ -6,6 +6,7 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; @@ -13,7 +14,7 @@ /** * @author Voxel */ -public class pMatComboNoPhysics extends vPerformer { +public class pMatComboNoPhysics extends BasePerformer { private VoxelMaterial voxelMaterial; private IBlockData targetSubstance; @@ -29,6 +30,11 @@ public void init(SnipeData v) { targetSubstance = v.getReplaceSubstance(); } + @Override + public boolean test(IBlock b) { + return b.getBlockData().matches(targetSubstance); + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -38,11 +44,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getBlockData().matches(targetSubstance)) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData(), false); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData(), false); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMat.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMat.java index 5a199d00..47effc7d 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMat.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMat.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** * @author Voxel */ -public class pMatMat extends vPerformer { +public class pMatMat extends BasePerformer { private VoxelMaterial voxelMaterial; private VoxelMaterial targetMaterial; @@ -28,6 +29,11 @@ public void init(SnipeData v) { targetMaterial = v.getReplaceMaterial(); } + @Override + public boolean test(IBlock b) { + return b.getMaterial() == targetMaterial; + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -36,11 +42,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getMaterial() == targetMaterial) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData()); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData()); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMatNoPhysics.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMatNoPhysics.java index 069544c7..8f42eaf2 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMatNoPhysics.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMatMatNoPhysics.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** * @author Voxel */ -public class pMatMatNoPhysics extends vPerformer { +public class pMatMatNoPhysics extends BasePerformer { private VoxelMaterial voxelMaterial; private VoxelMaterial targetMaterial; @@ -28,6 +29,11 @@ public void init(SnipeData v) { targetMaterial = v.getReplaceMaterial(); } + @Override + public boolean test(IBlock b) { + return b.getMaterial() == targetMaterial; + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -36,11 +42,8 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getMaterial() == targetMaterial) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData(), false); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData(), false); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterial.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterial.java index c631204d..49eb340f 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterial.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterial.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** * @author Voxel */ -public class pMaterial extends vPerformer { +public class pMaterial extends BasePerformer { private VoxelMaterial voxelMaterial; @@ -26,6 +27,11 @@ public void init(SnipeData v) { voxelMaterial = v.getVoxelMaterial(); } + @Override + public boolean test(IBlock b) { + return b.getMaterial() != voxelMaterial; + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -33,10 +39,7 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getMaterial() != voxelMaterial) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData()); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData()); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterialNoPhysics.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterialNoPhysics.java index b66341c4..51e74363 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterialNoPhysics.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/perform/pMaterialNoPhysics.java @@ -6,13 +6,14 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** * @author Voxel */ -public class pMaterialNoPhysics extends vPerformer { +public class pMaterialNoPhysics extends BasePerformer { private VoxelMaterial voxelMaterial; @@ -26,6 +27,11 @@ public void init(SnipeData v) { voxelMaterial = v.getVoxelMaterial(); } + @Override + public boolean test(IBlock b) { + return b.getMaterial() != voxelMaterial; + } + @Override public void info(VoxelMessage vm) { vm.performerName(name); @@ -33,10 +39,7 @@ public void info(VoxelMessage vm) { } @Override - public void perform(IBlock b) { - if (b.getMaterial() != voxelMaterial) { - h.put(b); - b.setBlockData(voxelMaterial.createBlockData(), false); - } + public BlockOperation perform(IBlock b) { + return new BlockOperation(b.getLocation(), b.getBlockData(), voxelMaterial.createBlockData(), false); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellBallBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellBallBrush.java new file mode 100644 index 00000000..c6f73ce4 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellBallBrush.java @@ -0,0 +1,38 @@ +package com.github.kevindagame.brush.shell; + +import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; +import com.github.kevindagame.util.brushOperation.BlockOperation; + +/** + * THIS BRUSH SHOULD NOT USE PERFORMERS. http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes + * + * @author Voxel + */ +public class ShellBallBrush extends ShellBrushBase { + + /** + * + */ + public ShellBallBrush() { + this.setName("Shell Ball"); + } + + @Override + protected final void shell(final SnipeData v) { + var positions = Shapes.ball(this.getTargetBlock().getLocation(), v.getBrushSize(), false); + var newMaterials = this.bShell(v); + final int brushSize = v.getBrushSize(); + for (var position : positions) { + var material = newMaterials[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockY() - this.getTargetBlock().getY() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + addOperation(new BlockOperation(position, position.getBlock().getBlockData(), material.createBlockData())); + } + v.sendMessage(Messages.SHELL_BRUSH_COMPLETE); + } + + @Override + public String getPermissionNode() { + return "voxelsniper.brush.shellball"; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellBallBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellBrushBase.java similarity index 63% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellBallBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellBrushBase.java index 33deecc7..3db2e36c 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellBallBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellBrushBase.java @@ -1,36 +1,34 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.shell; +import com.github.kevindagame.brush.AbstractBrush; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; -import com.github.kevindagame.util.Messages; import com.github.kevindagame.util.VoxelMessage; -import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; /** - * THIS BRUSH SHOULD NOT USE PERFORMERS. http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes + * THIS BRUSH SHOULD NOT USE PERFORMERS. ... * * @author Voxel */ -public class ShellBallBrush extends AbstractBrush { +public abstract class ShellBrushBase extends AbstractBrush { + /** - * + * @param v */ - public ShellBallBrush() { - this.setName("Shell Ball"); - } + protected abstract void shell(SnipeData v); - // parameters isn't an abstract method, gilt. You can just leave it out if there are none. - private void bShell(final SnipeData v, IBlock targetBlock) { + protected VoxelMaterial[][][] bShell(final SnipeData v) { final int brushSize = v.getBrushSize(); final int brushSizeDoubled = 2 * brushSize; final VoxelMaterial[][][] oldMaterials = new VoxelMaterial[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer final VoxelMaterial[][][] newMaterials = new VoxelMaterial[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the hollowed materials + final var targetBlock = getTargetBlock(); int blockPositionX = targetBlock.getX(); int blockPositionY = targetBlock.getY(); int blockPositionZ = targetBlock.getZ(); + // Log current materials into oldmats for (int x = 0; x <= 2 * (brushSize + 1); x++) { for (int y = 0; y <= 2 * (brushSize + 1); y++) { @@ -80,38 +78,17 @@ private void bShell(final SnipeData v, IBlock targetBlock) { } } } - - // Make the changes - final Undo undo = new Undo(); - final double rSquared = Math.pow(brushSize + 0.5, 2); - - for (int x = brushSizeDoubled; x >= 0; x--) { - final double xSquared = Math.pow(x - brushSize, 2); - - for (int y = 0; y <= 2 * brushSize; y++) { - final double ySquared = Math.pow(y - brushSize, 2); - - for (int z = 2 * brushSize; z >= 0; z--) { - if (xSquared + ySquared + Math.pow(z - brushSize, 2) <= rSquared) { - setBlockMaterialAt(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z, newMaterials[x][y][z], undo); - } - } - } - } - v.owner().storeUndo(undo); - - // This is needed because most uses of this brush will not be sible to the sniper. - v.sendMessage(Messages.SHELL_BRUSH_COMPLETE); + return newMaterials; } @Override - protected final void arrow(final SnipeData v) { - this.bShell(v, this.getTargetBlock()); + protected void arrow(final SnipeData v) { + this.shell(v); } @Override - protected final void powder(final SnipeData v) { - this.bShell(v, this.getLastBlock()); + protected void powder(final SnipeData v) { + this.shell(v); } @Override @@ -121,9 +98,4 @@ public final void info(final VoxelMessage vm) { vm.voxel(); vm.replace(); } - - @Override - public String getPermissionNode() { - return "voxelsniper.brush.shellball"; - } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellSetBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellSetBrush.java similarity index 84% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellSetBrush.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellSetBrush.java index ed0f7565..ee8f881c 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/ShellSetBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellSetBrush.java @@ -1,21 +1,22 @@ -package com.github.kevindagame.brush; +package com.github.kevindagame.brush.shell; import com.github.kevindagame.snipe.SnipeData; -import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.util.BlockWrapper; import com.github.kevindagame.util.Messages; -import com.github.kevindagame.util.VoxelMessage; +import com.github.kevindagame.util.brushOperation.BlockOperation; import com.github.kevindagame.voxelsniper.block.IBlock; import java.util.ArrayList; /** - * http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes + * ... * * @author Piotr */ -public class ShellSetBrush extends AbstractBrush { +public class ShellSetBrush extends ShellBrushBase { private static final int MAX_SIZE = 5000000; + private final ArrayList operations = new ArrayList<>(); private IBlock block = null; /** @@ -26,6 +27,7 @@ public ShellSetBrush() { } private boolean set(final IBlock bl, final SnipeData v) { + operations.clear(); if (this.block == null) { this.block = bl; return true; @@ -64,16 +66,13 @@ private boolean set(final IBlock bl, final SnipeData v) { } } } - - final Undo undo = new Undo(); for (final IBlock currentBlock : blocks) { if (currentBlock.getMaterial() != v.getVoxelMaterial()) { - undo.put(currentBlock); - currentBlock.setBlockData(v.getVoxelMaterial().createBlockData()); + addOperation(new BlockOperation(currentBlock.getLocation(), currentBlock.getBlockData(), v.getVoxelMaterial().createBlockData())); } } - v.owner().storeUndo(undo); v.sendMessage(Messages.SHELL_BRUSH_COMPLETE); + } this.block = null; @@ -81,6 +80,11 @@ private boolean set(final IBlock bl, final SnipeData v) { } } + @Override + protected void shell(SnipeData v) { + //empty because method is not needed right now + } + @Override protected final void arrow(final SnipeData v) { if (this.set(this.getTargetBlock(), v)) { @@ -95,13 +99,6 @@ protected final void powder(final SnipeData v) { } } - @Override - public final void info(final VoxelMessage vm) { - vm.brushName(this.getName()); - vm.size(); - vm.voxel(); - vm.replace(); - } @Override public String getPermissionNode() { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellVoxelBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellVoxelBrush.java new file mode 100644 index 00000000..7ec96d0b --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/shell/ShellVoxelBrush.java @@ -0,0 +1,39 @@ +package com.github.kevindagame.brush.shell; + +import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Shapes; +import com.github.kevindagame.util.brushOperation.BlockOperation; + +/** + * THIS BRUSH SHOULD NOT USE PERFORMERS. ... + * + * @author Voxel + */ +public class ShellVoxelBrush extends ShellBrushBase { + + /** + * + */ + public ShellVoxelBrush() { + this.setName("Shell Voxel"); + } + + @Override + protected void shell(SnipeData v) { + var positions = Shapes.voxel(getTargetBlock().getLocation(), v.getBrushSize()); + final int brushSize = v.getBrushSize(); + var newMaterials = this.bShell(v); + for (var position : positions) { + var material = newMaterials[position.getBlockX() - this.getTargetBlock().getX() + brushSize][position.getBlockY() - this.getTargetBlock().getY() + brushSize][position.getBlockZ() - this.getTargetBlock().getZ() + brushSize]; + addOperation(new BlockOperation(position, position.getBlock().getBlockData(), material.createBlockData())); + } + v.sendMessage(Messages.SHELL_BRUSH_COMPLETE); + } + + @Override + public String getPermissionNode() { + return "voxelsniper.brush.shellvoxel"; + } + +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/MaterialCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/MaterialCommand.java index bc3b0083..f7c39d92 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/MaterialCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/MaterialCommand.java @@ -1,8 +1,8 @@ package com.github.kevindagame.command; -import com.google.common.collect.Lists; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushCommand.java index c38e931e..954dfe38 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushCommand.java @@ -2,13 +2,14 @@ import com.github.kevindagame.VoxelBrushManager; import com.github.kevindagame.VoxelProfileManager; -import com.github.kevindagame.VoxelSniper; import com.github.kevindagame.brush.IBrush; import com.github.kevindagame.brush.perform.IPerformerBrush; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Sniper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.player.PlayerBrushChangedEvent; +import com.github.kevindagame.voxelsniper.events.player.PlayerBrushSizeChangedEvent; import java.util.ArrayList; import java.util.Arrays; @@ -56,12 +57,15 @@ public boolean doCommand(IPlayer player, final String[] args) { // Command: /b -- Change brush size try { int originalSize = snipeData.getBrushSize(); - snipeData.setBrushSize(Integer.parseInt(args[0])); - VoxelSniper.voxelsniper.getEventManager().callSniperBrushSizeChangedEvent(sniper, currentToolId, originalSize, snipeData.getBrushSize()); + if (!new PlayerBrushSizeChangedEvent(player, currentToolId, sniper.getBrush(currentToolId), originalSize, snipeData.getBrushSize()).callEvent().isCancelled()) { + snipeData.setBrushSize(Integer.parseInt(args[0])); + snipeData.getVoxelMessage().size(); + return true; + + } + return false; - snipeData.getVoxelMessage().size(); - return true; } catch (NumberFormatException ignored) { } @@ -78,7 +82,7 @@ public boolean doCommand(IPlayer player, final String[] args) { snipeData.sendMessage(Messages.BRUSH_HANDLE_NOT_FOUND.replace("%arg%", args[0])); } else { IBrush oldBrush = sniper.getBrush(currentToolId); - IBrush newBrush = sniper.setBrush(currentToolId, brush); + IBrush newBrush = sniper.getBrush(currentToolId); if (newBrush == null) { snipeData.sendMessage(Messages.VOXEL_BRUSH_NO_PERMISSION); @@ -97,8 +101,10 @@ public boolean doCommand(IPlayer player, final String[] args) { } return true; } - VoxelSniper.voxelsniper.getEventManager().callSniperBrushChangedEvent(sniper, currentToolId, oldBrush, newBrush); - sniper.displayInfo(); + if (!new PlayerBrushChangedEvent(player, currentToolId, oldBrush, newBrush).callEvent().isCancelled()) { + sniper.setBrush(currentToolId, brush); + sniper.displayInfo(); + } } return true; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushToolCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushToolCommand.java index 4c567b89..904fe9aa 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushToolCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelBrushToolCommand.java @@ -1,12 +1,12 @@ package com.github.kevindagame.command; -import com.google.common.collect.Lists; import com.github.kevindagame.VoxelProfileManager; import com.github.kevindagame.snipe.SnipeAction; import com.github.kevindagame.snipe.Sniper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.Arrays; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelPerformerCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelPerformerCommand.java index 2b09e48d..2939b7c0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelPerformerCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelPerformerCommand.java @@ -1,6 +1,5 @@ package com.github.kevindagame.command; -import com.google.common.collect.Lists; import com.github.kevindagame.VoxelProfileManager; import com.github.kevindagame.brush.IBrush; import com.github.kevindagame.brush.perform.IPerformerBrush; @@ -9,6 +8,7 @@ import com.github.kevindagame.snipe.Sniper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelReplaceCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelReplaceCommand.java index e0a91aac..566d25f1 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelReplaceCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelReplaceCommand.java @@ -7,6 +7,7 @@ import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.player.materialChange.PlayerReplaceMaterialChangedEvent; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; public class VoxelReplaceCommand extends MaterialCommand { @@ -34,8 +35,10 @@ public boolean doCommand(IPlayer player, String[] args) { if (args.length == 0) { IBlock selectedBlock = new BlockHelper(sniper.getPlayer()).getTargetBlock(); if (selectedBlock != null) { - snipeData.setReplaceSubstance(selectedBlock.getBlockData()); - snipeData.getVoxelMessage().replace(); + if (!new PlayerReplaceMaterialChangedEvent(sniper.getPlayer(), sniper.getSnipeData(sniper.getCurrentToolId()).getReplaceSubstance(), selectedBlock.getBlockData()).callEvent().isCancelled()) { + snipeData.setReplaceSubstance(selectedBlock.getBlockData()); + snipeData.getVoxelMessage().replace(); + } } else { sniper.sendMessage(Messages.REPLACE_NOTHING_TO_IMITATE); } @@ -43,10 +46,12 @@ public boolean doCommand(IPlayer player, String[] args) { } // Command: /vr [material] <- Sets the defined material as voxel substance. - VoxelMaterial material = VoxelMaterial.getMaterial(args[0]); // TODO: Match old ID numbers to materials + VoxelMaterial material = VoxelMaterial.getMaterial(args[0]); if (material != null && material.isBlock()) { - snipeData.setReplaceSubstance(material.createBlockData()); - snipeData.getVoxelMessage().replace(); + if (!new PlayerReplaceMaterialChangedEvent(sniper.getPlayer(), sniper.getSnipeData(sniper.getCurrentToolId()).getReplaceSubstance(), material.createBlockData()).callEvent().isCancelled()) { + snipeData.setReplaceSubstance(material.createBlockData()); + snipeData.getVoxelMessage().replace(); + } } else { sniper.sendMessage(Messages.INVALID_ITEM_ID); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelSniperCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelSniperCommand.java index 1b90da35..b4995ffc 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelSniperCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelSniperCommand.java @@ -1,11 +1,11 @@ package com.github.kevindagame.command; -import com.google.common.collect.Lists; import com.github.kevindagame.VoxelProfileManager; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Sniper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVariablesCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVariablesCommand.java index b9716b01..2aec6084 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVariablesCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVariablesCommand.java @@ -1,12 +1,12 @@ package com.github.kevindagame.command; -import com.google.common.collect.Lists; import com.github.kevindagame.VoxelProfileManager; import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Sniper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.Arrays; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxCommand.java index 30602d48..47664f34 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxCommand.java @@ -1,10 +1,10 @@ package com.github.kevindagame.command; -import com.google.common.collect.Lists; import com.github.kevindagame.util.BlockHelper; import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.List; @@ -52,7 +52,7 @@ public boolean doCommand(IPlayer player, String[] args) { final int x = Integer.parseInt(args[0]); final int z = Integer.parseInt(args[1]); - player.teleport(new VoxelLocation(player.getWorld(), x, player.getWorld().getHighestBlockYAt(x, z), z)); + player.teleport(new BaseLocation(player.getWorld(), x, player.getWorld().getHighestBlockYAt(x, z), z)); player.sendMessage(Messages.GOTO_MSG); } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { player.sendMessage(Messages.GOTO_INVALID_SYNTAX); @@ -98,7 +98,7 @@ public boolean doCommand(IPlayer player, String[] args) { final int x = Integer.parseInt(args[1]); final int z = Integer.parseInt(args[2]); - player.teleport(new VoxelLocation(player.getWorld(), x, player.getWorld().getHighestBlockYAt(x, z), z)); + player.teleport(new BaseLocation(player.getWorld(), x, player.getWorld().getHighestBlockYAt(x, z), z)); player.sendMessage(Messages.GOTO_MSG); } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { player.sendMessage(Messages.VOX_GOTO_USAGE.replace("%alias%", getActiveAlias()).replace("%name%", getName())); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxelCommand.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxelCommand.java index 0514b157..b82ff973 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxelCommand.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/command/VoxelVoxelCommand.java @@ -7,6 +7,7 @@ import com.github.kevindagame.util.Messages; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.player.materialChange.PlayerMaterialChangedEvent; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; @@ -34,8 +35,10 @@ public boolean doCommand(IPlayer player, String[] args) { if (args.length == 0) { IBlock selectedBlock = new BlockHelper(sniper.getPlayer()).getTargetBlock(); if (selectedBlock != null) { - snipeData.setVoxelSubstance(selectedBlock.getBlockData()); - snipeData.getVoxelMessage().voxel(); + if (!new PlayerMaterialChangedEvent(sniper.getPlayer(), sniper.getSnipeData(sniper.getCurrentToolId()).getVoxelSubstance(), selectedBlock.getBlockData()).callEvent().isCancelled()) { + snipeData.setVoxelSubstance(selectedBlock.getBlockData()); + snipeData.getVoxelMessage().voxel(); + } } else { sniper.sendMessage(Messages.NOTHING_TO_SET_SUBSTANCE); } @@ -46,8 +49,10 @@ public boolean doCommand(IPlayer player, String[] args) { VoxelMaterial material = VoxelMaterial.getMaterial(args[0]); if (material != null && material.isBlock()) { - snipeData.setVoxelSubstance(material.createBlockData()); - snipeData.getVoxelMessage().voxel(); + if (!new PlayerMaterialChangedEvent(sniper.getPlayer(), sniper.getSnipeData(sniper.getCurrentToolId()).getVoxelSubstance(), material.createBlockData()).callEvent().isCancelled()) { + snipeData.setVoxelSubstance(material.createBlockData()); + snipeData.getVoxelMessage().voxel(); + } } else { sniper.sendMessage(Messages.INVALID_TYPE_ID); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeData.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeData.java index 7ec67b7c..c22ece17 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeData.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeData.java @@ -20,7 +20,7 @@ public class SnipeData { public static final IBlockData DEFAULT_VOXEL_SUBSTANCE = VoxelMaterial.AIR.createBlockData(); public static final IBlockData DEFAULT_TARGET_SUBSTANCE = VoxelMaterial.AIR.createBlockData(); - // Sniper varaibles + // Sniper variables private final Sniper owner; private final boolean lightning = false; private VoxelMessage voxelMessage; @@ -29,7 +29,6 @@ public class SnipeData { private int brushSize = SnipeData.DEFAULT_BRUSH_SIZE; // Voxel and ReplaceTarget Materials & BlockData - //todo abstract these variables private IBlockData voxelSubstance = SnipeData.DEFAULT_VOXEL_SUBSTANCE; private IBlockData replaceSubstance = SnipeData.DEFAULT_TARGET_SUBSTANCE; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeTool.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeTool.java index 3335b010..4bb9acf1 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeTool.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/SnipeTool.java @@ -1,11 +1,11 @@ package com.github.kevindagame.snipe; -import com.google.common.base.Preconditions; -import com.google.common.collect.*; import com.github.kevindagame.brush.IBrush; import com.github.kevindagame.brush.SnipeBrush; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.base.Preconditions; +import com.google.common.collect.*; /** * @author ervinnnc @@ -29,7 +29,7 @@ protected SnipeTool(Class currentBrush, SnipeData snipeData) { snipeData.setVoxelMessage(messageHelper); IBrush newBrushInstance = instanciateBrush(currentBrush); - if (snipeData.owner().getPlayer().hasPermission(newBrushInstance.getPermissionNode())) { + if (snipeData.owner().getPlayer().hasPermission(newBrushInstance.getPermissionNode()) || snipeData.owner().getPlayer().hasPermission("voxelsniper.brush.*")) { brushes.put(currentBrush, newBrushInstance); this.currentBrush = currentBrush; } @@ -71,14 +71,14 @@ public IBrush setCurrentBrush(Class brush) { if (brushInstance == null) { brushInstance = instanciateBrush(brush); Preconditions.checkNotNull(brushInstance, "Could not instanciate brush class."); - if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) { + if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode()) || snipeData.owner().getPlayer().hasPermission("voxelsniper.brush.*")) { brushes.put(brush, brushInstance); previousBrush = currentBrush; currentBrush = brush; return brushInstance; } } - if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) { + if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode()) || snipeData.owner().getPlayer().hasPermission("voxelsniper.brush.*")) { previousBrush = currentBrush; currentBrush = brush; return brushInstance; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Sniper.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Sniper.java index 9e95d640..521a7335 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Sniper.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Sniper.java @@ -1,6 +1,5 @@ package com.github.kevindagame.snipe; -import com.google.common.collect.Maps; import com.github.kevindagame.VoxelSniper; import com.github.kevindagame.brush.IBrush; import com.github.kevindagame.brush.perform.IPerformerBrush; @@ -12,6 +11,7 @@ import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.Maps; import net.kyori.adventure.text.ComponentLike; import org.jetbrains.annotations.NotNull; @@ -127,27 +127,19 @@ private boolean handleRightClick(IBlock clickedBlock, SnipeTool sniperTool, Snip performerBrush.initP(snipeData); } - var success = sniperTool.getCurrentBrush().perform(snipeAction, snipeData, targetBlock, lastBlock); - VoxelSniper.voxelsniper.getEventManager().callSniperSnipeEvent(this, sniperTool.getCurrentBrush(), success); - return success; + return sniperTool.getCurrentBrush().perform(snipeAction, snipeData, targetBlock, lastBlock); } private boolean handleSneakLeftClick(String toolId, SnipeData snipeData, SnipeAction snipeAction, IBlock targetBlock) { IBlockData oldSubstance, newSubstance; switch (snipeAction) { case GUNPOWDER: - oldSubstance = snipeData.getReplaceSubstance(); snipeData.setReplaceSubstance(targetBlock != null ? targetBlock.getBlockData() : SnipeData.DEFAULT_VOXEL_SUBSTANCE); - newSubstance = snipeData.getReplaceSubstance(); - VoxelSniper.voxelsniper.getEventManager().callSniperReplaceMaterialChangedEvent(this, toolId, oldSubstance, newSubstance); snipeData.getVoxelMessage().replace(); return true; case ARROW: - oldSubstance = snipeData.getVoxelSubstance(); snipeData.setVoxelSubstance(targetBlock != null ? targetBlock.getBlockData() : SnipeData.DEFAULT_VOXEL_SUBSTANCE); - newSubstance = snipeData.getVoxelSubstance(); - VoxelSniper.voxelsniper.getEventManager().callSniperMaterialChangedEvent(this, toolId, oldSubstance, newSubstance); snipeData.getVoxelMessage().voxel(); return true; default: @@ -244,13 +236,12 @@ public int undo(int amount) { if (undo != null) { undo.undo(); changedBlocks += undo.getSize(); - } else { // TODO: Check if this logic makes sense + } else { break; } } sendMessage(Messages.UNDO_SUCCESSFUL.replace("%changedBlocks%", String.valueOf(changedBlocks))); - ; } return changedBlocks; } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Undo.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Undo.java index 8e5cdb7d..cf958b09 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Undo.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/snipe/Undo.java @@ -1,10 +1,10 @@ package com.github.kevindagame.snipe; -import com.google.common.collect.Sets; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockstate.IBlockState; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.google.common.collect.Sets; import java.util.Arrays; import java.util.LinkedList; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Actions.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Actions.java new file mode 100644 index 00000000..f173b5a1 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Actions.java @@ -0,0 +1,21 @@ +package com.github.kevindagame.util; + +import com.github.kevindagame.voxelsniper.location.BaseLocation; + +import java.util.List; +import java.util.stream.Collectors; + +public class Actions { + + /** + * Returns the locations that are on a checker grid, according to their sum + * + * @param locations A list of locations + * @param even whether the sum of x + y + z should be even or odd + * @return The locations of which the sum of x + y + z is even or odd + */ + public static List checker(List locations, boolean even) { + return locations.stream().filter(location -> (location.getBlockX() + location.getBlockY() + location.getBlockZ()) % 2 != (even ? 0 : 1)).collect(Collectors.toList()); + + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockHelper.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockHelper.java index 3fa772fb..a3399be1 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockHelper.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockHelper.java @@ -3,9 +3,10 @@ import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.entity.IEntity; -import com.github.kevindagame.voxelsniper.entity.Painting.IPainting; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; +import com.github.kevindagame.voxelsniper.entity.painting.IPainting; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.location.VoxelLocation; import com.github.kevindagame.voxelsniper.vector.VoxelVector; import com.github.kevindagame.voxelsniper.world.IWorld; @@ -19,9 +20,9 @@ public class BlockHelper { private static final double DEFAULT_STEP = 0.2; private static final int DEFAULT_RANGE = 250; private final IWorld world; - private VoxelLocation startPoint; + private BaseLocation startPoint; private VoxelLocation current; - private VoxelLocation last; + private BaseLocation last; private VoxelVector direction; private double rangeSquared; private int maxWorldHeight; @@ -32,7 +33,7 @@ public class BlockHelper { * * @param location */ - public BlockHelper(final VoxelLocation location) { + public BlockHelper(final BaseLocation location) { this(location, BlockHelper.DEFAULT_RANGE, BlockHelper.DEFAULT_STEP); } @@ -43,7 +44,7 @@ public BlockHelper(final VoxelLocation location) { * @param range * @param step */ - public BlockHelper(final VoxelLocation location, final double range, final double step) { + public BlockHelper(final BaseLocation location, final double range, final double step) { this.world = location.getWorld(); this.init(location, range, step); } @@ -86,7 +87,7 @@ public BlockHelper(final IPlayer player, final double range) { * @param choice Chosen index to set the painting to */ public static void painting(final IPlayer p, final boolean auto, final boolean back, final int choice) { - VoxelLocation targetLocation = p.getTargetBlock(null, 4).getLocation(); + BaseLocation targetLocation = p.getTargetBlock(null, 4).getLocation(); IChunk paintingChunk = targetLocation.getChunk(); double bestDistanceMatch = 50.0; IPainting bestMatch = null; @@ -121,7 +122,7 @@ public static void painting(final IPlayer p, final boolean auto, final boolean b } } - private boolean isOutsideBuildHeight(VoxelLocation loc) { + private boolean isOutsideBuildHeight(BaseLocation loc) { // above worldHeight and going up, or below worldHeight and going down return (loc.getBlockY() >= maxWorldHeight && direction.getY() >= 0) || (loc.getBlockY() < minWorldHeight && direction.getY() <= 0); } @@ -219,12 +220,12 @@ private IBlock getRange() { } } - private void init(final VoxelLocation location, final double range, final double step) { + private void init(final BaseLocation location, final double range, final double step) { this.maxWorldHeight = world.getMaxWorldHeight(); this.minWorldHeight = world.getMinWorldHeight(); this.startPoint = location; - this.current = location.clone(); + this.current = location.makeMutable(); this.last = this.current; this.direction = location.getDirection(); this.direction.normalize(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockWrapper.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockWrapper.java index a1d69694..bfbb7fe2 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockWrapper.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/BlockWrapper.java @@ -2,13 +2,14 @@ import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; /** * @author MikeMatrix */ -public class BlockWrapper { +public class BlockWrapper implements Cloneable { private IBlockData blockData; private int x; @@ -27,6 +28,32 @@ public BlockWrapper(final IBlock block) { this.setWorld(block.getWorld()); } + /** + * @param location + * @param material + */ + public BlockWrapper(final BaseLocation location, final VoxelMaterial material) { + this.setMaterial(material); + this.setX(location.getBlockX()); + this.setY(location.getBlockY()); + this.setZ(location.getBlockZ()); + this.setWorld(location.getWorld()); + } + + /** + * @param b + * @param blx + * @param bly + * @param blz + */ + public BlockWrapper(final IBlock b, final int blx, final int bly, final int blz, final IWorld world) { + this.blockData = b.getBlockData(); + this.x = blx; + this.y = bly; + this.z = blz; + this.world = world; + } + /** * @return the data */ @@ -37,8 +64,9 @@ public final IBlockData getBlockData() { /** * @param blockData the data to set */ - public final void setBlockData(final IBlockData blockData) { + public final BlockWrapper setBlockData(final IBlockData blockData) { this.blockData = blockData; + return this; } /** @@ -48,6 +76,14 @@ public final VoxelMaterial getMaterial() { return this.blockData.getMaterial(); } + /** + * @param material the material to set + */ + public final BlockWrapper setMaterial(final VoxelMaterial material) { + setBlockData(material.createBlockData()); + return this; + } + /** * @return the world */ @@ -58,8 +94,16 @@ public final IWorld getWorld() { /** * @param world the world to set */ - public final void setWorld(final IWorld world) { + public final BlockWrapper setWorld(final IWorld world) { this.world = world; + return this; + } + + /** + * @return the BaseLocation + */ + public final BaseLocation getLocation() { + return new BaseLocation(this.world, this.x, this.y, this.z); } /** @@ -72,8 +116,9 @@ public final int getX() { /** * @param x the x to set */ - public final void setX(final int x) { + public final BlockWrapper setX(final int x) { this.x = x; + return this; } /** @@ -86,8 +131,9 @@ public final int getY() { /** * @param y the y to set */ - public final void setY(final int y) { + public final BlockWrapper setY(final int y) { this.y = y; + return this; } /** @@ -100,7 +146,19 @@ public final int getZ() { /** * @param z the z to set */ - public final void setZ(final int z) { + public final BlockWrapper setZ(final int z) { this.z = z; + return this; + } + + @Override + public BlockWrapper clone() { + try { + BlockWrapper clone = (BlockWrapper) super.clone(); + clone.blockData = this.blockData.getCopy(); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Messages.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Messages.java index 0f819534..182c73e3 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Messages.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Messages.java @@ -358,7 +358,8 @@ public enum Messages implements ComponentLike { // - private @NotNull String message = this.name().toLowerCase(Locale.ROOT); + private @NotNull + String message = this.name().toLowerCase(Locale.ROOT); public static void load(IVoxelsniper voxelSniper) { File langFile = new File(voxelSniper.getFileHandler().getDataFolder(), "lang.yml"); @@ -415,7 +416,8 @@ public ComponentLike append(ComponentLike message) { } @Override - public @NotNull Component asComponent() { + public @NotNull + Component asComponent() { return MiniMessage.miniMessage().deserialize(this.message); } @@ -455,7 +457,8 @@ public Message append(String message) { } @Override - public @NotNull Component asComponent() { + public @NotNull + Component asComponent() { return MiniMessage.miniMessage().deserialize(this.message); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Shapes.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Shapes.java new file mode 100644 index 00000000..9bf28463 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Shapes.java @@ -0,0 +1,189 @@ +package com.github.kevindagame.util; + +import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.voxelsniper.block.BlockFace; +import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.github.kevindagame.voxelsniper.world.IWorld; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Shapes { + static double SMOOTH_CIRCLE_VALUE = 0.5; + static double VOXEL_CIRCLE_VALUE = 0.0; + + public static List ball(BaseLocation location, double radius, boolean smooth) { + List positions = new ArrayList<>(); + double SMOOTH_SPHERE_VALUE = 0.5; + int VOXEL_SPHERE_VALUE = 0; + + int bx = location.getBlockX(); + int by = location.getBlockY(); + int bz = location.getBlockZ(); + var radiusSquared = Math.pow(radius + (smooth ? SMOOTH_SPHERE_VALUE : VOXEL_SPHERE_VALUE), 2); + for (int x = (int) (bx - radius); x <= bx + radius; x++) { + for (int y = (int) (by - radius); y <= by + radius; y++) { + for (int z = (int) (bz - radius); z <= bz + radius; z++) { + + double distance = ((bx - x) * (bx - x) + ((bz - z) * (bz - z)) + ((by - y) * (by - y))); + if (distance <= radiusSquared) { + positions.add(new BaseLocation(location.getWorld(), x, y, z)); + } + } + } + } + + return positions; + } + + public static List voxel(BaseLocation location, int brushSize) { + List positions = new ArrayList<>(); + for (int z = brushSize; z >= -brushSize; z--) { + for (int x = brushSize; x >= -brushSize; x--) { + for (int y = brushSize; y >= -brushSize; y--) { + positions.add(new BaseLocation(location.getWorld(), location.getX() + x, location.getY() + z, location.getZ() + y)); + } + } + } + return positions; + } + + public static List disc(BaseLocation location, int brushSize, boolean smooth) { + List positions = new ArrayList<>(); + final double radiusSquared = (brushSize + (smooth ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE)) * (brushSize + (smooth ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE)); + final VoxelVector centerPoint = location.toVector(); + final VoxelVector currentPoint = centerPoint.clone(); + + for (int x = -brushSize; x <= brushSize; x++) { + currentPoint.setX(centerPoint.getX() + x); + for (int z = -brushSize; z <= brushSize; z++) { + currentPoint.setZ(centerPoint.getZ() + z); + if (centerPoint.distanceSquared(currentPoint) <= radiusSquared) { + positions.add(new BaseLocation(location.getWorld(), currentPoint.getBlockX(), currentPoint.getBlockY(), currentPoint.getBlockZ())); + } + } + } + return positions; + } + + public static List voxelDisc(BaseLocation location, int brushSize) { + List positions = new ArrayList<>(); + for (int x = brushSize; x >= -brushSize; x--) { + for (int z = brushSize; z >= -brushSize; z--) { + positions.add(new BaseLocation(location.getWorld(), location.getX() + x, location.getY(), location.getZ() + z)); + } + } + return positions; + } + + public static List cylinder(BaseLocation location, int brushSize, int height, int shift, boolean smooth) { + List positions = new ArrayList<>(); + for (int y = 0; y < height; y++) { + positions.addAll(disc(new BaseLocation(location.getWorld(), location.getX(), location.getY() + y - (height / 2.0) + 1 + shift, location.getZ()), brushSize, smooth)); + } + return positions; + } + + public static List discFace(BaseLocation location, int brushSize, boolean smooth, BlockFace face) { + List disc = disc(location, brushSize, smooth); + return face(location, disc, face); + } + + public static List voxelDiscFace(BaseLocation location, int brushSize, BlockFace face) { + List voxelDisc = voxelDisc(location, brushSize); + return face(location, voxelDisc, face); + } + + public static List face(BaseLocation center, List locations, BlockFace face) { + if (face == BlockFace.UP || face == BlockFace.DOWN) return locations; + + List positions = new ArrayList<>(); + for (var pos : locations) { + VoxelVector diff = center.toVector().subtract(pos.toVector()); + switch (face) { + case NORTH, SOUTH -> positions.add(new BaseLocation(center.getWorld(), center.getX() + diff.getBlockX(), center.getY() + diff.getBlockZ(), center.getZ())); + case EAST, WEST -> positions.add(new BaseLocation(center.getWorld(), center.getX(), center.getY() + diff.getBlockX(), center.getZ() + diff.getBlockZ())); + } + } + return positions; + } + + public static List dome(BaseLocation location, int brushSize, int height) { + + final List positions = new ArrayList<>(); + final int absoluteHeight = Math.abs(height); + final boolean negative = height < 0; + + final Undo undo = new Undo(); + + final int brushSizeTimesVoxelHeight = brushSize * absoluteHeight; + final double stepScale = ((brushSize * brushSize) + brushSizeTimesVoxelHeight + brushSizeTimesVoxelHeight) / 5.0; + + final double stepSize = 1 / stepScale; + + for (double u = 0; u <= Math.PI / 2; u += stepSize) { + final double y = absoluteHeight * Math.sin(u); + for (double stepV = -Math.PI; stepV <= -(Math.PI / 2); stepV += stepSize) { + final double x = brushSize * Math.cos(u) * Math.cos(stepV); + final double z = brushSize * Math.cos(u) * Math.sin(stepV); + + final double targetBlockX = location.getX() + 0.5; + final double targetBlockZ = location.getZ() + 0.5; + final int targetY = ((int) Math.floor(location.getY() + (negative ? -y : y))); + final int currentBlockXAdd = ((int) Math.floor(targetBlockX + x)); + final int currentBlockZAdd = ((int) Math.floor(targetBlockZ + z)); + final int currentBlockXSubtract = ((int) Math.floor(targetBlockX - x)); + final int currentBlockZSubtract = ((int) Math.floor(targetBlockZ - z)); + positions.add(new BaseLocation(location.getWorld(), currentBlockXAdd, targetY, currentBlockZAdd)); + positions.add(new BaseLocation(location.getWorld(), currentBlockXSubtract, targetY, currentBlockZAdd)); + positions.add(new BaseLocation(location.getWorld(), currentBlockXAdd, targetY, currentBlockZSubtract)); + positions.add(new BaseLocation(location.getWorld(), currentBlockXSubtract, targetY, currentBlockZSubtract)); + + } + } + return positions; + } + + public static List line(VoxelVector originCoords, VoxelVector targetCoords, IWorld world) { + final VoxelVector HALF_BLOCK_OFFSET = new VoxelVector(0.5, 0.5, 0.5); + final VoxelVector originClone = originCoords.clone().add(HALF_BLOCK_OFFSET); + final VoxelVector targetClone = targetCoords.clone().add(HALF_BLOCK_OFFSET); + + List positions = new ArrayList<>(); + final VoxelVector direction = targetClone.clone().subtract(originClone); + final double length = targetCoords.distance(originCoords); + + if (length == 0) { + positions.add(targetCoords.getLocation(world)); + } else { + for (final Iterator blockIterator = world.getBlockIterator(originClone, direction, 0, (int) Math.round(length)); blockIterator.hasNext(); ) { + final IBlock currentBlock = blockIterator.next(); + positions.add(currentBlock.getLocation()); + } + } + return positions; + } + + public static List ring(BaseLocation location, int radius, double innerSize, boolean smooth) { + List positions = new ArrayList<>(); + final double outerSquared = Math.pow(radius + (smooth ? SMOOTH_CIRCLE_VALUE : VOXEL_CIRCLE_VALUE), 2); + final double innerSquared = Math.pow(innerSize, 2); + + for (int x = radius; x >= 0; x--) { + final double xSquared = Math.pow(x, 2); + for (int z = radius; z >= 0; z--) { + final double ySquared = Math.pow(z, 2); + if ((xSquared + ySquared) <= outerSquared && (xSquared + ySquared) >= innerSquared) { + positions.add(new BaseLocation(location.getWorld(), location.getX() + x, location.getY(), location.getZ() + z)); + positions.add(new BaseLocation(location.getWorld(), location.getX() - x, location.getY(), location.getZ() + z)); + positions.add(new BaseLocation(location.getWorld(), location.getX() + x, location.getY(), location.getZ() - z)); + positions.add(new BaseLocation(location.getWorld(), location.getX() - x, location.getY(), location.getZ() - z)); + } + } + } + return positions; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelList.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelList.java index 0acb635a..42089056 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelList.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelList.java @@ -1,7 +1,7 @@ package com.github.kevindagame.util; -import com.google.common.collect.ImmutableList; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelMessage.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelMessage.java index 9b83db96..b3eadb97 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelMessage.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/VoxelMessage.java @@ -1,6 +1,7 @@ package com.github.kevindagame.util; import com.github.kevindagame.snipe.SnipeData; +import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import net.kyori.adventure.text.ComponentLike; import java.util.stream.Collectors; @@ -113,7 +114,7 @@ public void toggleLightning() { /** * Display toggle printout message. */ - public final void togglePrintout() { + public void togglePrintout() { // TODO seems to do the same as toggleLightning() String state = ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isLightningEnabled()) ? "on" : "off"); snipeData.sendMessage(Messages.TOGGLE_PRINTOUT.replace("%state%", state)); @@ -136,7 +137,7 @@ public void voxelList() { snipeData.sendMessage(Messages.VOXEL_LIST_EMPTY); } else { - String blocks = snipeData.getVoxelList().getList().stream().map(e -> e.getKey().toString()).collect(Collectors.joining(",")); + String blocks = snipeData.getVoxelList().getList().stream().map(VoxelMaterial::getKey).collect(Collectors.joining(",")); snipeData.sendMessage(Messages.VOXEL_LIST.replace("%blocks%", blocks)); } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BiomeOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BiomeOperation.kt new file mode 100644 index 00000000..3301e1dd --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BiomeOperation.kt @@ -0,0 +1,18 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.biome.VoxelBiome +import com.github.kevindagame.voxelsniper.location.BaseLocation + +/** + * Represents a brush operation that changes the biome of a location. + */ +class BiomeOperation(location: BaseLocation, val oldBiome: VoxelBiome, var newBiome: VoxelBiome) : + BrushOperation(location) { + + override fun perform(undo: Undo): Boolean { + val location = location + location.world.setBiome(location.blockX, location.blockY, location.blockZ, newBiome) + return true + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BlockOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BlockOperation.kt new file mode 100644 index 00000000..045f321a --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BlockOperation.kt @@ -0,0 +1,40 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.blockdata.IBlockData +import com.github.kevindagame.voxelsniper.location.BaseLocation +import com.github.kevindagame.voxelsniper.material.VoxelMaterial + +/** + * Operation that is performed on a block. This operation modifies blockData. + */ +class BlockOperation(location: BaseLocation, val oldData: IBlockData, var newData: IBlockData) : + BrushOperation(location) { + private var applyPhysics = true + + constructor(location: BaseLocation, oldData: IBlockData, newData: IBlockData, applyPhysics: Boolean) : this( + location, + oldData, + newData + ) { + this.applyPhysics = applyPhysics + } + + fun applyPhysics(): Boolean { + return applyPhysics + } + + /** + * @param newMaterial the material to create blockData for + */ + fun setNewMaterial(newMaterial: VoxelMaterial) { + newData = newMaterial.createBlockData() + } + + override fun perform(undo: Undo): Boolean { + val block = location.block + undo.put(block) + block.setBlockData(newData, applyPhysics()) + return false + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BlockStateOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BlockStateOperation.kt new file mode 100644 index 00000000..077da8a3 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BlockStateOperation.kt @@ -0,0 +1,34 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.blockstate.IBlockState +import com.github.kevindagame.voxelsniper.location.BaseLocation + +class BlockStateOperation(location: BaseLocation, val oldState: IBlockState, var newState: IBlockState) : + BrushOperation(location) { + private var force = false + private var applyPhysics = true + + constructor(location: BaseLocation, oldState: IBlockState, newState: IBlockState, force: Boolean) : this( + location, oldState, newState + ) { + this.force = force + } + + constructor( + location: BaseLocation, + oldState: IBlockState, + newState: IBlockState, + force: Boolean, + applyPhysics: Boolean + ) : this( + location, oldState, newState, force + ) { + this.applyPhysics = applyPhysics + } + + override fun perform(undo: Undo): Boolean { + undo.put(oldState) + return newState.update(force, applyPhysics) + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BrushOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BrushOperation.kt new file mode 100644 index 00000000..eb9dc33c --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/BrushOperation.kt @@ -0,0 +1,28 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.events.Cancellable +import com.github.kevindagame.voxelsniper.location.BaseLocation + +/** + * This class is the base class for all operations + */ +abstract class BrushOperation(val location: BaseLocation) : Cancellable { + private var cancelled = false + override fun isCancelled(): Boolean { + return cancelled + } + + override fun setCancelled(cancel: Boolean) { + cancelled = cancel + } + + /** + * Performs the operation. + * + * @param undo the undo object to add the operation to + * + * @return whether to reload the brush area + */ + internal abstract fun perform(undo: Undo): Boolean +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/CustomOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/CustomOperation.kt new file mode 100644 index 00000000..b3dd1827 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/CustomOperation.kt @@ -0,0 +1,22 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.brush.CustomBrush +import com.github.kevindagame.snipe.SnipeData +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.location.BaseLocation + +/** + * This class serves as an operation for brushes that don't fit one of the other operations. + */ +@Suppress("unused") +class CustomOperation( + location: BaseLocation, + private var customBrush: CustomBrush, + private var snipeData: SnipeData, + val context: CustomOperationContext +) : + BrushOperation(location) { + override fun perform(undo: Undo): Boolean { + throw UnsupportedOperationException("Not implemented") + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/CustomOperationContext.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/CustomOperationContext.kt new file mode 100644 index 00000000..4e63de05 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/CustomOperationContext.kt @@ -0,0 +1,7 @@ +package com.github.kevindagame.util.brushOperation + +enum class CustomOperationContext { + PLAYERLOCATION, + TARGETLOCATION, + OTHER +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/EntityRemoveOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/EntityRemoveOperation.kt new file mode 100644 index 00000000..dd81a34f --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/EntityRemoveOperation.kt @@ -0,0 +1,16 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.entity.IEntity +import com.github.kevindagame.voxelsniper.location.BaseLocation + +/** + * Operation that is performed on an entity. This operation removes an entity + */ +class EntityRemoveOperation(location: BaseLocation, val entity: IEntity) : BrushOperation(location) { + + override fun perform(undo: Undo): Boolean { + entity.remove() + return false + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/EntitySpawnOperation.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/EntitySpawnOperation.kt new file mode 100644 index 00000000..3be1da0d --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/brushOperation/EntitySpawnOperation.kt @@ -0,0 +1,16 @@ +package com.github.kevindagame.util.brushOperation + +import com.github.kevindagame.snipe.Undo +import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType +import com.github.kevindagame.voxelsniper.location.BaseLocation + +/** + * Operation that is performed on an entity. This operation spawns an entity + */ +class EntitySpawnOperation(location: BaseLocation, var entityType: VoxelEntityType) : BrushOperation(location) { + + override fun perform(undo: Undo): Boolean { + location.world.spawn(location, entityType) + return false + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/IVoxelsniper.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/IVoxelsniper.java index cb0bd584..e342d652 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/IVoxelsniper.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/IVoxelsniper.java @@ -1,7 +1,6 @@ package com.github.kevindagame.voxelsniper; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; -import com.github.kevindagame.voxelsniper.events.IEventManager; import com.github.kevindagame.voxelsniper.fileHandler.IFileHandler; import com.github.kevindagame.voxelsniper.fileHandler.VoxelSniperConfiguration; import com.github.kevindagame.voxelsniper.material.IMaterial; @@ -33,6 +32,4 @@ public interface IVoxelsniper { @Nullable IMaterial getMaterial(VoxelMaterial material); - - IEventManager getEventManager(); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/biome/VoxelBiome.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/biome/VoxelBiome.java index ff79e11d..6c457c64 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/biome/VoxelBiome.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/biome/VoxelBiome.java @@ -6,7 +6,6 @@ import java.util.HashMap; import java.util.Map; -//todo: backwards compatibility @SuppressWarnings("unused") public record VoxelBiome(String namespace, String key, Version version) { public static final String DEFAULT_NAMESPACE = "minecraft"; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/AbstractBlock.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/AbstractBlock.java index 970acc27..1a12ffc0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/AbstractBlock.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/AbstractBlock.java @@ -1,13 +1,13 @@ package com.github.kevindagame.voxelsniper.block; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; public abstract class AbstractBlock implements IBlock { - final VoxelLocation location; + final BaseLocation location; VoxelMaterial material; - public AbstractBlock(VoxelLocation location, VoxelMaterial material) { + public AbstractBlock(BaseLocation location, VoxelMaterial material) { this.location = location; this.material = material; } @@ -19,7 +19,7 @@ public final VoxelMaterial getMaterial() { } @Override - public final VoxelLocation getLocation() { + public final BaseLocation getLocation() { return location; } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/IBlock.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/IBlock.java index 0089920c..51d9014a 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/IBlock.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/block/IBlock.java @@ -4,16 +4,15 @@ import com.github.kevindagame.voxelsniper.blockstate.IBlockState; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.entity.IEntity; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; +import org.jetbrains.annotations.Nullable; import java.util.List; -import org.jetbrains.annotations.Nullable; - public interface IBlock { - VoxelLocation getLocation(); + BaseLocation getLocation(); VoxelMaterial getMaterial(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockdata/IBlockData.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockdata/IBlockData.java index 4ae7edc7..ab767b05 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockdata/IBlockData.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockdata/IBlockData.java @@ -10,4 +10,7 @@ public interface IBlockData { String getAsString(); IBlockData merge(IBlockData newData); + + //no default clone because it's protected + IBlockData getCopy(); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/AbstractBlockState.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/AbstractBlockState.java index 828f9466..2a5dd86b 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/AbstractBlockState.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/AbstractBlockState.java @@ -1,7 +1,7 @@ package com.github.kevindagame.voxelsniper.blockstate; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.world.IWorld; public abstract class AbstractBlockState implements IBlockState { @@ -17,8 +17,8 @@ public final IBlock getBlock() { } @Override - public final VoxelLocation getLocation() { - return new VoxelLocation(getWorld(), getX(), getY(), getZ()); + public final BaseLocation getLocation() { + return this.block.getLocation(); } @Override diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/IBlockState.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/IBlockState.java index 6317b56f..460e6605 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/IBlockState.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/blockstate/IBlockState.java @@ -2,7 +2,7 @@ import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; @@ -21,7 +21,7 @@ public interface IBlockState { IBlockData getBlockData(); - VoxelLocation getLocation(); + BaseLocation getLocation(); boolean update(); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/IEntity.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/IEntity.java index 0fcaf7e5..95863b68 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/IEntity.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/IEntity.java @@ -1,7 +1,7 @@ package com.github.kevindagame.voxelsniper.entity; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.world.IWorld; import java.util.List; @@ -13,14 +13,15 @@ public interface IEntity { int getEntityId(); - VoxelLocation getLocation(); + BaseLocation getLocation(); IWorld getWorld(); void addPassenger(IEntity entity); + List getPassengers(); - VoxelLocation getEyeLocation(); + BaseLocation getEyeLocation(); List getNearbyEntities(int x, int y, int z); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/Painting/IPainting.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/painting/IPainting.java similarity index 76% rename from VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/Painting/IPainting.java rename to VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/painting/IPainting.java index afc2bb21..a960985e 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/Painting/IPainting.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/painting/IPainting.java @@ -1,4 +1,4 @@ -package com.github.kevindagame.voxelsniper.entity.Painting; +package com.github.kevindagame.voxelsniper.entity.painting; import com.github.kevindagame.voxelsniper.entity.IEntity; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/player/IPlayer.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/player/IPlayer.java index 6baa37b5..773a7fff 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/player/IPlayer.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/entity/player/IPlayer.java @@ -3,7 +3,7 @@ import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.entity.IEntity; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.vector.VoxelVector; import net.kyori.adventure.audience.Audience; @@ -26,7 +26,7 @@ public interface IPlayer extends IEntity, Audience { String getName(); - void teleport(VoxelLocation location); + void teleport(BaseLocation location); IEntity launchProjectile(VoxelEntityType type, VoxelVector velocity); diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/Cancellable.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/Cancellable.java new file mode 100644 index 00000000..733309cb --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/Cancellable.java @@ -0,0 +1,20 @@ +package com.github.kevindagame.voxelsniper.events; + +public interface Cancellable { + /** + * Gets the cancellation state of this event. A cancelled event will not + * be executed by VoxelSniper, but will still pass to other {@link EventListener}s + * + * @return True if this event is cancelled by another {@link EventListener} + */ + boolean isCancelled(); + + /** + * Sets the cancellation state of this event. A cancelled event will not + * be executed by VoxelSniper, but will still pass to other {@link EventListener}s. + * + * @param cancel True if you wish to cancel this event. + * @apiNote Another {@link EventListener} might be able to un-cancel the event + */ + void setCancelled(boolean cancel); +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/Event.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/Event.java new file mode 100644 index 00000000..e493a10e --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/Event.java @@ -0,0 +1,23 @@ +package com.github.kevindagame.voxelsniper.events; + +/** + * Abstract class for all events + * + * @param The Event type this {@link HandlerList} is for + */ +public abstract class Event> { + + /** + * @return the {@link HandlerList} for this event + */ + protected abstract HandlerList getHandlers(); + + /** + * Call the registered {@link EventListener}s for this event + */ + public final T callEvent() { + return getHandlers().callEvent((T) this); + } + + +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/EventListener.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/EventListener.java new file mode 100644 index 00000000..27c42597 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/EventListener.java @@ -0,0 +1,25 @@ +package com.github.kevindagame.voxelsniper.events; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +/** + * Container to keep track of different settings for EventListeners + * + * @param The {@link Event} type to listen for + */ +public record EventListener>(EventPriority priority, + Consumer handler) implements Consumer, Comparable> { + + @Override + public void accept(T event) { + this.handler.accept(event); + } + + @Override + public int compareTo(@NotNull EventListener o) { + return this.priority.compareTo(o.priority); + } + +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/EventPriority.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/EventPriority.java new file mode 100644 index 00000000..f52c78b6 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/EventPriority.java @@ -0,0 +1,31 @@ +package com.github.kevindagame.voxelsniper.events; + +/** + * Represents an {@link EventListener}'s priority in execution. + *

+ * Listeners with lower priority are called first, + * listeners with higher priority are called last. + *

+ * Listeners are called in following order: + * {@link #LOW} -> {@link #MEDIUM} -> {@link #HIGH} + */ +public enum EventPriority { + + /** + * Event call is of low importance and should be run first, to allow + * other plugins to further customise the outcome + */ + LOW, + /** + * Event call is neither important nor unimportant, and may be run + * normally. + *

+ * This is also the default EventPriority when registering events. + */ + MEDIUM, + /** + * Event call is critical and must have the final say in what happens + * to the event + */ + HIGH +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/HandlerList.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/HandlerList.java new file mode 100644 index 00000000..14b30059 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/HandlerList.java @@ -0,0 +1,46 @@ +package com.github.kevindagame.voxelsniper.events; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +/** + * Keeps track of all the eventListeners for a specific {@link Event} + * + * @param The {@link Event} type this HandlerList is for + */ +public class HandlerList> { + private final List> handlers = new ArrayList<>(); + + /** + * Registers an {@link EventListener} with a given {@link EventPriority} + * + * @param priority The {@link EventPriority} for this event + * @param handler The handler to register + */ + public void registerListener(EventPriority priority, Consumer handler) { + this.handlers.add(new EventListener<>(priority, handler)); + Collections.sort(this.handlers); + } + + /** + * Registers an {@link EventListener} + * + * @param handler The handler to register + */ + public void registerListener(Consumer handler) { + this.registerListener(EventPriority.MEDIUM, handler); + } + + /** + * Call the registered {@link EventListener}s for this event + */ + public T callEvent(T ev) { + for (Consumer handler : handlers) { + handler.accept(ev); + } + return ev; + } + +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/IEventManager.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/IEventManager.java deleted file mode 100644 index 11cbdcfb..00000000 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/IEventManager.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.kevindagame.voxelsniper.events; - -import com.github.kevindagame.brush.IBrush; -import com.github.kevindagame.snipe.Sniper; -import com.github.kevindagame.voxelsniper.blockdata.IBlockData; - -public interface IEventManager { - - void callSniperReplaceMaterialChangedEvent(Sniper sniper, String toolId, IBlockData oldSubstance, IBlockData newSubstance); - - void callSniperMaterialChangedEvent(Sniper sniper, String toolId, IBlockData oldSubstance, IBlockData newSubstance); - - void callSniperBrushChangedEvent(Sniper owner, String currentToolId, IBrush originalBrush, IBrush newBrush); - - void callSniperBrushSizeChangedEvent(Sniper sniper, String currentToolId, int originalSize, int newSize); - - void callSniperSnipeEvent(Sniper sniper, IBrush brush, boolean success); -} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/EventResult.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/EventResult.java new file mode 100644 index 00000000..f386677e --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/EventResult.java @@ -0,0 +1,7 @@ +package com.github.kevindagame.voxelsniper.events.player; + +public enum EventResult { + ALLOW, + DEFAULT, + DENY, +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerBrushChangedEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerBrushChangedEvent.java new file mode 100644 index 00000000..665a1712 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerBrushChangedEvent.java @@ -0,0 +1,60 @@ +package com.github.kevindagame.voxelsniper.events.player; + +import com.github.kevindagame.brush.IBrush; +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.Cancellable; +import com.github.kevindagame.voxelsniper.events.EventPriority; +import com.github.kevindagame.voxelsniper.events.HandlerList; + +import java.util.function.Consumer; + +public class PlayerBrushChangedEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList<>(); + private final IBrush oldBrush; + private final IBrush newBrush; + private final String toolId; + private EventResult status; + + public PlayerBrushChangedEvent(IPlayer p, String toolId, IBrush oldBrush, IBrush newBrush) { + super(p); + this.oldBrush = oldBrush; + this.newBrush = newBrush; + this.toolId = toolId; + } + + public static void registerListener(Consumer handler) { + handlers.registerListener(handler); + } + + public static void registerListener(EventPriority priority, Consumer handler) { + handlers.registerListener(priority, handler); + } + + public IBrush getOldBrush() { + return oldBrush; + } + + public IBrush getNewBrush() { + return newBrush; + } + + public String getToolId() { + return toolId; + } + + @Override + protected HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return status == EventResult.DENY; + } + + @Override + public void setCancelled(boolean cancel) { + status = cancel ? EventResult.DENY : EventResult.DEFAULT; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerBrushSizeChangedEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerBrushSizeChangedEvent.java new file mode 100644 index 00000000..ed17843e --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerBrushSizeChangedEvent.java @@ -0,0 +1,66 @@ +package com.github.kevindagame.voxelsniper.events.player; + +import com.github.kevindagame.brush.IBrush; +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.Cancellable; +import com.github.kevindagame.voxelsniper.events.EventPriority; +import com.github.kevindagame.voxelsniper.events.HandlerList; + +import java.util.function.Consumer; + +public class PlayerBrushSizeChangedEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList<>(); + private final int oldSize; + private final int newSize; + private final String toolId; + private final IBrush brush; + private EventResult status; + + public PlayerBrushSizeChangedEvent(IPlayer p, String toolId, IBrush brush, int oldSize, int newSize) { + super(p); + this.oldSize = oldSize; + this.newSize = newSize; + this.toolId = toolId; + this.brush = brush; + } + + public static void registerListener(Consumer handler) { + handlers.registerListener(handler); + } + + public static void registerListener(EventPriority priority, Consumer handler) { + handlers.registerListener(priority, handler); + } + + public int getOldSize() { + return oldSize; + } + + public int getNewSize() { + return newSize; + } + + public String getToolId() { + return toolId; + } + + public IBrush getBrush() { + return brush; + } + + @Override + protected HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return status == EventResult.DENY; + } + + @Override + public void setCancelled(boolean cancel) { + status = cancel ? EventResult.DENY : EventResult.DEFAULT; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerEvent.java new file mode 100644 index 00000000..c7af973a --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerEvent.java @@ -0,0 +1,16 @@ +package com.github.kevindagame.voxelsniper.events.player; + +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.Event; + +public abstract class PlayerEvent> extends Event { + private final IPlayer player; + + public PlayerEvent(IPlayer p) { + this.player = p; + } + + public final IPlayer getPlayer() { + return player; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerSnipeEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerSnipeEvent.java new file mode 100644 index 00000000..0c3e891d --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/PlayerSnipeEvent.java @@ -0,0 +1,87 @@ +package com.github.kevindagame.voxelsniper.events.player; + +import com.github.kevindagame.brush.IBrush; +import com.github.kevindagame.util.brushOperation.BrushOperation; +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.Cancellable; +import com.github.kevindagame.voxelsniper.events.EventPriority; +import com.github.kevindagame.voxelsniper.events.HandlerList; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +public class PlayerSnipeEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList<>(); + private final IBrush brush; + private final ImmutableList operations; + private boolean isCustom; + private EventResult status; + + public PlayerSnipeEvent(final IPlayer p, final IBrush brush, ImmutableList operations) { + super(p); + this.brush = brush; + this.status = EventResult.DEFAULT; + this.operations = operations; + this.isCustom = false; + } + + public PlayerSnipeEvent(final IPlayer p, final IBrush brush, ImmutableList operations, boolean isCustom) { + this(p, brush, operations); + this.isCustom = isCustom; + } + + public static void registerListener(Consumer handler) { + handlers.registerListener(handler); + } + + public static void registerListener(EventPriority priority, Consumer handler) { + handlers.registerListener(priority, handler); + } + + public IBrush getBrush() { + return brush; + } + + public ImmutableList getOperations() { + return operations; + } + + public EventResult getStatus() { + return status; + } + + @NotNull + @Override + protected HandlerList getHandlers() { + return handlers; + } + + /** + * @return whether this event is custom. This means that the event uses custom operations + */ + public boolean isCustom() { + return isCustom; + } + + @Override + public boolean isCancelled() { + return status == EventResult.DENY || !hasNonCancelledOperation(); + } + + @Override + public void setCancelled(boolean cancel) { + status = cancel ? EventResult.DENY : EventResult.DEFAULT; + } + + private boolean hasNonCancelledOperation() { + for (var operation : + getOperations()) { + if (!operation.isCancelled()) { + return true; + } + } + return false; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/AbstractMaterialChangedEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/AbstractMaterialChangedEvent.java new file mode 100644 index 00000000..4c34efa3 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/AbstractMaterialChangedEvent.java @@ -0,0 +1,38 @@ +package com.github.kevindagame.voxelsniper.events.player.materialChange; + +import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.Cancellable; +import com.github.kevindagame.voxelsniper.events.player.EventResult; +import com.github.kevindagame.voxelsniper.events.player.PlayerEvent; + +abstract class AbstractMaterialChangedEvent> extends PlayerEvent implements Cancellable { + + private final IBlockData oldMaterial; + private final IBlockData newMaterial; + private EventResult status; + + public AbstractMaterialChangedEvent(IPlayer p, IBlockData oldMaterial, IBlockData newMaterial) { + super(p); + this.oldMaterial = oldMaterial; + this.newMaterial = newMaterial; + } + + public IBlockData getOldMaterial() { + return oldMaterial; + } + + public IBlockData getNewMaterial() { + return newMaterial; + } + + @Override + public boolean isCancelled() { + return status == EventResult.DENY; + } + + @Override + public void setCancelled(boolean cancel) { + status = cancel ? EventResult.DENY : EventResult.DEFAULT; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/PlayerMaterialChangedEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/PlayerMaterialChangedEvent.java new file mode 100644 index 00000000..17ddcc39 --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/PlayerMaterialChangedEvent.java @@ -0,0 +1,30 @@ +package com.github.kevindagame.voxelsniper.events.player.materialChange; + +import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.EventPriority; +import com.github.kevindagame.voxelsniper.events.HandlerList; + +import java.util.function.Consumer; + +public class PlayerMaterialChangedEvent extends AbstractMaterialChangedEvent { + + private static final HandlerList handlers = new HandlerList<>(); + + public PlayerMaterialChangedEvent(IPlayer p, IBlockData oldMaterial, IBlockData newMaterial) { + super(p, oldMaterial, newMaterial); + } + + public static void registerListener(Consumer handler) { + handlers.registerListener(handler); + } + + public static void registerListener(EventPriority priority, Consumer handler) { + handlers.registerListener(priority, handler); + } + + @Override + protected HandlerList getHandlers() { + return handlers; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/PlayerReplaceMaterialChangedEvent.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/PlayerReplaceMaterialChangedEvent.java new file mode 100644 index 00000000..1b67fa7a --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/events/player/materialChange/PlayerReplaceMaterialChangedEvent.java @@ -0,0 +1,31 @@ +package com.github.kevindagame.voxelsniper.events.player.materialChange; + +import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.entity.player.IPlayer; +import com.github.kevindagame.voxelsniper.events.EventPriority; +import com.github.kevindagame.voxelsniper.events.HandlerList; + +import java.util.function.Consumer; + +public class PlayerReplaceMaterialChangedEvent extends AbstractMaterialChangedEvent { + + private static final HandlerList handlers = new HandlerList<>(); + + public PlayerReplaceMaterialChangedEvent(IPlayer p, IBlockData oldMaterial, IBlockData newMaterial) { + super(p, oldMaterial, newMaterial); + } + + public static void registerListener(Consumer handler) { + handlers.registerListener(handler); + } + + public static void registerListener(EventPriority priority, Consumer handler) { + handlers.registerListener(priority, handler); + } + + @Override + protected HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/fileHandler/VoxelSniperConfiguration.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/fileHandler/VoxelSniperConfiguration.java index 3b144145..133772a0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/fileHandler/VoxelSniperConfiguration.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/fileHandler/VoxelSniperConfiguration.java @@ -13,6 +13,8 @@ public class VoxelSniperConfiguration { public static final String CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED = "message-on-login-enabled"; public static final int DEFAULT_UNDO_CACHE_SIZE = 20; public static final boolean DEFAULT_MESSAGE_ON_LOGIN_ENABLED = true; + private static final boolean DEFAULT_USE_PLOTSQUARED = false; + private static final boolean DEFAULT_USE_WORLDGUARD = false; private final YamlConfiguration configuration; /** @@ -57,4 +59,12 @@ public boolean isMessageOnLoginEnabled() { public void setMessageOnLoginEnabled(boolean enabled) { configuration.set(CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED, enabled); } + + public boolean isPlotSquaredIntegrationEnabled() { + return configuration.getBoolean("plotsquared-integration-enabled", DEFAULT_USE_PLOTSQUARED); + } + + public boolean isWorldGuardIntegrationEnabled() { + return configuration.getBoolean("worldguard-integration-enabled", DEFAULT_USE_WORLDGUARD); + } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/BaseLocation.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/BaseLocation.java new file mode 100644 index 00000000..f381db1a --- /dev/null +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/BaseLocation.java @@ -0,0 +1,153 @@ +package com.github.kevindagame.voxelsniper.location; + +import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.chunk.IChunk; +import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import com.github.kevindagame.voxelsniper.world.IWorld; + +import java.util.Objects; + +public class BaseLocation implements Cloneable { + + protected final IWorld world; + protected double x; + protected double y; + protected double z; + protected float yaw; + protected float pitch; + + public BaseLocation(IWorld world, double x, double y, double z, float yaw, float pitch) { + this.world = world; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + + public BaseLocation(IWorld world, double x, double y, double z) { + this(world, x, y, z, 0, 0); + } + + private static double square(double num) { + return num * num; + } + + public final double getX() { + return this.x; + } + + public final double getY() { + return this.y; + } + + public final double getZ() { + return this.z; + } + + public final int getBlockX() { + return (int) Math.floor(getX()); + } + + public final int getBlockY() { + return (int) Math.floor(getY()); + } + + public final int getBlockZ() { + return (int) Math.floor(getZ()); + } + + public final float getYaw() { + return this.yaw; + } + + public final void setYaw(float yaw) { + this.yaw = yaw; + } + + public final float getPitch() { + return this.pitch; + } + + public final void setPitch(float pitch) { + this.pitch = pitch; + } + + public final IWorld getWorld() { + return this.world; + } + + @Override + public BaseLocation clone() { + try { + return (BaseLocation) super.clone(); + } catch (CloneNotSupportedException e) { + throw new Error(e); + } + } + + public VoxelLocation makeMutable() { + return new VoxelLocation(world, x, y, z, yaw, pitch); + } + + public final IBlock getBlock() { + return getWorld().getBlock(this); + } + + public final VoxelVector toVector() { + return new VoxelVector(x, y, z); + } + + public final IChunk getChunk() { + return world.getChunkAtLocation(this); + } + + public final double distanceSquared(BaseLocation targetLocation) { + return square(x - targetLocation.getX()) + square(y - targetLocation.getY()) + square(z - targetLocation.getZ()); + } + + public final double distance(BaseLocation location) { + return Math.sqrt(distanceSquared(location)); + } + + @Override + public final boolean equals(Object o) { + if (this == o) return true; + if (o instanceof BaseLocation loc) { + return Double.compare(loc.x, x) == 0 && Double.compare(loc.y, y) == 0 && Double.compare(loc.z, z) == 0 && Float.compare(loc.yaw, yaw) == 0 && Float.compare(loc.pitch, pitch) == 0 && world.equals(loc.world); + } + return false; + } + + @Override + public String toString() { + return "BaseLocation{" + + "x=" + x + + ", y=" + y + + ", z=" + z + + ", yaw=" + yaw + + ", pitch=" + pitch + + '}'; + } + + @Override + public final int hashCode() { + return Objects.hash(world, x, y, z, yaw, pitch); + } + + public final VoxelVector getDirection() { + VoxelVector vector = new VoxelVector(); + + double rotX = this.getYaw(); + double rotY = this.getPitch(); + + vector.setY(-Math.sin(Math.toRadians(rotY))); + + double xz = Math.cos(Math.toRadians(rotY)); + + vector.setX(-xz * Math.sin(Math.toRadians(rotX))); + vector.setZ(xz * Math.cos(Math.toRadians(rotX))); + + return vector; + } +} diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/VoxelLocation.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/VoxelLocation.java index 88a4cd65..581a00c5 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/VoxelLocation.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/location/VoxelLocation.java @@ -1,90 +1,30 @@ package com.github.kevindagame.voxelsniper.location; -import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.vector.VoxelVector; import com.github.kevindagame.voxelsniper.world.IWorld; -import java.util.Objects; - -public class VoxelLocation implements Cloneable{ - - private final IWorld world; - private double x; - private double y; - private double z; - private float yaw; - private float pitch; +public final class VoxelLocation extends BaseLocation implements Cloneable { public VoxelLocation(IWorld world, double x, double y, double z, float yaw, float pitch) { - this.world = world; - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; + super(world, x, y, z, yaw, pitch); } public VoxelLocation(IWorld world, double x, double y, double z) { - this(world, x, y, z, 0, 0); - } - - private static double square(double num) { - return num * num; - } - - public double getX() { - return this.x; + super(world, x, y, z); } public void setX(double x) { this.x = x; } - public double getY() { - return this.y; - } - public void setY(double y) { this.y = y; } - public double getZ() { - return this.z; - } - public void setZ(double z) { this.z = z; } - public int getBlockX() { - return (int) Math.floor(getX()); - } - - public int getBlockY() { - return (int) Math.floor(getY()); - } - - public int getBlockZ() { - return (int) Math.floor(getZ()); - } - - public float getYaw() { - return this.yaw; - } - - public void setYaw(float yaw) { - this.yaw = yaw; - } - - public float getPitch() { - return this.pitch; - } - - public void setPitch(float pitch) { - this.pitch = pitch; - } - public void addX(double x) { this.setX(this.getX() + x); } @@ -103,7 +43,7 @@ public void add(int x, int y, int z) { this.addZ(z); } - public void add(VoxelLocation location) { + public void add(BaseLocation location) { this.addX(location.getX()); this.addY(location.getY()); this.addZ(location.getZ()); @@ -115,49 +55,18 @@ public void add(VoxelVector direction) { this.addZ(direction.getZ()); } - public IWorld getWorld() { - return this.world; + public BaseLocation makeImmutable() { + return new BaseLocation(world, x, y, z, yaw, pitch); } @Override - public VoxelLocation clone() { - try { - return (VoxelLocation) super.clone(); - } catch (CloneNotSupportedException e) { - throw new Error(e); - } - } - - public IBlock getClampedBlock() { - return getWorld().getBlock(getBlockX(), Math.max(Math.min(getBlockY(), getWorld().getMaxWorldHeight()), getWorld().getMinWorldHeight()), getBlockZ()); - } - - public IBlock getBlock() { - return getWorld().getBlock(this); - } - - public VoxelVector toVector() { - return new VoxelVector(x, y, z); - } - - public IChunk getChunk() { - return world.getChunkAtLocation(this); - } - - public double distanceSquared(VoxelLocation targetLocation) { - return square(x - targetLocation.getX()) + square(y - targetLocation.getY()) + square(z - targetLocation.getZ()); - } - - public double distance(VoxelLocation location) { - return Math.sqrt(distanceSquared(location)); + public VoxelLocation makeMutable() { + return this.clone(); } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - VoxelLocation that = (VoxelLocation) o; - return Double.compare(that.x, x) == 0 && Double.compare(that.y, y) == 0 && Double.compare(that.z, z) == 0 && Float.compare(that.yaw, yaw) == 0 && Float.compare(that.pitch, pitch) == 0 && world.equals(that.world); + public VoxelLocation clone() { + return (VoxelLocation) super.clone(); } @Override @@ -170,25 +79,4 @@ public String toString() { ", pitch=" + pitch + '}'; } - - @Override - public int hashCode() { - return Objects.hash(world, x, y, z, yaw, pitch); - } - - public VoxelVector getDirection() { - VoxelVector vector = new VoxelVector(); - - double rotX = this.getYaw(); - double rotY = this.getPitch(); - - vector.setY(-Math.sin(Math.toRadians(rotY))); - - double xz = Math.cos(Math.toRadians(rotY)); - - vector.setX(-xz * Math.sin(Math.toRadians(rotX))); - vector.setZ(xz * Math.cos(Math.toRadians(rotX))); - - return vector; - } } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/material/VoxelMaterial.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/material/VoxelMaterial.java index 0110b76b..42acd173 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/material/VoxelMaterial.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/material/VoxelMaterial.java @@ -968,6 +968,7 @@ public class VoxelMaterial implements IMaterial { private final String namespace; private final List tags; private IMaterial material = null; + public VoxelMaterial(String namespace, String key, Version version, Tags... tags) { this.namespace = namespace; this.key = key; diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/vector/VoxelVector.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/vector/VoxelVector.java index 16553ab3..d7426147 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/vector/VoxelVector.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/vector/VoxelVector.java @@ -1,6 +1,6 @@ package com.github.kevindagame.voxelsniper.vector; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.world.IWorld; import java.util.Objects; @@ -24,8 +24,8 @@ private static double square(double num) { return num * num; } - public VoxelLocation getLocation(IWorld world) { - return new VoxelLocation(world, getX(), getY(), getZ()); + public BaseLocation getLocation(IWorld world) { + return new BaseLocation(world, getX(), getY(), getZ()); } public VoxelVector getMidpoint(VoxelVector other) { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/world/IWorld.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/world/IWorld.java index df850b23..5f060357 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/world/IWorld.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/voxelsniper/world/IWorld.java @@ -1,20 +1,21 @@ package com.github.kevindagame.voxelsniper.world; -import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.util.brushOperation.BrushOperation; import com.github.kevindagame.voxelsniper.biome.VoxelBiome; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.chunk.IChunk; import com.github.kevindagame.voxelsniper.entity.IEntity; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.treeType.VoxelTreeType; import com.github.kevindagame.voxelsniper.vector.VoxelVector; +import org.jetbrains.annotations.Nullable; import java.util.Iterator; import java.util.List; public interface IWorld { - IBlock getBlock(VoxelLocation location); + IBlock getBlock(BaseLocation location); IBlock getBlock(int x, int y, int z); @@ -31,7 +32,7 @@ public interface IWorld { */ IChunk getChunkAtLocation(int x, int z); - default IChunk getChunkAtLocation(VoxelLocation location) { + default IChunk getChunkAtLocation(BaseLocation location) { return getChunkAtLocation(((int) Math.floor(location.getBlockX() / 16f)), ((int) Math.floor(location.getBlockZ() / 16f))); } @@ -44,21 +45,21 @@ default IChunk getChunkAtLocation(VoxelLocation location) { * search bounding box. * * @param location The center of the bounding box - * @param x 1/2 the size of the box along x axis - * @param y 1/2 the size of the box along y axis - * @param z 1/2 the size of the box along z axis + * @param x 1/2 the size of the box along x axis + * @param y 1/2 the size of the box along y axis + * @param z 1/2 the size of the box along z axis * @return the collection of entities near location. This will always be a - * non-null collection. + * non-null collection. */ - List getNearbyEntities(VoxelLocation location, double x, double y, double z); + List getNearbyEntities(BaseLocation location, double x, double y, double z); void refreshChunk(int x, int z); - void strikeLightning(VoxelLocation location); + void strikeLightning(BaseLocation location); String getName(); - void spawn(VoxelLocation location, VoxelEntityType entity); + void spawn(BaseLocation location, VoxelEntityType entity); void setBiome(int x, int z, VoxelBiome selectedBiome); @@ -68,7 +69,15 @@ default IChunk getChunkAtLocation(VoxelLocation location) { void regenerateChunk(int x, int z); - void generateTree(VoxelLocation location, VoxelTreeType treeType, Undo undo); + @Nullable + List generateTree(BaseLocation location, VoxelTreeType treeType, boolean updateBlocks); + + @Nullable + default List generateTree(BaseLocation location, VoxelTreeType treeType) { + return generateTree(location, treeType, true); + } Iterator getBlockIterator(VoxelVector origin, VoxelVector direction, double yOffset, int maxDistance); + + VoxelBiome getBiome(BaseLocation location); } diff --git a/VoxelSniperCore/src/main/resources/config.yml b/VoxelSniperCore/src/main/resources/config.yml index 0f9d5b5a..0e06ad08 100644 --- a/VoxelSniperCore/src/main/resources/config.yml +++ b/VoxelSniperCore/src/main/resources/config.yml @@ -1,3 +1,6 @@ litesniper-max-brush-size: 5 undo-cache-size: 20 -message-on-login-enabled: true \ No newline at end of file +message-on-login-enabled: true + +worldguard-integration-enabled: false +plotsquared-integration-enabled: false \ No newline at end of file diff --git a/VoxelSniperCore/src/test/java/com/github/kevindagame/util/BlockWrapperTest.java b/VoxelSniperCore/src/test/java/com/github/kevindagame/util/BlockWrapperTest.java new file mode 100644 index 00000000..d15b58fd --- /dev/null +++ b/VoxelSniperCore/src/test/java/com/github/kevindagame/util/BlockWrapperTest.java @@ -0,0 +1,27 @@ +package com.github.kevindagame.util; + +import com.github.kevindagame.voxelsniper.block.IBlock; +import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.material.VoxelMaterial; +import junit.framework.TestCase; +import org.mockito.Mockito; + +import static org.mockito.Mockito.when; + +public class BlockWrapperTest extends TestCase { + + public void testTestClone() { + var blockdata = Mockito.mock(IBlockData.class); + when(blockdata.getMaterial()).thenReturn(Mockito.mock(VoxelMaterial.class)); + var mock = Mockito.mock(IBlock.class); + when(mock.getBlockData()).thenReturn(blockdata); + + BlockWrapper bw = new BlockWrapper(mock); + var clone = bw.clone(); + assert clone.getBlockData() != bw.getBlockData(); // assert that it was cloned deeply + assertEquals(bw.getX(), clone.getX()); + assertEquals(bw.getY(), clone.getY()); + assertEquals(bw.getZ(), clone.getZ()); + assertEquals(bw.getWorld(), clone.getWorld()); + } +} \ No newline at end of file diff --git a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java index d3caeb9e..cd1fe6f8 100644 --- a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java +++ b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java @@ -2,7 +2,6 @@ import com.github.kevindagame.VoxelBrushManager; import com.github.kevindagame.VoxelSniper; -import com.google.common.collect.Multimap; import com.github.kevindagame.brush.IBrush; import com.github.kevindagame.brush.perform.Performer; import com.github.kevindagame.brush.perform.PerformerBrush; @@ -68,15 +67,15 @@ public void testGetSniperBrushHandles() { } @Test - public void testGetRegisteredBrushesMultimap() { + public void testGetRegisteredBrushesMap() { IBrush brush = Mockito.mock(IBrush.class); brushes.registerSniperBrush(brush.getClass(), "mockhandle", "testhandle"); - Multimap, String> registeredBrushesMultimap = brushes.getRegisteredBrushesMultimap(); - Assert.assertTrue(registeredBrushesMultimap.containsKey(brush.getClass())); - Assert.assertFalse(registeredBrushesMultimap.containsKey(IBrush.class)); - Assert.assertTrue(registeredBrushesMultimap.containsEntry(brush.getClass(), "mockhandle")); - Assert.assertTrue(registeredBrushesMultimap.containsEntry(brush.getClass(), "testhandle")); - Assert.assertFalse(registeredBrushesMultimap.containsEntry(brush.getClass(), "notAnEntry")); + Map> registeredBrushesMap = brushes.getRegisteredBrushesMap(); + Assert.assertTrue(registeredBrushesMap.containsValue(brush.getClass())); + Assert.assertFalse(registeredBrushesMap.containsValue(IBrush.class)); + Assert.assertSame(registeredBrushesMap.get("mockhandle"), brush.getClass()); + Assert.assertSame(registeredBrushesMap.get("testhandle"), brush.getClass()); + Assert.assertNotSame(registeredBrushesMap.get("notAnEntry"), brush.getClass()); } @Test diff --git a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/SniperManagerTest.java b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/SniperManagerTest.java index b9571555..b3eabbbc 100644 --- a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/SniperManagerTest.java +++ b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/SniperManagerTest.java @@ -3,7 +3,6 @@ import com.github.kevindagame.VoxelProfileManager; import com.github.kevindagame.VoxelSniper; import com.github.kevindagame.snipe.Sniper; -import com.github.kevindagame.voxelsniper.IVoxelsniper; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; import com.github.kevindagame.voxelsniper.material.IMaterial; diff --git a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/UndoTest.java b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/UndoTest.java index bef0f86a..b4b9380b 100644 --- a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/UndoTest.java +++ b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/UndoTest.java @@ -4,7 +4,7 @@ import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.voxelsniper.block.IBlock; import com.github.kevindagame.voxelsniper.blockstate.IBlockState; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.world.IWorld; import org.junit.Assert; @@ -28,7 +28,7 @@ public void setUp() { undo = new Undo(); } - private IBlock mockBlock(VoxelLocation loc, VoxelMaterial t) { + private IBlock mockBlock(BaseLocation loc, VoxelMaterial t) { IBlock block = Mockito.mock(IBlock.class); IBlockState normalBlockState = Mockito.mock(IBlockState.class); Mockito.when(block.getLocation()) @@ -57,13 +57,13 @@ public void testUndoEmpty() { public void testGetSize() { IWorld world = Mockito.mock(IWorld.class); for (int i = 0; i < 5; i++) { - VoxelLocation location = new VoxelLocation(world, 0, 0, i); + BaseLocation location = new BaseLocation(world, 0, 0, i); IBlock block = mockBlock(location, VoxelMaterial.DIRT); undo.put(block); } Assert.assertEquals(5, undo.getSize()); - VoxelLocation location = new VoxelLocation(world, 0, 0, 8); + BaseLocation location = new BaseLocation(world, 0, 0, 8); IBlock block = mockBlock(location, VoxelMaterial.DIRT); undo.put(block); Assert.assertEquals(6, undo.getSize()); @@ -75,7 +75,7 @@ public void testGetSize() { @Test public void testPut() { IWorld world = Mockito.mock(IWorld.class); - VoxelLocation location = new VoxelLocation(world, 0, 0, 0); + BaseLocation location = new BaseLocation(world, 0, 0, 0); IBlock block = mockBlock(location, VoxelMaterial.DIRT); undo.put(block); @@ -86,15 +86,15 @@ public void testPut() { public void testUndo() { IWorld world = Mockito.mock(IWorld.class); - VoxelLocation normalBlockLocation = new VoxelLocation(world, 0, 0, 0); + BaseLocation normalBlockLocation = new BaseLocation(world, 0, 0, 0); IBlock normalBlock = mockBlock(normalBlockLocation, VoxelMaterial.STONE); IBlockState normalBlockState = normalBlock.getState(); - VoxelLocation fragileBlockLocation = new VoxelLocation(world, 0, 0, 1); + BaseLocation fragileBlockLocation = new BaseLocation(world, 0, 0, 1); IBlock fragileBlock = mockBlock(fragileBlockLocation, VoxelMaterial.TORCH); IBlockState fragileBlockState = fragileBlock.getState(); - VoxelLocation waterBlockLocation = new VoxelLocation(world, 0, 0, 2); + BaseLocation waterBlockLocation = new BaseLocation(world, 0, 0, 2); IBlock waterBlock = mockBlock(waterBlockLocation, VoxelMaterial.WATER); IBlockState waterBlockState = waterBlock.getState(); diff --git a/VoxelSniperSpigot/build.gradle.kts b/VoxelSniperSpigot/build.gradle.kts index c036ac06..6634c348 100644 --- a/VoxelSniperSpigot/build.gradle.kts +++ b/VoxelSniperSpigot/build.gradle.kts @@ -3,11 +3,22 @@ plugins { id("xyz.jpenilla.run-paper") version "1.0.6" } +repositories { + maven { url = uri("https://maven.enginehub.org/repo/") } + maven { url = uri("https://repo.papermc.io/repository/maven-public/") } +} dependencies { compileOnly("org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.5") // newest worldguard that supports 1.16.5 + compileOnly("com.plotsquared:PlotSquared-Core") + + implementation(platform("com.intellectualsites.bom:bom-1.18.x:1.20")) + implementation("org.bstats:bstats-bukkit:3.0.0") + implementation("net.kyori:adventure-platform-bukkit:4.2.0") + implementation(kotlin("stdlib-jdk8")) - implementation("net.kyori:adventure-platform-bukkit:4.1.1") + shadow("org.bstats:bstats-bukkit:3.0.0") testImplementation("org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT") } @@ -24,18 +35,15 @@ tasks { } } shadowJar { - + dependencies { +// include(dependency("org.bstats:bstats-bukkit")) + } + relocate("org.bstats", "com.github.kevindagame.voxelsniper.libs.org.bstats") } runServer { minecraftVersion("1.16.5") } } - -//tasks.register("run16") { -// dependsOn(tasks.shadowJar) -//// pluginJars(tasks.shadowJar.getArchiveFile()) -// minecraftVersion("1.16.5") -//} tasks.register("run17") { dependsOn(tasks.shadowJar) pluginJars(File("../output/voxelsniper-${version}-${platform}.jar")) @@ -49,5 +57,5 @@ tasks.register("run18") { tasks.register("run19") { dependsOn(tasks.shadowJar) pluginJars(File("../output/voxelsniper-${version}-${platform}.jar")) - minecraftVersion("1.19.2") + minecraftVersion("1.19.3") } \ No newline at end of file diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandHandler.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandHandler.java index 06ec743a..2c0cab42 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandHandler.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandHandler.java @@ -7,6 +7,7 @@ import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -19,7 +20,7 @@ public SpigotCommandHandler(VoxelCommand command) { } @Override - public final boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + public final boolean onCommand(@NotNull CommandSender sender, Command command, @NotNull String label, @NotNull String[] args) { this.command.setActiveIdentifier(command.getLabel()); // This is the root command. this.command.setActiveAlias(label); // This is the alias that was executed. @@ -32,7 +33,7 @@ public final boolean onCommand(CommandSender sender, Command command, String lab } @Override - public final List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + public final List onTabComplete(@NotNull CommandSender sender, Command command, @NotNull String alias, @NotNull String[] args) { this.command.setActiveIdentifier(command.getLabel()); // This is the root command. this.command.setActiveAlias(alias); // This is the alias that was executed. diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandManager.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandManager.java index 15b5e227..e7ce4c3c 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandManager.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotCommandManager.java @@ -27,9 +27,7 @@ public void registerCommand(VoxelCommand command) { SpigotCommandHandler executor = new SpigotCommandHandler(command); if (bukkitCommand != null) { bukkitCommand.setExecutor(executor); - bukkitCommand.getAliases().forEach(e -> { - argumentsMap.put(e, command.registerTabCompletion()); - }); + bukkitCommand.getAliases().forEach(e -> argumentsMap.put(e, command.registerTabCompletion())); } // Initializes command alternates that use the same executors @@ -39,9 +37,7 @@ public void registerCommand(VoxelCommand command) { if (bukkitCommandAlt != null) { bukkitCommandAlt.setExecutor(executor); - bukkitCommandAlt.getAliases().forEach(e -> { - argumentsMap.put(e, command.registerTabCompletion()); - }); + bukkitCommandAlt.getAliases().forEach(e -> argumentsMap.put(e, command.registerTabCompletion())); } }); } diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotVoxelSniper.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotVoxelSniper.java index bbfe67c0..cc6d3a2f 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotVoxelSniper.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/SpigotVoxelSniper.java @@ -4,21 +4,24 @@ import com.github.kevindagame.VoxelProfileManager; import com.github.kevindagame.VoxelSniper; import com.github.kevindagame.util.Messages; -import com.github.kevindagame.voxelsniper.bstats.BrushUsageCounter; -import com.github.kevindagame.voxelsniper.bstats.Metrics; -import com.github.kevindagame.voxelsniper.entity.player.SpigotPlayer; import com.github.kevindagame.voxelsniper.entity.player.IPlayer; -import com.github.kevindagame.voxelsniper.events.IEventManager; -import com.github.kevindagame.voxelsniper.events.bukkit.SpigotEventManager; -import com.github.kevindagame.voxelsniper.fileHandler.SpigotFileHandler; +import com.github.kevindagame.voxelsniper.entity.player.SpigotPlayer; import com.github.kevindagame.voxelsniper.fileHandler.IFileHandler; +import com.github.kevindagame.voxelsniper.fileHandler.SpigotFileHandler; import com.github.kevindagame.voxelsniper.fileHandler.VoxelSniperConfiguration; -import com.github.kevindagame.voxelsniper.material.SpigotMaterial; +import com.github.kevindagame.voxelsniper.integration.bstats.BrushUsageCounter; +import com.github.kevindagame.voxelsniper.integration.bstats.BrushUsersCounter; +import com.github.kevindagame.voxelsniper.integration.plotsquared.PlotSquaredIntegration; +import com.github.kevindagame.voxelsniper.integration.worldguard.WorldGuardIntegration; import com.github.kevindagame.voxelsniper.material.IMaterial; +import com.github.kevindagame.voxelsniper.material.SpigotMaterial; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; -import com.github.kevindagame.voxelsniper.world.SpigotWorld; import com.github.kevindagame.voxelsniper.world.IWorld; +import com.github.kevindagame.voxelsniper.world.SpigotWorld; import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import org.bstats.bukkit.Metrics; +import org.bstats.charts.SimplePie; +import org.bstats.charts.SingleLineChart; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; @@ -49,7 +52,6 @@ public class SpigotVoxelSniper extends JavaPlugin implements IVoxelsniper, Liste private final Map players = new HashMap<>(); private VoxelSniperConfiguration voxelSniperConfiguration; private IFileHandler fileHandler; - private IEventManager eventManager; /** * @return {@link SpigotVoxelSniper} @@ -66,30 +68,52 @@ public static BukkitAudiences getAdventure() { public void onEnable() { VoxelSniper.voxelsniper = this; SpigotVoxelSniper.instance = this; + this.fileHandler = new SpigotFileHandler(this); - this.eventManager = new SpigotEventManager(); + // Initialize profile manager (Sniper) VoxelProfileManager.initialize(); + // Initialize messages Messages.load(this); SpigotVoxelSniper.adventure = BukkitAudiences.create(this); + // Initialize brush manager VoxelBrushManager brushManager = VoxelBrushManager.initialize(); getLogger().log(Level.INFO, "Registered {0} Sniper Brushes with {1} handles.", new Object[]{brushManager.registeredSniperBrushes(), brushManager.registeredSniperBrushHandles()}); + // Initialize configuration saveDefaultConfig(); voxelSniperConfiguration = new VoxelSniperConfiguration(this); + //register events and listeners Bukkit.getPluginManager().registerEvents(this.voxelSniperListener, this); Bukkit.getPluginManager().registerEvents(this, this); getLogger().info("Registered Sniper Listener."); - Bukkit.getPluginManager().registerEvents(new BrushUsageCounter(), this); + + new BrushUsageCounter().registerListeners(); + new BrushUsersCounter().registerListeners(); // Initialize commands SpigotCommandManager.initialize(); + + // Initialize metrics Metrics metrics = new Metrics(this, 16602); - metrics.addCustomChart(new Metrics.SingleLineChart("total_brush_uses_in_last_30_minutes", BrushUsageCounter::getTotalBrushUses)); + + if (Bukkit.getPluginManager().isPluginEnabled("WorldGuard") && voxelSniperConfiguration.isWorldGuardIntegrationEnabled()) { + new WorldGuardIntegration(); + getLogger().info("WorldGuard integration enabled."); + } + if (Bukkit.getPluginManager().isPluginEnabled("PlotSquared") && voxelSniperConfiguration.isPlotSquaredIntegrationEnabled()) { + new PlotSquaredIntegration(); + getLogger().info("PlotSquared integration enabled."); + } + + metrics.addCustomChart(new SimplePie("worldguard_integration", () -> WorldGuardIntegration.Companion.getEnabled() ? "enabled" : "disabled")); + metrics.addCustomChart(new SimplePie("plotsquared_integration", () -> PlotSquaredIntegration.Companion.getEnabled() ? "enabled" : "disabled")); + metrics.addCustomChart(new SingleLineChart("total_brush_uses_in_last_30_minutes", BrushUsageCounter::getTotalBrushUses)); // metrics.addCustomChart(new Metrics.MultiLineChart("uses_per_brush", BrushUsageCounter::getUsagePerBrush)); + metrics.addCustomChart(new SingleLineChart("total_snipers", BrushUsersCounter.Companion::getTotalBrushUses)); } @Override @@ -173,11 +197,6 @@ public IFileHandler getFileHandler() { return fileHandler; } - @Override - public IEventManager getEventManager() { - return this.eventManager; - } - @NotNull public IWorld getWorld(@NotNull World world) { if (this.worlds.get(world.getName()) != null) return this.worlds.get(world.getName()); diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/block/SpigotBlock.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/block/SpigotBlock.java index f930354e..3b02cba9 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/block/SpigotBlock.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/block/SpigotBlock.java @@ -1,11 +1,11 @@ package com.github.kevindagame.voxelsniper.block; import com.github.kevindagame.voxelsniper.SpigotVoxelSniper; -import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; -import com.github.kevindagame.voxelsniper.blockstate.SpigotBlockState; +import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; import com.github.kevindagame.voxelsniper.blockstate.IBlockState; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.blockstate.SpigotBlockState; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.material.SpigotMaterial; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import org.bukkit.block.Block; @@ -16,7 +16,7 @@ public class SpigotBlock extends AbstractBlock { private final Block block; public SpigotBlock(Block block) { - super(new VoxelLocation(SpigotVoxelSniper.getInstance().getWorld(block.getWorld()), block.getX(), block.getY(), block.getZ()), SpigotMaterial.fromSpigotMaterial(block.getType())); + super(new BaseLocation(SpigotVoxelSniper.getInstance().getWorld(block.getWorld()), block.getX(), block.getY(), block.getZ()), SpigotMaterial.fromSpigotMaterial(block.getType())); this.block = block; } @@ -32,7 +32,6 @@ public void setMaterial(VoxelMaterial material, boolean applyPhysics) { block.setType(((SpigotMaterial) material.getIMaterial()).material(), applyPhysics); } - //todo test if this works @Override @Nullable public BlockFace getFace(IBlock block) { diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockdata/SpigotBlockData.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockdata/SpigotBlockData.java index 000885d5..2346ff04 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockdata/SpigotBlockData.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockdata/SpigotBlockData.java @@ -42,4 +42,9 @@ public String getAsString() { public IBlockData merge(IBlockData newData) { return new SpigotBlockData(this.blockData.merge(((SpigotBlockData) newData).getBlockData())); } + + @Override + public IBlockData getCopy() { + return new SpigotBlockData(blockData.clone()); + } } diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockstate/SpigotBlockState.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockstate/SpigotBlockState.java index ddb987ac..3590b3f4 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockstate/SpigotBlockState.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/blockstate/SpigotBlockState.java @@ -1,9 +1,9 @@ package com.github.kevindagame.voxelsniper.blockstate; -import com.github.kevindagame.voxelsniper.block.SpigotBlock; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; +import com.github.kevindagame.voxelsniper.block.SpigotBlock; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; import com.github.kevindagame.voxelsniper.blockstate.sign.SpigotSign; import com.github.kevindagame.voxelsniper.material.SpigotMaterial; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/bstats/BrushUsageCounter.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/bstats/BrushUsageCounter.java deleted file mode 100644 index b71cd927..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/bstats/BrushUsageCounter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.kevindagame.voxelsniper.bstats; - -import com.github.kevindagame.voxelsniper.events.bukkit.SniperSnipeEvent; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -public class BrushUsageCounter implements Listener { -// private static final Map perBrushCounter = new HashMap<>(); - private static int counter = 0; - - @EventHandler - private void onBrushUse(SniperSnipeEvent event) { - if(!event.isSuccessful()) return; -// String brushName = event.getBrush().getName(); -// perBrushCounter.put(brushName, perBrushCounter.getOrDefault(brushName, 0) + 1); - counter++; - } - - public static int getTotalBrushUses() { - var val = counter; - counter = 0; - return val; - } - -// public static Map getUsagePerBrush() { -// var map = new HashMap<>(perBrushCounter); -// perBrushCounter.clear(); -// return map; -// } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/bstats/Metrics.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/bstats/Metrics.java deleted file mode 100644 index 7f91cd4f..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/bstats/Metrics.java +++ /dev/null @@ -1,863 +0,0 @@ -/* - * This Metrics class was auto-generated and can be copied into your project if you are - * not using a build tool like Gradle or Maven for dependency management. - * - * IMPORTANT: You are not allowed to modify this class, except changing the package. - * - * Unallowed modifications include but are not limited to: - * - Remove the option for users to opt-out - * - Change the frequency for data submission - * - Obfuscate the code (every obfucator should allow you to make an exception for specific files) - * - Reformat the code (if you use a linter, add an exception) - * - * Violations will result in a ban of your plugin and account from bStats. - */ -package com.github.kevindagame.voxelsniper.bstats; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.stream.Collectors; -import java.util.zip.GZIPOutputStream; -import javax.net.ssl.HttpsURLConnection; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; - -public class Metrics { - - private final Plugin plugin; - - private final MetricsBase metricsBase; - - /** - * Creates a new Metrics instance. - * - * @param plugin Your plugin instance. - * @param serviceId The id of the service. It can be found at What is my plugin id? - */ - public Metrics(JavaPlugin plugin, int serviceId) { - this.plugin = plugin; - // Get the config file - File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - if (!config.isSet("serverUuid")) { - config.addDefault("enabled", true); - config.addDefault("serverUuid", UUID.randomUUID().toString()); - config.addDefault("logFailedRequests", false); - config.addDefault("logSentData", false); - config.addDefault("logResponseStatusText", false); - // Inform the server owners about bStats - config - .options() - .header( - "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" - + "many people use their plugin and their total player count. It's recommended to keep bStats\n" - + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" - + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" - + "anonymous.") - .copyDefaults(true); - try { - config.save(configFile); - } catch (IOException ignored) { - } - } - // Load the data - boolean enabled = config.getBoolean("enabled", true); - String serverUUID = config.getString("serverUuid"); - boolean logErrors = config.getBoolean("logFailedRequests", false); - boolean logSentData = config.getBoolean("logSentData", false); - boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); - metricsBase = - new MetricsBase( - "bukkit", - serverUUID, - serviceId, - enabled, - this::appendPlatformData, - this::appendServiceData, - submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), - plugin::isEnabled, - (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), - (message) -> this.plugin.getLogger().log(Level.INFO, message), - logErrors, - logSentData, - logResponseStatusText); - } - - /** - * Adds a custom chart. - * - * @param chart The chart to add. - */ - public void addCustomChart(CustomChart chart) { - metricsBase.addCustomChart(chart); - } - - private void appendPlatformData(JsonObjectBuilder builder) { - builder.appendField("playerAmount", getPlayerAmount()); - builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); - builder.appendField("bukkitVersion", Bukkit.getVersion()); - builder.appendField("bukkitName", Bukkit.getName()); - builder.appendField("javaVersion", System.getProperty("java.version")); - builder.appendField("osName", System.getProperty("os.name")); - builder.appendField("osArch", System.getProperty("os.arch")); - builder.appendField("osVersion", System.getProperty("os.version")); - builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); - } - - private void appendServiceData(JsonObjectBuilder builder) { - builder.appendField("pluginVersion", plugin.getDescription().getVersion()); - } - - private int getPlayerAmount() { - try { - // Around MC 1.8 the return type was changed from an array to a collection, - // This fixes java.lang.NoSuchMethodError: - // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); - return onlinePlayersMethod.getReturnType().equals(Collection.class) - ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() - : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; - } catch (Exception e) { - // Just use the new method if the reflection failed - return Bukkit.getOnlinePlayers().size(); - } - } - - public static class MetricsBase { - - /** The version of the Metrics class. */ - public static final String METRICS_VERSION = "3.0.0"; - - private static final ScheduledExecutorService scheduler = - Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics")); - - private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; - - private final String platform; - - private final String serverUuid; - - private final int serviceId; - - private final Consumer appendPlatformDataConsumer; - - private final Consumer appendServiceDataConsumer; - - private final Consumer submitTaskConsumer; - - private final Supplier checkServiceEnabledSupplier; - - private final BiConsumer errorLogger; - - private final Consumer infoLogger; - - private final boolean logErrors; - - private final boolean logSentData; - - private final boolean logResponseStatusText; - - private final Set customCharts = new HashSet<>(); - - private final boolean enabled; - - /** - * Creates a new MetricsBase class instance. - * - * @param platform The platform of the service. - * @param serviceId The id of the service. - * @param serverUuid The server uuid. - * @param enabled Whether or not data sending is enabled. - * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and - * appends all platform-specific data. - * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and - * appends all service-specific data. - * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be - * used to delegate the data collection to a another thread to prevent errors caused by - * concurrency. Can be {@code null}. - * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled. - * @param errorLogger A consumer that accepts log message and an error. - * @param infoLogger A consumer that accepts info log messages. - * @param logErrors Whether or not errors should be logged. - * @param logSentData Whether or not the sent data should be logged. - * @param logResponseStatusText Whether or not the response status text should be logged. - */ - public MetricsBase( - String platform, - String serverUuid, - int serviceId, - boolean enabled, - Consumer appendPlatformDataConsumer, - Consumer appendServiceDataConsumer, - Consumer submitTaskConsumer, - Supplier checkServiceEnabledSupplier, - BiConsumer errorLogger, - Consumer infoLogger, - boolean logErrors, - boolean logSentData, - boolean logResponseStatusText) { - this.platform = platform; - this.serverUuid = serverUuid; - this.serviceId = serviceId; - this.enabled = enabled; - this.appendPlatformDataConsumer = appendPlatformDataConsumer; - this.appendServiceDataConsumer = appendServiceDataConsumer; - this.submitTaskConsumer = submitTaskConsumer; - this.checkServiceEnabledSupplier = checkServiceEnabledSupplier; - this.errorLogger = errorLogger; - this.infoLogger = infoLogger; - this.logErrors = logErrors; - this.logSentData = logSentData; - this.logResponseStatusText = logResponseStatusText; - checkRelocation(); - if (enabled) { - // WARNING: Removing the option to opt-out will get your plugin banned from bStats - startSubmitting(); - } - } - - public void addCustomChart(CustomChart chart) { - this.customCharts.add(chart); - } - - private void startSubmitting() { - final Runnable submitTask = - () -> { - if (!enabled || !checkServiceEnabledSupplier.get()) { - // Submitting data or service is disabled - scheduler.shutdown(); - return; - } - if (submitTaskConsumer != null) { - submitTaskConsumer.accept(this::submitData); - } else { - this.submitData(); - } - }; - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution - // of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial - // and second delay. - // WARNING: You must not modify and part of this Metrics class, including the submit delay or - // frequency! - // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! - long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); - long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); - scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); - scheduler.scheduleAtFixedRate( - submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); - } - - private void submitData() { - final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); - appendPlatformDataConsumer.accept(baseJsonBuilder); - final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); - appendServiceDataConsumer.accept(serviceJsonBuilder); - JsonObjectBuilder.JsonObject[] chartData = - customCharts.stream() - .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) - .filter(Objects::nonNull) - .toArray(JsonObjectBuilder.JsonObject[]::new); - serviceJsonBuilder.appendField("id", serviceId); - serviceJsonBuilder.appendField("customCharts", chartData); - baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); - baseJsonBuilder.appendField("serverUUID", serverUuid); - baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); - JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); - scheduler.execute( - () -> { - try { - // Send the data - sendData(data); - } catch (Exception e) { - // Something went wrong! :( - if (logErrors) { - errorLogger.accept("Could not submit bStats metrics data", e); - } - } - }); - } - - private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { - if (logSentData) { - infoLogger.accept("Sent bStats metrics data: " + data.toString()); - } - String url = String.format(REPORT_URL, platform); - HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setRequestProperty("User-Agent", "Metrics-Service/1"); - connection.setDoOutput(true); - try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { - outputStream.write(compressedData); - } - StringBuilder builder = new StringBuilder(); - try (BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(connection.getInputStream()))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - builder.append(line); - } - } - if (logResponseStatusText) { - infoLogger.accept("Sent data to bStats and received response: " + builder); - } - } - - /** Checks that the class was properly relocated. */ - private void checkRelocation() { - // You can use the property to disable the check in your test environment - if (System.getProperty("bstats.relocatecheck") == null - || !System.getProperty("bstats.relocatecheck").equals("false")) { - // Maven's Relocate is clever and changes strings, too. So we have to use this little - // "trick" ... :D - final String defaultPackage = - new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'}); - final String examplePackage = - new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); - // We want to make sure no one just copy & pastes the example and uses the wrong package - // names - if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) - || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { - throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); - } - } - } - - /** - * Gzips the given string. - * - * @param str The string to gzip. - * @return The gzipped string. - */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { - gzip.write(str.getBytes(StandardCharsets.UTF_8)); - } - return outputStream.toByteArray(); - } - } - - public static class DrilldownPie extends CustomChart { - - private final Callable>> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public DrilldownPie(String chartId, Callable>> callable) { - super(chartId); - this.callable = callable; - } - - @Override - public JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map> map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean reallyAllSkipped = true; - for (Map.Entry> entryValues : map.entrySet()) { - JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); - boolean allSkipped = true; - for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { - valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); - allSkipped = false; - } - if (!allSkipped) { - reallyAllSkipped = false; - valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); - } - } - if (reallyAllSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class AdvancedPie extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedPie(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class MultiLineChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public MultiLineChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class SimpleBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimpleBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - for (Map.Entry entry : map.entrySet()) { - valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()}); - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public abstract static class CustomChart { - - private final String chartId; - - protected CustomChart(String chartId) { - if (chartId == null) { - throw new IllegalArgumentException("chartId must not be null"); - } - this.chartId = chartId; - } - - public JsonObjectBuilder.JsonObject getRequestJsonObject( - BiConsumer errorLogger, boolean logErrors) { - JsonObjectBuilder builder = new JsonObjectBuilder(); - builder.appendField("chartId", chartId); - try { - JsonObjectBuilder.JsonObject data = getChartData(); - if (data == null) { - // If the data is null we don't send the chart. - return null; - } - builder.appendField("data", data); - } catch (Throwable t) { - if (logErrors) { - errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); - } - return null; - } - return builder.build(); - } - - protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception; - } - - public static class SimplePie extends CustomChart { - - private final Callable callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimplePie(String chartId, Callable callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - String value = callable.call(); - if (value == null || value.isEmpty()) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("value", value).build(); - } - } - - public static class AdvancedBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue().length == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class SingleLineChart extends CustomChart { - - private final Callable callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SingleLineChart(String chartId, Callable callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - int value = callable.call(); - if (value == 0) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("value", value).build(); - } - } - - /** - * An extremely simple JSON builder. - * - *

While this class is neither feature-rich nor the most performant one, it's sufficient enough - * for its use-case. - */ - public static class JsonObjectBuilder { - - private StringBuilder builder = new StringBuilder(); - - private boolean hasAtLeastOneField = false; - - public JsonObjectBuilder() { - builder.append("{"); - } - - /** - * Appends a null field to the JSON. - * - * @param key The key of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendNull(String key) { - appendFieldUnescaped(key, "null"); - return this; - } - - /** - * Appends a string field to the JSON. - * - * @param key The key of the field. - * @param value The value of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, String value) { - if (value == null) { - throw new IllegalArgumentException("JSON value must not be null"); - } - appendFieldUnescaped(key, "\"" + escape(value) + "\""); - return this; - } - - /** - * Appends an integer field to the JSON. - * - * @param key The key of the field. - * @param value The value of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, int value) { - appendFieldUnescaped(key, String.valueOf(value)); - return this; - } - - /** - * Appends an object to the JSON. - * - * @param key The key of the field. - * @param object The object. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, JsonObject object) { - if (object == null) { - throw new IllegalArgumentException("JSON object must not be null"); - } - appendFieldUnescaped(key, object.toString()); - return this; - } - - /** - * Appends a string array to the JSON. - * - * @param key The key of the field. - * @param values The string array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, String[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values) - .map(value -> "\"" + escape(value) + "\"") - .collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends an integer array to the JSON. - * - * @param key The key of the field. - * @param values The integer array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, int[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends an object array to the JSON. - * - * @param key The key of the field. - * @param values The integer array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, JsonObject[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends a field to the object. - * - * @param key The key of the field. - * @param escapedValue The escaped value of the field. - */ - private void appendFieldUnescaped(String key, String escapedValue) { - if (builder == null) { - throw new IllegalStateException("JSON has already been built"); - } - if (key == null) { - throw new IllegalArgumentException("JSON key must not be null"); - } - if (hasAtLeastOneField) { - builder.append(","); - } - builder.append("\"").append(escape(key)).append("\":").append(escapedValue); - hasAtLeastOneField = true; - } - - /** - * Builds the JSON string and invalidates this builder. - * - * @return The built JSON string. - */ - public JsonObject build() { - if (builder == null) { - throw new IllegalStateException("JSON has already been built"); - } - JsonObject object = new JsonObject(builder.append("}").toString()); - builder = null; - return object; - } - - /** - * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt. - * - *

This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'. - * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n"). - * - * @param value The value to escape. - * @return The escaped value. - */ - private static String escape(String value) { - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (c == '"') { - builder.append("\\\""); - } else if (c == '\\') { - builder.append("\\\\"); - } else if (c <= '\u000F') { - builder.append("\\u000").append(Integer.toHexString(c)); - } else if (c <= '\u001F') { - builder.append("\\u00").append(Integer.toHexString(c)); - } else { - builder.append(c); - } - } - return builder.toString(); - } - - /** - * A super simple representation of a JSON object. - * - *

This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not - * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String, - * JsonObject)}. - */ - public static class JsonObject { - - private final String value; - - private JsonObject(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } - } - } -} \ No newline at end of file diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/chunk/SpigotChunk.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/chunk/SpigotChunk.java index 6f00c644..dad7c06d 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/chunk/SpigotChunk.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/chunk/SpigotChunk.java @@ -1,10 +1,9 @@ package com.github.kevindagame.voxelsniper.chunk; import com.github.kevindagame.voxelsniper.SpigotVoxelSniper; -import com.github.kevindagame.voxelsniper.entity.SpigotEntity; import com.github.kevindagame.voxelsniper.entity.IEntity; +import com.github.kevindagame.voxelsniper.entity.SpigotEntity; import com.github.kevindagame.voxelsniper.world.IWorld; - import org.bukkit.Chunk; import java.util.Arrays; diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/SpigotEntity.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/SpigotEntity.java index 3b4b7964..50423f4b 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/SpigotEntity.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/SpigotEntity.java @@ -1,9 +1,9 @@ package com.github.kevindagame.voxelsniper.entity; import com.github.kevindagame.voxelsniper.SpigotVoxelSniper; -import com.github.kevindagame.voxelsniper.entity.Painting.SpigotPainting; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; +import com.github.kevindagame.voxelsniper.entity.painting.SpigotPainting; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.world.IWorld; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -48,9 +48,9 @@ public int getEntityId() { } @Override - public VoxelLocation getLocation() { + public BaseLocation getLocation() { Location loc = entity.getLocation(); - return new VoxelLocation(getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); + return new BaseLocation(getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); } @Override @@ -70,14 +70,14 @@ public List getPassengers() { @Override public boolean teleport(IEntity other) { - return this.entity.teleport(((SpigotEntity)other).getEntity()); + return this.entity.teleport(((SpigotEntity) other).getEntity()); } @Override - public VoxelLocation getEyeLocation() { + public BaseLocation getEyeLocation() { if (entity instanceof LivingEntity living) { Location loc = living.getEyeLocation(); - return new VoxelLocation(getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); + return new BaseLocation(getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); } return this.getLocation(); } diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/Painting/SpigotPainting.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/painting/SpigotPainting.java similarity index 92% rename from VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/Painting/SpigotPainting.java rename to VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/painting/SpigotPainting.java index 3e04601c..93da453f 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/Painting/SpigotPainting.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/painting/SpigotPainting.java @@ -1,4 +1,4 @@ -package com.github.kevindagame.voxelsniper.entity.Painting; +package com.github.kevindagame.voxelsniper.entity.painting; import com.github.kevindagame.voxelsniper.entity.SpigotEntity; import org.bukkit.Art; diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/player/SpigotPlayer.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/player/SpigotPlayer.java index 951b10c6..f04d5623 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/player/SpigotPlayer.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/entity/player/SpigotPlayer.java @@ -1,13 +1,13 @@ package com.github.kevindagame.voxelsniper.entity.player; import com.github.kevindagame.voxelsniper.SpigotVoxelSniper; -import com.github.kevindagame.voxelsniper.block.SpigotBlock; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.entity.SpigotEntity; +import com.github.kevindagame.voxelsniper.block.SpigotBlock; import com.github.kevindagame.voxelsniper.entity.IEntity; +import com.github.kevindagame.voxelsniper.entity.SpigotEntity; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.location.SpigotLocation; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; import com.github.kevindagame.voxelsniper.material.SpigotMaterial; import com.github.kevindagame.voxelsniper.material.VoxelMaterial; import com.github.kevindagame.voxelsniper.vector.VoxelVector; @@ -62,7 +62,7 @@ public String getName() { } @Override - public void teleport(VoxelLocation location) { + public void teleport(BaseLocation location) { player.teleport(SpigotLocation.toSpigotLocation(location)); } diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperBrushChangedEvent.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperBrushChangedEvent.java deleted file mode 100644 index 87441357..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperBrushChangedEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.github.kevindagame.voxelsniper.events.bukkit; - -import com.github.kevindagame.brush.IBrush; -import com.github.kevindagame.snipe.Sniper; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * - */ -public class SniperBrushChangedEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - private final Sniper sniper; - private final IBrush originalBrush; - private final IBrush newBrush; - private final String toolId; - - public SniperBrushChangedEvent(Sniper sniper, String toolId, IBrush originalBrush, IBrush newBrush) { - this.sniper = sniper; - this.originalBrush = originalBrush; - this.newBrush = newBrush; - this.toolId = toolId; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - public IBrush getOriginalBrush() { - return originalBrush; - } - - public IBrush getNewBrush() { - return newBrush; - } - - public Sniper getSniper() { - return sniper; - } - - public String getToolId() { - return toolId; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperBrushSizeChangedEvent.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperBrushSizeChangedEvent.java deleted file mode 100644 index 96fbc134..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperBrushSizeChangedEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.github.kevindagame.voxelsniper.events.bukkit; - -import com.github.kevindagame.snipe.Sniper; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * - */ -public class SniperBrushSizeChangedEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - private final Sniper sniper; - private final int originalSize; - private final int newSize; - private final String toolId; - - public SniperBrushSizeChangedEvent(Sniper sniper, String toolId, int originalSize, int newSize) { - this.sniper = sniper; - this.originalSize = originalSize; - this.newSize = newSize; - this.toolId = toolId; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - public int getOriginalSize() { - return originalSize; - } - - public int getNewSize() { - return newSize; - } - - public Sniper getSniper() { - return sniper; - } - - public String getToolId() { - return toolId; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperMaterialChangedEvent.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperMaterialChangedEvent.java deleted file mode 100644 index c9b8493b..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperMaterialChangedEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.github.kevindagame.voxelsniper.events.bukkit; - -import com.github.kevindagame.snipe.Sniper; -import com.github.kevindagame.voxelsniper.blockdata.IBlockData; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * - */ -public class SniperMaterialChangedEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - private final Sniper sniper; - private final IBlockData originalMaterial; - private final IBlockData newMaterial; - private final String toolId; - - public SniperMaterialChangedEvent(Sniper sniper, String toolId, IBlockData originalMaterial, IBlockData newMaterial) { - this.sniper = sniper; - this.originalMaterial = originalMaterial; - this.newMaterial = newMaterial; - this.toolId = toolId; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - public IBlockData getOriginalMaterial() { - return originalMaterial; - } - - public IBlockData getNewMaterial() { - return newMaterial; - } - - public Sniper getSniper() { - return sniper; - } - - public String getToolId() { - return toolId; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperReplaceMaterialChangedEvent.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperReplaceMaterialChangedEvent.java deleted file mode 100644 index 944599e9..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperReplaceMaterialChangedEvent.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.kevindagame.voxelsniper.events.bukkit; - -import com.github.kevindagame.snipe.Sniper; -import com.github.kevindagame.voxelsniper.blockdata.IBlockData; -import org.bukkit.event.HandlerList; - -/** - * - */ -public class SniperReplaceMaterialChangedEvent extends SniperMaterialChangedEvent { - - private static final HandlerList handlers = new HandlerList(); - - public SniperReplaceMaterialChangedEvent(Sniper sniper, String toolId, IBlockData originalMaterial, IBlockData newMaterial) { - super(sniper, toolId, originalMaterial, newMaterial); - } - - public static HandlerList getHandlerList() { - return handlers; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperSnipeEvent.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperSnipeEvent.java deleted file mode 100644 index 73d933b0..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SniperSnipeEvent.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.github.kevindagame.voxelsniper.events.bukkit; - -import com.github.kevindagame.brush.IBrush; -import com.github.kevindagame.snipe.Sniper; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.jetbrains.annotations.NotNull; - -public class SniperSnipeEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - private final Sniper sniper; - private final IBrush brush; - - private final boolean success; - public SniperSnipeEvent(Sniper sniper, IBrush brush, boolean success) { - this.sniper = sniper; - this.brush = brush; - this.success = success; - } - - public Sniper getSniper() { - return sniper; - } - - public IBrush getBrush() { - return brush; - } - - public boolean isSuccessful() { - return success; - } - - @NotNull - @Override - public HandlerList getHandlers() { - return handlers; - } - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SpigotEventManager.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SpigotEventManager.java deleted file mode 100644 index b42e9577..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/events/bukkit/SpigotEventManager.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.github.kevindagame.voxelsniper.events.bukkit; - -import com.github.kevindagame.brush.IBrush; -import com.github.kevindagame.snipe.Sniper; -import com.github.kevindagame.voxelsniper.blockdata.IBlockData; -import com.github.kevindagame.voxelsniper.events.IEventManager; -import org.bukkit.Bukkit; - -public class SpigotEventManager implements IEventManager { - - @Override - public void callSniperReplaceMaterialChangedEvent(Sniper sniper, String toolId, IBlockData oldSubstance, IBlockData newSubstance) { - Bukkit.getPluginManager().callEvent(new SniperReplaceMaterialChangedEvent(sniper, toolId, oldSubstance, newSubstance)); - } - - @Override - public void callSniperMaterialChangedEvent(Sniper sniper, String toolId, IBlockData oldSubstance, IBlockData newSubstance) { - Bukkit.getPluginManager().callEvent(new SniperMaterialChangedEvent(sniper, toolId, oldSubstance, newSubstance)); - } - - @Override - public void callSniperBrushChangedEvent(Sniper owner, String currentToolId, IBrush originalBrush, IBrush newBrush) { - SniperBrushChangedEvent event = new SniperBrushChangedEvent(owner, currentToolId, originalBrush, newBrush); - Bukkit.getPluginManager().callEvent(event); - } - - @Override - public void callSniperBrushSizeChangedEvent(Sniper sniper, String currentToolId, int originalSize, int newSize) { - SniperBrushSizeChangedEvent event = new SniperBrushSizeChangedEvent(sniper, currentToolId, originalSize, newSize); - Bukkit.getPluginManager().callEvent(event); - } - @Override - public void callSniperSnipeEvent(Sniper owner, IBrush brush, boolean success) { - SniperSnipeEvent event = new SniperSnipeEvent(owner, brush, success); - Bukkit.getPluginManager().callEvent(event); - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/bstats/BrushUsageCounter.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/bstats/BrushUsageCounter.java new file mode 100644 index 00000000..d48736f8 --- /dev/null +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/bstats/BrushUsageCounter.java @@ -0,0 +1,22 @@ +package com.github.kevindagame.voxelsniper.integration.bstats; + +import com.github.kevindagame.voxelsniper.events.player.PlayerSnipeEvent; + +public class BrushUsageCounter { + private static int counter = 0; + + public static int getTotalBrushUses() { + var val = counter; + counter = 0; + return val; + } + + public void registerListeners() { + PlayerSnipeEvent.registerListener(this::onBrushUse); + } + + private void onBrushUse(PlayerSnipeEvent event) { + if (event.isCancelled()) return; + counter++; + } +} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/bstats/BrushUsersCounter.kt b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/bstats/BrushUsersCounter.kt new file mode 100644 index 00000000..764373aa --- /dev/null +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/bstats/BrushUsersCounter.kt @@ -0,0 +1,24 @@ +package com.github.kevindagame.voxelsniper.integration.bstats + +import com.github.kevindagame.voxelsniper.events.player.PlayerSnipeEvent +import java.util.* + +class BrushUsersCounter { + fun registerListeners() { + PlayerSnipeEvent.registerListener(this::onBrushUse) + } + + private fun onBrushUse(event: PlayerSnipeEvent) { + if (event.isCancelled) return + users.add(event.player.uniqueId) + } + + companion object { + private val users: MutableSet = HashSet() + fun getTotalBrushUses(): Int { + val brushUsers = users.size + users.clear() + return brushUsers + } + } +} \ No newline at end of file diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/plotsquared/PlotSquaredIntegration.kt b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/plotsquared/PlotSquaredIntegration.kt new file mode 100644 index 00000000..f9ff90de --- /dev/null +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/plotsquared/PlotSquaredIntegration.kt @@ -0,0 +1,47 @@ +package com.github.kevindagame.voxelsniper.integration.plotsquared + +import com.github.kevindagame.voxelsniper.events.player.PlayerSnipeEvent +import com.github.kevindagame.voxelsniper.world.SpigotWorld +import com.plotsquared.core.PlotAPI +import com.plotsquared.core.database.DBFunc +import com.plotsquared.core.location.Location +import com.plotsquared.core.plot.Plot + +class PlotSquaredIntegration { + + init { + enabled = true + PlayerSnipeEvent.registerListener(this::handleEvent) + } + + private fun handleEvent(event: PlayerSnipeEvent) { + if (event.isCancelled) return + val world = (event.player.world as SpigotWorld).world + val plotAPI = PlotAPI() + + // if there are no plots in the world, don't do anything + if (plotAPI.getPlotAreas(world.name).isEmpty()) return + if (event.player.hasPermission("voxelsniper.bypass.plotsquared")) return + for (operation in event.operations) { + if (operation.isCancelled) continue + val loc = operation.location + + //get plot for location + + val plot = Plot.getPlot(Location.at(world.name, loc.blockX, loc.blockY, loc.blockZ)) + if (plot != null) { + if (plot.isOwner(event.player.uniqueId) || plot.trusted.contains(event.player.uniqueId) || plot.trusted.contains( + DBFunc.EVERYONE + ) + ) { + continue + } + } + operation.isCancelled = true + } + } + + companion object { + var enabled: Boolean = false + } +} \ No newline at end of file diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/worldguard/WorldGuardIntegration.kt b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/worldguard/WorldGuardIntegration.kt new file mode 100644 index 00000000..2f5efe7f --- /dev/null +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/integration/worldguard/WorldGuardIntegration.kt @@ -0,0 +1,43 @@ +package com.github.kevindagame.voxelsniper.integration.worldguard + +import com.github.kevindagame.voxelsniper.entity.player.SpigotPlayer +import com.github.kevindagame.voxelsniper.events.player.PlayerSnipeEvent +import com.sk89q.worldedit.util.Location +import com.sk89q.worldguard.WorldGuard +import com.sk89q.worldguard.bukkit.WorldGuardPlugin +import com.sk89q.worldguard.protection.flags.Flags + + +class WorldGuardIntegration { + init { + enabled = true + PlayerSnipeEvent.registerListener(this::handleEvent) + } + + private fun handleEvent(event: PlayerSnipeEvent) { + if (event.isCancelled) return + if (event.player.hasPermission("voxelsniper.bypass.worldguard")) return + //Check if each operation is within the worldguard area + val instance = WorldGuard.getInstance() + val localPlayer = WorldGuardPlugin.inst().wrapPlayer((event.player as SpigotPlayer).player) + val world = localPlayer.world + val container = instance.platform.regionContainer + val query = container.createQuery() + + if (instance.platform.sessionManager.hasBypass(localPlayer, world)) return + + for (operation in event.operations) { + if (operation.isCancelled) continue + val loc = operation.location + val location = Location(world, loc.x, loc.y, loc.z) + + if (!query.testState(location, localPlayer, Flags.BUILD)) { + operation.isCancelled = true + } + } + } + + companion object { + var enabled: Boolean = false + } +} \ No newline at end of file diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/location/SpigotLocation.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/location/SpigotLocation.java index 2b90adf7..5398da08 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/location/SpigotLocation.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/location/SpigotLocation.java @@ -4,7 +4,7 @@ import org.bukkit.Location; public final class SpigotLocation { - public static Location toSpigotLocation(VoxelLocation location) { + public static Location toSpigotLocation(BaseLocation location) { return new Location(((SpigotWorld) location.getWorld()).world(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); } } diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/material/SpigotMaterial.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/material/SpigotMaterial.java index b6df38b3..0a92e738 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/material/SpigotMaterial.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/material/SpigotMaterial.java @@ -1,7 +1,7 @@ package com.github.kevindagame.voxelsniper.material; -import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; import com.github.kevindagame.voxelsniper.blockdata.IBlockData; +import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; import org.bukkit.Material; public record SpigotMaterial(Material material) implements IMaterial { diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotBlockLogger.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotBlockLogger.java new file mode 100644 index 00000000..3327b2e4 --- /dev/null +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotBlockLogger.java @@ -0,0 +1,67 @@ +package com.github.kevindagame.voxelsniper.world; + +import com.github.kevindagame.util.brushOperation.BlockOperation; +import com.github.kevindagame.util.brushOperation.BlockStateOperation; +import com.github.kevindagame.util.brushOperation.BrushOperation; +import com.github.kevindagame.voxelsniper.blockdata.SpigotBlockData; +import com.github.kevindagame.voxelsniper.blockstate.SpigotBlockState; +import com.github.kevindagame.voxelsniper.location.BaseLocation; +import org.bukkit.BlockChangeDelegate; +import org.bukkit.World; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.BlockData; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +/** + * + */ +public class SpigotBlockLogger implements BlockChangeDelegate, Predicate { + + final List operations = new ArrayList<>(); + final boolean updateBlocks; + private final IWorld world; + private final World targetWorld; + + public SpigotBlockLogger(SpigotWorld targetWorld, boolean updateBlocks) { + this.world = targetWorld; + this.targetWorld = targetWorld.world(); + this.updateBlocks = updateBlocks; + } + + @Override + public boolean setBlockData(int x, int y, int z, @NotNull BlockData blockData) { + var oldData = SpigotBlockData.fromSpigotData(getBlockData(x, y, z)); + operations.add(new BlockOperation(new BaseLocation(this.world, x, y, z), oldData, SpigotBlockData.fromSpigotData(blockData))); + if (updateBlocks) + this.targetWorld.getBlockAt(x, y, z).setBlockData(blockData, false); + return true; + } + + @NotNull + @Override + public BlockData getBlockData(int x, int y, int z) { + return this.targetWorld.getBlockAt(x, y, z).getBlockData(); + } + + @Override + public int getHeight() { + return this.targetWorld.getMaxHeight(); + } + + @Override + public boolean isEmpty(int x, int y, int z) { + return this.targetWorld.getBlockAt(x, y, z).isEmpty(); + } + + @Override + public boolean test(BlockState blockState) { + var oldState = SpigotBlockState.fromSpigotState(blockState.getBlock().getState()); + var newState = SpigotBlockState.fromSpigotState(blockState); + operations.add(new BlockStateOperation(new BaseLocation(this.world, blockState.getX(), blockState.getY(), blockState.getZ()), oldState, newState, true, true)); + return this.updateBlocks; + } +} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotUndoDelegate.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotUndoDelegate.java deleted file mode 100644 index a5e85e59..00000000 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotUndoDelegate.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.github.kevindagame.voxelsniper.world; - -import com.github.kevindagame.snipe.Undo; -import com.github.kevindagame.voxelsniper.blockstate.SpigotBlockState; -import org.bukkit.BlockChangeDelegate; -import org.bukkit.World; -import org.bukkit.block.data.BlockData; -import org.jetbrains.annotations.NotNull; - -/** - * - */ -public class SpigotUndoDelegate implements BlockChangeDelegate { - - private final World targetWorld; - private final Undo currentUndo; - - public SpigotUndoDelegate(World targetWorld, Undo undo) { - this.targetWorld = targetWorld; - this.currentUndo = undo; - } - - @Override - public boolean setBlockData(int x, int y, int z, @NotNull BlockData blockData) { - this.currentUndo.put(SpigotBlockState.fromSpigotState(targetWorld.getBlockAt(x, y, z).getState())); - this.targetWorld.getBlockAt(x, y, z).setBlockData(blockData, false); - return true; - } - - @NotNull - @Override - public BlockData getBlockData(int x, int y, int z) { - return this.targetWorld.getBlockAt(x, y, z).getBlockData(); - } - - @Override - public int getHeight() { - return this.targetWorld.getMaxHeight(); - } - - @Override - public boolean isEmpty(int x, int y, int z) { - return this.targetWorld.getBlockAt(x, y, z).isEmpty(); - } -} diff --git a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotWorld.java b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotWorld.java index eaf587e5..1bffd95b 100644 --- a/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotWorld.java +++ b/VoxelSniperSpigot/src/main/java/com/github/kevindagame/voxelsniper/world/SpigotWorld.java @@ -1,16 +1,16 @@ package com.github.kevindagame.voxelsniper.world; -import com.github.kevindagame.snipe.Undo; +import com.github.kevindagame.util.brushOperation.BrushOperation; import com.github.kevindagame.voxelsniper.biome.VoxelBiome; -import com.github.kevindagame.voxelsniper.block.SpigotBlock; import com.github.kevindagame.voxelsniper.block.IBlock; -import com.github.kevindagame.voxelsniper.chunk.SpigotChunk; +import com.github.kevindagame.voxelsniper.block.SpigotBlock; import com.github.kevindagame.voxelsniper.chunk.IChunk; -import com.github.kevindagame.voxelsniper.entity.SpigotEntity; +import com.github.kevindagame.voxelsniper.chunk.SpigotChunk; import com.github.kevindagame.voxelsniper.entity.IEntity; +import com.github.kevindagame.voxelsniper.entity.SpigotEntity; import com.github.kevindagame.voxelsniper.entity.entitytype.VoxelEntityType; +import com.github.kevindagame.voxelsniper.location.BaseLocation; import com.github.kevindagame.voxelsniper.location.SpigotLocation; -import com.github.kevindagame.voxelsniper.location.VoxelLocation; import com.github.kevindagame.voxelsniper.treeType.VoxelTreeType; import com.github.kevindagame.voxelsniper.vector.VoxelVector; import org.bukkit.TreeType; @@ -23,11 +23,13 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Random; public record SpigotWorld(World world) implements IWorld { + private static final Random RANDOM = new Random(); @Override - public IBlock getBlock(VoxelLocation location) { + public IBlock getBlock(BaseLocation location) { return new SpigotBlock(world.getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ())); } @@ -52,7 +54,7 @@ public IChunk getChunkAtLocation(int x, int z) { } @Override - public List getNearbyEntities(VoxelLocation location, double x, double y, double z) { + public List getNearbyEntities(BaseLocation location, double x, double y, double z) { return this.world.getNearbyEntities(SpigotLocation.toSpigotLocation(location), x, y, z).stream().map(SpigotEntity::fromSpigotEntity).toList(); } @@ -62,7 +64,7 @@ public void refreshChunk(int x, int z) { } @Override - public void strikeLightning(VoxelLocation location) { + public void strikeLightning(BaseLocation location) { world.strikeLightning(SpigotLocation.toSpigotLocation(location)); } @@ -72,7 +74,7 @@ public String getName() { } @Override - public void spawn(VoxelLocation location, VoxelEntityType entity) { + public void spawn(BaseLocation location, VoxelEntityType entity) { world.spawnEntity(SpigotLocation.toSpigotLocation(location), EntityType.valueOf(entity.getKey().toUpperCase(Locale.ROOT))); } @@ -81,6 +83,7 @@ public void spawn(VoxelLocation location, VoxelEntityType entity) { public void setBiome(int x, int z, VoxelBiome selectedBiome) { world.setBiome(x, z, Biome.valueOf(selectedBiome.key().toUpperCase())); } + @Override public void setBiome(int x, int y, int z, VoxelBiome selectedBiome) { world.setBiome(x, y, z, Biome.valueOf(selectedBiome.key().toUpperCase())); @@ -98,12 +101,21 @@ public void regenerateChunk(int x, int z) { } @Override - public void generateTree(VoxelLocation location, VoxelTreeType treeType, Undo undo) { + public List generateTree(BaseLocation location, VoxelTreeType treeType, boolean updateBlocks) { if (treeType.isSupported()) { - SpigotUndoDelegate undoDelegate = new SpigotUndoDelegate(world, undo); TreeType bukkitType = TreeType.valueOf(treeType.name()); - world.generateTree(SpigotLocation.toSpigotLocation(location), bukkitType, undoDelegate); + var loc = SpigotLocation.toSpigotLocation(location); + SpigotBlockLogger logger = new SpigotBlockLogger(this, updateBlocks); + try { + // This is a better implementation that handles tile entities (bee nests) better, but is not supported below MC 1.18 + this.world.generateTree(loc, RANDOM, bukkitType, logger); + } catch (Exception e) { + // fallback implementation in case the above implementation is unavailable + this.world.generateTree(loc, bukkitType, logger); + } + return logger.operations; } + return null; } @Override @@ -121,4 +133,9 @@ public IBlock next() { } }; } + + @Override + public VoxelBiome getBiome(BaseLocation location) { + return VoxelBiome.getBiome(world.getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ()).getKey().getKey()); + } } diff --git a/VoxelSniperSpigot/src/main/resources/plugin.yml b/VoxelSniperSpigot/src/main/resources/plugin.yml index 430ce352..2267b4aa 100644 --- a/VoxelSniperSpigot/src/main/resources/plugin.yml +++ b/VoxelSniperSpigot/src/main/resources/plugin.yml @@ -3,34 +3,34 @@ main: com.github.kevindagame.voxelsniper.SpigotVoxelSniper version: ${version} api-version: 1.15 website: https://github.com/KevinDaGame/VoxelSniper-Reimagined -authors: [przerwap, MikeMatrix, Gavjenks, giltwist, psanker, Deamon5550, DivineRage, KevDaDev, Lennart99] +authors: [ przerwap, MikeMatrix, Gavjenks, giltwist, psanker, Deamon5550, DivineRage, KevDaDev, Lennart99 ] description: The premier long-distance brush editor for Minecraft, reimagined! -softdepend: [VoxelModPackPlugin] +softdepend: [ WorldGuard, PlotSquared ] commands: u: description: Undo changes made by yourself or other players. permission: voxelsniper.sniper - aliases: [undo] + aliases: [ undo ] usage: Invalid syntax. Use / help to see valid syntax. uu: description: Undo changes made by other players. permission: voxelsniper.sniper - aliases: [undouser] + aliases: [ undouser ] usage: Invalid syntax. Use / help to see valid syntax. d: description: Reverts all values back to defaults. permission: voxelsniper.sniper - alias: [default] + alias: [ default ] usage: Invalid syntax. Use / help to see valid syntax. p: description: Change the currently active performer for the performer brush. permission: voxelsniper.sniper - aliases: [perf, performer] + aliases: [ perf, performer ] usage: Invalid syntax. Use / help to see valid syntax. sniper: description: View and change settings related to VoxelSniper. permission: voxelsniper.sniper - aliases: [voxelsniper, vs] + aliases: [ voxelsniper, vs ] usage: Invalid syntax. Use / help to see valid syntax. vi: description: Changes the data value of the currently active voxel material. @@ -59,17 +59,24 @@ commands: vox: description: Multi-purpose command to perform various utility functions. permission: voxelsniper.sniper - aliases: [painting, vchunk, goto] + aliases: [ painting, vchunk, goto ] usage: Invalid syntax. Use / help to see valid syntax. vv: description: Changes various variables related to voxel brushes. permission: voxelsniper.sniper - aliases: [vl, vc, vh, vvariables, vvar, variables] + aliases: [ vl, vc, vh, vvariables, vvar, variables ] usage: Invalid syntax. Use / help to see valid syntax. permissions: voxelsniper.*: description: Allows access to all VoxelSniper commands. children: + voxelsniper.bypass: + description: Allows bypassing of restricions of worldguard or plotSquared + children: + voxelSniper.bypass.worldguard: + description: Allows bypassing of worldguard restrictions + voxelsniper.bypass.plotsquared: + description: Allows bypassing of plotSquared restrictions voxelsniper.sniper: description: Allows acces to snipe commands voxelsniper.ignorelimitations: diff --git a/VoxelSniperSpigot/src/test/java/com/github/kevindagame/voxelsniper/biome/material/VoxelMaterialTest.java b/VoxelSniperSpigot/src/test/java/com/github/kevindagame/voxelsniper/biome/material/VoxelMaterialTest.java deleted file mode 100644 index 866cccbf..00000000 --- a/VoxelSniperSpigot/src/test/java/com/github/kevindagame/voxelsniper/biome/material/VoxelMaterialTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.kevindagame.voxelsniper.biome.material; - -import junit.framework.TestCase; - -public class VoxelMaterialTest extends TestCase { - - public void testGetMaterial() { - } - - public void testTestGetMaterial() { - } -} \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index a8273999..5590892f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -7,18 +7,19 @@ repositories { } dependencies { - implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") + implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") + implementation("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.22") } tasks { - compileJava { - options.encoding = Charsets.UTF_8.name() - options.release.set(17) - } + compileJava { + options.encoding = Charsets.UTF_8.name() + options.release.set(17) + } - compileKotlin { - kotlinOptions { - jvmTarget = "17" + compileKotlin { + kotlinOptions { + jvmTarget = "17" + } } - } } diff --git a/buildSrc/src/main/kotlin/voxel-core.gradle.kts b/buildSrc/src/main/kotlin/voxel-core.gradle.kts index d0f81ce4..9dd43aed 100644 --- a/buildSrc/src/main/kotlin/voxel-core.gradle.kts +++ b/buildSrc/src/main/kotlin/voxel-core.gradle.kts @@ -1,12 +1,17 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { `java-library` + `maven-publish` id("com.github.johnrengelman.shadow") + kotlin("jvm") } // Projects should use Maven Central for external dependencies // This could be the organization's private repository repositories { mavenLocal() + mavenCentral() maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") } @@ -23,10 +28,11 @@ repositories { dependencies { compileOnly("org.jetbrains:annotations-java5:23.0.0") - implementation("net.kyori:adventure-api:4.11.0") - implementation("net.kyori:adventure-text-minimessage:4.11.0") - implementation("net.kyori:adventure-text-serializer-legacy:4.11.0") + implementation("net.kyori:adventure-api:4.12.0") + implementation("net.kyori:adventure-text-minimessage:4.12.0") + implementation("net.kyori:adventure-text-serializer-legacy:4.12.0") + implementation(kotlin("stdlib-jdk8")) implementation("com.google.guava:guava:31.1-jre") implementation("org.yaml:snakeyaml:1.31") @@ -42,17 +48,25 @@ java { } group = "com.github.kevindagame" -version = "8.3.0" +version = "8.4.0" //java.sourceCompatibility = JavaVersion.VERSION_16 -tasks.withType() { +tasks.withType { options.encoding = "UTF-8" } +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "17" +} +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "17" +} tasks { compileJava { options.encoding = Charsets.UTF_8.name() - options.release.set(16) + options.release.set(17) } shadowJar { @@ -69,4 +83,13 @@ tasks { clean { delete("../output") } +} + +publishing { + publications { + create("maven") { + + from(components["java"]) + } + } } \ No newline at end of file