mirror of
https://github.com/songoda/UltimateTimber.git
synced 2024-09-29 22:27:36 +02:00
Compare commits
99 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
bbdcdfbc36 | ||
|
412d96fe18 | ||
|
4b1fa2b37c | ||
|
ee570e4719 | ||
|
6a82c260b5 | ||
|
f65872827d | ||
|
139b15cc8d | ||
|
b533be2c26 | ||
|
3455ad87e3 | ||
|
7553a3c897 | ||
|
3847ff9dc5 | ||
|
01355d3e13 | ||
|
963875d5bf | ||
|
12c5c78a1d | ||
|
2523487543 | ||
|
5c84ee51e8 | ||
|
490f55388d | ||
|
096a1f25b4 | ||
|
2858427d86 | ||
|
b1cb59b7e8 | ||
|
ea940d573d | ||
|
3e9f7d2eec | ||
|
d243aba6af | ||
|
16091dcb59 | ||
|
e04a4af615 | ||
|
3bb28b8d2d | ||
|
ca8d830ee5 | ||
|
5cb3e2e56d | ||
|
79276c0eba | ||
|
101b783c36 | ||
|
84e8fc8eb6 | ||
|
5637a0d85e | ||
|
75202b8007 | ||
|
f4bd38f794 | ||
|
228deb9f17 | ||
|
94d8a27e4a | ||
|
b3f11ff819 | ||
|
04ebcb4a52 | ||
|
48a4cf416b | ||
|
59ef36fe1c | ||
|
0f3f8f0e7b | ||
|
1c4146abff | ||
|
c39f3cc1bd | ||
|
ad153088eb | ||
|
7479ed36b7 | ||
|
fc5e102e0c | ||
|
7f1c9ab3a3 | ||
|
7cff210782 | ||
|
5c5f938f3c | ||
|
07c6afdad2 | ||
|
f4f8540aec | ||
|
30923352a5 | ||
|
23bd964898 | ||
|
a97feabe74 | ||
|
bc405fb3fa | ||
|
7d39c8d967 | ||
|
9011160798 | ||
|
e2a32dfdee | ||
|
7fc7c11808 | ||
|
b5bb178569 | ||
|
d9eb494a6f | ||
|
564bfa6e8c | ||
|
ef7c7ac4fa | ||
|
5d8600df12 | ||
|
5cc632f625 | ||
|
1e2a41fd90 | ||
|
24a556eacf | ||
|
c94ec4c055 | ||
|
3e1fa6f937 | ||
|
49c9a1a42e | ||
|
daa4e8dcc2 | ||
|
b600ca6bac | ||
|
fb9d299eee | ||
|
c234f202bc | ||
|
cfc53d5b72 | ||
|
5833234da4 | ||
|
4d78edcb45 | ||
|
76e3b1fc3b | ||
|
2da515f31f | ||
|
c706ce3e6c | ||
|
5355e227ab | ||
|
6096047bae | ||
|
ac8d2a9714 | ||
|
7817beb831 | ||
|
e174ebc5bf | ||
|
3585ce75bb | ||
|
fdd4286195 | ||
|
c445e132e2 | ||
|
ae1d967628 | ||
|
99af64c422 | ||
|
6fe148a667 | ||
|
33b6c14811 | ||
|
8be488173f | ||
|
4f079a384e | ||
|
5dcb528eea | ||
|
9d58e513b4 | ||
|
a6926de3a2 | ||
|
ffb7657a78 | ||
|
065a5b809b |
39
.gitignore
vendored
39
.gitignore
vendored
@ -1,31 +1,10 @@
|
|||||||
# Compiled class file
|
## JetBrains IDEs
|
||||||
*.class
|
/.idea/
|
||||||
|
|
||||||
# Log file
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# BlueJ files
|
|
||||||
*.ctxt
|
|
||||||
|
|
||||||
# Mobile Tools for Java (J2ME)
|
|
||||||
.mtj.tmp/
|
|
||||||
|
|
||||||
# Package Files #
|
|
||||||
*.jar
|
|
||||||
*.war
|
|
||||||
*.nar
|
|
||||||
*.settings
|
|
||||||
*.ear
|
|
||||||
*.zip
|
|
||||||
*.tar.gz
|
|
||||||
*.rar
|
|
||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
|
||||||
hs_err_pid*
|
|
||||||
/.gradle/
|
|
||||||
/.settings/
|
|
||||||
.idea/
|
|
||||||
build/
|
|
||||||
target/
|
|
||||||
*.iml
|
*.iml
|
||||||
/bin/
|
|
||||||
|
## Maven
|
||||||
|
/**/target/
|
||||||
|
/dependency-reduced-pom.xml
|
||||||
|
|
||||||
|
## Misc.
|
||||||
|
.DS_Store
|
||||||
|
328
LICENSE
328
LICENSE
@ -1,9 +1,327 @@
|
|||||||
Copyright (c) 2019 Brianna O’Keefe
|
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0
|
||||||
|
International Public License
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software with minimal restriction, including the rights to use, copy, modify or merge while excluding the rights to publish, (re)distribute, sub-license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-NonCommercial-NoDerivatives 4.0 International Public
|
||||||
|
License ("Public License"). To the extent this Public License may be
|
||||||
|
interpreted as a contract, You are granted the Licensed Rights in
|
||||||
|
consideration of Your acceptance of these terms and conditions, and the
|
||||||
|
Licensor grants You such rights in consideration of benefits the
|
||||||
|
Licensor receives from making the Licensed Material available under
|
||||||
|
these terms and conditions.
|
||||||
|
|
||||||
The same distribution rights and limitations above shall similarly apply to any and all source code, and other means that can be used to emulate this work.
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
c. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
d. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
e. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
f. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
g. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
h. NonCommercial means not primarily intended for or directed towards
|
||||||
|
commercial advantage or monetary compensation. For purposes of
|
||||||
|
this Public License, the exchange of the Licensed Material for
|
||||||
|
other material subject to Copyright and Similar Rights by digital
|
||||||
|
file-sharing or similar means is NonCommercial provided there is
|
||||||
|
no payment of monetary compensation in connection with the
|
||||||
|
exchange.
|
||||||
|
|
||||||
|
i. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
j. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
k. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part, for NonCommercial purposes only; and
|
||||||
|
|
||||||
|
b. produce and reproduce, but not Share, Adapted Material
|
||||||
|
for NonCommercial purposes only.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties, including when
|
||||||
|
the Licensed Material is used other than for NonCommercial
|
||||||
|
purposes.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material, You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
For the avoidance of doubt, You do not have permission under
|
||||||
|
this Public License to Share Adapted Material.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database for NonCommercial purposes
|
||||||
|
only and provided You do not Share Adapted Material;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material; and
|
||||||
|
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
44
README.md
Normal file
44
README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<!--suppress HtmlDeprecatedAttribute -->
|
||||||
|
<div align="center">
|
||||||
|
<img src="docs/Logo.png" width="128px">
|
||||||
|
|
||||||
|
# UltimateTimber
|
||||||
|
**Give your players a new and exciting way to chop down trees.**
|
||||||
|
**Includes animated block falling, excellent tree detection, custom drops, realistic sounds, and more.**
|
||||||
|
|
||||||
|
|
||||||
|
[![Discord][Discord shield]][Discord invite]
|
||||||
|
<br>
|
||||||
|
[![Latest version][Latest version shield]][Plugin page]
|
||||||
|
[![bStats Servers][bStats shield]][bStats page]
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
## Download (Marketplace)
|
||||||
|
You can visit [our marketplace][Plugin page] to download UltimateTimber as well as take a
|
||||||
|
look at many other fantastic plugins which are sure to catch your eye.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
You can find all the information about UltimateTimber, including dependencies, commands, permissions and incompatible
|
||||||
|
plugins on [our wiki][Plugin wiki].
|
||||||
|
|
||||||
|
Feel free to also contribute to the wiki as a way to help others in the community with using the plugin.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
If you encounter any issues while using the plugin, feel free to contact us on
|
||||||
|
[our Discord server][Discord invite].
|
||||||
|
|
||||||
|
## Suggestions
|
||||||
|
For suggestions about features you think should be added to the plugin to increase its functionality, feel free to
|
||||||
|
create a thread over on [our Discord server][Discord invite].
|
||||||
|
|
||||||
|
|
||||||
|
[Plugin page]: https://songoda.com/product/2
|
||||||
|
[Plugin wiki]: https://songoda.notion.site/UltimateTimber-95103806d7f84353bb308335bd8ce37e
|
||||||
|
[Discord invite]: https://discord.gg/7TXM8xr2Ng
|
||||||
|
|
||||||
|
[Discord shield]: https://img.shields.io/discord/1214289374506917889?color=5865F2&label=Discord&logo=discord&logoColor=5865F2
|
||||||
|
[Latest version shield]: https://img.shields.io/badge/dynamic/xml?style=flat&color=blue&logo=github&logoColor=white&label=Latest&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcraftaro%2FUltimateTimber%2Fmaster%2Fpom.xml&query=%2F*%5Blocal-name()%3D'project'%5D%2F*%5Blocal-name()%3D'version'%5D
|
||||||
|
|
||||||
|
[bStats page]: https://bstats.org/plugin/bukkit/UltimateTimber/4184
|
||||||
|
[bStats shield]: https://img.shields.io/bstats/servers/4184?label=Servers
|
@ -1,35 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.songoda</groupId>
|
|
||||||
<artifactId>UltimateTimber</artifactId>
|
|
||||||
<version>2.0.9b</version>
|
|
||||||
<relativePath>../../</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>CurrentAdapter</artifactId>
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot</artifactId>
|
|
||||||
<version>1.15</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>Core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.songoda</groupId>
|
|
||||||
<artifactId>SongodaCore</artifactId>
|
|
||||||
<version>LATEST</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,169 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter.current;
|
|
||||||
|
|
||||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapterType;
|
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
|
||||||
import com.songoda.ultimatetimber.utils.Methods;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.Particle;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.enchantments.Enchantment;
|
|
||||||
import org.bukkit.entity.FallingBlock;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.Damageable;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
import org.bukkit.event.player.PlayerItemBreakEvent;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class CurrentAdapter implements VersionAdapter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VersionAdapterType getVersionAdapterType() {
|
|
||||||
return VersionAdapterType.CURRENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockData parseBlockDataFromString(String blockDataString) {
|
|
||||||
Material material = Material.matchMaterial(blockDataString);
|
|
||||||
if (material == null) return null;
|
|
||||||
return new CurrentBlockData(material);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack parseItemStackFromString(String itemStackString) {
|
|
||||||
CompatibleMaterial compatibleMaterial = CompatibleMaterial.getMaterial(itemStackString);
|
|
||||||
if (compatibleMaterial == null) return null;
|
|
||||||
return compatibleMaterial.getItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<ItemStack> getBlockDrops(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
|
||||||
Set<ItemStack> drops = new HashSet<>();
|
|
||||||
if (treeBlock.getBlock() instanceof Block) {
|
|
||||||
Block block = (Block)treeBlock.getBlock();
|
|
||||||
if (block.getType().equals(Material.AIR))
|
|
||||||
return drops;
|
|
||||||
drops.add(new ItemStack(block.getType()));
|
|
||||||
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
|
||||||
FallingBlock fallingBlock = (FallingBlock)treeBlock.getBlock();
|
|
||||||
drops.add(new ItemStack(fallingBlock.getBlockData().getMaterial()));
|
|
||||||
}
|
|
||||||
return drops;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyToolDurability(Player player, int damage) {
|
|
||||||
ItemStack tool = this.getItemInHand(player);
|
|
||||||
if (tool.getType().getMaxDurability() < 1 || (tool.getItemMeta() != null && tool.getItemMeta().isUnbreakable()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int unbreakingLevel = tool.getEnchantmentLevel(Enchantment.DURABILITY);
|
|
||||||
Damageable damageable = (Damageable) tool.getItemMeta();
|
|
||||||
|
|
||||||
int actualDamage = 0;
|
|
||||||
for (int i = 0; i < damage; i++)
|
|
||||||
if (Methods.checkUnbreakingChance(unbreakingLevel))
|
|
||||||
actualDamage++;
|
|
||||||
|
|
||||||
damageable.setDamage(damageable.getDamage() + actualDamage);
|
|
||||||
tool.setItemMeta((ItemMeta) damageable);
|
|
||||||
|
|
||||||
if (!this.hasEnoughDurability(tool, 1)) {
|
|
||||||
PlayerItemBreakEvent breakEvent = new PlayerItemBreakEvent(player, tool);
|
|
||||||
Bukkit.getServer().getPluginManager().callEvent(breakEvent);
|
|
||||||
this.removeItemInHand(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasEnoughDurability(ItemStack tool, int requiredAmount) {
|
|
||||||
if (!tool.hasItemMeta() || !(tool.getItemMeta() instanceof Damageable) || tool.getType().getMaxDurability() < 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Damageable damageable = (Damageable) tool.getItemMeta();
|
|
||||||
int durabilityRemaining = tool.getType().getMaxDurability() - damageable.getDamage();
|
|
||||||
return durabilityRemaining > requiredAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getItemInHand(Player player) {
|
|
||||||
return player.getInventory().getItemInMainHand();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeItemInHand(Player player) {
|
|
||||||
player.getInventory().setItemInMainHand(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FallingBlock spawnFallingBlock(Location location, Block block) {
|
|
||||||
return location.getWorld().spawnFallingBlock(location, block.getBlockData());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configureFallingBlock(FallingBlock fallingBlock) {
|
|
||||||
this.toggleGravityFallingBlock(fallingBlock, false);
|
|
||||||
fallingBlock.setDropItem(false);
|
|
||||||
fallingBlock.setHurtEntities(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void toggleGravityFallingBlock(FallingBlock fallingBlock, boolean applyGravity) {
|
|
||||||
fallingBlock.setGravity(applyGravity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playFallingParticles(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
|
||||||
BlockData blockData;
|
|
||||||
if (treeBlock.getBlock() instanceof Block) {
|
|
||||||
blockData = ((Block)treeBlock.getBlock()).getBlockData();
|
|
||||||
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
|
||||||
blockData = ((FallingBlock)treeBlock.getBlock()).getBlockData();
|
|
||||||
} else return;
|
|
||||||
|
|
||||||
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
|
||||||
location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playLandingParticles(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
|
||||||
BlockData blockData;
|
|
||||||
if (treeBlock.getBlock() instanceof Block) {
|
|
||||||
blockData = ((Block)treeBlock.getBlock()).getBlockData();
|
|
||||||
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
|
||||||
blockData = ((FallingBlock)treeBlock.getBlock()).getBlockData();
|
|
||||||
} else return;
|
|
||||||
|
|
||||||
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
|
||||||
location.getWorld().spawnParticle(Particle.BLOCK_CRACK, location, 10, blockData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playFallingSound(ITreeBlock treeBlock) {
|
|
||||||
Location location = treeBlock.getLocation();
|
|
||||||
location.getWorld().playSound(location, Sound.BLOCK_CHEST_OPEN, 2F, 0.1F);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playLandingSound(ITreeBlock treeBlock) {
|
|
||||||
Location location = treeBlock.getLocation();
|
|
||||||
if (treeBlock.getTreeBlockType().equals(TreeBlockType.LOG)) {
|
|
||||||
location.getWorld().playSound(location, Sound.BLOCK_WOOD_FALL, 2F, 0.1F);
|
|
||||||
} else {
|
|
||||||
location.getWorld().playSound(location, Sound.BLOCK_GRASS_BREAK, 0.5F, 0.75F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter.current;
|
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
|
|
||||||
public class CurrentBlockData implements IBlockData {
|
|
||||||
|
|
||||||
private final Material material;
|
|
||||||
|
|
||||||
public CurrentBlockData(Material material) {
|
|
||||||
this.material = material;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Material getMaterial() {
|
|
||||||
return this.material;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte getData() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSimilar(IBlockData otherBlockData) {
|
|
||||||
return this.material.equals(otherBlockData.getMaterial());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSimilar(Block block) {
|
|
||||||
return this.material.equals(block.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlock(Block block) {
|
|
||||||
block.setType(this.material);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.songoda</groupId>
|
|
||||||
<artifactId>UltimateTimber</artifactId>
|
|
||||||
<version>2.0.9b</version>
|
|
||||||
<relativePath>../../</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>LegacyAdapter</artifactId>
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot</artifactId>
|
|
||||||
<version>1.12.2</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>Core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,216 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter.legacy;
|
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapterType;
|
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
|
||||||
import com.songoda.ultimatetimber.utils.Methods;
|
|
||||||
import com.songoda.ultimatetimber.utils.NMSUtil;
|
|
||||||
import org.bukkit.Effect;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.Particle;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.enchantments.Enchantment;
|
|
||||||
import org.bukkit.entity.FallingBlock;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public class LegacyAdapter implements VersionAdapter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VersionAdapterType getVersionAdapterType() {
|
|
||||||
return VersionAdapterType.LEGACY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockData parseBlockDataFromString(String blockDataString) {
|
|
||||||
String[] split = blockDataString.split(":");
|
|
||||||
Material material = Material.matchMaterial(split[0]);
|
|
||||||
List<Byte> data = new ArrayList<>();
|
|
||||||
if (split.length > 1) {
|
|
||||||
String[] splitData = split[1].split(",");
|
|
||||||
for (String dataValue : splitData)
|
|
||||||
data.add(Byte.parseByte(dataValue));
|
|
||||||
} else {
|
|
||||||
data.add((byte)0);
|
|
||||||
}
|
|
||||||
return new LegacyBlockData(material, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack parseItemStackFromString(String itemStackString) {
|
|
||||||
String[] split = itemStackString.split(":");
|
|
||||||
Material material = Material.matchMaterial(split[0]);
|
|
||||||
byte data = 0;
|
|
||||||
if (split.length > 1) {
|
|
||||||
data = Byte.parseByte(split[1]);
|
|
||||||
}
|
|
||||||
return new ItemStack(material, 1, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<ItemStack> getBlockDrops(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
|
||||||
Set<ItemStack> drops = new HashSet<>();
|
|
||||||
|
|
||||||
IBlockData treeBlockData;
|
|
||||||
if (treeBlock.getBlock() instanceof Block) {
|
|
||||||
Block block = (Block)treeBlock.getBlock();
|
|
||||||
if (block.getType().equals(Material.AIR))
|
|
||||||
return drops;
|
|
||||||
List<Byte> data = new ArrayList<>();
|
|
||||||
data.add(block.getData());
|
|
||||||
treeBlockData = new LegacyBlockData(block.getType(), data);
|
|
||||||
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
|
||||||
FallingBlock fallingBlock = (FallingBlock)treeBlock.getBlock();
|
|
||||||
List<Byte> data = new ArrayList<>();
|
|
||||||
data.add(fallingBlock.getBlockData());
|
|
||||||
treeBlockData = new LegacyBlockData(fallingBlock.getMaterial(), data);
|
|
||||||
} else return drops;
|
|
||||||
|
|
||||||
Set<IBlockData> typedBlockData = treeBlock.getTreeBlockType().equals(TreeBlockType.LOG) ? treeDefinition.getLogBlockData() : treeDefinition.getLeafBlockData();
|
|
||||||
|
|
||||||
IBlockData definitionBlockData = null;
|
|
||||||
for (IBlockData blockData : typedBlockData) {
|
|
||||||
if (blockData.getMaterial().equals(treeBlockData.getMaterial()) && blockData.getData() == treeBlockData.getData()) {
|
|
||||||
definitionBlockData = blockData;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definitionBlockData == null) {
|
|
||||||
for (IBlockData blockData : typedBlockData) {
|
|
||||||
if (blockData.getMaterial().equals(treeBlockData.getMaterial())) {
|
|
||||||
definitionBlockData = blockData;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definitionBlockData != null && definitionBlockData.isSimilar(treeBlockData))
|
|
||||||
drops.add(new ItemStack(definitionBlockData.getMaterial(), 1, definitionBlockData.getData()));
|
|
||||||
|
|
||||||
return drops;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyToolDurability(Player player, int damage) {
|
|
||||||
ItemStack tool = this.getItemInHand(player);
|
|
||||||
if (tool.getType().getMaxDurability() < 1 || (tool.getItemMeta() != null && tool.getItemMeta().spigot().isUnbreakable()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int unbreakingLevel = tool.getEnchantmentLevel(Enchantment.DURABILITY);
|
|
||||||
|
|
||||||
int actualDamage = 0;
|
|
||||||
for (int i = 0; i < damage; i++)
|
|
||||||
if (Methods.checkUnbreakingChance(unbreakingLevel))
|
|
||||||
actualDamage++;
|
|
||||||
|
|
||||||
tool.setDurability((short)(tool.getDurability() + actualDamage));
|
|
||||||
|
|
||||||
if (!this.hasEnoughDurability(tool, 1))
|
|
||||||
this.removeItemInHand(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasEnoughDurability(ItemStack tool, int requiredAmount) {
|
|
||||||
if (tool.getType().getMaxDurability() <= 1)
|
|
||||||
return true;
|
|
||||||
return tool.getDurability() + requiredAmount <= tool.getType().getMaxDurability();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getItemInHand(Player player) {
|
|
||||||
return player.getItemInHand();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeItemInHand(Player player) {
|
|
||||||
player.setItemInHand(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FallingBlock spawnFallingBlock(Location location, Block block) {
|
|
||||||
return location.getWorld().spawnFallingBlock(location, block.getType(), block.getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configureFallingBlock(FallingBlock fallingBlock) {
|
|
||||||
this.toggleGravityFallingBlock(fallingBlock, false);
|
|
||||||
fallingBlock.setDropItem(false);
|
|
||||||
fallingBlock.setHurtEntities(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void toggleGravityFallingBlock(FallingBlock fallingBlock, boolean applyGravity) {
|
|
||||||
if (NMSUtil.getVersionNumber() > 9)
|
|
||||||
fallingBlock.setGravity(applyGravity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playFallingParticles(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
|
||||||
Collection<ItemStack> blockDrops = this.getBlockDrops(treeDefinition, treeBlock);
|
|
||||||
if (!blockDrops.iterator().hasNext())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
|
||||||
if (NMSUtil.getVersionNumber() > 8) {
|
|
||||||
location.getWorld().spawnParticle(Particle.BLOCK_CRACK, location, 10, blockDrops.iterator().next().getData());
|
|
||||||
} else {
|
|
||||||
location.getWorld().playEffect(location, Effect.SMOKE, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playLandingParticles(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
|
||||||
Collection<ItemStack> blockDrops = this.getBlockDrops(treeDefinition, treeBlock);
|
|
||||||
if (!blockDrops.iterator().hasNext())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
|
||||||
if (NMSUtil.getVersionNumber() > 8) {
|
|
||||||
location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockDrops.iterator().next().getData());
|
|
||||||
} else {
|
|
||||||
location.getWorld().playEffect(location, Effect.SMOKE, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playFallingSound(ITreeBlock treeBlock) {
|
|
||||||
Location location = treeBlock.getLocation();
|
|
||||||
if (NMSUtil.getVersionNumber() > 8) {
|
|
||||||
location.getWorld().playSound(location, Sound.BLOCK_CHEST_OPEN, 2F, 0.1F);
|
|
||||||
} else {
|
|
||||||
location.getWorld().playSound(location, Sound.valueOf("CHEST_OPEN"), 2F, 0.1F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playLandingSound(ITreeBlock treeBlock) {
|
|
||||||
Location location = treeBlock.getLocation();
|
|
||||||
if (treeBlock.getTreeBlockType().equals(TreeBlockType.LOG)) {
|
|
||||||
if (NMSUtil.getVersionNumber() > 8) {
|
|
||||||
location.getWorld().playSound(location, Sound.BLOCK_WOOD_FALL, 3F, 0.1F);
|
|
||||||
} else {
|
|
||||||
location.getWorld().playSound(location, Sound.valueOf("DIG_WOOD"), 3F, 0.1F);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (NMSUtil.getVersionNumber() > 8) {
|
|
||||||
location.getWorld().playSound(location, Sound.BLOCK_GRASS_BREAK, 0.5F, 0.75F);
|
|
||||||
} else {
|
|
||||||
location.getWorld().playSound(location, Sound.valueOf("DIG_GRASS"), 0.5F, 0.75F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter.legacy;
|
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public class LegacyBlockData implements IBlockData {
|
|
||||||
|
|
||||||
private final Material material;
|
|
||||||
private final List<Byte> data;
|
|
||||||
|
|
||||||
public LegacyBlockData(Material material, List<Byte> data) {
|
|
||||||
this.material = material;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Material getMaterial() {
|
|
||||||
return this.material;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte getData() {
|
|
||||||
return this.data.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSimilar(IBlockData otherBlockData) {
|
|
||||||
if (this.data.size() == 1)
|
|
||||||
return this.material.equals(otherBlockData.getMaterial()) && this.getData() == otherBlockData.getData();
|
|
||||||
|
|
||||||
Material blockMaterial = otherBlockData.getMaterial();
|
|
||||||
byte blockData = otherBlockData.getData();
|
|
||||||
|
|
||||||
if (!this.material.equals(blockMaterial))
|
|
||||||
return false;
|
|
||||||
for (byte value : this.data)
|
|
||||||
if (value == blockData)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSimilar(Block block) {
|
|
||||||
if (this.data.size() == 1)
|
|
||||||
return this.material.equals(block.getType()) && this.getData() == block.getData();
|
|
||||||
|
|
||||||
Material blockMaterial = block.getType();
|
|
||||||
byte blockData = block.getData();
|
|
||||||
if (!this.material.equals(blockMaterial))
|
|
||||||
return false;
|
|
||||||
for (byte value : this.data)
|
|
||||||
if (value == blockData)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlock(Block block) {
|
|
||||||
block.setType(this.material);
|
|
||||||
block.setData(this.data.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.songoda</groupId>
|
|
||||||
<artifactId>UltimateTimber</artifactId>
|
|
||||||
<version>2.0.9b</version>
|
|
||||||
<relativePath>../../</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>Core</artifactId>
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot</artifactId>
|
|
||||||
<version>1.15</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,43 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter;
|
|
||||||
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
|
|
||||||
public interface IBlockData {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Material of the BlockData
|
|
||||||
*
|
|
||||||
* @return The Material
|
|
||||||
*/
|
|
||||||
Material getMaterial();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the data of the BlockData
|
|
||||||
*
|
|
||||||
* @return The data
|
|
||||||
*/
|
|
||||||
byte getData();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares this IBlockData with another one to see if they are similar
|
|
||||||
*
|
|
||||||
* @return True if they are similar, otherwise false
|
|
||||||
*/
|
|
||||||
boolean isSimilar(IBlockData otherBlockData);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares this IBlockData with a block to see if they are similar
|
|
||||||
*
|
|
||||||
* @return True if they are similar, otherwise false
|
|
||||||
*/
|
|
||||||
boolean isSimilar(Block block);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a given Block to use this IBlockData
|
|
||||||
*
|
|
||||||
* @param block The Block to set
|
|
||||||
*/
|
|
||||||
void setBlock(Block block);
|
|
||||||
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter;
|
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.entity.FallingBlock;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public interface VersionAdapter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the version adapter type
|
|
||||||
*
|
|
||||||
* @return The VersionAdapterType
|
|
||||||
*/
|
|
||||||
VersionAdapterType getVersionAdapterType();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a String into an IBlockData instance
|
|
||||||
*
|
|
||||||
* @param blockDataString The String to parse
|
|
||||||
* @return An IBlockData instance that the given String represents
|
|
||||||
*/
|
|
||||||
IBlockData parseBlockDataFromString(String blockDataString);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a String into an ItemStack
|
|
||||||
*
|
|
||||||
* @param itemStackString The String to parse
|
|
||||||
* @return An ItemStack that the given String represents
|
|
||||||
*/
|
|
||||||
ItemStack parseItemStackFromString(String itemStackString);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the items that a tree block should drop when it breaks
|
|
||||||
*
|
|
||||||
* @param treeDefinition The tree definition to get the items for
|
|
||||||
* @param treeBlock The tree block
|
|
||||||
* @return A Set of ItemStacks that should be dropped
|
|
||||||
*/
|
|
||||||
Collection<ItemStack> getBlockDrops(TreeDefinition treeDefinition, ITreeBlock treeBlock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies damage to a tool
|
|
||||||
*
|
|
||||||
* @param player The Player who's tool to apply damage to
|
|
||||||
* @param damage The amount of damage to apply
|
|
||||||
*/
|
|
||||||
void applyToolDurability(Player player, int damage);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a given tool has enough durability remaining
|
|
||||||
*
|
|
||||||
* @param tool The tool to check
|
|
||||||
* @param requiredAmount The amount of durability required
|
|
||||||
* @return True if enough durability is remaining to not break the tool, otherwise false
|
|
||||||
*/
|
|
||||||
boolean hasEnoughDurability(ItemStack tool, int requiredAmount);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the item in the player's main hand
|
|
||||||
*
|
|
||||||
* @param player The Player to get the item from
|
|
||||||
* @return The ItemStack in the Player's main hand
|
|
||||||
*/
|
|
||||||
ItemStack getItemInHand(Player player);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the item in the player's main hand
|
|
||||||
*
|
|
||||||
* @param player The Player to remove the item from
|
|
||||||
*/
|
|
||||||
void removeItemInHand(Player player);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawns a falling block at the given location with the given block data
|
|
||||||
*
|
|
||||||
* @param location The location to spawn at
|
|
||||||
* @param block The block to use block data
|
|
||||||
* @return A newly spawned FallingBlock entity
|
|
||||||
*/
|
|
||||||
FallingBlock spawnFallingBlock(Location location, Block block);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures a falling block for animating
|
|
||||||
*
|
|
||||||
* @param fallingBlock The falling block to configure
|
|
||||||
*/
|
|
||||||
void configureFallingBlock(FallingBlock fallingBlock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables/Disables gravity for a falling block
|
|
||||||
*
|
|
||||||
* @param fallingBlock The falling block to apply gravity settings to
|
|
||||||
* @param applyGravity Whether or not to apply the gravity
|
|
||||||
*/
|
|
||||||
void toggleGravityFallingBlock(FallingBlock fallingBlock, boolean applyGravity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plays particles to indicate a tree block has started falling
|
|
||||||
*
|
|
||||||
* @param treeDefinition The TreeDefinition of the block
|
|
||||||
* @param treeBlock The TreeBlock to play the particles for
|
|
||||||
*/
|
|
||||||
void playFallingParticles(TreeDefinition treeDefinition, ITreeBlock treeBlock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plays particles to indicate a tree block has hit the ground
|
|
||||||
*
|
|
||||||
* @param treeDefinition The TreeDefinition of the block
|
|
||||||
* @param treeBlock The TreeBlock to play the particles for
|
|
||||||
*/
|
|
||||||
void playLandingParticles(TreeDefinition treeDefinition, ITreeBlock treeBlock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plays a sound to indicate a tree block has started falling
|
|
||||||
*
|
|
||||||
* @param treeBlock The TreeBlock to play the sound for
|
|
||||||
*/
|
|
||||||
void playFallingSound(ITreeBlock treeBlock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plays a sound to indicate a tree block has hit the ground
|
|
||||||
*
|
|
||||||
* @param treeBlock The TreeBlock to play the sound for
|
|
||||||
*/
|
|
||||||
void playLandingSound(ITreeBlock treeBlock);
|
|
||||||
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version adapter type
|
|
||||||
* Used to determine what version adapter is being used
|
|
||||||
*/
|
|
||||||
public enum VersionAdapterType {
|
|
||||||
CURRENT,
|
|
||||||
LEGACY
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.misc;
|
|
||||||
|
|
||||||
public enum OnlyToppleWhile {
|
|
||||||
SNEAKING,
|
|
||||||
NOT_SNEAKING,
|
|
||||||
ALWAYS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an OnlyToppleWhile from a given string
|
|
||||||
*
|
|
||||||
* @param string The string
|
|
||||||
* @return The TreeAnimationType, returns FANCY if the string is an invalid type
|
|
||||||
*/
|
|
||||||
public static OnlyToppleWhile fromString(String string) {
|
|
||||||
for (OnlyToppleWhile value : values())
|
|
||||||
if (value.name().equalsIgnoreCase(string))
|
|
||||||
return value;
|
|
||||||
return OnlyToppleWhile.ALWAYS;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a tree block type and whether it is a log or a leaf block
|
|
||||||
*/
|
|
||||||
public enum TreeBlockType {
|
|
||||||
LOG,
|
|
||||||
LEAF
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.utils;
|
|
||||||
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class Methods {
|
|
||||||
|
|
||||||
private static Random random = new Random();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a given string replacing colors
|
|
||||||
*
|
|
||||||
* @param text The string
|
|
||||||
* @return The formatted string
|
|
||||||
*/
|
|
||||||
public static String formatText(String text) {
|
|
||||||
if (text == null || text.equals(""))
|
|
||||||
return "";
|
|
||||||
return formatText(text, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a given string replacing colors and optionally capitalizing the first word
|
|
||||||
*
|
|
||||||
* @param text The string
|
|
||||||
* @param cap If the first word should be capitalized
|
|
||||||
* @return The formatted string
|
|
||||||
*/
|
|
||||||
private static String formatText(String text, boolean cap) {
|
|
||||||
if (text == null || text.equals(""))
|
|
||||||
return "";
|
|
||||||
if (cap)
|
|
||||||
text = text.substring(0, 1).toUpperCase() + text.substring(1);
|
|
||||||
return ChatColor.translateAlternateColorCodes('&', text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if durbility should be applied based on the unbreaking enchantment
|
|
||||||
*
|
|
||||||
* @param level The level of the unbreaking enchantment
|
|
||||||
* @return True if durability should be applied, otherwise false
|
|
||||||
*/
|
|
||||||
public static boolean checkUnbreakingChance(int level) {
|
|
||||||
return (1.0 / (level + 1)) > random.nextDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.utils;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
|
|
||||||
public class NMSUtil {
|
|
||||||
|
|
||||||
public static String getVersion() {
|
|
||||||
String name = Bukkit.getServer().getClass().getPackage().getName();
|
|
||||||
return name.substring(name.lastIndexOf('.') + 1) + ".";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getVersionNumber() {
|
|
||||||
String name = getVersion().substring(3);
|
|
||||||
return Integer.valueOf(name.substring(0, name.length() - 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getVersionReleaseNumber() {
|
|
||||||
String NMSVersion = getVersion();
|
|
||||||
return Integer.valueOf(NMSVersion.substring(NMSVersion.length() - 2).replace(".", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.songoda</groupId>
|
|
||||||
<artifactId>UltimateTimber</artifactId>
|
|
||||||
<version>2.0.9b</version>
|
|
||||||
<relativePath>../../</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>Plugin</artifactId>
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>${parent.artifactId}-${parent.version}</finalName>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>2.3.2</version>
|
|
||||||
<configuration>
|
|
||||||
<showDeprecation>false</showDeprecation>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>com.google.code.maven-replacer-plugin</groupId>
|
|
||||||
<artifactId>replacer</artifactId>
|
|
||||||
<version>1.5.3</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>replace</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<file>${project.build.directory}/classes/plugin.yml</file>
|
|
||||||
<replacements>
|
|
||||||
<replacement>
|
|
||||||
<token>maven-version-number</token>
|
|
||||||
<value>${project.version}</value>
|
|
||||||
</replacement>
|
|
||||||
</replacements>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>3.1.0</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>shaded</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
|
||||||
<minimizeJar>true</minimizeJar>
|
|
||||||
<artifactSet>
|
|
||||||
<includes>
|
|
||||||
<include>com.songoda:SongodaCore</include>
|
|
||||||
<include>com.songoda:Core</include>
|
|
||||||
<include>com.songoda:CurrentAdapter</include>
|
|
||||||
<include>com.songoda:LegacyAdapter</include>
|
|
||||||
</includes>
|
|
||||||
</artifactSet>
|
|
||||||
<filters>
|
|
||||||
<filter>
|
|
||||||
<artifact>*:*</artifact>
|
|
||||||
<excludes>
|
|
||||||
<exclude>META-INF/*.SF</exclude>
|
|
||||||
<exclude>META-INF/*.DSA</exclude>
|
|
||||||
<exclude>META-INF/*.RSA</exclude>
|
|
||||||
</excludes>
|
|
||||||
</filter>
|
|
||||||
<filter>
|
|
||||||
<artifact>com.songoda:Lootables</artifact>
|
|
||||||
<excludes>
|
|
||||||
<exclude>com/songoda/core/**</exclude>
|
|
||||||
</excludes>
|
|
||||||
</filter>
|
|
||||||
</filters>
|
|
||||||
<relocations>
|
|
||||||
<relocation>
|
|
||||||
<pattern>com.songoda.core</pattern>
|
|
||||||
<shadedPattern>${project.groupId}.ultimatestacker.core</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
</relocations>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot</artifactId>
|
|
||||||
<version>1.16.1</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.songoda</groupId>
|
|
||||||
<artifactId>SongodaCore</artifactId>
|
|
||||||
<version>LATEST</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>Core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>CurrentAdapter</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>LegacyAdapter</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,399 +0,0 @@
|
|||||||
# ____ ___ __ __ __ __ ___________ __ ___
|
|
||||||
# | | \ |_/ |_|__| _____ _____ _/ |_ ___\__ ___/|__| _____\_ |__ ___________
|
|
||||||
# | | / |\ __\ |/ \\__ \\ __\/ __ \| | | |/ \| __ \_/ __ \_ __ \
|
|
||||||
# | | /| |_| | | | Y Y \/ __ \| | \ ___/| | | | Y Y \ \_\ \ ___/| | \/
|
|
||||||
# |______/ |____/__| |__|__|_| (____ /__| \___ |____| |__|__|_| /___ /\___ >__|
|
|
||||||
|
|
||||||
# The type of server you are running in relation to this plugin
|
|
||||||
# If you ever upgrade from a legacy version of Minecraft to a current version, you will need to reset this config
|
|
||||||
# Do not change this value
|
|
||||||
# Default: LEGACY
|
|
||||||
server-type: LEGACY
|
|
||||||
|
|
||||||
# The locale to use in the /locale folder
|
|
||||||
# Default: en_US
|
|
||||||
locale: en_US
|
|
||||||
|
|
||||||
# A list of worlds that the plugin is disabled in
|
|
||||||
# Default:
|
|
||||||
# - disabled_world_name
|
|
||||||
disabled-worlds:
|
|
||||||
- disabled_world_name
|
|
||||||
|
|
||||||
# The max number of logs that can be broken at one time
|
|
||||||
# Default: 150
|
|
||||||
max-logs-per-chop: 150
|
|
||||||
|
|
||||||
# The minimum number of leaves required for something to be considered a tree
|
|
||||||
# Default: 5
|
|
||||||
leaves-required-for-tree: 5
|
|
||||||
|
|
||||||
# If leaves should be destroyed
|
|
||||||
# Default: true
|
|
||||||
destroy-leaves: true
|
|
||||||
|
|
||||||
# Apply realistic damage to the tools based on the number of logs chopped
|
|
||||||
# If false, only one durability will be removed from the tool
|
|
||||||
# Default: true
|
|
||||||
realistic-tool-damage: true
|
|
||||||
|
|
||||||
# Protect the tool used to chop down the tree from breaking
|
|
||||||
# Prevents the tree from being toppled if the tool would break
|
|
||||||
# Default: false
|
|
||||||
protect-tool: false
|
|
||||||
|
|
||||||
# Use the silk touch enchantment if the tool has it
|
|
||||||
# Logs and leaves will drop their original block 100% of the time
|
|
||||||
# Default: true
|
|
||||||
apply-silk-touch: true
|
|
||||||
|
|
||||||
# Damage the tool extra for each leaf block broken, this is vanilla behavior but can be disabled here
|
|
||||||
# Does nothing if realistic-tool-damage is false
|
|
||||||
# Default: true
|
|
||||||
apply-silk-touch-tool-damage: true
|
|
||||||
|
|
||||||
# Require the entire base of the tree to be broken before it topples
|
|
||||||
# Default: false
|
|
||||||
break-entire-tree-base: false
|
|
||||||
|
|
||||||
# Don't drop a block for the block that initiates the tree fall
|
|
||||||
# Default: false
|
|
||||||
destroy-initiated-block: false
|
|
||||||
|
|
||||||
# Only detect logs above the initiated block
|
|
||||||
# Default: true
|
|
||||||
only-detect-logs-upwards: true
|
|
||||||
|
|
||||||
# Only topple trees while the player is doing something
|
|
||||||
# Valid values: SNEAKING, NOT_SNEAKING, ALWAYS
|
|
||||||
# Default: ALWAYS
|
|
||||||
only-topple-while: ALWAYS
|
|
||||||
|
|
||||||
# Allow toppling trees in creative mode
|
|
||||||
# Default: true
|
|
||||||
allow-creative-mode: true
|
|
||||||
|
|
||||||
# Require the player to have the permission 'ultimatetimber.chop' to topple trees
|
|
||||||
# Default: false
|
|
||||||
require-chop-permission: false
|
|
||||||
|
|
||||||
# If a player should only be allowed to chop one tree per cooldown length
|
|
||||||
# Default: false
|
|
||||||
player-tree-topple-cooldown: false
|
|
||||||
|
|
||||||
# The amount of seconds a player has to wait before they can chop a tree again
|
|
||||||
# Does nothing if player-tree-topple-cooldown is false
|
|
||||||
# The time is in seconds and must be a postive whole number
|
|
||||||
# Default: 5
|
|
||||||
player-tree-topple-cooldown-length: 5
|
|
||||||
|
|
||||||
# Allow players to topple trees regardless of what they are holding in their hand
|
|
||||||
# Default: false
|
|
||||||
ignore-required-tools: false
|
|
||||||
|
|
||||||
# Automatically replant saplings when a tree is toppled
|
|
||||||
# Default: true
|
|
||||||
replant-saplings: true
|
|
||||||
|
|
||||||
# Always replant saplings for base tree blocks, regardless of player permissions
|
|
||||||
# Default: false
|
|
||||||
always-replant-sapling: false
|
|
||||||
|
|
||||||
# How many seconds to prevent players from breaking replanted saplings
|
|
||||||
# Set to 0 to disable
|
|
||||||
# Does nothing if replant-saplings is false
|
|
||||||
# The time is in seconds and must be a postive whole number
|
|
||||||
# Default: 3
|
|
||||||
replant-saplings-cooldown: 3
|
|
||||||
|
|
||||||
# Give fallen leaf blocks a chance to replant saplings when they hit the ground
|
|
||||||
# Default: true
|
|
||||||
falling-blocks-replant-saplings: true
|
|
||||||
|
|
||||||
# The percent chance that fallen leaves have of planting a sapling
|
|
||||||
# Does nothing if falling-blocks-replant-saplings is false
|
|
||||||
# The chance is out of 100 and may contain decimals
|
|
||||||
# Default: 1
|
|
||||||
falling-blocks-replant-saplings-chance: 1
|
|
||||||
|
|
||||||
# Make falling tree blocks deal damage to players if they get hit
|
|
||||||
# Default: true
|
|
||||||
falling-blocks-deal-damage: true
|
|
||||||
|
|
||||||
# The amount of damage that falling tree blocks do
|
|
||||||
# This does nothing if falling-blocks-deal-damage is false
|
|
||||||
# Default: 1
|
|
||||||
falling-block-damage: 1
|
|
||||||
|
|
||||||
# Automatically add tree blocks to the player's inventory instead of dropping them
|
|
||||||
# Default: false
|
|
||||||
add-items-to-inventory: false
|
|
||||||
|
|
||||||
# Use custom sounds when toppling trees
|
|
||||||
# Default: true
|
|
||||||
use-custom-sounds: true
|
|
||||||
|
|
||||||
# Use custom particles when toppling trees
|
|
||||||
# Default: true
|
|
||||||
use-custom-particles: true
|
|
||||||
|
|
||||||
# The bonus loot multiplier when a player has the permission ultimatetimber.bonusloot
|
|
||||||
# Multiplies the chance of tree drops by this value
|
|
||||||
# Decimal values are allowed
|
|
||||||
# Default: 2
|
|
||||||
bonus-loot-multiplier: 2
|
|
||||||
|
|
||||||
# If placed blocks should be ignored for toppling trees
|
|
||||||
# Note: This only keeps track of blocks placed during the current server load
|
|
||||||
# If your server restarts, the placed tree blocks could be toppled again
|
|
||||||
# Default: true
|
|
||||||
ignore-placed-blocks: true
|
|
||||||
|
|
||||||
# The maximum number of blocks to keep track of in memory at once
|
|
||||||
# Use a lower number if this starts to take up too much memory or trees start taking too long to detect
|
|
||||||
# Default: 5000
|
|
||||||
ignore-placed-blocks-memory-size: 5000
|
|
||||||
|
|
||||||
# Applies experience when using Jobs/mcMMO
|
|
||||||
# Only does something if Jobs or mcMMO is installed
|
|
||||||
# Default: true
|
|
||||||
hooks-apply-experience: true
|
|
||||||
|
|
||||||
# Applies extra drops passive ability when using mcMMO
|
|
||||||
# Only does something if mcMMO is installed
|
|
||||||
# Default: true
|
|
||||||
hooks-apply-extra-drops: true
|
|
||||||
|
|
||||||
# Requires the tree feller ability in mcMMO to be active to use timber
|
|
||||||
# Only does something if mcMMO is installed
|
|
||||||
# Default: false
|
|
||||||
hooks-require-ability-active: false
|
|
||||||
|
|
||||||
# The type of animation to use for tree toppling
|
|
||||||
# Types: FANCY, DISINTEGRATE, CRUMBLE, NONE
|
|
||||||
tree-animation-type: FANCY
|
|
||||||
|
|
||||||
# If the tree-animation-type is FANCY or CRUMBLE, make the blocks stick to the ground
|
|
||||||
# Does nothing if tree-animation-type is not FANCY or CRUMBLE
|
|
||||||
# Default: false
|
|
||||||
scatter-tree-blocks-on-ground: false
|
|
||||||
|
|
||||||
# Tree configuration
|
|
||||||
# Allows for extreme fine-tuning of tree detection and what are considered trees
|
|
||||||
# Multiple log and leaf types are allowed, only one sapling type is allowed
|
|
||||||
# You can add your own custom tree types here, just add a new section
|
|
||||||
trees:
|
|
||||||
oak:
|
|
||||||
logs:
|
|
||||||
- LOG:0,4,8,12
|
|
||||||
leaves:
|
|
||||||
- LEAVES:0,4,8,12
|
|
||||||
sapling: SAPLING:0
|
|
||||||
plantable-soil: []
|
|
||||||
max-log-distance-from-trunk: 6
|
|
||||||
max-leaf-distance-from-log: 6
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: true
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: SAPLING:0
|
|
||||||
chance: 5
|
|
||||||
1:
|
|
||||||
material: APPLE
|
|
||||||
chance: 0.5
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
spruce:
|
|
||||||
logs:
|
|
||||||
- LOG:1,5,9,13
|
|
||||||
leaves:
|
|
||||||
- LEAVES:1,5,9,13
|
|
||||||
sapling: SAPLING:1
|
|
||||||
plantable-soil: []
|
|
||||||
max-log-distance-from-trunk: 2
|
|
||||||
max-leaf-distance-from-log: 6
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: true
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: SAPLING:1
|
|
||||||
chance: 5
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
birch:
|
|
||||||
logs:
|
|
||||||
- LOG:2,6,10,14
|
|
||||||
leaves:
|
|
||||||
- LEAVES:2,6,10,14
|
|
||||||
sapling: SAPLING:2
|
|
||||||
plantable-soil: []
|
|
||||||
max-log-distance-from-trunk: 1
|
|
||||||
max-leaf-distance-from-log: 4
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: true
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: SAPLING:2
|
|
||||||
chance: 5
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
jungle:
|
|
||||||
logs:
|
|
||||||
- LOG:3,7,11,15
|
|
||||||
leaves:
|
|
||||||
- LEAVES:3,7,11,15
|
|
||||||
sapling: SAPLING:3
|
|
||||||
plantable-soil: []
|
|
||||||
max-log-distance-from-trunk: 6
|
|
||||||
max-leaf-distance-from-log: 6
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: true
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: SAPLING:3
|
|
||||||
chance: 2.5
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
acacia:
|
|
||||||
logs:
|
|
||||||
- LOG_2:0,4,8,12
|
|
||||||
leaves:
|
|
||||||
- LEAVES_2:0,4,8,12
|
|
||||||
sapling: SAPLING:4
|
|
||||||
plantable-soil: []
|
|
||||||
max-log-distance-from-trunk: 4
|
|
||||||
max-leaf-distance-from-log: 5
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: true
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: SAPLING:4
|
|
||||||
chance: 5
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
dark_oak:
|
|
||||||
logs:
|
|
||||||
- LOG_2:1,5,9,13
|
|
||||||
leaves:
|
|
||||||
- LEAVES_2:1,5,9,13
|
|
||||||
sapling: SAPLING:5
|
|
||||||
plantable-soil: []
|
|
||||||
max-log-distance-from-trunk: 3
|
|
||||||
max-leaf-distance-from-log: 5
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: true
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: SAPLING:5
|
|
||||||
chance: 5
|
|
||||||
1:
|
|
||||||
material: APPLE
|
|
||||||
chance: 0.5
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
brown_mushroom:
|
|
||||||
logs:
|
|
||||||
- HUGE_MUSHROOM_1:15,10
|
|
||||||
leaves:
|
|
||||||
- HUGE_MUSHROOM_1:14,0,1,2,3,4,5,6,7,8,9
|
|
||||||
sapling: BROWN_MUSHROOM
|
|
||||||
plantable-soil:
|
|
||||||
- MYCEL
|
|
||||||
max-log-distance-from-trunk: 4
|
|
||||||
max-leaf-distance-from-log: 4
|
|
||||||
search-for-leaves-diagonally: false
|
|
||||||
drop-original-log: false
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: BROWN_MUSHROOM
|
|
||||||
chance: 25
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
red_mushroom:
|
|
||||||
logs:
|
|
||||||
- HUGE_MUSHROOM_2:15,10
|
|
||||||
leaves:
|
|
||||||
- HUGE_MUSHROOM_2:14,0,1,2,3,4,5,6,7,8,9
|
|
||||||
sapling: RED_MUSHROOM
|
|
||||||
plantable-soil:
|
|
||||||
- MYCEL
|
|
||||||
max-log-distance-from-trunk: 4
|
|
||||||
max-leaf-distance-from-log: 4
|
|
||||||
search-for-leaves-diagonally: true
|
|
||||||
drop-original-log: false
|
|
||||||
drop-original-leaf: false
|
|
||||||
log-loot: []
|
|
||||||
leaf-loot:
|
|
||||||
0:
|
|
||||||
material: RED_MUSHROOM
|
|
||||||
chance: 25
|
|
||||||
entire-tree-loot: []
|
|
||||||
required-tools: []
|
|
||||||
|
|
||||||
# All soil types that the tree type's saplings can be planted on
|
|
||||||
global-plantable-soil:
|
|
||||||
- GRASS
|
|
||||||
- DIRT:0
|
|
||||||
- DIRT:1
|
|
||||||
- DIRT:2
|
|
||||||
|
|
||||||
# Custom loot that is available for all tree types
|
|
||||||
# The loot applies to each log broken in the tree
|
|
||||||
# To add more, increment the number by 1
|
|
||||||
# The chance is out of 100 and can contain decimals
|
|
||||||
# The default examples here are to show what you can do with custom loot
|
|
||||||
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
|
|
||||||
global-log-loot:
|
|
||||||
0:
|
|
||||||
material: DIAMOND
|
|
||||||
chance: 0
|
|
||||||
1:
|
|
||||||
command: 'eco give %player% 5'
|
|
||||||
chance: 0
|
|
||||||
2:
|
|
||||||
material: GOLDEN_APPLE
|
|
||||||
command: 'broadcast %player% found a golden apple in a %type% tree at %xPos% %yPos% %zPos%!'
|
|
||||||
chance: 0
|
|
||||||
|
|
||||||
# Custom loot that is available for all tree types
|
|
||||||
# The loot applies to each leaf broken in the tree
|
|
||||||
# To add more, increment the number by 1
|
|
||||||
# The chance is out of 100 and can contain decimals
|
|
||||||
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
|
|
||||||
global-leaf-loot:
|
|
||||||
0:
|
|
||||||
material: GOLDEN_APPLE
|
|
||||||
chance: 0.1
|
|
||||||
|
|
||||||
# Custom entire tree loot that is available for all tree types
|
|
||||||
# The loot will be dropped only one time for the entire tree
|
|
||||||
# To add more, increment the number by 1
|
|
||||||
# The chance is out of 100 and can contain decimals
|
|
||||||
# Valid command placeholders: %player%, %type%, %xPos%, %yPos%, %zPos%
|
|
||||||
global-entire-tree-loot:
|
|
||||||
0:
|
|
||||||
material: DIAMOND
|
|
||||||
chance: 0
|
|
||||||
|
|
||||||
# Tools that must be used to topple over a tree
|
|
||||||
# Applies to all tree types
|
|
||||||
global-required-tools:
|
|
||||||
- WOOD_AXE
|
|
||||||
- STONE_AXE
|
|
||||||
- IRON_AXE
|
|
||||||
- GOLD_AXE
|
|
||||||
- DIAMOND_AXE
|
|
@ -1,40 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.events;
|
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a tree will fall
|
|
||||||
*/
|
|
||||||
public class TreeFallEvent extends TreeEvent implements Cancellable {
|
|
||||||
|
|
||||||
private boolean cancelled = false;
|
|
||||||
|
|
||||||
public TreeFallEvent(Player player, DetectedTree detectedTree) {
|
|
||||||
super(player, detectedTree);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return this.cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCancelled(boolean cancelled) {
|
|
||||||
this.cancelled = cancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.events;
|
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a tree fell
|
|
||||||
*/
|
|
||||||
public class TreeFellEvent extends TreeEvent {
|
|
||||||
|
|
||||||
public TreeFellEvent(Player player, DetectedTree detectedTree) {
|
|
||||||
super(player, detectedTree);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final HandlerList handlers = new HandlerList();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HandlerList getHandlerList() {
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,362 +0,0 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
|
||||||
|
|
||||||
import com.songoda.core.hooks.McMMOHook;
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
|
||||||
import com.songoda.ultimatetimber.tree.TreeLoot;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class TreeDefinitionManager extends Manager {
|
|
||||||
|
|
||||||
private final Random random;
|
|
||||||
private Set<TreeDefinition> treeDefinitions;
|
|
||||||
private Set<IBlockData> globalPlantableSoil;
|
|
||||||
private Set<TreeLoot> globalLogLoot, globalLeafLoot, globalEntireTreeLoot;
|
|
||||||
private Set<ItemStack> globalRequiredTools;
|
|
||||||
|
|
||||||
public TreeDefinitionManager(UltimateTimber ultimateTimber) {
|
|
||||||
super(ultimateTimber);
|
|
||||||
this.random = new Random();
|
|
||||||
this.treeDefinitions = new HashSet<>();
|
|
||||||
this.globalPlantableSoil = new HashSet<>();
|
|
||||||
this.globalLogLoot = new HashSet<>();
|
|
||||||
this.globalLeafLoot = new HashSet<>();
|
|
||||||
this.globalEntireTreeLoot = new HashSet<>();
|
|
||||||
this.globalRequiredTools = new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reload() {
|
|
||||||
this.treeDefinitions.clear();
|
|
||||||
this.globalPlantableSoil.clear();
|
|
||||||
this.globalLogLoot.clear();
|
|
||||||
this.globalLeafLoot.clear();
|
|
||||||
this.globalEntireTreeLoot.clear();
|
|
||||||
this.globalRequiredTools.clear();
|
|
||||||
|
|
||||||
VersionAdapter versionAdapter = this.plugin.getVersionAdapter();
|
|
||||||
ConfigurationManager configurationManager = this.plugin.getConfigurationManager();
|
|
||||||
YamlConfiguration config = configurationManager.getConfig();
|
|
||||||
|
|
||||||
// Load tree settings
|
|
||||||
ConfigurationSection treeSection = config.getConfigurationSection("trees");
|
|
||||||
top:
|
|
||||||
for (String key : treeSection.getKeys(false)) {
|
|
||||||
ConfigurationSection tree = treeSection.getConfigurationSection(key);
|
|
||||||
|
|
||||||
Set<IBlockData> logBlockData = new HashSet<>();
|
|
||||||
Set<IBlockData> leafBlockData = new HashSet<>();
|
|
||||||
IBlockData saplingBlockData;
|
|
||||||
Set<IBlockData> plantableSoilBlockData = new HashSet<>();
|
|
||||||
double maxLogDistanceFromTrunk;
|
|
||||||
int maxLeafDistanceFromLog;
|
|
||||||
boolean detectLeavesDiagonally;
|
|
||||||
boolean dropOriginalLog;
|
|
||||||
boolean dropOriginalLeaf;
|
|
||||||
Set<TreeLoot> logLoot = new HashSet<>();
|
|
||||||
Set<TreeLoot> leafLoot = new HashSet<>();
|
|
||||||
Set<TreeLoot> entireTreeLoot = new HashSet<>();
|
|
||||||
Set<ItemStack> requiredTools = new HashSet<>();
|
|
||||||
|
|
||||||
for (String blockDataString : tree.getStringList("logs")) {
|
|
||||||
IBlockData blockData = versionAdapter.parseBlockDataFromString(blockDataString);
|
|
||||||
if (blockData == null || blockData.getMaterial() == null) continue top;
|
|
||||||
logBlockData.add(blockData);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String blockDataString : tree.getStringList("leaves")) {
|
|
||||||
IBlockData blockData = versionAdapter.parseBlockDataFromString(blockDataString);
|
|
||||||
if (blockData == null || blockData.getMaterial() == null) continue top;
|
|
||||||
leafBlockData.add(blockData);
|
|
||||||
}
|
|
||||||
|
|
||||||
saplingBlockData = versionAdapter.parseBlockDataFromString(tree.getString("sapling"));
|
|
||||||
|
|
||||||
for (String blockDataString : tree.getStringList("plantable-soil"))
|
|
||||||
plantableSoilBlockData.add(versionAdapter.parseBlockDataFromString(blockDataString));
|
|
||||||
|
|
||||||
maxLogDistanceFromTrunk = tree.getDouble("max-log-distance-from-trunk");
|
|
||||||
maxLeafDistanceFromLog = tree.getInt("max-leaf-distance-from-log");
|
|
||||||
detectLeavesDiagonally = tree.getBoolean("search-for-leaves-diagonally");
|
|
||||||
dropOriginalLog = tree.getBoolean("drop-original-log");
|
|
||||||
dropOriginalLeaf = tree.getBoolean("drop-original-leaf");
|
|
||||||
|
|
||||||
ConfigurationSection logLootSection = tree.getConfigurationSection("log-loot");
|
|
||||||
if (logLootSection != null)
|
|
||||||
for (String lootKey : logLootSection.getKeys(false))
|
|
||||||
logLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LOG, logLootSection.getConfigurationSection(lootKey)));
|
|
||||||
|
|
||||||
ConfigurationSection leafLootSection = tree.getConfigurationSection("leaf-loot");
|
|
||||||
if (leafLootSection != null)
|
|
||||||
for (String lootKey : leafLootSection.getKeys(false))
|
|
||||||
leafLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LEAF, leafLootSection.getConfigurationSection(lootKey)));
|
|
||||||
|
|
||||||
ConfigurationSection entireTreeLootSection = tree.getConfigurationSection("entire-tree-loot");
|
|
||||||
if (entireTreeLootSection != null)
|
|
||||||
for (String lootKey : entireTreeLootSection.getKeys(false))
|
|
||||||
entireTreeLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LEAF, entireTreeLootSection.getConfigurationSection(lootKey)));
|
|
||||||
|
|
||||||
for (String itemStackString : tree.getStringList("required-tools")) {
|
|
||||||
ItemStack tool = versionAdapter.parseItemStackFromString(itemStackString);
|
|
||||||
if (tool == null) continue top;
|
|
||||||
requiredTools.add(tool);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.treeDefinitions.add(new TreeDefinition(key, logBlockData, leafBlockData, saplingBlockData, plantableSoilBlockData, maxLogDistanceFromTrunk,
|
|
||||||
maxLeafDistanceFromLog, detectLeavesDiagonally, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, entireTreeLoot, requiredTools));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load global plantable soil
|
|
||||||
for (String blockDataString : config.getStringList("global-plantable-soil"))
|
|
||||||
this.globalPlantableSoil.add(versionAdapter.parseBlockDataFromString(blockDataString));
|
|
||||||
|
|
||||||
// Load global log drops
|
|
||||||
ConfigurationSection logSection = config.getConfigurationSection("global-log-loot");
|
|
||||||
if (logSection != null)
|
|
||||||
for (String lootKey : logSection.getKeys(false))
|
|
||||||
this.globalLogLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LOG, logSection.getConfigurationSection(lootKey)));
|
|
||||||
|
|
||||||
// Load global leaf drops
|
|
||||||
ConfigurationSection leafSection = config.getConfigurationSection("global-leaf-loot");
|
|
||||||
if (leafSection != null)
|
|
||||||
for (String lootKey : leafSection.getKeys(false))
|
|
||||||
this.globalLeafLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LEAF, leafSection.getConfigurationSection(lootKey)));
|
|
||||||
|
|
||||||
// Load global entire tree drops
|
|
||||||
ConfigurationSection entireTreeSection = config.getConfigurationSection("global-entire-tree-loot");
|
|
||||||
if (entireTreeSection != null)
|
|
||||||
for (String lootKey : entireTreeSection.getKeys(false))
|
|
||||||
this.globalEntireTreeLoot.add(this.getTreeLootEntry(versionAdapter, TreeBlockType.LOG, entireTreeSection.getConfigurationSection(lootKey)));
|
|
||||||
|
|
||||||
// Load global tools
|
|
||||||
for (String itemStackString : config.getStringList("global-required-tools")) {
|
|
||||||
ItemStack tool = versionAdapter.parseItemStackFromString(itemStackString);
|
|
||||||
if (tool == null) continue;
|
|
||||||
this.globalRequiredTools.add(tool);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disable() {
|
|
||||||
this.treeDefinitions.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a Set of possible TreeDefinitions that match the given Block
|
|
||||||
*
|
|
||||||
* @param block The Block to check
|
|
||||||
* @return A Set of TreeDefinitions for the given Block
|
|
||||||
*/
|
|
||||||
public Set<TreeDefinition> getTreeDefinitionsForLog(Block block) {
|
|
||||||
return this.narrowTreeDefinition(this.treeDefinitions, block, TreeBlockType.LOG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Narrows a Set of TreeDefinitions down to ones matching the given Block and TreeBlockType
|
|
||||||
*
|
|
||||||
* @param possibleTreeDefinitions The possible TreeDefinitions
|
|
||||||
* @param block The Block to narrow to
|
|
||||||
* @param treeBlockType The TreeBlockType of the given Block
|
|
||||||
* @return A Set of TreeDefinitions narrowed down
|
|
||||||
*/
|
|
||||||
public Set<TreeDefinition> narrowTreeDefinition(Set<TreeDefinition> possibleTreeDefinitions, Block block, TreeBlockType treeBlockType) {
|
|
||||||
Set<TreeDefinition> matchingTreeDefinitions = new HashSet<>();
|
|
||||||
switch (treeBlockType) {
|
|
||||||
case LOG:
|
|
||||||
for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
|
|
||||||
for (IBlockData logBlockData : treeDefinition.getLogBlockData()) {
|
|
||||||
if (logBlockData.isSimilar(block)) {
|
|
||||||
matchingTreeDefinitions.add(treeDefinition);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LEAF:
|
|
||||||
for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
|
|
||||||
for (IBlockData leafBlockData : treeDefinition.getLeafBlockData()) {
|
|
||||||
if (leafBlockData.isSimilar(block)) {
|
|
||||||
matchingTreeDefinitions.add(treeDefinition);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchingTreeDefinitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a given tool is valid for any tree definitions, also takes into account global tools
|
|
||||||
*
|
|
||||||
* @param tool The tool to check
|
|
||||||
* @return True if the tool is allowed for toppling any trees
|
|
||||||
*/
|
|
||||||
public boolean isToolValidForAnyTreeDefinition(ItemStack tool) {
|
|
||||||
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean())
|
|
||||||
return true;
|
|
||||||
for (TreeDefinition treeDefinition : this.treeDefinitions)
|
|
||||||
for (ItemStack requiredTool : treeDefinition.getRequiredTools())
|
|
||||||
if (requiredTool.getType().equals(tool.getType()))
|
|
||||||
return true;
|
|
||||||
for (ItemStack requiredTool : this.globalRequiredTools)
|
|
||||||
if (requiredTool.getType().equals(tool.getType()))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a given tool is valid for a given tree definition, also takes into account global tools
|
|
||||||
*
|
|
||||||
* @param treeDefinition The TreeDefinition to use
|
|
||||||
* @param tool The tool to check
|
|
||||||
* @return True if the tool is allowed for toppling the given TreeDefinition
|
|
||||||
*/
|
|
||||||
public boolean isToolValidForTreeDefinition(TreeDefinition treeDefinition, ItemStack tool) {
|
|
||||||
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean())
|
|
||||||
return true;
|
|
||||||
for (ItemStack requiredTool : treeDefinition.getRequiredTools())
|
|
||||||
if (requiredTool.getType().equals(tool.getType()))
|
|
||||||
return true;
|
|
||||||
for (ItemStack requiredTool : this.globalRequiredTools)
|
|
||||||
if (requiredTool.getType().equals(tool.getType()))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to spawn loot for a given TreeBlock with the given TreeDefinition for a given Player
|
|
||||||
*
|
|
||||||
* @param treeDefinition The TreeDefinition to use
|
|
||||||
* @param treeBlock The TreeBlock to drop for
|
|
||||||
* @param player The Player to drop for
|
|
||||||
* @param isForEntireTree If the loot is for the entire tree
|
|
||||||
*/
|
|
||||||
public void dropTreeLoot(TreeDefinition treeDefinition, ITreeBlock treeBlock, Player player, boolean hasSilkTouch, boolean isForEntireTree) {
|
|
||||||
VersionAdapter versionAdapter = this.plugin.getVersionAdapter();
|
|
||||||
|
|
||||||
boolean addToInventory = ConfigurationManager.Setting.ADD_ITEMS_TO_INVENTORY.getBoolean();
|
|
||||||
boolean hasBonusChance = player.hasPermission("ultimatetimber.bonusloot");
|
|
||||||
List<ItemStack> lootedItems = new ArrayList<>();
|
|
||||||
List<String> lootedCommands = new ArrayList<>();
|
|
||||||
|
|
||||||
// Get the loot that we should try to drop
|
|
||||||
List<TreeLoot> toTry = new ArrayList<>();
|
|
||||||
if (isForEntireTree) {
|
|
||||||
toTry.addAll(treeDefinition.getEntireTreeLoot());
|
|
||||||
toTry.addAll(this.globalEntireTreeLoot);
|
|
||||||
} else {
|
|
||||||
if (ConfigurationManager.Setting.APPLY_SILK_TOUCH.getBoolean() && hasSilkTouch) {
|
|
||||||
if (McMMOHook.hasWoodcuttingDoubleDrops(player))
|
|
||||||
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
|
|
||||||
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
|
|
||||||
} else {
|
|
||||||
switch (treeBlock.getTreeBlockType()) {
|
|
||||||
case LOG:
|
|
||||||
toTry.addAll(treeDefinition.getLogLoot());
|
|
||||||
toTry.addAll(this.globalLogLoot);
|
|
||||||
if (treeDefinition.shouldDropOriginalLog()) {
|
|
||||||
if (McMMOHook.hasWoodcuttingDoubleDrops(player))
|
|
||||||
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
|
|
||||||
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LEAF:
|
|
||||||
toTry.addAll(treeDefinition.getLeafLoot());
|
|
||||||
toTry.addAll(this.globalLeafLoot);
|
|
||||||
if (treeDefinition.shouldDropOriginalLeaf()) {
|
|
||||||
if (McMMOHook.hasWoodcuttingDoubleDrops(player))
|
|
||||||
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
|
|
||||||
lootedItems.addAll(versionAdapter.getBlockDrops(treeDefinition, treeBlock));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Roll the dice
|
|
||||||
double bonusLootMultiplier = ConfigurationManager.Setting.BONUS_LOOT_MULTIPLIER.getDouble();
|
|
||||||
for (TreeLoot treeLoot : toTry) {
|
|
||||||
double chance = hasBonusChance ? treeLoot.getChance() * bonusLootMultiplier : treeLoot.getChance();
|
|
||||||
if (this.random.nextDouble() > chance / 100)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (treeLoot.hasItem()) {
|
|
||||||
if (McMMOHook.hasWoodcuttingDoubleDrops(player))
|
|
||||||
lootedItems.add(treeLoot.getItem());
|
|
||||||
lootedItems.add(treeLoot.getItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (treeLoot.hasCommand()) {
|
|
||||||
if (McMMOHook.hasWoodcuttingDoubleDrops(player))
|
|
||||||
lootedCommands.add(treeLoot.getCommand());
|
|
||||||
lootedCommands.add(treeLoot.getCommand());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to inventory or drop on ground
|
|
||||||
if (addToInventory && player.getWorld().equals(treeBlock.getLocation().getWorld())) {
|
|
||||||
List<ItemStack> extraItems = new ArrayList<>();
|
|
||||||
for (ItemStack lootedItem : lootedItems)
|
|
||||||
extraItems.addAll(player.getInventory().addItem(lootedItem).values());
|
|
||||||
Location location = player.getLocation().clone().subtract(0.5, 0, 0.5);
|
|
||||||
for (ItemStack extraItem : extraItems)
|
|
||||||
location.getWorld().dropItemNaturally(location, extraItem);
|
|
||||||
} else {
|
|
||||||
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
|
||||||
for (ItemStack lootedItem : lootedItems)
|
|
||||||
location.getWorld().dropItemNaturally(location, lootedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run looted commands
|
|
||||||
for (String lootedCommand : lootedCommands)
|
|
||||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(),
|
|
||||||
lootedCommand.replace("%player%", player.getName())
|
|
||||||
.replace("%type%", treeDefinition.getKey())
|
|
||||||
.replace("%xPos%", treeBlock.getLocation().getBlockX() + "")
|
|
||||||
.replace("%yPos%", treeBlock.getLocation().getBlockY() + "")
|
|
||||||
.replace("%zPos%", treeBlock.getLocation().getBlockZ() + ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all possible plantable soil blocks for the given tree definition
|
|
||||||
*
|
|
||||||
* @param treeDefinition The TreeDefinition
|
|
||||||
* @return A Set of IBlockData of plantable soil
|
|
||||||
*/
|
|
||||||
public Set<IBlockData> getPlantableSoilBlockData(TreeDefinition treeDefinition) {
|
|
||||||
Set<IBlockData> plantableSoilBlockData = new HashSet<>();
|
|
||||||
plantableSoilBlockData.addAll(treeDefinition.getPlantableSoilBlockData());
|
|
||||||
plantableSoilBlockData.addAll(this.globalPlantableSoil);
|
|
||||||
return plantableSoilBlockData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a TreeLoot entry from a ConfigurationSection
|
|
||||||
*
|
|
||||||
* @param versionAdapter The VersionAdapter to use
|
|
||||||
* @param treeBlockType The TreeBlockType to use
|
|
||||||
* @param configurationSection The ConfigurationSection
|
|
||||||
* @return A TreeLoot entry from the section
|
|
||||||
*/
|
|
||||||
private TreeLoot getTreeLootEntry(VersionAdapter versionAdapter, TreeBlockType treeBlockType, ConfigurationSection configurationSection) {
|
|
||||||
String material = configurationSection.getString("material");
|
|
||||||
ItemStack item = material != null ? versionAdapter.parseItemStackFromString(material) : null;
|
|
||||||
String command = configurationSection.getString("command");
|
|
||||||
double chance = configurationSection.getDouble("chance");
|
|
||||||
return new TreeLoot(treeBlockType, item, command, chance);
|
|
||||||
}
|
|
||||||
}
|
|
BIN
docs/Logo.png
Normal file
BIN
docs/Logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 177 KiB |
189
pom.xml
189
pom.xml
@ -1,104 +1,133 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
<groupId>com.songoda</groupId>
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<artifactId>UltimateTimber</artifactId>
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<version>2.0.9b</version>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<modules>
|
<groupId>com.craftaro</groupId>
|
||||||
<module>UltimateTimber/Core</module>
|
<artifactId>UltimateTimber</artifactId>
|
||||||
<module>UltimateTimber/Plugin</module>
|
<version>3.0.0</version>
|
||||||
<module>UltimateTimber-Adapter/Current</module>
|
|
||||||
<module>UltimateTimber-Adapter/Legacy</module>
|
|
||||||
</modules>
|
|
||||||
|
|
||||||
<repositories>
|
<name>UltimateTimber</name>
|
||||||
<repository>
|
<description>Give your players a new and exciting way to chop down trees</description>
|
||||||
<id>private</id>
|
<url>https://craftaro.com/marketplace/product/18</url>
|
||||||
<url>https://repo.songoda.com/repository/private/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>public</id>
|
|
||||||
<url>http://repo.songoda.com/repository/public/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>spigot-repo</id>
|
|
||||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>jitpack.io</id>
|
|
||||||
<url>https://jitpack.io</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>8</maven.compiler.release>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<url>https://discord.gg/craftaro</url>
|
||||||
|
<system>Discord server</system>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<url>https://github.com/craftaro/UltimateTimber</url>
|
||||||
|
<connection>scm:git:git://github.com/craftaro/UltimateTimber.git</connection>
|
||||||
|
</scm>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<defaultGoal>clean install</defaultGoal>
|
|
||||||
<sourceDirectory>src</sourceDirectory>
|
|
||||||
<testSourceDirectory>test</testSourceDirectory>
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.1</version>
|
<version>3.4.1</version>
|
||||||
<configuration>
|
|
||||||
<source>1.8</source>
|
|
||||||
<target>1.8</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-antrun-plugin</artifactId>
|
|
||||||
<version>1.7</version>
|
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>validate</phase>
|
<phase>package</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>run</goal>
|
<goal>shade</goal>
|
||||||
</goals>
|
</goals>
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<finalName>${project.name}-${project.version}</finalName>
|
||||||
|
|
||||||
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
|
<useDependencyReducedPomInJar>true</useDependencyReducedPomInJar>
|
||||||
|
<minimizeJar>true</minimizeJar>
|
||||||
|
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.craftaro.core</pattern>
|
||||||
|
<shadedPattern>com.craftaro.ultimatetimber.core</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/**</exclude>
|
||||||
|
<exclude>LICENSE</exclude>
|
||||||
|
<exclude>LICENSE.**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<artifact>com.craftaro:CraftaroCore</artifact>
|
||||||
|
<excludeDefaults>false</excludeDefaults>
|
||||||
|
<includes>
|
||||||
|
<include>**/nms/v*/**</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/third_party/org/apache/**</exclude>
|
||||||
|
<exclude>**/third_party/net/kyori/**</exclude>
|
||||||
|
<exclude>**/third_party/com/zaxxer/**</exclude>
|
||||||
|
<exclude>**/third_party/org/jooq/**</exclude>
|
||||||
|
<exclude>**/third_party/org/mariadb/**</exclude>
|
||||||
|
<exclude>**/third_party/com/h2database/**</exclude>
|
||||||
|
<exclude>**/third_party/org/h2/**</exclude>
|
||||||
|
<exclude>**/third_party/com/cryptomorin/**</exclude>
|
||||||
|
<exclude>**/third_party/org/reactivestreams/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
<inherited>false</inherited>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<version>2.8</version>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>jars</outputDirectory>
|
|
||||||
<stripVersion>true</stripVersion>
|
|
||||||
<artifactItems>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>LegacyAdapter</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>McMMO</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>Plugin</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>Core</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
</configuration>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>craftaro-minecraft-plugins</id>
|
||||||
|
<url>https://repo.craftaro.com/repository/minecraft-plugins/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>SpigotMC</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.craftaro</groupId>
|
||||||
|
<artifactId>CraftaroCore</artifactId>
|
||||||
|
<version>3.0.0-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- TODO: Check if spigot-api can be downgraded to 1.8 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.18-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,35 +1,35 @@
|
|||||||
package com.songoda.ultimatetimber;
|
package com.craftaro.ultimatetimber;
|
||||||
|
|
||||||
import com.songoda.core.SongodaCore;
|
import com.craftaro.core.SongodaCore;
|
||||||
import com.songoda.core.SongodaPlugin;
|
import com.craftaro.core.SongodaPlugin;
|
||||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
import com.craftaro.core.commands.CommandManager;
|
||||||
import com.songoda.core.configuration.Config;
|
import com.craftaro.core.configuration.Config;
|
||||||
import com.songoda.core.hooks.LogManager;
|
import com.craftaro.core.dependency.Dependency;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.core.hooks.LogManager;
|
||||||
import com.songoda.ultimatetimber.adapter.current.CurrentAdapter;
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
import com.songoda.ultimatetimber.adapter.legacy.LegacyAdapter;
|
import com.craftaro.ultimatetimber.commands.CommandGiveAxe;
|
||||||
import com.songoda.ultimatetimber.commands.CommandReload;
|
import com.craftaro.ultimatetimber.commands.CommandReload;
|
||||||
import com.songoda.ultimatetimber.commands.CommandToggle;
|
import com.craftaro.ultimatetimber.commands.CommandToggle;
|
||||||
import com.songoda.ultimatetimber.manager.*;
|
import com.craftaro.ultimatetimber.manager.PlacedBlockManager;
|
||||||
import com.songoda.ultimatetimber.utils.NMSUtil;
|
import com.craftaro.ultimatetimber.manager.TreeDetectionManager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.ChoppingManager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.ConfigurationManager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.Manager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.SaplingManager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.TreeAnimationManager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.TreeDefinitionManager;
|
||||||
|
import com.craftaro.ultimatetimber.manager.TreeFallManager;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Esophose
|
|
||||||
*/
|
|
||||||
public class UltimateTimber extends SongodaPlugin {
|
public class UltimateTimber extends SongodaPlugin {
|
||||||
|
private final Set<Manager> managers = new HashSet<>();
|
||||||
|
|
||||||
private static UltimateTimber INSTANCE;
|
|
||||||
|
|
||||||
private Set<Manager> managers;
|
|
||||||
|
|
||||||
private VersionAdapter versionAdapter;
|
|
||||||
private ChoppingManager choppingManager;
|
private ChoppingManager choppingManager;
|
||||||
private ConfigurationManager configurationManager;
|
private ConfigurationManager configurationManager;
|
||||||
private com.songoda.core.commands.CommandManager commandManager;
|
|
||||||
private PlacedBlockManager placedBlockManager;
|
private PlacedBlockManager placedBlockManager;
|
||||||
private SaplingManager saplingManager;
|
private SaplingManager saplingManager;
|
||||||
private TreeAnimationManager treeAnimationManager;
|
private TreeAnimationManager treeAnimationManager;
|
||||||
@ -37,32 +37,41 @@ public class UltimateTimber extends SongodaPlugin {
|
|||||||
private TreeDetectionManager treeDetectionManager;
|
private TreeDetectionManager treeDetectionManager;
|
||||||
private TreeFallManager treeFallManager;
|
private TreeFallManager treeFallManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getPlugin(Class)} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static UltimateTimber getInstance() {
|
public static UltimateTimber getInstance() {
|
||||||
return INSTANCE;
|
return getPlugin(UltimateTimber.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<Dependency> getDependencies() {
|
||||||
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPluginLoad() {
|
public void onPluginLoad() {
|
||||||
INSTANCE = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPluginEnable() {
|
public void onPluginEnable() {
|
||||||
// Run Songoda Updater
|
// Run Songoda Updater
|
||||||
SongodaCore.registerPlugin(this, 18, CompatibleMaterial.IRON_AXE);
|
SongodaCore.registerPlugin(this, 18, XMaterial.IRON_AXE);
|
||||||
|
|
||||||
// Load hooks
|
// Load hooks
|
||||||
LogManager.load();
|
LogManager.load();
|
||||||
|
|
||||||
// Setup plugin commands
|
// Setup plugin commands
|
||||||
this.commandManager = new com.songoda.core.commands.CommandManager(this);
|
CommandManager commandManager = new CommandManager(this);
|
||||||
this.commandManager.addMainCommand("ut")
|
commandManager.addMainCommand("ut")
|
||||||
.addSubCommands(new CommandReload(this),
|
.addSubCommands(
|
||||||
new CommandToggle(this)
|
new CommandReload(this),
|
||||||
|
new CommandToggle(this),
|
||||||
|
new CommandGiveAxe(this)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Register managers
|
// Register managers
|
||||||
this.managers = new HashSet<>();
|
|
||||||
this.choppingManager = this.registerManager(ChoppingManager.class);
|
this.choppingManager = this.registerManager(ChoppingManager.class);
|
||||||
this.configurationManager = new ConfigurationManager(this);
|
this.configurationManager = new ConfigurationManager(this);
|
||||||
this.placedBlockManager = this.registerManager(PlacedBlockManager.class);
|
this.placedBlockManager = this.registerManager(PlacedBlockManager.class);
|
||||||
@ -72,14 +81,13 @@ public class UltimateTimber extends SongodaPlugin {
|
|||||||
this.treeDetectionManager = this.registerManager(TreeDetectionManager.class);
|
this.treeDetectionManager = this.registerManager(TreeDetectionManager.class);
|
||||||
this.treeFallManager = this.registerManager(TreeFallManager.class);
|
this.treeFallManager = this.registerManager(TreeFallManager.class);
|
||||||
|
|
||||||
// Load version adapter and managers
|
|
||||||
this.setupVersionAdapter();
|
|
||||||
this.reloadConfig();
|
this.reloadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPluginDisable() {
|
public void onPluginDisable() {
|
||||||
this.disable();
|
this.configurationManager.disable();
|
||||||
|
this.managers.forEach(Manager::disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -95,26 +103,7 @@ public class UltimateTimber extends SongodaPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Config> getExtraConfig() {
|
public List<Config> getExtraConfig() {
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables most of the plugin
|
|
||||||
*/
|
|
||||||
public void disable() {
|
|
||||||
this.configurationManager.disable();
|
|
||||||
this.managers.forEach(Manager::disable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the version adapter
|
|
||||||
*/
|
|
||||||
private void setupVersionAdapter() {
|
|
||||||
if (NMSUtil.getVersionNumber() > 12) {
|
|
||||||
this.versionAdapter = new CurrentAdapter();
|
|
||||||
} else {
|
|
||||||
this.versionAdapter = new LegacyAdapter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,85 +124,35 @@ public class UltimateTimber extends SongodaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the active version adapter being used
|
|
||||||
*
|
|
||||||
* @return The VersionAdapter being used for the plugin
|
|
||||||
*/
|
|
||||||
public VersionAdapter getVersionAdapter() {
|
|
||||||
return this.versionAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the chopping manager
|
|
||||||
*
|
|
||||||
* @return The ChoppingManager instance
|
|
||||||
*/
|
|
||||||
public ChoppingManager getChoppingManager() {
|
public ChoppingManager getChoppingManager() {
|
||||||
return this.choppingManager;
|
return this.choppingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the configuration manager
|
|
||||||
*
|
|
||||||
* @return The ConfigurationManager instance
|
|
||||||
*/
|
|
||||||
public ConfigurationManager getConfigurationManager() {
|
public ConfigurationManager getConfigurationManager() {
|
||||||
return this.configurationManager;
|
return this.configurationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the placed block manager
|
|
||||||
*
|
|
||||||
* @return The PlacedBlockManager instance
|
|
||||||
*/
|
|
||||||
public PlacedBlockManager getPlacedBlockManager() {
|
public PlacedBlockManager getPlacedBlockManager() {
|
||||||
return this.placedBlockManager;
|
return this.placedBlockManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the sapling manager
|
|
||||||
*
|
|
||||||
* @return The SaplingManager instance
|
|
||||||
*/
|
|
||||||
public SaplingManager getSaplingManager() {
|
public SaplingManager getSaplingManager() {
|
||||||
return this.saplingManager;
|
return this.saplingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the tree animation manager
|
|
||||||
*
|
|
||||||
* @return The TreeAnimationManager instance
|
|
||||||
*/
|
|
||||||
public TreeAnimationManager getTreeAnimationManager() {
|
public TreeAnimationManager getTreeAnimationManager() {
|
||||||
return this.treeAnimationManager;
|
return this.treeAnimationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the tree definition manager
|
|
||||||
*
|
|
||||||
* @return The TreeDefinitionManager instance
|
|
||||||
*/
|
|
||||||
public TreeDefinitionManager getTreeDefinitionManager() {
|
public TreeDefinitionManager getTreeDefinitionManager() {
|
||||||
return this.treeDefinitionManager;
|
return this.treeDefinitionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the tree detection manager
|
|
||||||
*
|
|
||||||
* @return The TreeDetectionManager instance
|
|
||||||
*/
|
|
||||||
public TreeDetectionManager getTreeDetectionManager() {
|
public TreeDetectionManager getTreeDetectionManager() {
|
||||||
return this.treeDetectionManager;
|
return this.treeDetectionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the tree fall manager
|
|
||||||
*
|
|
||||||
* @return The TreeFallManager instance
|
|
||||||
*/
|
|
||||||
public TreeFallManager getTreeFallManager() {
|
public TreeFallManager getTreeFallManager() {
|
||||||
return this.treeFallManager;
|
return this.treeFallManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,12 +1,15 @@
|
|||||||
package com.songoda.ultimatetimber.animation;
|
package com.craftaro.ultimatetimber.animation;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleHand;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
import com.craftaro.ultimatetimber.tree.FallingTreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockSet;
|
||||||
|
import com.craftaro.ultimatetimber.utils.BlockUtils;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@ -16,7 +19,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
public abstract class TreeAnimation {
|
public abstract class TreeAnimation {
|
||||||
|
|
||||||
protected final TreeAnimationType treeAnimationType;
|
protected final TreeAnimationType treeAnimationType;
|
||||||
protected final DetectedTree detectedTree;
|
protected final DetectedTree detectedTree;
|
||||||
protected final Player player;
|
protected final Player player;
|
||||||
@ -28,7 +30,7 @@ public abstract class TreeAnimation {
|
|||||||
this.detectedTree = detectedTree;
|
this.detectedTree = detectedTree;
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
ItemStack itemInHand = UltimateTimber.getInstance().getVersionAdapter().getItemInHand(player);
|
ItemStack itemInHand = CompatibleHand.getHand(CompatibleHand.MAIN_HAND).getItem(player);
|
||||||
this.hasSilkTouch = itemInHand != null && itemInHand.hasItemMeta() && itemInHand.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH);
|
this.hasSilkTouch = itemInHand != null && itemInHand.hasItemMeta() && itemInHand.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH);
|
||||||
|
|
||||||
this.fallingTreeBlocks = new TreeBlockSet<>(); // Should be overridden in any subclasses that need to use it
|
this.fallingTreeBlocks = new TreeBlockSet<>(); // Should be overridden in any subclasses that need to use it
|
||||||
@ -94,17 +96,16 @@ public abstract class TreeAnimation {
|
|||||||
* @return A FallingTreeBlock that has been converted from a TreeBlock
|
* @return A FallingTreeBlock that has been converted from a TreeBlock
|
||||||
*/
|
*/
|
||||||
protected FallingTreeBlock convertToFallingBlock(TreeBlock treeBlock) {
|
protected FallingTreeBlock convertToFallingBlock(TreeBlock treeBlock) {
|
||||||
VersionAdapter versionAdapter = UltimateTimber.getInstance().getVersionAdapter();
|
|
||||||
Location location = treeBlock.getLocation().clone().add(0.5, 0, 0.5);
|
Location location = treeBlock.getLocation().clone().add(0.5, 0, 0.5);
|
||||||
Block block = treeBlock.getBlock();
|
Block block = treeBlock.getBlock();
|
||||||
|
XMaterial material = CompatibleMaterial.getMaterial(block.getType()).get();
|
||||||
if (block.getType().equals(Material.AIR)) {
|
if (CompatibleMaterial.isAir(material)) {
|
||||||
this.replaceBlock(treeBlock);
|
this.replaceBlock(treeBlock);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
FallingBlock fallingBlock = versionAdapter.spawnFallingBlock(location, block);
|
FallingBlock fallingBlock = BlockUtils.spawnFallingBlock(location, material);
|
||||||
UltimateTimber.getInstance().getVersionAdapter().configureFallingBlock(fallingBlock);
|
BlockUtils.configureFallingBlock(fallingBlock);
|
||||||
|
|
||||||
FallingTreeBlock fallingTreeBlock = new FallingTreeBlock(fallingBlock, treeBlock.getTreeBlockType());
|
FallingTreeBlock fallingTreeBlock = new FallingTreeBlock(fallingBlock, treeBlock.getTreeBlockType());
|
||||||
this.replaceBlock(treeBlock);
|
this.replaceBlock(treeBlock);
|
@ -1,15 +1,18 @@
|
|||||||
package com.songoda.ultimatetimber.animation;
|
package com.craftaro.ultimatetimber.animation;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.manager.ConfigurationManager;
|
import com.craftaro.ultimatetimber.manager.ConfigurationManager;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
|
import com.craftaro.ultimatetimber.tree.FallingTreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
import com.craftaro.ultimatetimber.tree.TreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
import com.craftaro.ultimatetimber.tree.TreeBlockSet;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
import com.craftaro.ultimatetimber.tree.TreeBlockType;
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
import com.craftaro.ultimatetimber.tree.TreeDefinition;
|
||||||
|
import com.craftaro.ultimatetimber.utils.BlockUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.ParticleUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.SoundUtils;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
@ -21,7 +24,6 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TreeAnimationCrumble extends TreeAnimation {
|
public class TreeAnimationCrumble extends TreeAnimation {
|
||||||
|
|
||||||
public TreeAnimationCrumble(DetectedTree detectedTree, Player player) {
|
public TreeAnimationCrumble(DetectedTree detectedTree, Player player) {
|
||||||
super(TreeAnimationType.CRUMBLE, detectedTree, player);
|
super(TreeAnimationType.CRUMBLE, detectedTree, player);
|
||||||
}
|
}
|
||||||
@ -29,7 +31,6 @@ public class TreeAnimationCrumble extends TreeAnimation {
|
|||||||
@Override
|
@Override
|
||||||
public void playAnimation(Runnable whenFinished) {
|
public void playAnimation(Runnable whenFinished) {
|
||||||
UltimateTimber ultimateTimber = UltimateTimber.getInstance();
|
UltimateTimber ultimateTimber = UltimateTimber.getInstance();
|
||||||
VersionAdapter versionAdapter = ultimateTimber.getVersionAdapter();
|
|
||||||
|
|
||||||
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
||||||
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
||||||
@ -62,29 +63,35 @@ public class TreeAnimationCrumble extends TreeAnimation {
|
|||||||
List<ITreeBlock<Block>> partition = treeBlocks.get(0);
|
List<ITreeBlock<Block>> partition = treeBlocks.get(0);
|
||||||
for (int i = 0; i < 3 && !partition.isEmpty(); i++) {
|
for (int i = 0; i < 3 && !partition.isEmpty(); i++) {
|
||||||
ITreeBlock<Block> treeBlock = partition.remove(0);
|
ITreeBlock<Block> treeBlock = partition.remove(0);
|
||||||
if (treeBlock.getTreeBlockType().equals(TreeBlockType.LOG)) {
|
if (treeBlock.getTreeBlockType() == TreeBlockType.LOG) {
|
||||||
if (td.getLogBlockData().stream().noneMatch(x -> x.isSimilar(treeBlock.getBlock())))
|
if (td.getLogMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) {
|
||||||
continue;
|
continue;
|
||||||
} else if (treeBlock.getTreeBlockType().equals(TreeBlockType.LEAF)) {
|
}
|
||||||
if (td.getLeafBlockData().stream().noneMatch(x -> x.isSimilar(treeBlock.getBlock())))
|
} else if (treeBlock.getTreeBlockType() == TreeBlockType.LEAF) {
|
||||||
|
if (td.getLeafMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FallingTreeBlock fallingTreeBlock = TreeAnimationCrumble.this.convertToFallingBlock((TreeBlock)treeBlock);
|
FallingTreeBlock fallingTreeBlock = TreeAnimationCrumble.this.convertToFallingBlock((TreeBlock) treeBlock);
|
||||||
if (fallingTreeBlock == null)
|
if (fallingTreeBlock == null) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
versionAdapter.toggleGravityFallingBlock(fallingTreeBlock.getBlock(), true);
|
BlockUtils.toggleGravityFallingBlock(fallingTreeBlock.getBlock(), true);
|
||||||
fallingTreeBlock.getBlock().setVelocity(Vector.getRandom().setY(0).subtract(new Vector(0.5, 0, 0.5)).multiply(0.15));
|
fallingTreeBlock.getBlock().setVelocity(Vector.getRandom().setY(0).subtract(new Vector(0.5, 0, 0.5)).multiply(0.15));
|
||||||
TreeAnimationCrumble.this.fallingTreeBlocks.add(fallingTreeBlock);
|
TreeAnimationCrumble.this.fallingTreeBlocks.add(fallingTreeBlock);
|
||||||
|
|
||||||
if (TreeAnimationCrumble.this.fallingTreeBlocks == null)
|
if (TreeAnimationCrumble.this.fallingTreeBlocks == null) {
|
||||||
TreeAnimationCrumble.this.fallingTreeBlocks = new TreeBlockSet<>(fallingTreeBlock);
|
TreeAnimationCrumble.this.fallingTreeBlocks = new TreeBlockSet<>(fallingTreeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
if (useCustomSound)
|
if (useCustomSound) {
|
||||||
versionAdapter.playLandingSound(treeBlock);
|
SoundUtils.playLandingSound(treeBlock);
|
||||||
if (useCustomParticles)
|
}
|
||||||
versionAdapter.playFallingParticles(td, treeBlock);
|
if (useCustomParticles) {
|
||||||
|
ParticleUtils.playFallingParticles(treeBlock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partition.isEmpty()) {
|
if (partition.isEmpty()) {
|
||||||
@ -100,4 +107,3 @@ public class TreeAnimationCrumble extends TreeAnimation {
|
|||||||
}.runTaskTimer(ultimateTimber, 0, 1);
|
}.runTaskTimer(ultimateTimber, 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,16 @@
|
|||||||
package com.songoda.ultimatetimber.animation;
|
package com.craftaro.ultimatetimber.animation;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.manager.ConfigurationManager;
|
import com.craftaro.ultimatetimber.manager.TreeDefinitionManager;
|
||||||
import com.songoda.ultimatetimber.manager.TreeDefinitionManager;
|
import com.craftaro.ultimatetimber.manager.ConfigurationManager;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
import com.craftaro.ultimatetimber.tree.TreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
import com.craftaro.ultimatetimber.tree.TreeBlockType;
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
import com.craftaro.ultimatetimber.tree.TreeDefinition;
|
||||||
|
import com.craftaro.ultimatetimber.utils.ParticleUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.SoundUtils;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.FallingBlock;
|
import org.bukkit.entity.FallingBlock;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -21,7 +23,6 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TreeAnimationDisintegrate extends TreeAnimation {
|
public class TreeAnimationDisintegrate extends TreeAnimation {
|
||||||
|
|
||||||
public TreeAnimationDisintegrate(DetectedTree detectedTree, Player player) {
|
public TreeAnimationDisintegrate(DetectedTree detectedTree, Player player) {
|
||||||
super(TreeAnimationType.DISINTEGRATE, detectedTree, player);
|
super(TreeAnimationType.DISINTEGRATE, detectedTree, player);
|
||||||
}
|
}
|
||||||
@ -30,7 +31,6 @@ public class TreeAnimationDisintegrate extends TreeAnimation {
|
|||||||
public void playAnimation(Runnable whenFinished) {
|
public void playAnimation(Runnable whenFinished) {
|
||||||
UltimateTimber ultimateTimber = UltimateTimber.getInstance();
|
UltimateTimber ultimateTimber = UltimateTimber.getInstance();
|
||||||
TreeDefinitionManager treeDefinitionManager = ultimateTimber.getTreeDefinitionManager();
|
TreeDefinitionManager treeDefinitionManager = ultimateTimber.getTreeDefinitionManager();
|
||||||
VersionAdapter versionAdapter = ultimateTimber.getVersionAdapter();
|
|
||||||
|
|
||||||
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
||||||
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
||||||
@ -70,20 +70,24 @@ public class TreeAnimationDisintegrate extends TreeAnimation {
|
|||||||
|
|
||||||
if (!toDestroy.isEmpty()) {
|
if (!toDestroy.isEmpty()) {
|
||||||
ITreeBlock<Block> first = toDestroy.get(0);
|
ITreeBlock<Block> first = toDestroy.get(0);
|
||||||
if (useCustomSound)
|
if (useCustomSound) {
|
||||||
versionAdapter.playLandingSound(first);
|
SoundUtils.playLandingSound(first);
|
||||||
|
}
|
||||||
|
|
||||||
for (ITreeBlock<Block> treeBlock : toDestroy) {
|
for (ITreeBlock<Block> treeBlock : toDestroy) {
|
||||||
if (treeBlock.getTreeBlockType().equals(TreeBlockType.LOG)) {
|
if (treeBlock.getTreeBlockType() == TreeBlockType.LOG) {
|
||||||
if (td.getLogBlockData().stream().noneMatch(x -> x.isSimilar(treeBlock.getBlock())))
|
if (td.getLogMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) {
|
||||||
continue;
|
continue;
|
||||||
} else if (treeBlock.getTreeBlockType().equals(TreeBlockType.LEAF)) {
|
}
|
||||||
if (td.getLeafBlockData().stream().noneMatch(x -> x.isSimilar(treeBlock.getBlock())))
|
} else if (treeBlock.getTreeBlockType() == TreeBlockType.LEAF) {
|
||||||
|
if (td.getLeafMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useCustomParticles)
|
if (useCustomParticles) {
|
||||||
versionAdapter.playFallingParticles(td, treeBlock);
|
ParticleUtils.playFallingParticles(treeBlock);
|
||||||
|
}
|
||||||
treeDefinitionManager.dropTreeLoot(td, treeBlock, p, hst, false);
|
treeDefinitionManager.dropTreeLoot(td, treeBlock, p, hst, false);
|
||||||
TreeAnimationDisintegrate.this.replaceBlock((TreeBlock) treeBlock);
|
TreeAnimationDisintegrate.this.replaceBlock((TreeBlock) treeBlock);
|
||||||
}
|
}
|
||||||
@ -94,5 +98,4 @@ public class TreeAnimationDisintegrate extends TreeAnimation {
|
|||||||
}
|
}
|
||||||
}.runTaskTimer(ultimateTimber, 0, 1);
|
}.runTaskTimer(ultimateTimber, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +1,16 @@
|
|||||||
package com.songoda.ultimatetimber.animation;
|
package com.craftaro.ultimatetimber.animation;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.ultimatetimber.manager.ConfigurationManager;
|
||||||
import com.songoda.ultimatetimber.manager.ConfigurationManager;
|
import com.craftaro.ultimatetimber.manager.TreeAnimationManager;
|
||||||
import com.songoda.ultimatetimber.manager.TreeAnimationManager;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.tree.FallingTreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.FallingTreeBlock;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.tree.TreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
import com.craftaro.ultimatetimber.tree.TreeBlockSet;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
import com.craftaro.ultimatetimber.utils.BlockUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.ParticleUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.SoundUtils;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.FallingBlock;
|
import org.bukkit.entity.FallingBlock;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -16,7 +18,6 @@ import org.bukkit.scheduler.BukkitRunnable;
|
|||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public class TreeAnimationFancy extends TreeAnimation {
|
public class TreeAnimationFancy extends TreeAnimation {
|
||||||
|
|
||||||
public TreeAnimationFancy(DetectedTree detectedTree, Player player) {
|
public TreeAnimationFancy(DetectedTree detectedTree, Player player) {
|
||||||
super(TreeAnimationType.FANCY, detectedTree, player);
|
super(TreeAnimationType.FANCY, detectedTree, player);
|
||||||
}
|
}
|
||||||
@ -24,30 +25,32 @@ public class TreeAnimationFancy extends TreeAnimation {
|
|||||||
@Override
|
@Override
|
||||||
public void playAnimation(Runnable whenFinished) {
|
public void playAnimation(Runnable whenFinished) {
|
||||||
UltimateTimber ultimateTimber = UltimateTimber.getInstance();
|
UltimateTimber ultimateTimber = UltimateTimber.getInstance();
|
||||||
VersionAdapter versionAdapter = ultimateTimber.getVersionAdapter();
|
|
||||||
|
|
||||||
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
||||||
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
||||||
|
|
||||||
ITreeBlock<Block> initialTreeBlock = this.detectedTree.getDetectedTreeBlocks().getInitialLogBlock();
|
ITreeBlock<Block> initialTreeBlock = this.detectedTree.getDetectedTreeBlocks().getInitialLogBlock();
|
||||||
FallingTreeBlock initialFallingBlock = this.convertToFallingBlock((TreeBlock)this.detectedTree.getDetectedTreeBlocks().getInitialLogBlock());
|
FallingTreeBlock initialFallingBlock = this.convertToFallingBlock((TreeBlock) this.detectedTree.getDetectedTreeBlocks().getInitialLogBlock());
|
||||||
|
|
||||||
if (useCustomSound)
|
if (useCustomSound) {
|
||||||
versionAdapter.playFallingSound(initialTreeBlock);
|
SoundUtils.playFallingSound(initialTreeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
Vector velocityVector = initialTreeBlock.getLocation().clone().subtract(this.player.getLocation().clone()).toVector().normalize().setY(0);
|
Vector velocityVector = initialTreeBlock.getLocation().clone().subtract(this.player.getLocation().clone()).toVector().normalize().setY(0);
|
||||||
|
|
||||||
this.fallingTreeBlocks = new TreeBlockSet<>(initialFallingBlock);
|
this.fallingTreeBlocks = new TreeBlockSet<>(initialFallingBlock);
|
||||||
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
|
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
|
||||||
FallingTreeBlock fallingTreeBlock = this.convertToFallingBlock((TreeBlock)treeBlock);
|
FallingTreeBlock fallingTreeBlock = this.convertToFallingBlock((TreeBlock) treeBlock);
|
||||||
if (fallingTreeBlock == null)
|
if (fallingTreeBlock == null) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
||||||
this.fallingTreeBlocks.add(fallingTreeBlock);
|
this.fallingTreeBlocks.add(fallingTreeBlock);
|
||||||
|
|
||||||
if (useCustomParticles)
|
if (useCustomParticles) {
|
||||||
versionAdapter.playFallingParticles(this.detectedTree.getTreeDefinition(), treeBlock);
|
ParticleUtils.playFallingParticles(treeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
double multiplier = (treeBlock.getLocation().getY() - this.player.getLocation().getY()) * 0.05;
|
double multiplier = (treeBlock.getLocation().getY() - this.player.getLocation().getY()) * 0.05;
|
||||||
fallingBlock.setVelocity(velocityVector.clone().multiply(multiplier));
|
fallingBlock.setVelocity(velocityVector.clone().multiply(multiplier));
|
||||||
@ -62,7 +65,7 @@ public class TreeAnimationFancy extends TreeAnimation {
|
|||||||
if (this.timer == 0) {
|
if (this.timer == 0) {
|
||||||
for (ITreeBlock<FallingBlock> fallingTreeBlock : TreeAnimationFancy.this.fallingTreeBlocks.getAllTreeBlocks()) {
|
for (ITreeBlock<FallingBlock> fallingTreeBlock : TreeAnimationFancy.this.fallingTreeBlocks.getAllTreeBlocks()) {
|
||||||
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
||||||
versionAdapter.toggleGravityFallingBlock(fallingBlock, true);
|
BlockUtils.toggleGravityFallingBlock(fallingBlock, true);
|
||||||
fallingBlock.setVelocity(fallingBlock.getVelocity().multiply(1.5));
|
fallingBlock.setVelocity(fallingBlock.getVelocity().multiply(1.5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,13 +85,13 @@ public class TreeAnimationFancy extends TreeAnimation {
|
|||||||
|
|
||||||
if (this.timer > 4 * 20) {
|
if (this.timer > 4 * 20) {
|
||||||
TreeAnimationManager treeAnimationManager = ultimateTimber.getTreeAnimationManager();
|
TreeAnimationManager treeAnimationManager = ultimateTimber.getTreeAnimationManager();
|
||||||
for (ITreeBlock<FallingBlock> fallingTreeBlock : TreeAnimationFancy.this.fallingTreeBlocks.getAllTreeBlocks())
|
for (ITreeBlock<FallingBlock> fallingTreeBlock : TreeAnimationFancy.this.fallingTreeBlocks.getAllTreeBlocks()) {
|
||||||
treeAnimationManager.runFallingBlockImpact(TreeAnimationFancy.this, fallingTreeBlock);
|
treeAnimationManager.runFallingBlockImpact(TreeAnimationFancy.this, fallingTreeBlock);
|
||||||
|
}
|
||||||
whenFinished.run();
|
whenFinished.run();
|
||||||
this.cancel();
|
this.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.runTaskTimer(ultimateTimber, 20L, 1L);
|
}.runTaskTimer(ultimateTimber, 20L, 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,17 +1,17 @@
|
|||||||
package com.songoda.ultimatetimber.animation;
|
package com.craftaro.ultimatetimber.animation;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.ultimatetimber.manager.TreeDefinitionManager;
|
||||||
import com.songoda.ultimatetimber.manager.ConfigurationManager;
|
import com.craftaro.ultimatetimber.manager.ConfigurationManager;
|
||||||
import com.songoda.ultimatetimber.manager.TreeDefinitionManager;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.tree.TreeBlock;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlock;
|
import com.craftaro.ultimatetimber.utils.ParticleUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.SoundUtils;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class TreeAnimationNone extends TreeAnimation {
|
public class TreeAnimationNone extends TreeAnimation {
|
||||||
|
|
||||||
public TreeAnimationNone(DetectedTree detectedTree, Player player) {
|
public TreeAnimationNone(DetectedTree detectedTree, Player player) {
|
||||||
super(TreeAnimationType.NONE, detectedTree, player);
|
super(TreeAnimationType.NONE, detectedTree, player);
|
||||||
}
|
}
|
||||||
@ -19,14 +19,13 @@ public class TreeAnimationNone extends TreeAnimation {
|
|||||||
@Override
|
@Override
|
||||||
public void playAnimation(Runnable whenFinished) {
|
public void playAnimation(Runnable whenFinished) {
|
||||||
TreeDefinitionManager treeDefinitionManager = UltimateTimber.getInstance().getTreeDefinitionManager();
|
TreeDefinitionManager treeDefinitionManager = UltimateTimber.getInstance().getTreeDefinitionManager();
|
||||||
VersionAdapter versionAdapter = UltimateTimber.getInstance().getVersionAdapter();
|
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean())
|
if (ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean())
|
||||||
versionAdapter.playFallingSound(this.detectedTree.getDetectedTreeBlocks().getInitialLogBlock());
|
SoundUtils.playFallingSound(this.detectedTree.getDetectedTreeBlocks().getInitialLogBlock());
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean())
|
if (ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean())
|
||||||
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks())
|
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks())
|
||||||
versionAdapter.playFallingParticles(this.detectedTree.getTreeDefinition(), treeBlock);
|
ParticleUtils.playFallingParticles(treeBlock);
|
||||||
|
|
||||||
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
|
for (ITreeBlock<Block> treeBlock : this.detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
|
||||||
treeDefinitionManager.dropTreeLoot(this.detectedTree.getTreeDefinition(), treeBlock, this.player, this.hasSilkTouch, false);
|
treeDefinitionManager.dropTreeLoot(this.detectedTree.getTreeDefinition(), treeBlock, this.player, this.hasSilkTouch, false);
|
||||||
@ -35,5 +34,4 @@ public class TreeAnimationNone extends TreeAnimation {
|
|||||||
|
|
||||||
whenFinished.run();
|
whenFinished.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,13 +1,10 @@
|
|||||||
package com.songoda.ultimatetimber.animation;
|
package com.craftaro.ultimatetimber.animation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The types of tree animations that are available
|
* The types of tree animations that are available
|
||||||
*/
|
*/
|
||||||
public enum TreeAnimationType {
|
public enum TreeAnimationType {
|
||||||
FANCY,
|
FANCY, DISINTEGRATE, CRUMBLE, NONE;
|
||||||
DISINTEGRATE,
|
|
||||||
CRUMBLE,
|
|
||||||
NONE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a TreeAnimationType from a given string
|
* Gets a TreeAnimationType from a given string
|
||||||
@ -16,9 +13,12 @@ public enum TreeAnimationType {
|
|||||||
* @return The TreeAnimationType, returns FANCY if the string is an invalid type
|
* @return The TreeAnimationType, returns FANCY if the string is an invalid type
|
||||||
*/
|
*/
|
||||||
public static TreeAnimationType fromString(String string) {
|
public static TreeAnimationType fromString(String string) {
|
||||||
for (TreeAnimationType value : values())
|
for (TreeAnimationType value : values()) {
|
||||||
if (value.name().equalsIgnoreCase(string))
|
if (value.name().equalsIgnoreCase(string)) {
|
||||||
return value;
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TreeAnimationType.FANCY;
|
return TreeAnimationType.FANCY;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package com.craftaro.ultimatetimber.commands;
|
||||||
|
|
||||||
|
import com.craftaro.core.commands.AbstractCommand;
|
||||||
|
import com.craftaro.core.utils.PlayerUtils;
|
||||||
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CommandGiveAxe extends AbstractCommand {
|
||||||
|
private final UltimateTimber plugin;
|
||||||
|
|
||||||
|
public CommandGiveAxe(UltimateTimber plugin) {
|
||||||
|
super(CommandType.CONSOLE_OK, true, "give");
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
return ReturnType.SYNTAX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = Bukkit.getPlayer(args[0]);
|
||||||
|
if (player == null) {
|
||||||
|
if (args[0].trim().equalsIgnoreCase("me")) {
|
||||||
|
if (!(sender instanceof Player)) {
|
||||||
|
return ReturnType.NEEDS_PLAYER;
|
||||||
|
}
|
||||||
|
player = (Player) sender;
|
||||||
|
} else {
|
||||||
|
this.plugin.getLocale().getMessageOrDefault("command.give.not-a-player", "&cNot a player.")
|
||||||
|
.sendPrefixedMessage(sender);
|
||||||
|
return ReturnType.FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack axe = this.plugin.getTreeDefinitionManager().getRequiredAxe();
|
||||||
|
|
||||||
|
if (axe == null) {
|
||||||
|
this.plugin.getLocale().getMessageOrDefault("command.give.no-axe", "&cThe axe could not be loaded.")
|
||||||
|
.sendPrefixedMessage(sender);
|
||||||
|
return ReturnType.FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.getInventory().addItem(axe);
|
||||||
|
this.plugin.getLocale().getMessageOrDefault("command.give.given", "&fAxe given to &a%player%")
|
||||||
|
.processPlaceholder("player", player.getName())
|
||||||
|
.sendPrefixedMessage(sender);
|
||||||
|
return ReturnType.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> onTab(CommandSender sender, String... args) {
|
||||||
|
List<String> suggestions = null;
|
||||||
|
if (args.length == 1) {
|
||||||
|
suggestions = PlayerUtils.getVisiblePlayerNames(sender, args[0]);
|
||||||
|
suggestions.add("me");
|
||||||
|
}
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPermissionNode() {
|
||||||
|
return "ultimatetimber.give";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSyntax() {
|
||||||
|
return "give <player/me>";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Give a required axe.";
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,12 @@
|
|||||||
package com.songoda.ultimatetimber.commands;
|
package com.craftaro.ultimatetimber.commands;
|
||||||
|
|
||||||
import com.songoda.core.commands.AbstractCommand;
|
import com.craftaro.core.commands.AbstractCommand;
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CommandReload extends AbstractCommand {
|
public class CommandReload extends AbstractCommand {
|
||||||
|
|
||||||
private final UltimateTimber plugin;
|
private final UltimateTimber plugin;
|
||||||
|
|
||||||
public CommandReload(UltimateTimber plugin) {
|
public CommandReload(UltimateTimber plugin) {
|
||||||
@ -17,8 +16,8 @@ public class CommandReload extends AbstractCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ReturnType runCommand(CommandSender sender, String... args) {
|
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||||
plugin.reloadConfig();
|
this.plugin.reloadConfig();
|
||||||
plugin.getLocale().getMessage("command.reload.reloaded").sendPrefixedMessage(sender);
|
this.plugin.getLocale().getMessage("command.reload.reloaded").sendPrefixedMessage(sender);
|
||||||
return ReturnType.SUCCESS;
|
return ReturnType.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +38,6 @@ public class CommandReload extends AbstractCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return plugin.getLocale().getMessage("command.reload.description").getMessage();
|
return this.plugin.getLocale().getMessage("command.reload.description").getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +1,13 @@
|
|||||||
package com.songoda.ultimatetimber.commands;
|
package com.craftaro.ultimatetimber.commands;
|
||||||
|
|
||||||
import com.songoda.core.commands.AbstractCommand;
|
import com.craftaro.core.commands.AbstractCommand;
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CommandToggle extends AbstractCommand {
|
public class CommandToggle extends AbstractCommand {
|
||||||
|
|
||||||
private final UltimateTimber plugin;
|
private final UltimateTimber plugin;
|
||||||
|
|
||||||
public CommandToggle(UltimateTimber plugin) {
|
public CommandToggle(UltimateTimber plugin) {
|
||||||
@ -18,10 +17,10 @@ public class CommandToggle extends AbstractCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ReturnType runCommand(CommandSender sender, String... args) {
|
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||||
if (UltimateTimber.getInstance().getChoppingManager().togglePlayer((Player) sender)) {
|
if (this.plugin.getChoppingManager().togglePlayer((Player) sender)) {
|
||||||
plugin.getLocale().getMessage("command.toggle.enabled").sendPrefixedMessage(sender);
|
this.plugin.getLocale().getMessage("command.toggle.enabled").sendPrefixedMessage(sender);
|
||||||
} else {
|
} else {
|
||||||
plugin.getLocale().getMessage("command.toggle.disabled").sendPrefixedMessage(sender);
|
this.plugin.getLocale().getMessage("command.toggle.disabled").sendPrefixedMessage(sender);
|
||||||
}
|
}
|
||||||
return ReturnType.SUCCESS;
|
return ReturnType.SUCCESS;
|
||||||
}
|
}
|
||||||
@ -43,7 +42,7 @@ public class CommandToggle extends AbstractCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return plugin.getLocale().getMessage("command.toggle.description").getMessage();
|
return this.plugin.getLocale().getMessage("command.toggle.description").getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.craftaro.ultimatetimber.events;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.FallingBlock;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
|
|
||||||
|
public class TreeDamageEvent extends PlayerEvent implements Cancellable {
|
||||||
|
|
||||||
|
private boolean cancelled = false;
|
||||||
|
private FallingBlock blockAttacker = null;
|
||||||
|
private Player playerAttacker = null;
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a TreeDamage event.
|
||||||
|
*/
|
||||||
|
public TreeDamageEvent(FallingBlock attacker, Player victim) {
|
||||||
|
super(victim);
|
||||||
|
this.blockAttacker = attacker;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hoping this one is used whenever possible
|
||||||
|
/**
|
||||||
|
* Represents a TreeDamage event.
|
||||||
|
*/
|
||||||
|
public TreeDamageEvent(Player attacker, Player victim) {
|
||||||
|
super(victim);
|
||||||
|
this.playerAttacker = attacker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the attacker as either FallingBlock or Player
|
||||||
|
*/
|
||||||
|
public Entity getAttacker() {
|
||||||
|
if (this.playerAttacker != null)
|
||||||
|
return this.playerAttacker;
|
||||||
|
if (this.blockAttacker != null)
|
||||||
|
return this.blockAttacker;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Player damaged by this event. This method is only here for clarification
|
||||||
|
*/
|
||||||
|
public Player getVictim() {
|
||||||
|
return this.getPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {return handlers;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return this.cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancelState) {this.cancelled = cancelState;}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package com.songoda.ultimatetimber.events;
|
package com.craftaro.ultimatetimber.events;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
|
|
||||||
@ -8,11 +8,10 @@ import org.bukkit.event.player.PlayerEvent;
|
|||||||
* Abstract tree event containing tree's blocks and broke block
|
* Abstract tree event containing tree's blocks and broke block
|
||||||
*/
|
*/
|
||||||
public abstract class TreeEvent extends PlayerEvent {
|
public abstract class TreeEvent extends PlayerEvent {
|
||||||
|
protected final DetectedTree detectedTree;
|
||||||
|
|
||||||
protected final DetectedTree detectedTree;
|
public TreeEvent(Player who, DetectedTree detectedTree) {
|
||||||
|
super(who);
|
||||||
public TreeEvent(Player player, DetectedTree detectedTree) {
|
|
||||||
super(player);
|
|
||||||
this.detectedTree = detectedTree;
|
this.detectedTree = detectedTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,5 +23,4 @@ public abstract class TreeEvent extends PlayerEvent {
|
|||||||
public DetectedTree getDetectedTree() {
|
public DetectedTree getDetectedTree() {
|
||||||
return this.detectedTree;
|
return this.detectedTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.craftaro.ultimatetimber.events;
|
||||||
|
|
||||||
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a tree will fall
|
||||||
|
*/
|
||||||
|
public class TreeFallEvent extends TreeEvent implements Cancellable {
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
|
||||||
|
private boolean cancelled = false;
|
||||||
|
|
||||||
|
public TreeFallEvent(Player who, DetectedTree detectedTree) {
|
||||||
|
super(who, detectedTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return this.cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancel) {
|
||||||
|
this.cancelled = cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.craftaro.ultimatetimber.events;
|
||||||
|
|
||||||
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a tree fell
|
||||||
|
*/
|
||||||
|
public class TreeFellEvent extends TreeEvent {
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
|
||||||
|
public TreeFellEvent(Player who, DetectedTree detectedTree) {
|
||||||
|
super(who, detectedTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -11,14 +11,13 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ChoppingManager extends Manager {
|
public class ChoppingManager extends Manager {
|
||||||
|
private final Set<UUID> disabledPlayers;
|
||||||
private Set<UUID> disabledPlayers;
|
private final Map<UUID, Boolean> cooldownedPlayers;
|
||||||
private Map<UUID, Boolean> cooldownedPlayers;
|
|
||||||
private boolean useCooldown;
|
private boolean useCooldown;
|
||||||
private int cooldownAmount;
|
private int cooldownAmount;
|
||||||
|
|
||||||
public ChoppingManager(UltimateTimber ultimateTimber) {
|
public ChoppingManager(UltimateTimber plugin) {
|
||||||
super(ultimateTimber);
|
super(plugin);
|
||||||
this.disabledPlayers = new HashSet<>();
|
this.disabledPlayers = new HashSet<>();
|
||||||
this.cooldownedPlayers = new HashMap<>();
|
this.cooldownedPlayers = new HashMap<>();
|
||||||
}
|
}
|
||||||
@ -72,8 +71,7 @@ public class ChoppingManager extends Manager {
|
|||||||
|
|
||||||
this.cooldownedPlayers.put(player.getUniqueId(), false);
|
this.cooldownedPlayers.put(player.getUniqueId(), false);
|
||||||
|
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () ->
|
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.cooldownedPlayers.remove(player.getUniqueId()), this.cooldownAmount * 20L);
|
||||||
this.cooldownedPlayers.remove(player.getUniqueId()), this.cooldownAmount * 20L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,5 +88,4 @@ public class ChoppingManager extends Manager {
|
|||||||
}
|
}
|
||||||
return cooldowned;
|
return cooldowned;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,16 +1,13 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapterType;
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ConfigurationManager extends Manager {
|
public class ConfigurationManager extends Manager {
|
||||||
|
|
||||||
public enum Setting {
|
public enum Setting {
|
||||||
SERVER_TYPE(SettingType.STRING),
|
SERVER_TYPE(SettingType.STRING),
|
||||||
LOCALE(SettingType.STRING),
|
LOCALE(SettingType.STRING),
|
||||||
@ -48,9 +45,10 @@ public class ConfigurationManager extends Manager {
|
|||||||
HOOKS_APPLY_EXTRA_DROPS(SettingType.BOOLEAN),
|
HOOKS_APPLY_EXTRA_DROPS(SettingType.BOOLEAN),
|
||||||
HOOKS_REQUIRE_ABILITY_ACTIVE(SettingType.BOOLEAN),
|
HOOKS_REQUIRE_ABILITY_ACTIVE(SettingType.BOOLEAN),
|
||||||
TREE_ANIMATION_TYPE(SettingType.STRING),
|
TREE_ANIMATION_TYPE(SettingType.STRING),
|
||||||
SCATTER_TREE_BLOCKS_ON_GROUND(SettingType.BOOLEAN);
|
SCATTER_TREE_BLOCKS_ON_GROUND(SettingType.BOOLEAN),
|
||||||
|
FRAGILE_BLOCKS(SettingType.STRING_LIST);
|
||||||
|
|
||||||
private SettingType settingType;
|
private final SettingType settingType;
|
||||||
private Object value = null;
|
private Object value = null;
|
||||||
|
|
||||||
Setting(SettingType settingType) {
|
Setting(SettingType settingType) {
|
||||||
@ -119,10 +117,11 @@ public class ConfigurationManager extends Manager {
|
|||||||
* Loads the value from the config and caches it if it isn't set yet
|
* Loads the value from the config and caches it if it isn't set yet
|
||||||
*/
|
*/
|
||||||
private void loadValue() {
|
private void loadValue() {
|
||||||
if (this.value != null)
|
if (this.value != null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FileConfiguration config = UltimateTimber.getInstance().getConfigurationManager().getConfig();
|
FileConfiguration config = UltimateTimber.getPlugin(UltimateTimber.class).getConfigurationManager().getConfig();
|
||||||
switch (this.settingType) {
|
switch (this.settingType) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
this.value = config.getBoolean(this.getNameAsKey());
|
this.value = config.getBoolean(this.getNameAsKey());
|
||||||
@ -162,8 +161,8 @@ public class ConfigurationManager extends Manager {
|
|||||||
|
|
||||||
private YamlConfiguration configuration;
|
private YamlConfiguration configuration;
|
||||||
|
|
||||||
public ConfigurationManager(UltimateTimber ultimateTimber) {
|
public ConfigurationManager(UltimateTimber plugin) {
|
||||||
super(ultimateTimber);
|
super(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -172,7 +171,7 @@ public class ConfigurationManager extends Manager {
|
|||||||
|
|
||||||
File configFile = new File(this.plugin.getDataFolder() + "/config.yml");
|
File configFile = new File(this.plugin.getDataFolder() + "/config.yml");
|
||||||
|
|
||||||
// If an old config still exists, rename it so it doesn't interfere
|
// If an old config still exists, rename it, so it doesn't interfere
|
||||||
if (configFile.exists() && this.plugin.getConfig().get("server-type") == null) {
|
if (configFile.exists() && this.plugin.getConfig().get("server-type") == null) {
|
||||||
File renameConfigTo = new File(this.plugin.getDataFolder() + "/config-old.yml");
|
File renameConfigTo = new File(this.plugin.getDataFolder() + "/config-old.yml");
|
||||||
configFile.renameTo(renameConfigTo);
|
configFile.renameTo(renameConfigTo);
|
||||||
@ -181,8 +180,7 @@ public class ConfigurationManager extends Manager {
|
|||||||
|
|
||||||
// Create the new config if it doesn't exist
|
// Create the new config if it doesn't exist
|
||||||
if (!configFile.exists()) {
|
if (!configFile.exists()) {
|
||||||
boolean isCurrentConfig = this.plugin.getVersionAdapter().getVersionAdapterType() == VersionAdapterType.CURRENT;
|
String newConfigName = "config.yml";
|
||||||
String newConfigName = "config-" + (isCurrentConfig ? "current" : "legacy") + ".yml";
|
|
||||||
File newConfigFile = new File(this.plugin.getDataFolder() + "/" + newConfigName);
|
File newConfigFile = new File(this.plugin.getDataFolder() + "/" + newConfigName);
|
||||||
this.plugin.saveResource(newConfigName, false);
|
this.plugin.saveResource(newConfigName, false);
|
||||||
newConfigFile.renameTo(configFile);
|
newConfigFile.renameTo(configFile);
|
||||||
@ -190,14 +188,16 @@ public class ConfigurationManager extends Manager {
|
|||||||
|
|
||||||
this.configuration = YamlConfiguration.loadConfiguration(configFile);
|
this.configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||||
|
|
||||||
for (Setting setting : Setting.values())
|
for (Setting setting : Setting.values()) {
|
||||||
setting.reset();
|
setting.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
for (Setting setting : Setting.values())
|
for (Setting setting : Setting.values()) {
|
||||||
setting.reset();
|
setting.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -208,5 +208,4 @@ public class ConfigurationManager extends Manager {
|
|||||||
public YamlConfiguration getConfig() {
|
public YamlConfiguration getConfig() {
|
||||||
return this.configuration;
|
return this.configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,9 +1,8 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
|
|
||||||
public abstract class Manager {
|
public abstract class Manager {
|
||||||
|
|
||||||
protected UltimateTimber plugin;
|
protected UltimateTimber plugin;
|
||||||
|
|
||||||
Manager(UltimateTimber plugin) {
|
Manager(UltimateTimber plugin) {
|
||||||
@ -19,5 +18,4 @@ public abstract class Manager {
|
|||||||
* Cleans up the Manager's resources
|
* Cleans up the Manager's resources
|
||||||
*/
|
*/
|
||||||
public abstract void disable();
|
public abstract void disable();
|
||||||
|
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.events.TreeFellEvent;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.events.TreeFellEvent;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -22,14 +22,13 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class PlacedBlockManager extends Manager implements Listener {
|
public class PlacedBlockManager extends Manager implements Listener {
|
||||||
|
|
||||||
private Set<Location> placedBlocks;
|
private Set<Location> placedBlocks;
|
||||||
private boolean ignorePlacedBlocks;
|
private boolean ignorePlacedBlocks;
|
||||||
private int maxPlacedBlockMemorySize;
|
private int maxPlacedBlockMemorySize;
|
||||||
|
|
||||||
public PlacedBlockManager(UltimateTimber ultimateTimber) {
|
public PlacedBlockManager(UltimateTimber plugin) {
|
||||||
super(ultimateTimber);
|
super(plugin);
|
||||||
Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,48 +52,56 @@ public class PlacedBlockManager extends Manager implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onBlockPlaced(BlockPlaceEvent event) {
|
public void onBlockPlaced(BlockPlaceEvent event) {
|
||||||
if (!this.ignorePlacedBlocks)
|
if (!this.ignorePlacedBlocks) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore stripping logs
|
// Ignore stripping logs
|
||||||
if (event.getBlockPlaced().getType().name().contains("STRIPPED") && !event.getBlockReplacedState().getType().equals(Material.AIR))
|
if (event.getBlockPlaced().getType().name().contains("STRIPPED") && !CompatibleMaterial.isAir(CompatibleMaterial.getMaterial(event.getBlockReplacedState().getType()).get())) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.internalProtect(event.getBlock(), true);
|
this.internalProtect(event.getBlock(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
if (!this.ignorePlacedBlocks)
|
if (!this.ignorePlacedBlocks) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.internalProtect(event.getBlock(), false);
|
this.internalProtect(event.getBlock(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onLeafDecay(LeavesDecayEvent event) {
|
public void onLeafDecay(LeavesDecayEvent event) {
|
||||||
if (!this.ignorePlacedBlocks)
|
if (!this.ignorePlacedBlocks) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.internalProtect(event.getBlock(), false);
|
this.internalProtect(event.getBlock(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onStructureGrow(StructureGrowEvent event) {
|
public void onStructureGrow(StructureGrowEvent event) {
|
||||||
if (!this.ignorePlacedBlocks)
|
if (!this.ignorePlacedBlocks) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (BlockState blockState : event.getBlocks())
|
for (BlockState blockState : event.getBlocks()) {
|
||||||
this.internalProtect(blockState.getBlock(), false);
|
this.internalProtect(blockState.getBlock(), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onTreeFell(TreeFellEvent event) {
|
public void onTreeFell(TreeFellEvent event) {
|
||||||
if (!this.ignorePlacedBlocks)
|
if (!this.ignorePlacedBlocks) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (ITreeBlock<Block> treeBlock : event.getDetectedTree().getDetectedTreeBlocks().getAllTreeBlocks())
|
for (ITreeBlock<Block> treeBlock : event.getDetectedTree().getDetectedTreeBlocks().getAllTreeBlocks()) {
|
||||||
this.internalProtect(treeBlock.getBlock(), false);
|
this.internalProtect(treeBlock.getBlock(), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,8 +109,9 @@ public class PlacedBlockManager extends Manager implements Listener {
|
|||||||
*/
|
*/
|
||||||
private void internalProtect(Block block, boolean isPlaced) {
|
private void internalProtect(Block block, boolean isPlaced) {
|
||||||
if (isPlaced) {
|
if (isPlaced) {
|
||||||
if (this.isBlockPlaced(block))
|
if (this.isBlockPlaced(block)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.placedBlocks.add(block.getLocation());
|
this.placedBlocks.add(block.getLocation());
|
||||||
} else {
|
} else {
|
||||||
@ -120,5 +128,4 @@ public class PlacedBlockManager extends Manager implements Listener {
|
|||||||
public boolean isBlockPlaced(Block block) {
|
public boolean isBlockPlaced(Block block) {
|
||||||
return this.placedBlocks.contains(block.getLocation());
|
return this.placedBlocks.contains(block.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,12 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
import com.craftaro.third_party.com.cryptomorin.xseries.XBlock;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockType;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeDefinition;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -16,24 +18,21 @@ import java.util.Random;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class SaplingManager extends Manager {
|
public class SaplingManager extends Manager {
|
||||||
|
private final Random random;
|
||||||
|
private final Set<Location> protectedSaplings;
|
||||||
|
|
||||||
private Random random;
|
public SaplingManager(UltimateTimber plugin) {
|
||||||
private Set<Location> protectedSaplings;
|
super(plugin);
|
||||||
|
|
||||||
public SaplingManager(UltimateTimber ultimateTimber) {
|
|
||||||
super(ultimateTimber);
|
|
||||||
this.random = new Random();
|
this.random = new Random();
|
||||||
this.protectedSaplings = new HashSet<>();
|
this.protectedSaplings = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,15 +40,17 @@ public class SaplingManager extends Manager {
|
|||||||
* Takes into account config settings
|
* Takes into account config settings
|
||||||
*
|
*
|
||||||
* @param treeDefinition The TreeDefinition of the sapling
|
* @param treeDefinition The TreeDefinition of the sapling
|
||||||
* @param treeBlock The ITreeBlock to replant for
|
* @param treeBlock The ITreeBlock to replant for
|
||||||
*/
|
*/
|
||||||
public void replantSapling(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
public void replantSapling(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
||||||
if (!ConfigurationManager.Setting.REPLANT_SAPLINGS.getBoolean())
|
if (!ConfigurationManager.Setting.REPLANT_SAPLINGS.getBoolean()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Block block = treeBlock.getLocation().getBlock();
|
Block block = treeBlock.getLocation().getBlock();
|
||||||
if (!block.getType().equals(Material.AIR) || treeBlock.getTreeBlockType().equals(TreeBlockType.LEAF))
|
if (block.getType() != Material.AIR || treeBlock.getTreeBlockType() == TreeBlockType.LEAF) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.internalReplant(treeDefinition, treeBlock), 1L);
|
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.internalReplant(treeDefinition, treeBlock), 1L);
|
||||||
}
|
}
|
||||||
@ -59,15 +60,17 @@ public class SaplingManager extends Manager {
|
|||||||
* Takes into account config settings
|
* Takes into account config settings
|
||||||
*
|
*
|
||||||
* @param treeDefinition The TreeDefinition of the sapling
|
* @param treeDefinition The TreeDefinition of the sapling
|
||||||
* @param treeBlock The ITreeBlock to replant for
|
* @param treeBlock The ITreeBlock to replant for
|
||||||
*/
|
*/
|
||||||
public void replantSaplingWithChance(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
public void replantSaplingWithChance(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
||||||
if (!ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS.getBoolean() || !treeBlock.getLocation().getBlock().getType().equals(Material.AIR))
|
if (!ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS.getBoolean() || !CompatibleMaterial.isAir(CompatibleMaterial.getMaterial(treeBlock.getLocation().getBlock().getType()).get())) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double chance = ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS_CHANCE.getDouble();
|
double chance = ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS_CHANCE.getDouble();
|
||||||
if (this.random.nextDouble() > chance / 100)
|
if (this.random.nextDouble() > chance / 100) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.internalReplant(treeDefinition, treeBlock), 1L);
|
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.internalReplant(treeDefinition, treeBlock), 1L);
|
||||||
}
|
}
|
||||||
@ -76,7 +79,7 @@ public class SaplingManager extends Manager {
|
|||||||
* Replants a sapling given a TreeDefinition and Location
|
* Replants a sapling given a TreeDefinition and Location
|
||||||
*
|
*
|
||||||
* @param treeDefinition The TreeDefinition of the sapling
|
* @param treeDefinition The TreeDefinition of the sapling
|
||||||
* @param treeBlock The ITreeBlock to replant for
|
* @param treeBlock The ITreeBlock to replant for
|
||||||
*/
|
*/
|
||||||
private void internalReplant(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
private void internalReplant(TreeDefinition treeDefinition, ITreeBlock treeBlock) {
|
||||||
TreeDefinitionManager treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
TreeDefinitionManager treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
||||||
@ -84,18 +87,19 @@ public class SaplingManager extends Manager {
|
|||||||
Block block = treeBlock.getLocation().getBlock();
|
Block block = treeBlock.getLocation().getBlock();
|
||||||
Block blockBelow = block.getRelative(BlockFace.DOWN);
|
Block blockBelow = block.getRelative(BlockFace.DOWN);
|
||||||
boolean isValidSoil = false;
|
boolean isValidSoil = false;
|
||||||
for (IBlockData soilBlockData : treeDefinitionManager.getPlantableSoilBlockData(treeDefinition)) {
|
for (XMaterial soilMaterial : treeDefinitionManager.getPlantableSoilMaterial(treeDefinition)) {
|
||||||
if (soilBlockData.isSimilar(blockBelow)) {
|
if (soilMaterial == CompatibleMaterial.getMaterial(blockBelow.getType()).orElse(null)) {
|
||||||
isValidSoil = true;
|
isValidSoil = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidSoil)
|
if (!isValidSoil) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IBlockData saplingBlockData = treeDefinition.getSaplingBlockData();
|
XMaterial material = treeDefinition.getSaplingMaterial();
|
||||||
saplingBlockData.setBlock(block);
|
XBlock.setType(block, material);
|
||||||
|
|
||||||
int cooldown = ConfigurationManager.Setting.REPLANT_SAPLINGS_COOLDOWN.getInt();
|
int cooldown = ConfigurationManager.Setting.REPLANT_SAPLINGS_COOLDOWN.getInt();
|
||||||
if (cooldown != 0) {
|
if (cooldown != 0) {
|
||||||
@ -113,5 +117,4 @@ public class SaplingManager extends Manager {
|
|||||||
public boolean isSaplingProtected(Block block) {
|
public boolean isSaplingProtected(Block block) {
|
||||||
return this.protectedSaplings.contains(block.getLocation());
|
return this.protectedSaplings.contains(block.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,16 +1,20 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.core.compatibility.ServerVersion;
|
||||||
import com.songoda.ultimatetimber.animation.TreeAnimation;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.animation.TreeAnimationCrumble;
|
import com.craftaro.ultimatetimber.animation.TreeAnimation;
|
||||||
import com.songoda.ultimatetimber.animation.TreeAnimationDisintegrate;
|
import com.craftaro.ultimatetimber.animation.TreeAnimationCrumble;
|
||||||
import com.songoda.ultimatetimber.animation.TreeAnimationFancy;
|
import com.craftaro.ultimatetimber.animation.TreeAnimationDisintegrate;
|
||||||
import com.songoda.ultimatetimber.animation.TreeAnimationNone;
|
import com.craftaro.ultimatetimber.animation.TreeAnimationFancy;
|
||||||
import com.songoda.ultimatetimber.animation.TreeAnimationType;
|
import com.craftaro.ultimatetimber.animation.TreeAnimationNone;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.animation.TreeAnimationType;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.events.TreeDamageEvent;
|
||||||
import com.songoda.ultimatetimber.tree.TreeDefinition;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeDefinition;
|
||||||
|
import com.craftaro.ultimatetimber.utils.ParticleUtils;
|
||||||
|
import com.craftaro.ultimatetimber.utils.SoundUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
@ -27,15 +31,14 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class TreeAnimationManager extends Manager implements Listener, Runnable {
|
public class TreeAnimationManager extends Manager implements Listener, Runnable {
|
||||||
|
|
||||||
private final Set<TreeAnimation> activeAnimations;
|
private final Set<TreeAnimation> activeAnimations;
|
||||||
private int taskId;
|
private final int taskId;
|
||||||
|
|
||||||
public TreeAnimationManager(UltimateTimber ultimateTimber) {
|
public TreeAnimationManager(UltimateTimber plugin) {
|
||||||
super(ultimateTimber);
|
super(plugin);
|
||||||
this.activeAnimations = new HashSet<>();
|
this.activeAnimations = new HashSet<>();
|
||||||
this.taskId = -1;
|
this.taskId = -1;
|
||||||
Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0, 1L);
|
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0, 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,12 +59,16 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
Set<ITreeBlock<FallingBlock>> groundedBlocks = new HashSet<>();
|
Set<ITreeBlock<FallingBlock>> groundedBlocks = new HashSet<>();
|
||||||
for (ITreeBlock<FallingBlock> fallingTreeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
for (ITreeBlock<FallingBlock> fallingTreeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
||||||
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
FallingBlock fallingBlock = fallingTreeBlock.getBlock();
|
||||||
if (fallingBlock.isDead())
|
if (fallingBlock.isDead() || ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) && fallingBlock.isOnGround()) {
|
||||||
groundedBlocks.add(fallingTreeBlock);
|
groundedBlocks.add(fallingTreeBlock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ITreeBlock<FallingBlock> fallingBlock : groundedBlocks) {
|
for (ITreeBlock<FallingBlock> fallingBlock : groundedBlocks) {
|
||||||
this.runFallingBlockImpact(treeAnimation, fallingBlock);
|
this.runFallingBlockImpact(treeAnimation, fallingBlock);
|
||||||
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17)) {
|
||||||
|
fallingBlock.getBlock().remove();
|
||||||
|
}
|
||||||
treeAnimation.getFallingTreeBlocks().remove(fallingBlock);
|
treeAnimation.getFallingTreeBlocks().remove(fallingBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +78,7 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
* Plays an animation for toppling a tree
|
* Plays an animation for toppling a tree
|
||||||
*
|
*
|
||||||
* @param detectedTree The DetectedTree
|
* @param detectedTree The DetectedTree
|
||||||
* @param player The Player who toppled the tree
|
* @param player The Player who toppled the tree
|
||||||
*/
|
*/
|
||||||
public void runAnimation(DetectedTree detectedTree, Player player) {
|
public void runAnimation(DetectedTree detectedTree, Player player) {
|
||||||
switch (TreeAnimationType.fromString(ConfigurationManager.Setting.TREE_ANIMATION_TYPE.getString())) {
|
switch (TreeAnimationType.fromString(ConfigurationManager.Setting.TREE_ANIMATION_TYPE.getString())) {
|
||||||
@ -96,10 +103,13 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
* @param block The block to check
|
* @param block The block to check
|
||||||
*/
|
*/
|
||||||
public boolean isBlockInAnimation(Block block) {
|
public boolean isBlockInAnimation(Block block) {
|
||||||
for (TreeAnimation treeAnimation : this.activeAnimations)
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
||||||
for (ITreeBlock<Block> treeBlock : treeAnimation.getDetectedTree().getDetectedTreeBlocks().getAllTreeBlocks())
|
for (ITreeBlock<Block> treeBlock : treeAnimation.getDetectedTree().getDetectedTreeBlocks().getAllTreeBlocks()) {
|
||||||
if (treeBlock.getBlock().equals(block))
|
if (treeBlock.getBlock().equals(block)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,10 +119,13 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
* @param fallingBlock The falling block to check
|
* @param fallingBlock The falling block to check
|
||||||
*/
|
*/
|
||||||
public boolean isBlockInAnimation(FallingBlock fallingBlock) {
|
public boolean isBlockInAnimation(FallingBlock fallingBlock) {
|
||||||
for (TreeAnimation treeAnimation : this.activeAnimations)
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
||||||
for (ITreeBlock<FallingBlock> treeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks())
|
for (ITreeBlock<FallingBlock> treeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
||||||
if (treeBlock.getBlock().equals(fallingBlock))
|
if (treeBlock.getBlock().equals(fallingBlock)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,10 +135,13 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
* @return A TreeAnimation
|
* @return A TreeAnimation
|
||||||
*/
|
*/
|
||||||
private TreeAnimation getAnimationForBlock(FallingBlock fallingBlock) {
|
private TreeAnimation getAnimationForBlock(FallingBlock fallingBlock) {
|
||||||
for (TreeAnimation treeAnimation : this.activeAnimations)
|
for (TreeAnimation treeAnimation : this.activeAnimations) {
|
||||||
for (ITreeBlock<FallingBlock> treeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks())
|
for (ITreeBlock<FallingBlock> treeBlock : treeAnimation.getFallingTreeBlocks().getAllTreeBlocks()) {
|
||||||
if (treeBlock.getBlock().equals(fallingBlock))
|
if (treeBlock.getBlock().equals(fallingBlock)) {
|
||||||
return treeAnimation;
|
return treeAnimation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,19 +157,26 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
* Reacts to a falling block hitting the ground
|
* Reacts to a falling block hitting the ground
|
||||||
*
|
*
|
||||||
* @param treeAnimation The tree animation for the falling block
|
* @param treeAnimation The tree animation for the falling block
|
||||||
* @param treeBlock The tree block to impact
|
* @param treeBlock The tree block to impact
|
||||||
*/
|
*/
|
||||||
public void runFallingBlockImpact(TreeAnimation treeAnimation, ITreeBlock<FallingBlock> treeBlock) {
|
public void runFallingBlockImpact(TreeAnimation treeAnimation, ITreeBlock<FallingBlock> treeBlock) {
|
||||||
TreeDefinitionManager treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
TreeDefinitionManager treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
||||||
VersionAdapter versionAdapter = this.plugin.getVersionAdapter();
|
|
||||||
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
boolean useCustomSound = ConfigurationManager.Setting.USE_CUSTOM_SOUNDS.getBoolean();
|
||||||
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
boolean useCustomParticles = ConfigurationManager.Setting.USE_CUSTOM_PARTICLES.getBoolean();
|
||||||
TreeDefinition treeDefinition = treeAnimation.getDetectedTree().getTreeDefinition();
|
TreeDefinition treeDefinition = treeAnimation.getDetectedTree().getTreeDefinition();
|
||||||
|
|
||||||
if (useCustomParticles)
|
if (useCustomParticles) {
|
||||||
versionAdapter.playLandingParticles(treeDefinition, treeBlock);
|
ParticleUtils.playLandingParticles(treeBlock);
|
||||||
if (useCustomSound)
|
}
|
||||||
versionAdapter.playLandingSound(treeBlock);
|
if (useCustomSound) {
|
||||||
|
SoundUtils.playLandingSound(treeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block block = treeBlock.getLocation().subtract(0, 1, 0).getBlock();
|
||||||
|
if (ConfigurationManager.Setting.FRAGILE_BLOCKS.getStringList().contains(block.getType().toString())) {
|
||||||
|
block.getWorld().dropItemNaturally(block.getLocation(), CompatibleMaterial.getMaterial(block.getType()).get().parseItem());
|
||||||
|
block.breakNaturally();
|
||||||
|
}
|
||||||
|
|
||||||
treeDefinitionManager.dropTreeLoot(treeDefinition, treeBlock, treeAnimation.getPlayer(), treeAnimation.hasSilkTouch(), false);
|
treeDefinitionManager.dropTreeLoot(treeDefinition, treeBlock, treeAnimation.getPlayer(), treeAnimation.hasSilkTouch(), false);
|
||||||
this.plugin.getSaplingManager().replantSaplingWithChance(treeDefinition, treeBlock);
|
this.plugin.getSaplingManager().replantSaplingWithChance(treeDefinition, treeBlock);
|
||||||
@ -162,18 +185,29 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
public void onFallingBlockLand(EntityChangeBlockEvent event) {
|
public void onFallingBlockLand(EntityChangeBlockEvent event) {
|
||||||
if (!event.getEntityType().equals(EntityType.FALLING_BLOCK))
|
if (event.getEntityType() != EntityType.FALLING_BLOCK) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FallingBlock fallingBlock = (FallingBlock) event.getEntity();
|
FallingBlock fallingBlock = (FallingBlock) event.getEntity();
|
||||||
if (!this.isBlockInAnimation(fallingBlock))
|
if (!this.isBlockInAnimation(fallingBlock)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.FALLING_BLOCKS_DEAL_DAMAGE.getBoolean()) {
|
if (ConfigurationManager.Setting.FALLING_BLOCKS_DEAL_DAMAGE.getBoolean()) {
|
||||||
int damage = ConfigurationManager.Setting.FALLING_BLOCK_DAMAGE.getInt();
|
int damage = ConfigurationManager.Setting.FALLING_BLOCK_DAMAGE.getInt();
|
||||||
for (Entity entity : fallingBlock.getNearbyEntities(0.5, 0.5, 0.5)) {
|
for (Entity entity : fallingBlock.getNearbyEntities(0.5, 0.5, 0.5)) {
|
||||||
if (!(entity instanceof LivingEntity)) continue;
|
if (!(entity instanceof LivingEntity)) {
|
||||||
((LivingEntity)entity).damage(damage, fallingBlock);
|
continue;
|
||||||
|
}
|
||||||
|
if (entity instanceof Player) {
|
||||||
|
Player p = ((Player) entity).getPlayer();
|
||||||
|
TreeDamageEvent treeDamageEvent = new TreeDamageEvent(fallingBlock, p);
|
||||||
|
Bukkit.getServer().getPluginManager().callEvent(treeDamageEvent);
|
||||||
|
if (!treeDamageEvent.isCancelled())
|
||||||
|
((LivingEntity) entity).damage(damage, fallingBlock);
|
||||||
|
} else
|
||||||
|
((LivingEntity) entity).damage(damage, fallingBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,5 +221,4 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
|
|||||||
|
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,543 @@
|
|||||||
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
|
import com.craftaro.core.compatibility.ServerVersion;
|
||||||
|
import com.craftaro.core.hooks.McMMOHook;
|
||||||
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
|
import com.craftaro.core.third_party.de.tr7zw.nbtapi.NBTItem;
|
||||||
|
import com.craftaro.core.utils.TextUtils;
|
||||||
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockType;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeDefinition;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeLoot;
|
||||||
|
import com.craftaro.ultimatetimber.utils.BlockUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TreeDefinitionManager extends Manager {
|
||||||
|
private final Random random;
|
||||||
|
private final Set<TreeDefinition> treeDefinitions;
|
||||||
|
private final Set<XMaterial> globalPlantableSoil;
|
||||||
|
private final Set<TreeLoot> globalLogLoot, globalLeafLoot, globalEntireTreeLoot;
|
||||||
|
private final Set<ItemStack> globalRequiredTools;
|
||||||
|
|
||||||
|
private boolean globalAxeRequired;
|
||||||
|
private ItemStack requiredAxe;
|
||||||
|
private String requiredAxeKey;
|
||||||
|
|
||||||
|
public TreeDefinitionManager(UltimateTimber plugin) {
|
||||||
|
super(plugin);
|
||||||
|
this.random = new Random();
|
||||||
|
this.treeDefinitions = new HashSet<>();
|
||||||
|
this.globalPlantableSoil = new HashSet<>();
|
||||||
|
this.globalLogLoot = new HashSet<>();
|
||||||
|
this.globalLeafLoot = new HashSet<>();
|
||||||
|
this.globalEntireTreeLoot = new HashSet<>();
|
||||||
|
this.globalRequiredTools = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
this.treeDefinitions.clear();
|
||||||
|
this.globalPlantableSoil.clear();
|
||||||
|
this.globalLogLoot.clear();
|
||||||
|
this.globalLeafLoot.clear();
|
||||||
|
this.globalEntireTreeLoot.clear();
|
||||||
|
this.globalRequiredTools.clear();
|
||||||
|
|
||||||
|
ConfigurationManager configurationManager = this.plugin.getConfigurationManager();
|
||||||
|
YamlConfiguration config = configurationManager.getConfig();
|
||||||
|
|
||||||
|
// Load tree settings
|
||||||
|
ConfigurationSection treeSection = config.getConfigurationSection("trees");
|
||||||
|
top:
|
||||||
|
for (String key : treeSection.getKeys(false)) {
|
||||||
|
ConfigurationSection tree = treeSection.getConfigurationSection(key);
|
||||||
|
|
||||||
|
Set<XMaterial> logMaterials = new HashSet<>();
|
||||||
|
Set<XMaterial> leafMaterials = new HashSet<>();
|
||||||
|
XMaterial saplingMaterial;
|
||||||
|
Set<XMaterial> plantableSoilMaterial = new HashSet<>();
|
||||||
|
double maxLogDistanceFromTrunk;
|
||||||
|
int maxLeafDistanceFromLog;
|
||||||
|
boolean detectLeavesDiagonally;
|
||||||
|
boolean dropOriginalLog;
|
||||||
|
boolean dropOriginalLeaf;
|
||||||
|
Set<TreeLoot> logLoot = new HashSet<>();
|
||||||
|
Set<TreeLoot> leafLoot = new HashSet<>();
|
||||||
|
Set<TreeLoot> entireTreeLoot = new HashSet<>();
|
||||||
|
Set<ItemStack> requiredTools = new HashSet<>();
|
||||||
|
boolean requiredAxe;
|
||||||
|
|
||||||
|
for (String materialString : tree.getStringList("logs")) {
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(materialString);
|
||||||
|
if (!material.isPresent() || !material.get().isSupported()) {
|
||||||
|
continue top;
|
||||||
|
}
|
||||||
|
logMaterials.add(material.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String materialString : tree.getStringList("leaves")) {
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(materialString);
|
||||||
|
if (!material.isPresent() || !material.get().isSupported()) {
|
||||||
|
continue top;
|
||||||
|
}
|
||||||
|
leafMaterials.add(material.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
saplingMaterial = CompatibleMaterial.getMaterial(tree.getString("sapling")).get();
|
||||||
|
|
||||||
|
for (String materialString : tree.getStringList("plantable-soil")) {
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(materialString);
|
||||||
|
if (!material.isPresent() || !material.get().isSupported()) {
|
||||||
|
continue top;
|
||||||
|
}
|
||||||
|
plantableSoilMaterial.add(material.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
maxLogDistanceFromTrunk = tree.getDouble("max-log-distance-from-trunk");
|
||||||
|
maxLeafDistanceFromLog = tree.getInt("max-leaf-distance-from-log");
|
||||||
|
detectLeavesDiagonally = tree.getBoolean("search-for-leaves-diagonally");
|
||||||
|
dropOriginalLog = tree.getBoolean("drop-original-log");
|
||||||
|
dropOriginalLeaf = tree.getBoolean("drop-original-leaf");
|
||||||
|
|
||||||
|
ConfigurationSection logLootSection = tree.getConfigurationSection("log-loot");
|
||||||
|
if (logLootSection != null) {
|
||||||
|
for (String lootKey : logLootSection.getKeys(false)) {
|
||||||
|
logLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logLootSection.getConfigurationSection(lootKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationSection leafLootSection = tree.getConfigurationSection("leaf-loot");
|
||||||
|
if (leafLootSection != null) {
|
||||||
|
for (String lootKey : leafLootSection.getKeys(false)) {
|
||||||
|
leafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafLootSection.getConfigurationSection(lootKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationSection entireTreeLootSection = tree.getConfigurationSection("entire-tree-loot");
|
||||||
|
if (entireTreeLootSection != null) {
|
||||||
|
for (String lootKey : entireTreeLootSection.getKeys(false)) {
|
||||||
|
entireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, entireTreeLootSection.getConfigurationSection(lootKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String itemStackString : tree.getStringList("required-tools")) {
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(itemStackString);
|
||||||
|
if (!material.isPresent()) {
|
||||||
|
continue top;
|
||||||
|
}
|
||||||
|
requiredTools.add(material.get().parseItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredAxe = tree.getBoolean("required-axe", false);
|
||||||
|
|
||||||
|
this.treeDefinitions.add(new TreeDefinition(key, logMaterials, leafMaterials, saplingMaterial, plantableSoilMaterial, maxLogDistanceFromTrunk,
|
||||||
|
maxLeafDistanceFromLog, detectLeavesDiagonally, dropOriginalLog, dropOriginalLeaf, logLoot, leafLoot, entireTreeLoot, requiredTools, requiredAxe));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load global plantable soil
|
||||||
|
for (String material : config.getStringList("global-plantable-soil")) {
|
||||||
|
this.globalPlantableSoil.add(CompatibleMaterial.getMaterial(material).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load global log drops
|
||||||
|
ConfigurationSection logSection = config.getConfigurationSection("global-log-loot");
|
||||||
|
if (logSection != null) {
|
||||||
|
for (String lootKey : logSection.getKeys(false)) {
|
||||||
|
this.globalLogLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logSection.getConfigurationSection(lootKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load global leaf drops
|
||||||
|
ConfigurationSection leafSection = config.getConfigurationSection("global-leaf-loot");
|
||||||
|
if (leafSection != null) {
|
||||||
|
for (String lootKey : leafSection.getKeys(false)) {
|
||||||
|
this.globalLeafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafSection.getConfigurationSection(lootKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load global entire tree drops
|
||||||
|
ConfigurationSection entireTreeSection = config.getConfigurationSection("global-entire-tree-loot");
|
||||||
|
if (entireTreeSection != null) {
|
||||||
|
for (String lootKey : entireTreeSection.getKeys(false)) {
|
||||||
|
this.globalEntireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, entireTreeSection.getConfigurationSection(lootKey)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load global tools
|
||||||
|
for (String itemStackString : config.getStringList("global-required-tools")) {
|
||||||
|
Optional<XMaterial> tool = CompatibleMaterial.getMaterial(itemStackString);
|
||||||
|
if (!tool.isPresent()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.globalRequiredTools.add(tool.get().parseItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.globalAxeRequired = config.getBoolean("global-required-axe", false);
|
||||||
|
|
||||||
|
// Load required axe
|
||||||
|
if (config.contains("required-axe")) {
|
||||||
|
loadAxe(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadAxe(YamlConfiguration config) {
|
||||||
|
// Reset the axe loaded, but load the NBT anyway in case someone wanted to use another plugin to give it.
|
||||||
|
this.requiredAxeKey = config.getString("required-axe.nbt");
|
||||||
|
this.requiredAxe = null;
|
||||||
|
|
||||||
|
String typeString = config.getString("required-axe.type");
|
||||||
|
|
||||||
|
if (Strings.isNullOrEmpty(typeString)) {
|
||||||
|
this.plugin.getLogger().warning("Required-axe has to have a material set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(typeString);
|
||||||
|
if (!material.isPresent()) {
|
||||||
|
this.plugin.getLogger().warning("Material " + typeString + " is invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack item = material.get().parseItem();
|
||||||
|
|
||||||
|
// Add display name and lore
|
||||||
|
String displayName = TextUtils.formatText(config.getString("required-axe.name"));
|
||||||
|
List<String> lore = config.getStringList("required-axe.lore").stream()
|
||||||
|
.map(TextUtils::formatText)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
meta.setDisplayName(displayName);
|
||||||
|
meta.setLore(lore);
|
||||||
|
|
||||||
|
// Enchants
|
||||||
|
for (String enchantString : config.getStringList("required-axe.enchants")) {
|
||||||
|
String[] arr = enchantString.split(":");
|
||||||
|
int level = arr.length > 1 ? Math.max(1, parseInt(arr[1])) : 1;
|
||||||
|
|
||||||
|
// Enchantment#getKey is not present on versions below 1.13
|
||||||
|
Enchantment enchantment;
|
||||||
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
|
||||||
|
NamespacedKey key = NamespacedKey.minecraft(arr[0].trim().toLowerCase());
|
||||||
|
enchantment = Enchantment.getByKey(key);
|
||||||
|
|
||||||
|
// Try to fall back to #getByName() if someone uses the old names.
|
||||||
|
if (enchantment == null) {
|
||||||
|
enchantment = Enchantment.getByName(arr[0].trim());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
enchantment = Enchantment.getByName(arr[0].trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enchantment == null) {
|
||||||
|
this.plugin.getLogger().warning("Enchantment " + arr[0].trim() + " is invalid.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.addEnchant(enchantment, level, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
|
||||||
|
// Apply NBT
|
||||||
|
NBTItem nbtItem = new NBTItem(item);
|
||||||
|
nbtItem.setBoolean(this.requiredAxeKey, true);
|
||||||
|
item = nbtItem.getItem();
|
||||||
|
|
||||||
|
this.requiredAxe = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseInt(String str) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(str.trim());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getRequiredAxe() {
|
||||||
|
return this.requiredAxe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGlobalAxeRequired() {
|
||||||
|
return this.globalAxeRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disable() {
|
||||||
|
this.treeDefinitions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a Set of possible TreeDefinitions that match the given Block
|
||||||
|
*
|
||||||
|
* @param block The Block to check
|
||||||
|
* @return A Set of TreeDefinitions for the given Block
|
||||||
|
*/
|
||||||
|
public Set<TreeDefinition> getTreeDefinitionsForLog(Block block) {
|
||||||
|
return this.narrowTreeDefinition(this.treeDefinitions, block, TreeBlockType.LOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Narrows a Set of TreeDefinitions down to ones matching the given Block and TreeBlockType
|
||||||
|
*
|
||||||
|
* @param possibleTreeDefinitions The possible TreeDefinitions
|
||||||
|
* @param block The Block to narrow to
|
||||||
|
* @param treeBlockType The TreeBlockType of the given Block
|
||||||
|
* @return A Set of TreeDefinitions narrowed down
|
||||||
|
*/
|
||||||
|
public Set<TreeDefinition> narrowTreeDefinition(Set<TreeDefinition> possibleTreeDefinitions, Block block, TreeBlockType treeBlockType) {
|
||||||
|
Set<TreeDefinition> matchingTreeDefinitions = new HashSet<>();
|
||||||
|
switch (treeBlockType) {
|
||||||
|
case LOG:
|
||||||
|
for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
|
||||||
|
for (XMaterial material : treeDefinition.getLogMaterial()) {
|
||||||
|
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) {
|
||||||
|
matchingTreeDefinitions.add(treeDefinition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LEAF:
|
||||||
|
for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
|
||||||
|
for (XMaterial material : treeDefinition.getLeafMaterial()) {
|
||||||
|
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) {
|
||||||
|
matchingTreeDefinitions.add(treeDefinition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingTreeDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given tool is valid for any tree definitions, also takes into account global tools
|
||||||
|
*
|
||||||
|
* @param tool The tool to check
|
||||||
|
* @return True if the tool is allowed for toppling any trees
|
||||||
|
*/
|
||||||
|
public boolean isToolValidForAnyTreeDefinition(ItemStack tool) {
|
||||||
|
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TreeDefinition treeDefinition : this.treeDefinitions) {
|
||||||
|
if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) {
|
||||||
|
if (tool != null && !tool.getType().isAir() && new NBTItem(tool).hasTag(this.requiredAxeKey)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TreeDefinition treeDefinition : this.treeDefinitions) {
|
||||||
|
for (ItemStack requiredTool : treeDefinition.getRequiredTools()) {
|
||||||
|
if (tool != null && requiredTool.getType() == tool.getType()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ItemStack requiredTool : this.globalRequiredTools) {
|
||||||
|
if (tool != null && requiredTool.getType() == tool.getType()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given tool is valid for a given tree definition, also takes into account global tools
|
||||||
|
*
|
||||||
|
* @param treeDefinition The TreeDefinition to use
|
||||||
|
* @param tool The tool to check
|
||||||
|
* @return True if the tool is allowed for toppling the given TreeDefinition
|
||||||
|
*/
|
||||||
|
public boolean isToolValidForTreeDefinition(TreeDefinition treeDefinition, ItemStack tool) {
|
||||||
|
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the tree definition requires the custom axe, don't allow any other checks to pass.
|
||||||
|
if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) {
|
||||||
|
return tool != null && !tool.getType().isAir() && new NBTItem(tool).hasTag(this.requiredAxeKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ItemStack requiredTool : treeDefinition.getRequiredTools()) {
|
||||||
|
if (requiredTool.getType() == tool.getType()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ItemStack requiredTool : this.globalRequiredTools) {
|
||||||
|
if (requiredTool.getType() == tool.getType()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to spawn loot for a given TreeBlock with the given TreeDefinition for a given Player
|
||||||
|
*
|
||||||
|
* @param treeDefinition The TreeDefinition to use
|
||||||
|
* @param treeBlock The TreeBlock to drop for
|
||||||
|
* @param player The Player to drop for
|
||||||
|
* @param isForEntireTree If the loot is for the entire tree
|
||||||
|
*/
|
||||||
|
public void dropTreeLoot(TreeDefinition treeDefinition, ITreeBlock treeBlock, Player player, boolean hasSilkTouch, boolean isForEntireTree) {
|
||||||
|
boolean addToInventory = ConfigurationManager.Setting.ADD_ITEMS_TO_INVENTORY.getBoolean();
|
||||||
|
boolean hasBonusChance = player.hasPermission("ultimatetimber.bonusloot");
|
||||||
|
List<ItemStack> lootedItems = new ArrayList<>();
|
||||||
|
List<String> lootedCommands = new ArrayList<>();
|
||||||
|
|
||||||
|
// Get the loot that we should try to drop
|
||||||
|
List<TreeLoot> toTry = new ArrayList<>();
|
||||||
|
if (isForEntireTree) {
|
||||||
|
toTry.addAll(treeDefinition.getEntireTreeLoot());
|
||||||
|
toTry.addAll(this.globalEntireTreeLoot);
|
||||||
|
} else {
|
||||||
|
if (ConfigurationManager.Setting.APPLY_SILK_TOUCH.getBoolean() && hasSilkTouch) {
|
||||||
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
||||||
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) {
|
||||||
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
||||||
|
}
|
||||||
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
||||||
|
} else {
|
||||||
|
switch (treeBlock.getTreeBlockType()) {
|
||||||
|
case LOG:
|
||||||
|
toTry.addAll(treeDefinition.getLogLoot());
|
||||||
|
toTry.addAll(this.globalLogLoot);
|
||||||
|
if (treeDefinition.shouldDropOriginalLog()) {
|
||||||
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
||||||
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) {
|
||||||
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
||||||
|
}
|
||||||
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LEAF:
|
||||||
|
toTry.addAll(treeDefinition.getLeafLoot());
|
||||||
|
toTry.addAll(this.globalLeafLoot);
|
||||||
|
if (treeDefinition.shouldDropOriginalLeaf()) {
|
||||||
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
||||||
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) {
|
||||||
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
||||||
|
}
|
||||||
|
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roll the dice
|
||||||
|
double bonusLootMultiplier = ConfigurationManager.Setting.BONUS_LOOT_MULTIPLIER.getDouble();
|
||||||
|
for (TreeLoot treeLoot : toTry) {
|
||||||
|
if (treeLoot == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double chance = hasBonusChance ? treeLoot.getChance() * bonusLootMultiplier : treeLoot.getChance();
|
||||||
|
if (this.random.nextDouble() > chance / 100) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeLoot.hasItem()) {
|
||||||
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
||||||
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) {
|
||||||
|
lootedItems.add(treeLoot.getItem());
|
||||||
|
}
|
||||||
|
lootedItems.add(treeLoot.getItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treeLoot.hasCommand()) {
|
||||||
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
|
||||||
|
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) {
|
||||||
|
lootedCommands.add(treeLoot.getCommand());
|
||||||
|
}
|
||||||
|
lootedCommands.add(treeLoot.getCommand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to inventory or drop on ground
|
||||||
|
if (addToInventory && player.getWorld().equals(treeBlock.getLocation().getWorld())) {
|
||||||
|
List<ItemStack> extraItems = new ArrayList<>();
|
||||||
|
for (ItemStack lootedItem : lootedItems) {
|
||||||
|
extraItems.addAll(player.getInventory().addItem(lootedItem).values());
|
||||||
|
}
|
||||||
|
Location location = player.getLocation().clone().subtract(0.5, 0, 0.5);
|
||||||
|
for (ItemStack extraItem : extraItems) {
|
||||||
|
location.getWorld().dropItemNaturally(location, extraItem);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
||||||
|
for (ItemStack lootedItem : lootedItems) {
|
||||||
|
location.getWorld().dropItemNaturally(location, lootedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run looted commands
|
||||||
|
for (String lootedCommand : lootedCommands) {
|
||||||
|
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(),
|
||||||
|
lootedCommand.replace("%player%", player.getName())
|
||||||
|
.replace("%type%", treeDefinition.getKey())
|
||||||
|
.replace("%xPos%", String.valueOf(treeBlock.getLocation().getBlockX()))
|
||||||
|
.replace("%yPos%", String.valueOf(treeBlock.getLocation().getBlockY()))
|
||||||
|
.replace("%zPos%", String.valueOf(treeBlock.getLocation().getBlockZ())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all possible plantable soil blocks for the given tree definition
|
||||||
|
*
|
||||||
|
* @param treeDefinition The TreeDefinition
|
||||||
|
* @return A Set of IBlockData of plantable soil
|
||||||
|
*/
|
||||||
|
public Set<XMaterial> getPlantableSoilMaterial(TreeDefinition treeDefinition) {
|
||||||
|
Set<XMaterial> plantableSoilBlockData = new HashSet<>();
|
||||||
|
plantableSoilBlockData.addAll(treeDefinition.getPlantableSoilMaterial());
|
||||||
|
plantableSoilBlockData.addAll(this.globalPlantableSoil);
|
||||||
|
return plantableSoilBlockData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a TreeLoot entry from a ConfigurationSection
|
||||||
|
*
|
||||||
|
* @param treeBlockType The TreeBlockType to use
|
||||||
|
* @param configurationSection The ConfigurationSection
|
||||||
|
* @return A TreeLoot entry from the section
|
||||||
|
*/
|
||||||
|
private TreeLoot getTreeLootEntry(TreeBlockType treeBlockType, ConfigurationSection configurationSection) {
|
||||||
|
String material = configurationSection.getString("material");
|
||||||
|
Optional<XMaterial> compatibleMaterial = material == null ? Optional.empty() : CompatibleMaterial.getMaterial(material);
|
||||||
|
|
||||||
|
ItemStack item = compatibleMaterial.map(XMaterial::parseItem).orElse(null);
|
||||||
|
String command = configurationSection.getString("command");
|
||||||
|
double chance = configurationSection.getDouble("chance");
|
||||||
|
return new TreeLoot(treeBlockType, item, command, chance);
|
||||||
|
}
|
||||||
|
}
|
@ -1,42 +1,57 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
import com.songoda.ultimatetimber.tree.*;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockSet;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockType;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeDefinition;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class TreeDetectionManager extends Manager {
|
public class TreeDetectionManager extends Manager {
|
||||||
|
|
||||||
private final Set<Vector> VALID_TRUNK_OFFSETS, VALID_BRANCH_OFFSETS, VALID_LEAF_OFFSETS;
|
private final Set<Vector> VALID_TRUNK_OFFSETS, VALID_BRANCH_OFFSETS, VALID_LEAF_OFFSETS;
|
||||||
|
|
||||||
private TreeDefinitionManager treeDefinitionManager;
|
private TreeDefinitionManager treeDefinitionManager;
|
||||||
private PlacedBlockManager placedBlockManager;
|
private PlacedBlockManager placedBlockManager;
|
||||||
private int maxLogBlocksAllowed, numLeavesRequiredForTree;
|
private int numLeavesRequiredForTree;
|
||||||
private boolean onlyBreakLogsUpwards, entireTreeBase, destroyLeaves;
|
private boolean onlyBreakLogsUpwards, entireTreeBase, destroyLeaves;
|
||||||
|
|
||||||
public TreeDetectionManager(UltimateTimber ultimateTimber) {
|
public TreeDetectionManager(UltimateTimber plugin) {
|
||||||
super(ultimateTimber);
|
super(plugin);
|
||||||
|
|
||||||
this.VALID_BRANCH_OFFSETS = new HashSet<>();
|
this.VALID_BRANCH_OFFSETS = new HashSet<>();
|
||||||
this.VALID_TRUNK_OFFSETS = new HashSet<>();
|
this.VALID_TRUNK_OFFSETS = new HashSet<>();
|
||||||
this.VALID_LEAF_OFFSETS = new HashSet<>();
|
this.VALID_LEAF_OFFSETS = new HashSet<>();
|
||||||
|
|
||||||
// 3x2x3 centered around log, excluding -y axis
|
// 3x2x3 centered around log, excluding -y axis
|
||||||
for (int y = 0; y <= 1; y++)
|
for (int y = 0; y <= 1; y++) {
|
||||||
for (int x = -1; x <= 1; x++)
|
for (int x = -1; x <= 1; x++) {
|
||||||
for (int z = -1; z <= 1; z++)
|
for (int z = -1; z <= 1; z++) {
|
||||||
this.VALID_BRANCH_OFFSETS.add(new Vector(x, y, z));
|
this.VALID_BRANCH_OFFSETS.add(new Vector(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 3x3x3 centered around log
|
// 3x3x3 centered around log
|
||||||
for (int y = -1; y <= 1; y++)
|
for (int y = -1; y <= 1; y++) {
|
||||||
for (int x = -1; x <= 1; x++)
|
for (int x = -1; x <= 1; x++) {
|
||||||
for (int z = -1; z <= 1; z++)
|
for (int z = -1; z <= 1; z++) {
|
||||||
this.VALID_TRUNK_OFFSETS.add(new Vector(x, y, z));
|
this.VALID_TRUNK_OFFSETS.add(new Vector(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Adjacent blocks to log
|
// Adjacent blocks to log
|
||||||
for (int i = -1; i <= 1; i += 2) {
|
for (int i = -1; i <= 1; i += 2) {
|
||||||
@ -50,7 +65,6 @@ public class TreeDetectionManager extends Manager {
|
|||||||
public void reload() {
|
public void reload() {
|
||||||
this.treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
this.treeDefinitionManager = this.plugin.getTreeDefinitionManager();
|
||||||
this.placedBlockManager = this.plugin.getPlacedBlockManager();
|
this.placedBlockManager = this.plugin.getPlacedBlockManager();
|
||||||
this.maxLogBlocksAllowed = ConfigurationManager.Setting.MAX_LOGS_PER_CHOP.getInt();
|
|
||||||
this.numLeavesRequiredForTree = ConfigurationManager.Setting.LEAVES_REQUIRED_FOR_TREE.getInt();
|
this.numLeavesRequiredForTree = ConfigurationManager.Setting.LEAVES_REQUIRED_FOR_TREE.getInt();
|
||||||
this.onlyBreakLogsUpwards = ConfigurationManager.Setting.ONLY_DETECT_LOGS_UPWARDS.getBoolean();
|
this.onlyBreakLogsUpwards = ConfigurationManager.Setting.ONLY_DETECT_LOGS_UPWARDS.getBoolean();
|
||||||
this.entireTreeBase = ConfigurationManager.Setting.BREAK_ENTIRE_TREE_BASE.getBoolean();
|
this.entireTreeBase = ConfigurationManager.Setting.BREAK_ENTIRE_TREE_BASE.getBoolean();
|
||||||
@ -59,7 +73,6 @@ public class TreeDetectionManager extends Manager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,8 +88,9 @@ public class TreeDetectionManager extends Manager {
|
|||||||
TreeBlockSet<Block> detectedTreeBlocks = new TreeBlockSet<>(initialTreeBlock);
|
TreeBlockSet<Block> detectedTreeBlocks = new TreeBlockSet<>(initialTreeBlock);
|
||||||
Set<TreeDefinition> possibleTreeDefinitions = this.treeDefinitionManager.getTreeDefinitionsForLog(initialBlock);
|
Set<TreeDefinition> possibleTreeDefinitions = this.treeDefinitionManager.getTreeDefinitionsForLog(initialBlock);
|
||||||
|
|
||||||
if (possibleTreeDefinitions.isEmpty())
|
if (possibleTreeDefinitions.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Detect tree trunk
|
// Detect tree trunk
|
||||||
List<Block> trunkBlocks = new ArrayList<>();
|
List<Block> trunkBlocks = new ArrayList<>();
|
||||||
@ -99,45 +113,52 @@ public class TreeDetectionManager extends Manager {
|
|||||||
Collections.reverse(trunkBlocks);
|
Collections.reverse(trunkBlocks);
|
||||||
|
|
||||||
// Detect branches off the main trunk
|
// Detect branches off the main trunk
|
||||||
for (Block trunkBlock : trunkBlocks)
|
for (Block trunkBlock : trunkBlocks) {
|
||||||
this.recursiveBranchSearch(possibleTreeDefinitions, trunkBlocks, detectedTreeBlocks, trunkBlock, initialBlock.getLocation().getBlockY());
|
this.recursiveBranchSearch(possibleTreeDefinitions, trunkBlocks, detectedTreeBlocks, trunkBlock, initialBlock.getLocation().getBlockY());
|
||||||
|
}
|
||||||
|
|
||||||
// Detect leaves off the trunk/branches
|
// Detect leaves off the trunk/branches
|
||||||
Set<ITreeBlock<Block>> branchBlocks = new HashSet<>(detectedTreeBlocks.getLogBlocks());
|
Set<ITreeBlock<Block>> branchBlocks = new HashSet<>(detectedTreeBlocks.getLogBlocks());
|
||||||
for (ITreeBlock<Block> branchBlock : branchBlocks)
|
for (ITreeBlock<Block> branchBlock : branchBlocks) {
|
||||||
this.recursiveLeafSearch(possibleTreeDefinitions, detectedTreeBlocks, branchBlock.getBlock(), new HashSet<>());
|
this.recursiveLeafSearch(possibleTreeDefinitions, detectedTreeBlocks, branchBlock.getBlock(), new HashSet<>());
|
||||||
|
}
|
||||||
|
|
||||||
// Use the first tree definition in the set
|
// Use the first tree definition in the set
|
||||||
TreeDefinition actualTreeDefinition = possibleTreeDefinitions.iterator().next();
|
TreeDefinition actualTreeDefinition = possibleTreeDefinitions.iterator().next();
|
||||||
|
|
||||||
// Trees need at least a certain number of leaves
|
// Trees need at least a certain number of leaves
|
||||||
if (detectedTreeBlocks.getLeafBlocks().size() < this.numLeavesRequiredForTree)
|
if (detectedTreeBlocks.getLeafBlocks().size() < this.numLeavesRequiredForTree) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove leaves if we don't care about the leaves
|
// Remove leaves if we don't care about the leaves
|
||||||
if (!this.destroyLeaves)
|
if (!this.destroyLeaves) {
|
||||||
detectedTreeBlocks.removeAll(TreeBlockType.LEAF);
|
detectedTreeBlocks.removeAll(TreeBlockType.LEAF);
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the tree isn't on the ground if enabled
|
// Check that the tree isn't on the ground if enabled
|
||||||
if (this.entireTreeBase) {
|
if (this.entireTreeBase) {
|
||||||
Set<Block> groundBlocks = new HashSet<>();
|
Set<Block> groundBlocks = new HashSet<>();
|
||||||
for (ITreeBlock<Block> treeBlock : detectedTreeBlocks.getLogBlocks())
|
for (ITreeBlock<Block> treeBlock : detectedTreeBlocks.getLogBlocks()) {
|
||||||
if (treeBlock != detectedTreeBlocks.getInitialLogBlock() && treeBlock.getLocation().getBlockY() == initialBlock.getLocation().getBlockY())
|
if (treeBlock != detectedTreeBlocks.getInitialLogBlock() && treeBlock.getLocation().getBlockY() == initialBlock.getLocation().getBlockY()) {
|
||||||
groundBlocks.add(treeBlock.getBlock());
|
groundBlocks.add(treeBlock.getBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Block block : groundBlocks) {
|
for (Block block : groundBlocks) {
|
||||||
Block blockBelow = block.getRelative(BlockFace.DOWN);
|
Block blockBelow = block.getRelative(BlockFace.DOWN);
|
||||||
boolean blockBelowIsLog = this.isValidLogType(possibleTreeDefinitions, null, blockBelow);
|
boolean blockBelowIsLog = this.isValidLogType(possibleTreeDefinitions, null, blockBelow);
|
||||||
boolean blockBelowIsSoil = false;
|
boolean blockBelowIsSoil = false;
|
||||||
for (IBlockData blockData : treeDefinitionManager.getPlantableSoilBlockData(actualTreeDefinition)) {
|
for (XMaterial material : treeDefinitionManager.getPlantableSoilMaterial(actualTreeDefinition)) {
|
||||||
if (blockData.isSimilar(blockBelow)) {
|
if (material == CompatibleMaterial.getMaterial(blockBelow.getType()).orElse(null)) {
|
||||||
blockBelowIsSoil = true;
|
blockBelowIsSoil = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockBelowIsLog || blockBelowIsSoil)
|
if (blockBelowIsLog || blockBelowIsSoil) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,17 +175,15 @@ public class TreeDetectionManager extends Manager {
|
|||||||
* @param startingBlockY The Y coordinate of the initial block
|
* @param startingBlockY The Y coordinate of the initial block
|
||||||
*/
|
*/
|
||||||
private void recursiveBranchSearch(Set<TreeDefinition> treeDefinitions, List<Block> trunkBlocks, TreeBlockSet<Block> treeBlocks, Block block, int startingBlockY) {
|
private void recursiveBranchSearch(Set<TreeDefinition> treeDefinitions, List<Block> trunkBlocks, TreeBlockSet<Block> treeBlocks, Block block, int startingBlockY) {
|
||||||
if (treeBlocks.size() > this.maxLogBlocksAllowed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (Vector offset : this.onlyBreakLogsUpwards ? this.VALID_BRANCH_OFFSETS : this.VALID_TRUNK_OFFSETS) {
|
for (Vector offset : this.onlyBreakLogsUpwards ? this.VALID_BRANCH_OFFSETS : this.VALID_TRUNK_OFFSETS) {
|
||||||
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
||||||
TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LOG);
|
TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LOG);
|
||||||
if (this.isValidLogType(treeDefinitions, trunkBlocks, targetBlock) && !treeBlocks.contains(treeBlock)) {
|
if (this.isValidLogType(treeDefinitions, trunkBlocks, targetBlock) && !treeBlocks.contains(treeBlock)) {
|
||||||
treeBlocks.add(treeBlock);
|
treeBlocks.add(treeBlock);
|
||||||
treeDefinitions.retainAll(this.treeDefinitionManager.narrowTreeDefinition(treeDefinitions, targetBlock, TreeBlockType.LOG));
|
treeDefinitions.retainAll(this.treeDefinitionManager.narrowTreeDefinition(treeDefinitions, targetBlock, TreeBlockType.LOG));
|
||||||
if (!this.onlyBreakLogsUpwards || targetBlock.getLocation().getBlockY() > startingBlockY)
|
if (!this.onlyBreakLogsUpwards || targetBlock.getLocation().getBlockY() > startingBlockY) {
|
||||||
this.recursiveBranchSearch(treeDefinitions, trunkBlocks, treeBlocks, targetBlock, startingBlockY);
|
this.recursiveBranchSearch(treeDefinitions, trunkBlocks, treeBlocks, targetBlock, startingBlockY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,8 +200,9 @@ public class TreeDetectionManager extends Manager {
|
|||||||
|
|
||||||
for (Vector offset : !detectLeavesDiagonally ? this.VALID_LEAF_OFFSETS : this.VALID_TRUNK_OFFSETS) {
|
for (Vector offset : !detectLeavesDiagonally ? this.VALID_LEAF_OFFSETS : this.VALID_TRUNK_OFFSETS) {
|
||||||
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
||||||
if (visitedBlocks.contains(targetBlock))
|
if (visitedBlocks.contains(targetBlock)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
visitedBlocks.add(targetBlock);
|
visitedBlocks.add(targetBlock);
|
||||||
TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LEAF);
|
TreeBlock treeBlock = new TreeBlock(targetBlock, TreeBlockType.LEAF);
|
||||||
@ -205,8 +225,9 @@ public class TreeDetectionManager extends Manager {
|
|||||||
private boolean doesLeafBorderInvalidLog(Set<TreeDefinition> treeDefinitions, TreeBlockSet<Block> treeBlocks, Block block) {
|
private boolean doesLeafBorderInvalidLog(Set<TreeDefinition> treeDefinitions, TreeBlockSet<Block> treeBlocks, Block block) {
|
||||||
for (Vector offset : this.VALID_TRUNK_OFFSETS) {
|
for (Vector offset : this.VALID_TRUNK_OFFSETS) {
|
||||||
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
Block targetBlock = block.getRelative(offset.getBlockX(), offset.getBlockY(), offset.getBlockZ());
|
||||||
if (this.isValidLogType(treeDefinitions, null, targetBlock) && !treeBlocks.contains(new TreeBlock(targetBlock, TreeBlockType.LOG)))
|
if (this.isValidLogType(treeDefinitions, null, targetBlock) && !treeBlocks.contains(new TreeBlock(targetBlock, TreeBlockType.LOG))) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -221,35 +242,42 @@ public class TreeDetectionManager extends Manager {
|
|||||||
*/
|
*/
|
||||||
private boolean isValidLogType(Set<TreeDefinition> treeDefinitions, List<Block> trunkBlocks, Block block) {
|
private boolean isValidLogType(Set<TreeDefinition> treeDefinitions, List<Block> trunkBlocks, Block block) {
|
||||||
// Check if block is placed
|
// Check if block is placed
|
||||||
if (this.placedBlockManager.isBlockPlaced(block))
|
if (this.placedBlockManager.isBlockPlaced(block)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if it matches the tree definition
|
// Check if it matches the tree definition
|
||||||
boolean isCorrectType = false;
|
boolean isCorrectType = false;
|
||||||
for (TreeDefinition treeDefinition : treeDefinitions) {
|
for (TreeDefinition treeDefinition : treeDefinitions) {
|
||||||
for (IBlockData logBlockData : treeDefinition.getLogBlockData()) {
|
for (XMaterial material : treeDefinition.getLogMaterial()) {
|
||||||
if (logBlockData.isSimilar(block)) {
|
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) {
|
||||||
isCorrectType = true;
|
isCorrectType = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCorrectType)
|
if (!isCorrectType) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check that it is close enough to the trunk
|
// Check that it is close enough to the trunk
|
||||||
if (trunkBlocks == null || trunkBlocks.isEmpty())
|
if (trunkBlocks == null || trunkBlocks.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Location location = block.getLocation();
|
Location location = block.getLocation();
|
||||||
for (TreeDefinition treeDefinition : treeDefinitions) {
|
for (TreeDefinition treeDefinition : treeDefinitions) {
|
||||||
double maxDistance = treeDefinition.getMaxLogDistanceFromTrunk() * treeDefinition.getMaxLogDistanceFromTrunk();
|
double maxDistance = treeDefinition.getMaxLogDistanceFromTrunk() * treeDefinition.getMaxLogDistanceFromTrunk();
|
||||||
if (!this.onlyBreakLogsUpwards) // Help detect logs more often if the tree isn't broken at the base
|
if (!this.onlyBreakLogsUpwards) // Help detect logs more often if the tree isn't broken at the base
|
||||||
|
{
|
||||||
maxDistance *= 1.5;
|
maxDistance *= 1.5;
|
||||||
for (Block trunkBlock : trunkBlocks)
|
}
|
||||||
if (location.distanceSquared(trunkBlock.getLocation()) < maxDistance)
|
for (Block trunkBlock : trunkBlocks) {
|
||||||
|
if (location.distanceSquared(trunkBlock.getLocation()) < maxDistance) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -265,29 +293,31 @@ public class TreeDetectionManager extends Manager {
|
|||||||
*/
|
*/
|
||||||
private boolean isValidLeafType(Set<TreeDefinition> treeDefinitions, TreeBlockSet<Block> treeBlocks, Block block) {
|
private boolean isValidLeafType(Set<TreeDefinition> treeDefinitions, TreeBlockSet<Block> treeBlocks, Block block) {
|
||||||
// Check if block is placed
|
// Check if block is placed
|
||||||
if (this.placedBlockManager.isBlockPlaced(block))
|
if (this.placedBlockManager.isBlockPlaced(block)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if it matches the tree definition
|
// Check if it matches the tree definition
|
||||||
boolean isCorrectType = false;
|
boolean isCorrectType = false;
|
||||||
for (TreeDefinition treeDefinition : treeDefinitions) {
|
for (TreeDefinition treeDefinition : treeDefinitions) {
|
||||||
for (IBlockData leafBlockData : treeDefinition.getLeafBlockData()) {
|
for (XMaterial material : treeDefinition.getLeafMaterial()) {
|
||||||
if (leafBlockData.isSimilar(block)) {
|
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) {
|
||||||
isCorrectType = true;
|
isCorrectType = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCorrectType)
|
if (!isCorrectType) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check that it is close enough to a log
|
// Check that it is close enough to a log
|
||||||
if (treeBlocks == null || treeBlocks.isEmpty())
|
if (treeBlocks == null || treeBlocks.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int maxDistanceFromLog = treeDefinitions.stream().map(TreeDefinition::getMaxLeafDistanceFromLog).max(Integer::compareTo).orElse(0);
|
int maxDistanceFromLog = treeDefinitions.stream().map(TreeDefinition::getMaxLeafDistanceFromLog).max(Integer::compareTo).orElse(0);
|
||||||
return treeBlocks.getLogBlocks().stream().anyMatch(x -> x.getLocation().distanceSquared(block.getLocation()) < maxDistanceFromLog * maxDistanceFromLog);
|
return treeBlocks.getLogBlocks().stream().anyMatch(x -> x.getLocation().distanceSquared(block.getLocation()) < maxDistanceFromLog * maxDistanceFromLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,17 +1,19 @@
|
|||||||
package com.songoda.ultimatetimber.manager;
|
package com.craftaro.ultimatetimber.manager;
|
||||||
|
|
||||||
import com.songoda.core.hooks.JobsHook;
|
import com.craftaro.core.compatibility.CompatibleHand;
|
||||||
import com.songoda.core.hooks.LogManager;
|
import com.craftaro.core.compatibility.ServerVersion;
|
||||||
import com.songoda.core.hooks.McMMOHook;
|
import com.craftaro.core.hooks.JobsHook;
|
||||||
import com.songoda.ultimatetimber.UltimateTimber;
|
import com.craftaro.core.hooks.LogManager;
|
||||||
import com.songoda.ultimatetimber.adapter.VersionAdapter;
|
import com.craftaro.core.hooks.McMMOHook;
|
||||||
import com.songoda.ultimatetimber.events.TreeFallEvent;
|
import com.craftaro.core.utils.ItemUtils;
|
||||||
import com.songoda.ultimatetimber.events.TreeFellEvent;
|
import com.craftaro.core.world.SItemStack;
|
||||||
import com.songoda.ultimatetimber.misc.OnlyToppleWhile;
|
import com.craftaro.ultimatetimber.UltimateTimber;
|
||||||
import com.songoda.ultimatetimber.tree.DetectedTree;
|
import com.craftaro.ultimatetimber.events.TreeFallEvent;
|
||||||
import com.songoda.ultimatetimber.tree.ITreeBlock;
|
import com.craftaro.ultimatetimber.events.TreeFellEvent;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockSet;
|
import com.craftaro.ultimatetimber.tree.DetectedTree;
|
||||||
import com.songoda.ultimatetimber.tree.TreeBlockType;
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockSet;
|
||||||
|
import com.craftaro.ultimatetimber.misc.OnlyToppleWhile;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -23,24 +25,26 @@ import org.bukkit.event.EventPriority;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.Damageable;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TreeFallManager extends Manager implements Listener {
|
public class TreeFallManager extends Manager implements Listener {
|
||||||
|
private int maxLogBlocksAllowed;
|
||||||
|
|
||||||
public TreeFallManager(UltimateTimber ultimateTimber) {
|
public TreeFallManager(UltimateTimber plugin) {
|
||||||
super(ultimateTimber);
|
super(plugin);
|
||||||
Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
this.maxLogBlocksAllowed = ConfigurationManager.Setting.MAX_LOGS_PER_CHOP.getInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
@ -50,11 +54,10 @@ public class TreeFallManager extends Manager implements Listener {
|
|||||||
TreeAnimationManager treeAnimationManager = this.plugin.getTreeAnimationManager();
|
TreeAnimationManager treeAnimationManager = this.plugin.getTreeAnimationManager();
|
||||||
ChoppingManager choppingManager = this.plugin.getChoppingManager();
|
ChoppingManager choppingManager = this.plugin.getChoppingManager();
|
||||||
SaplingManager saplingManager = this.plugin.getSaplingManager();
|
SaplingManager saplingManager = this.plugin.getSaplingManager();
|
||||||
VersionAdapter versionAdapter = this.plugin.getVersionAdapter();
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
Block block = event.getBlock();
|
Block block = event.getBlock();
|
||||||
ItemStack tool = versionAdapter.getItemInHand(player);
|
ItemStack tool = CompatibleHand.getHand(event).getItem(player);
|
||||||
|
|
||||||
// Protect saplings
|
// Protect saplings
|
||||||
if (saplingManager.isSaplingProtected(block)) {
|
if (saplingManager.isSaplingProtected(block)) {
|
||||||
@ -65,85 +68,122 @@ public class TreeFallManager extends Manager implements Listener {
|
|||||||
// Condition checks
|
// Condition checks
|
||||||
boolean isValid = true;
|
boolean isValid = true;
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.DISABLED_WORLDS.getStringList().contains(player.getWorld().getName()))
|
if (ConfigurationManager.Setting.DISABLED_WORLDS.getStringList().contains(player.getWorld().getName())) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ConfigurationManager.Setting.ALLOW_CREATIVE_MODE.getBoolean() && player.getGameMode().equals(GameMode.CREATIVE))
|
if (!ConfigurationManager.Setting.ALLOW_CREATIVE_MODE.getBoolean() && player.getGameMode().equals(GameMode.CREATIVE)) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.checkToppleWhile(player))
|
if (!this.checkToppleWhile(player)) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.REQUIRE_CHOP_PERMISSION.getBoolean() && !player.hasPermission("ultimatetimber.chop"))
|
if (ConfigurationManager.Setting.REQUIRE_CHOP_PERMISSION.getBoolean() && !player.hasPermission("ultimatetimber.chop")) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!choppingManager.isChopping(player))
|
if (!choppingManager.isChopping(player)) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (choppingManager.isInCooldown(player))
|
if (choppingManager.isInCooldown(player)) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (treeAnimationManager.isBlockInAnimation(block)) {
|
if (treeAnimationManager.isBlockInAnimation(block)) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!treeDefinitionManager.isToolValidForAnyTreeDefinition(tool))
|
if (!treeDefinitionManager.isToolValidForAnyTreeDefinition(tool)) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.HOOKS_REQUIRE_ABILITY_ACTIVE.getBoolean()
|
if (ConfigurationManager.Setting.HOOKS_REQUIRE_ABILITY_ACTIVE.getBoolean() && !McMMOHook.isUsingTreeFeller(player)) {
|
||||||
&& McMMOHook.isUsingTreeFeller(player))
|
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
boolean alwaysReplantSapling = ConfigurationManager.Setting.ALWAYS_REPLANT_SAPLING.getBoolean();
|
boolean alwaysReplantSapling = ConfigurationManager.Setting.ALWAYS_REPLANT_SAPLING.getBoolean();
|
||||||
if (!isValid && !alwaysReplantSapling)
|
if (!isValid && !alwaysReplantSapling) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DetectedTree detectedTree = treeDetectionManager.detectTree(block);
|
DetectedTree detectedTree = treeDetectionManager.detectTree(block);
|
||||||
if (detectedTree == null)
|
if (detectedTree == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (alwaysReplantSapling) {
|
if (alwaysReplantSapling) {
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () ->
|
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () ->
|
||||||
saplingManager.replantSapling(detectedTree.getTreeDefinition(), detectedTree.getDetectedTreeBlocks().getInitialLogBlock()));
|
saplingManager.replantSapling(detectedTree.getTreeDefinition(), detectedTree.getDetectedTreeBlocks().getInitialLogBlock()));
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!treeDefinitionManager.isToolValidForTreeDefinition(detectedTree.getTreeDefinition(), tool))
|
if (!treeDefinitionManager.isToolValidForTreeDefinition(detectedTree.getTreeDefinition(), tool)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int toolDamage = this.getToolDamage(detectedTree.getDetectedTreeBlocks(), tool.containsEnchantment(Enchantment.SILK_TOUCH));
|
short toolDamage = this.getToolDamage(detectedTree.getDetectedTreeBlocks(), tool.containsEnchantment(Enchantment.SILK_TOUCH));
|
||||||
if (ConfigurationManager.Setting.PROTECT_TOOL.getBoolean() && !versionAdapter.hasEnoughDurability(tool, toolDamage))
|
if (ConfigurationManager.Setting.PROTECT_TOOL.getBoolean() && !ItemUtils.hasEnoughDurability(tool, toolDamage)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger fall event
|
// Trigger fall event
|
||||||
TreeFallEvent treeFallEvent = new TreeFallEvent(player, detectedTree);
|
TreeFallEvent treeFallEvent = new TreeFallEvent(player, detectedTree);
|
||||||
Bukkit.getPluginManager().callEvent(treeFallEvent);
|
Bukkit.getPluginManager().callEvent(treeFallEvent);
|
||||||
if (treeFallEvent.isCancelled())
|
if (treeFallEvent.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Valid tree and meets all conditions past this point
|
// Valid tree and meets all conditions past this point
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
detectedTree.getDetectedTreeBlocks().sortAndLimit(this.maxLogBlocksAllowed);
|
||||||
|
|
||||||
choppingManager.cooldownPlayer(player);
|
choppingManager.cooldownPlayer(player);
|
||||||
|
|
||||||
|
|
||||||
// Destroy initiated block if enabled
|
// Destroy initiated block if enabled
|
||||||
if (ConfigurationManager.Setting.DESTROY_INITIATED_BLOCK.getBoolean()) {
|
if (ConfigurationManager.Setting.DESTROY_INITIATED_BLOCK.getBoolean()) {
|
||||||
detectedTree.getDetectedTreeBlocks().getInitialLogBlock().getBlock().setType(Material.AIR);
|
detectedTree.getDetectedTreeBlocks().getInitialLogBlock().getBlock().setType(Material.AIR);
|
||||||
detectedTree.getDetectedTreeBlocks().remove(detectedTree.getDetectedTreeBlocks().getInitialLogBlock());
|
detectedTree.getDetectedTreeBlocks().remove(detectedTree.getDetectedTreeBlocks().getInitialLogBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!player.getGameMode().equals(GameMode.CREATIVE))
|
boolean isCreative = player.getGameMode() == GameMode.CREATIVE;
|
||||||
versionAdapter.applyToolDurability(player, toolDamage);
|
|
||||||
|
|
||||||
McMMOHook.addWoodcutting(player, detectedTree.getDetectedTreeBlocks().getAllTreeBlocks().stream()
|
if (!isCreative) {
|
||||||
.map(ITreeBlock::getBlock).collect(Collectors.toList()));
|
SItemStack sstack = new SItemStack(tool);
|
||||||
|
sstack.addDamage(player, toolDamage, true);
|
||||||
|
|
||||||
|
//Destroy item if durability is less than 0
|
||||||
|
ItemMeta meta = sstack.getItem().getItemMeta();
|
||||||
|
if (meta instanceof Damageable) {
|
||||||
|
Damageable damageable = (Damageable)meta;
|
||||||
|
int damage = damageable.getDamage();
|
||||||
|
if (damage >= sstack.getItem().getType().getMaxDurability()) {
|
||||||
|
//Break tool
|
||||||
|
player.getInventory().setItemInMainHand(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigurationManager.Setting.HOOKS_APPLY_EXPERIENCE.getBoolean()) {
|
||||||
|
McMMOHook.addWoodcutting(player, detectedTree.getDetectedTreeBlocks().getAllTreeBlocks().stream()
|
||||||
|
.map(ITreeBlock::getBlock).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
if (!isCreative && JobsHook.isEnabled()) {
|
||||||
|
for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getLogBlocks()) {
|
||||||
|
JobsHook.breakBlock(player, treeBlock.getBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
|
for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) {
|
||||||
if (JobsHook.isEnabled() && treeBlock.getTreeBlockType() == TreeBlockType.LOG)
|
|
||||||
JobsHook.breakBlock(player, block);
|
|
||||||
LogManager.logRemoval(player, treeBlock.getBlock());
|
LogManager.logRemoval(player, treeBlock.getBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,15 +212,15 @@ public class TreeFallManager extends Manager implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getToolDamage(TreeBlockSet<Block> treeBlocks, boolean hasSilkTouch) {
|
private short getToolDamage(TreeBlockSet<Block> treeBlocks, boolean hasSilkTouch) {
|
||||||
if (!ConfigurationManager.Setting.REALISTIC_TOOL_DAMAGE.getBoolean())
|
if (!ConfigurationManager.Setting.REALISTIC_TOOL_DAMAGE.getBoolean()) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigurationManager.Setting.APPLY_SILK_TOUCH_TOOL_DAMAGE.getBoolean() && hasSilkTouch) {
|
if (ConfigurationManager.Setting.APPLY_SILK_TOUCH_TOOL_DAMAGE.getBoolean() && hasSilkTouch) {
|
||||||
return treeBlocks.size();
|
return (short) treeBlocks.size();
|
||||||
} else {
|
} else {
|
||||||
return treeBlocks.getLogBlocks().size();
|
return (short) treeBlocks.getLogBlocks().size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.craftaro.ultimatetimber.misc;
|
||||||
|
|
||||||
|
public enum OnlyToppleWhile {
|
||||||
|
SNEAKING, NOT_SNEAKING, ALWAYS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an OnlyToppleWhile from a given string
|
||||||
|
*
|
||||||
|
* @return The TreeAnimationType, returns {@link #ALWAYS} if the string is an invalid type
|
||||||
|
*/
|
||||||
|
public static OnlyToppleWhile fromString(String string) {
|
||||||
|
for (OnlyToppleWhile value : values()) {
|
||||||
|
if (value.name().equalsIgnoreCase(string)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OnlyToppleWhile.ALWAYS;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
public class DetectedTree {
|
public class DetectedTree {
|
||||||
|
private final TreeDefinition treeDefinition;
|
||||||
private TreeDefinition treeDefinition;
|
private final TreeBlockSet<Block> detectedTreeBlocks;
|
||||||
private TreeBlockSet<Block> detectedTreeBlocks;
|
|
||||||
|
|
||||||
public DetectedTree(TreeDefinition treeDefinition, TreeBlockSet<Block> detectedTreeBlocks) {
|
public DetectedTree(TreeDefinition treeDefinition, TreeBlockSet<Block> detectedTreeBlocks) {
|
||||||
this.treeDefinition = treeDefinition;
|
this.treeDefinition = treeDefinition;
|
||||||
@ -29,5 +28,4 @@ public class DetectedTree {
|
|||||||
public TreeBlockSet<Block> getDetectedTreeBlocks() {
|
public TreeBlockSet<Block> getDetectedTreeBlocks() {
|
||||||
return this.detectedTreeBlocks;
|
return this.detectedTreeBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,9 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.FallingBlock;
|
import org.bukkit.entity.FallingBlock;
|
||||||
|
|
||||||
public class FallingTreeBlock implements ITreeBlock<FallingBlock> {
|
public class FallingTreeBlock implements ITreeBlock<FallingBlock> {
|
||||||
|
|
||||||
private final FallingBlock fallingBlock;
|
private final FallingBlock fallingBlock;
|
||||||
private final TreeBlockType treeBlockType;
|
private final TreeBlockType treeBlockType;
|
||||||
|
|
||||||
@ -27,5 +26,4 @@ public class FallingTreeBlock implements ITreeBlock<FallingBlock> {
|
|||||||
public TreeBlockType getTreeBlockType() {
|
public TreeBlockType getTreeBlockType() {
|
||||||
return this.treeBlockType;
|
return this.treeBlockType;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,9 +1,8 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
|
||||||
public interface ITreeBlock<BlockType> {
|
public interface ITreeBlock<BlockType> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the block this TreeBlock represents
|
* Gets the block this TreeBlock represents
|
||||||
*
|
*
|
||||||
@ -24,5 +23,4 @@ public interface ITreeBlock<BlockType> {
|
|||||||
* @return The TreeBlockType
|
* @return The TreeBlockType
|
||||||
*/
|
*/
|
||||||
TreeBlockType getTreeBlockType();
|
TreeBlockType getTreeBlockType();
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@ -6,7 +6,6 @@ import org.bukkit.block.Block;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class TreeBlock implements ITreeBlock<Block> {
|
public class TreeBlock implements ITreeBlock<Block> {
|
||||||
|
|
||||||
private final Block block;
|
private final Block block;
|
||||||
private final TreeBlockType treeBlockType;
|
private final TreeBlockType treeBlockType;
|
||||||
|
|
||||||
@ -36,11 +35,15 @@ public class TreeBlock implements ITreeBlock<Block> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object obj) {
|
||||||
if (!(o instanceof TreeBlock)) return false;
|
if (!(obj instanceof TreeBlock)) {
|
||||||
if (o == this) return true;
|
return false;
|
||||||
TreeBlock oTreeBlock = (TreeBlock)o;
|
}
|
||||||
return oTreeBlock.block.equals(this.block) && oTreeBlock.treeBlockType.equals(this.treeBlockType);
|
if (obj == this) {
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeBlock oTreeBlock = (TreeBlock) obj;
|
||||||
|
return oTreeBlock.block.equals(this.block) && oTreeBlock.treeBlockType == this.treeBlockType;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,29 +1,34 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TreeBlockSet<BlockType> implements Collection {
|
public class TreeBlockSet<BlockType> implements Collection {
|
||||||
|
|
||||||
private final ITreeBlock<BlockType> initialLogBlock;
|
private final ITreeBlock<BlockType> initialLogBlock;
|
||||||
private final Set<ITreeBlock<BlockType>> logBlocks, leafBlocks;
|
private List<ITreeBlock<BlockType>> logBlocks;
|
||||||
|
private final List<ITreeBlock<BlockType>> leafBlocks;
|
||||||
|
|
||||||
public TreeBlockSet() {
|
public TreeBlockSet() {
|
||||||
this.initialLogBlock = null;
|
this.initialLogBlock = null;
|
||||||
this.logBlocks = new HashSet<>();
|
this.logBlocks = new LinkedList<>();
|
||||||
this.leafBlocks = new HashSet<>();
|
this.leafBlocks = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreeBlockSet(ITreeBlock<BlockType> initialLogBlock) {
|
public TreeBlockSet(ITreeBlock<BlockType> initialLogBlock) {
|
||||||
this.initialLogBlock = initialLogBlock;
|
this.initialLogBlock = initialLogBlock;
|
||||||
this.logBlocks = new HashSet<>();
|
this.logBlocks = new LinkedList<>();
|
||||||
this.leafBlocks = new HashSet<>();
|
this.leafBlocks = new LinkedList<>();
|
||||||
|
|
||||||
if (initialLogBlock != null)
|
if (initialLogBlock != null) {
|
||||||
this.logBlocks.add(initialLogBlock);
|
this.logBlocks.add(initialLogBlock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +45,8 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
*
|
*
|
||||||
* @return A Set of TreeBlocks
|
* @return A Set of TreeBlocks
|
||||||
*/
|
*/
|
||||||
public Set<ITreeBlock<BlockType>> getLogBlocks() {
|
public List<ITreeBlock<BlockType>> getLogBlocks() {
|
||||||
return Collections.unmodifiableSet(this.logBlocks);
|
return Collections.unmodifiableList(this.logBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,8 +54,8 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
*
|
*
|
||||||
* @return A Set of TreeBlocks
|
* @return A Set of TreeBlocks
|
||||||
*/
|
*/
|
||||||
public Set<ITreeBlock<BlockType>> getLeafBlocks() {
|
public List<ITreeBlock<BlockType>> getLeafBlocks() {
|
||||||
return Collections.unmodifiableSet(this.leafBlocks);
|
return Collections.unmodifiableList(this.leafBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +98,9 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public boolean add(Object o) {
|
public boolean add(Object o) {
|
||||||
if (!(o instanceof ITreeBlock)) return false;
|
if (!(o instanceof ITreeBlock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ITreeBlock treeBlock = (ITreeBlock) o;
|
ITreeBlock treeBlock = (ITreeBlock) o;
|
||||||
switch (treeBlock.getTreeBlockType()) {
|
switch (treeBlock.getTreeBlockType()) {
|
||||||
case LOG:
|
case LOG:
|
||||||
@ -106,7 +113,9 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
if (!(o instanceof ITreeBlock)) return false;
|
if (!(o instanceof ITreeBlock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ITreeBlock treeBlock = (ITreeBlock) o;
|
ITreeBlock treeBlock = (ITreeBlock) o;
|
||||||
switch (treeBlock.getTreeBlockType()) {
|
switch (treeBlock.getTreeBlockType()) {
|
||||||
case LOG:
|
case LOG:
|
||||||
@ -160,6 +169,25 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
return removedAll;
|
return removedAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sortAndLimit(int max) {
|
||||||
|
if (this.logBlocks.size() < max) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logBlocks = this.logBlocks.stream().sorted(Comparator.comparingInt(b -> b.getLocation().getBlockY()))
|
||||||
|
.limit(max).collect(Collectors.toList());
|
||||||
|
|
||||||
|
int highest = this.logBlocks.get(this.logBlocks.size() - 1).getLocation().getBlockY();
|
||||||
|
|
||||||
|
if (this.logBlocks.size() >= max) {
|
||||||
|
for (ITreeBlock<BlockType> leafBlock : new LinkedList<>(this.leafBlocks)) {
|
||||||
|
if (leafBlock.getLocation().getY() > highest) {
|
||||||
|
this.leafBlocks.remove(leafBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all tree blocks of a given type
|
* Removes all tree blocks of a given type
|
||||||
*
|
*
|
||||||
@ -167,11 +195,12 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
* @return If any blocks were removed
|
* @return If any blocks were removed
|
||||||
*/
|
*/
|
||||||
public boolean removeAll(TreeBlockType treeBlockType) {
|
public boolean removeAll(TreeBlockType treeBlockType) {
|
||||||
if (treeBlockType.equals(TreeBlockType.LOG)) {
|
if (treeBlockType == TreeBlockType.LOG) {
|
||||||
boolean removedAny = !this.logBlocks.isEmpty();
|
boolean removedAny = !this.logBlocks.isEmpty();
|
||||||
this.logBlocks.clear();
|
this.logBlocks.clear();
|
||||||
return removedAny;
|
return removedAny;
|
||||||
} else if (treeBlockType.equals(TreeBlockType.LEAF)) {
|
}
|
||||||
|
if (treeBlockType == TreeBlockType.LEAF) {
|
||||||
boolean removedAny = !this.leafBlocks.isEmpty();
|
boolean removedAny = !this.leafBlocks.isEmpty();
|
||||||
this.leafBlocks.clear();
|
this.leafBlocks.clear();
|
||||||
return removedAny;
|
return removedAny;
|
||||||
@ -181,9 +210,11 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(Collection c) {
|
public boolean containsAll(Collection c) {
|
||||||
for (Object o : c)
|
for (Object o : c) {
|
||||||
if (!this.contains(o))
|
if (!this.contains(o)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,10 +222,12 @@ public class TreeBlockSet<BlockType> implements Collection {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Object[] toArray(Object[] a) {
|
public Object[] toArray(Object[] a) {
|
||||||
Set<ITreeBlock<BlockType>> treeBlocks = new HashSet<>();
|
Set<ITreeBlock<BlockType>> treeBlocks = new HashSet<>();
|
||||||
for (Object o : a)
|
for (Object o : a) {
|
||||||
if (o instanceof ITreeBlock)
|
if (o instanceof ITreeBlock) {
|
||||||
treeBlocks.add((ITreeBlock<BlockType>)o);
|
treeBlocks.add((ITreeBlock<BlockType>) o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return treeBlocks.toArray();
|
return treeBlocks.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
|
public enum TreeBlockType {
|
||||||
|
LOG, LEAF
|
||||||
|
}
|
@ -1,32 +1,32 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import com.songoda.ultimatetimber.adapter.IBlockData;
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class TreeDefinition {
|
public class TreeDefinition {
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
private final Set<IBlockData> logBlockData, leafBlockData, plantableSoilBlockData;
|
private final Set<XMaterial> logMaterial, leafMaterial, plantableSoilMaterial;
|
||||||
private final IBlockData saplingBlockData;
|
private final XMaterial saplingMaterial;
|
||||||
private final double maxLogDistanceFromTrunk;
|
private final double maxLogDistanceFromTrunk;
|
||||||
private final int maxLeafDistanceFromLog;
|
private final int maxLeafDistanceFromLog;
|
||||||
private final boolean detectLeavesDiagonally;
|
private final boolean detectLeavesDiagonally;
|
||||||
private final boolean dropOriginalLog, dropOriginalLeaf;
|
private final boolean dropOriginalLog, dropOriginalLeaf;
|
||||||
private final Set<TreeLoot> logLoot, leafLoot, entireTreeLoot;
|
private final Set<TreeLoot> logLoot, leafLoot, entireTreeLoot;
|
||||||
private final Set<ItemStack> requiredTools;
|
private final Set<ItemStack> requiredTools;
|
||||||
|
private final boolean requiredAxe;
|
||||||
|
|
||||||
public TreeDefinition(String key, Set<IBlockData> logBlockData, Set<IBlockData> leafBlockData, IBlockData saplingBlockData,
|
public TreeDefinition(String key, Set<XMaterial> logMaterial, Set<XMaterial> leafMaterial, XMaterial saplingMaterial,
|
||||||
Set<IBlockData> plantableSoilBlockData, double maxLogDistanceFromTrunk, int maxLeafDistanceFromLog,
|
Set<XMaterial> plantableSoilMaterial, double maxLogDistanceFromTrunk, int maxLeafDistanceFromLog,
|
||||||
boolean detectLeavesDiagonally, boolean dropOriginalLog, boolean dropOriginalLeaf, Set<TreeLoot> logLoot,
|
boolean detectLeavesDiagonally, boolean dropOriginalLog, boolean dropOriginalLeaf, Set<TreeLoot> logLoot,
|
||||||
Set<TreeLoot> leafLoot, Set<TreeLoot> entireTreeLoot, Set<ItemStack> requiredTools) {
|
Set<TreeLoot> leafLoot, Set<TreeLoot> entireTreeLoot, Set<ItemStack> requiredTools, boolean requiredAxe) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.logBlockData = logBlockData;
|
this.logMaterial = logMaterial;
|
||||||
this.leafBlockData = leafBlockData;
|
this.leafMaterial = leafMaterial;
|
||||||
this.saplingBlockData = saplingBlockData;
|
this.saplingMaterial = saplingMaterial;
|
||||||
this.plantableSoilBlockData = plantableSoilBlockData;
|
this.plantableSoilMaterial = plantableSoilMaterial;
|
||||||
this.maxLogDistanceFromTrunk = maxLogDistanceFromTrunk;
|
this.maxLogDistanceFromTrunk = maxLogDistanceFromTrunk;
|
||||||
this.maxLeafDistanceFromLog = maxLeafDistanceFromLog;
|
this.maxLeafDistanceFromLog = maxLeafDistanceFromLog;
|
||||||
this.detectLeavesDiagonally = detectLeavesDiagonally;
|
this.detectLeavesDiagonally = detectLeavesDiagonally;
|
||||||
@ -36,6 +36,7 @@ public class TreeDefinition {
|
|||||||
this.leafLoot = leafLoot;
|
this.leafLoot = leafLoot;
|
||||||
this.entireTreeLoot = entireTreeLoot;
|
this.entireTreeLoot = entireTreeLoot;
|
||||||
this.requiredTools = requiredTools;
|
this.requiredTools = requiredTools;
|
||||||
|
this.requiredAxe = requiredAxe;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,37 +51,37 @@ public class TreeDefinition {
|
|||||||
/**
|
/**
|
||||||
* Gets a set of valid log block data for this TreeDefinition
|
* Gets a set of valid log block data for this TreeDefinition
|
||||||
*
|
*
|
||||||
* @return A Set of IBlockData
|
* @return A Set of CompatibleMaterial
|
||||||
*/
|
*/
|
||||||
public Set<IBlockData> getLogBlockData() {
|
public Set<XMaterial> getLogMaterial() {
|
||||||
return Collections.unmodifiableSet(this.logBlockData);
|
return Collections.unmodifiableSet(this.logMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of valid leaf block data for this TreeDefinition
|
* Gets a set of valid leaf block data for this TreeDefinition
|
||||||
*
|
*
|
||||||
* @return A Set of IBlockData
|
* @return A Set of CompatibleMaterial
|
||||||
*/
|
*/
|
||||||
public Set<IBlockData> getLeafBlockData() {
|
public Set<XMaterial> getLeafMaterial() {
|
||||||
return Collections.unmodifiableSet(this.leafBlockData);
|
return Collections.unmodifiableSet(this.leafMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the sapling block data of this TreeDefinition
|
* Gets the sapling block data of this TreeDefinition
|
||||||
*
|
*
|
||||||
* @return An IBlockData instance for the sapling
|
* @return An CompatibleMaterial instance for the sapling
|
||||||
*/
|
*/
|
||||||
public IBlockData getSaplingBlockData() {
|
public XMaterial getSaplingMaterial() {
|
||||||
return this.saplingBlockData;
|
return this.saplingMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of plantable soil block data for this TreeDefinition
|
* Gets a set of plantable soil block data for this TreeDefinition
|
||||||
*
|
*
|
||||||
* @return A Set of IBlockData
|
* @return A Set of CompatibleMaterial
|
||||||
*/
|
*/
|
||||||
public Set<IBlockData> getPlantableSoilBlockData() {
|
public Set<XMaterial> getPlantableSoilMaterial() {
|
||||||
return Collections.unmodifiableSet(this.plantableSoilBlockData);
|
return Collections.unmodifiableSet(this.plantableSoilMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,4 +165,12 @@ public class TreeDefinition {
|
|||||||
return Collections.unmodifiableSet(this.requiredTools);
|
return Collections.unmodifiableSet(this.requiredTools);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this TreeDefinition requires a custom axe.
|
||||||
|
*
|
||||||
|
* @return True if the TreeDefinition requires a custom axe
|
||||||
|
*/
|
||||||
|
public boolean isRequiredAxe() {
|
||||||
|
return this.requiredAxe;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,9 +1,8 @@
|
|||||||
package com.songoda.ultimatetimber.tree;
|
package com.craftaro.ultimatetimber.tree;
|
||||||
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
public class TreeLoot {
|
public class TreeLoot {
|
||||||
|
|
||||||
private final TreeBlockType treeBlockType;
|
private final TreeBlockType treeBlockType;
|
||||||
private final ItemStack item;
|
private final ItemStack item;
|
||||||
private final String command;
|
private final String command;
|
||||||
@ -70,4 +69,13 @@ public class TreeLoot {
|
|||||||
return this.chance;
|
return this.chance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TreeLoot{" +
|
||||||
|
"treeBlockType=" + this.treeBlockType +
|
||||||
|
", item=" + this.item +
|
||||||
|
", command='" + this.command + '\'' +
|
||||||
|
", chance=" + this.chance +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.craftaro.ultimatetimber.utils;
|
||||||
|
|
||||||
|
import com.craftaro.core.compatibility.CompatibleMaterial;
|
||||||
|
import com.craftaro.core.compatibility.ServerVersion;
|
||||||
|
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.FallingBlock;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class BlockUtils {
|
||||||
|
public static Collection<ItemStack> getBlockDrops(ITreeBlock treeBlock) {
|
||||||
|
Set<ItemStack> drops = new HashSet<>();
|
||||||
|
if (treeBlock.getBlock() instanceof Block) {
|
||||||
|
Block block = (Block) treeBlock.getBlock();
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(block.getType());
|
||||||
|
if (!material.isPresent() || CompatibleMaterial.isAir(material.get())) {
|
||||||
|
return drops;
|
||||||
|
}
|
||||||
|
drops.add(material.get().parseItem());
|
||||||
|
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
||||||
|
Optional<XMaterial> material = CompatibleMaterial.getMaterial(((FallingBlock) treeBlock.getBlock()).getBlockData().getMaterial());
|
||||||
|
if (!material.isPresent()) {
|
||||||
|
return drops;
|
||||||
|
}
|
||||||
|
drops.add(material.get().parseItem());
|
||||||
|
}
|
||||||
|
return drops;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void toggleGravityFallingBlock(FallingBlock fallingBlock, boolean applyGravity) {
|
||||||
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
|
||||||
|
fallingBlock.setGravity(applyGravity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FallingBlock spawnFallingBlock(Location location, XMaterial material) {
|
||||||
|
return location.getWorld().spawnFallingBlock(location, material.parseMaterial(), material.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void configureFallingBlock(FallingBlock fallingBlock) {
|
||||||
|
toggleGravityFallingBlock(fallingBlock, false);
|
||||||
|
fallingBlock.setDropItem(false);
|
||||||
|
fallingBlock.setHurtEntities(false);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.craftaro.ultimatetimber.utils;
|
||||||
|
|
||||||
|
import com.craftaro.core.compatibility.ServerVersion;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import org.bukkit.Effect;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.FallingBlock;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class ParticleUtils {
|
||||||
|
public static void playFallingParticles(ITreeBlock treeBlock) {
|
||||||
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
|
||||||
|
BlockData blockData;
|
||||||
|
if (treeBlock.getBlock() instanceof Block) {
|
||||||
|
blockData = ((Block) treeBlock.getBlock()).getBlockData();
|
||||||
|
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
||||||
|
blockData = ((FallingBlock) treeBlock.getBlock()).getBlockData();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
||||||
|
location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<ItemStack> blockDrops = BlockUtils.getBlockDrops(treeBlock);
|
||||||
|
if (!blockDrops.iterator().hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
||||||
|
if (ServerVersion.isServerVersion(ServerVersion.V1_8)) {
|
||||||
|
location.getWorld().playEffect(location, Effect.SMOKE, 4);
|
||||||
|
} else {
|
||||||
|
location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockDrops.iterator().next().getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playLandingParticles(ITreeBlock treeBlock) {
|
||||||
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
|
||||||
|
BlockData blockData;
|
||||||
|
if (treeBlock.getBlock() instanceof Block) {
|
||||||
|
blockData = ((Block) treeBlock.getBlock()).getBlockData();
|
||||||
|
} else if (treeBlock.getBlock() instanceof FallingBlock) {
|
||||||
|
blockData = ((FallingBlock) treeBlock.getBlock()).getBlockData();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
||||||
|
location.getWorld().spawnParticle(Particle.BLOCK_CRACK, location, 10, blockData);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<ItemStack> blockDrops = BlockUtils.getBlockDrops(treeBlock);
|
||||||
|
if (!blockDrops.iterator().hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
|
||||||
|
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
|
||||||
|
location.getWorld().spawnParticle(Particle.BLOCK_CRACK, location, 10, blockDrops.iterator().next().getData());
|
||||||
|
} else {
|
||||||
|
location.getWorld().playEffect(location, Effect.SMOKE, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.craftaro.ultimatetimber.utils;
|
||||||
|
|
||||||
|
import com.craftaro.third_party.com.cryptomorin.xseries.XSound;
|
||||||
|
import com.craftaro.ultimatetimber.tree.ITreeBlock;
|
||||||
|
import com.craftaro.ultimatetimber.tree.TreeBlockType;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
public class SoundUtils {
|
||||||
|
public static void playFallingSound(ITreeBlock block) {
|
||||||
|
Location location = block.getLocation();
|
||||||
|
if (location.getWorld() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
XSound.BLOCK_CHEST_OPEN.play(location, 2, .1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playLandingSound(ITreeBlock block) {
|
||||||
|
Location location = block.getLocation();
|
||||||
|
if (location.getWorld() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.getTreeBlockType() == TreeBlockType.LOG) {
|
||||||
|
XSound.BLOCK_WOOD_FALL.play(location, 2, .1f);
|
||||||
|
} else {
|
||||||
|
XSound.BLOCK_GRASS_BREAK.play(location, .5f, .75f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -190,14 +190,15 @@ trees:
|
|||||||
- STRIPPED_OAK_WOOD
|
- STRIPPED_OAK_WOOD
|
||||||
leaves:
|
leaves:
|
||||||
- OAK_LEAVES
|
- OAK_LEAVES
|
||||||
|
- VINE
|
||||||
sapling: OAK_SAPLING
|
sapling: OAK_SAPLING
|
||||||
plantable-soil: []
|
plantable-soil: [ ]
|
||||||
max-log-distance-from-trunk: 6
|
max-log-distance-from-trunk: 6
|
||||||
max-leaf-distance-from-log: 6
|
max-leaf-distance-from-log: 6
|
||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: OAK_SAPLING
|
material: OAK_SAPLING
|
||||||
@ -205,8 +206,9 @@ trees:
|
|||||||
1:
|
1:
|
||||||
material: APPLE
|
material: APPLE
|
||||||
chance: 0.5
|
chance: 0.5
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
spruce:
|
spruce:
|
||||||
logs:
|
logs:
|
||||||
- SPRUCE_LOG
|
- SPRUCE_LOG
|
||||||
@ -215,20 +217,22 @@ trees:
|
|||||||
- STRIPPED_SPRUCE_WOOD
|
- STRIPPED_SPRUCE_WOOD
|
||||||
leaves:
|
leaves:
|
||||||
- SPRUCE_LEAVES
|
- SPRUCE_LEAVES
|
||||||
|
- VINE
|
||||||
sapling: SPRUCE_SAPLING
|
sapling: SPRUCE_SAPLING
|
||||||
plantable-soil: []
|
plantable-soil: [ ]
|
||||||
max-log-distance-from-trunk: 2
|
max-log-distance-from-trunk: 2
|
||||||
max-leaf-distance-from-log: 6
|
max-leaf-distance-from-log: 6
|
||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: SPRUCE_SAPLING
|
material: SPRUCE_SAPLING
|
||||||
chance: 5
|
chance: 5
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
birch:
|
birch:
|
||||||
logs:
|
logs:
|
||||||
- BIRCH_LOG
|
- BIRCH_LOG
|
||||||
@ -237,20 +241,22 @@ trees:
|
|||||||
- STRIPPED_BIRCH_WOOD
|
- STRIPPED_BIRCH_WOOD
|
||||||
leaves:
|
leaves:
|
||||||
- BIRCH_LEAVES
|
- BIRCH_LEAVES
|
||||||
|
- VINE
|
||||||
sapling: BIRCH_SAPLING
|
sapling: BIRCH_SAPLING
|
||||||
plantable-soil: []
|
plantable-soil: [ ]
|
||||||
max-log-distance-from-trunk: 1
|
max-log-distance-from-trunk: 1
|
||||||
max-leaf-distance-from-log: 4
|
max-leaf-distance-from-log: 4
|
||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: BIRCH_SAPLING
|
material: BIRCH_SAPLING
|
||||||
chance: 5
|
chance: 5
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
jungle:
|
jungle:
|
||||||
logs:
|
logs:
|
||||||
- JUNGLE_LOG
|
- JUNGLE_LOG
|
||||||
@ -259,20 +265,22 @@ trees:
|
|||||||
- STRIPPED_JUNGLE_WOOD
|
- STRIPPED_JUNGLE_WOOD
|
||||||
leaves:
|
leaves:
|
||||||
- JUNGLE_LEAVES
|
- JUNGLE_LEAVES
|
||||||
|
- VINE
|
||||||
sapling: JUNGLE_SAPLING
|
sapling: JUNGLE_SAPLING
|
||||||
plantable-soil: []
|
plantable-soil: [ ]
|
||||||
max-log-distance-from-trunk: 6
|
max-log-distance-from-trunk: 6
|
||||||
max-leaf-distance-from-log: 6
|
max-leaf-distance-from-log: 6
|
||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: JUNGLE_SAPLING
|
material: JUNGLE_SAPLING
|
||||||
chance: 2.5
|
chance: 2.5
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
acacia:
|
acacia:
|
||||||
logs:
|
logs:
|
||||||
- ACACIA_LOG
|
- ACACIA_LOG
|
||||||
@ -282,19 +290,20 @@ trees:
|
|||||||
leaves:
|
leaves:
|
||||||
- ACACIA_LEAVES
|
- ACACIA_LEAVES
|
||||||
sapling: ACACIA_SAPLING
|
sapling: ACACIA_SAPLING
|
||||||
plantable-soil: []
|
plantable-soil: [ ]
|
||||||
max-log-distance-from-trunk: 4
|
max-log-distance-from-trunk: 4
|
||||||
max-leaf-distance-from-log: 5
|
max-leaf-distance-from-log: 5
|
||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: ACACIA_SAPLING
|
material: ACACIA_SAPLING
|
||||||
chance: 5
|
chance: 5
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
dark_oak:
|
dark_oak:
|
||||||
logs:
|
logs:
|
||||||
- DARK_OAK_LOG
|
- DARK_OAK_LOG
|
||||||
@ -303,14 +312,15 @@ trees:
|
|||||||
- STRIPPED_DARK_OAK_WOOD
|
- STRIPPED_DARK_OAK_WOOD
|
||||||
leaves:
|
leaves:
|
||||||
- DARK_OAK_LEAVES
|
- DARK_OAK_LEAVES
|
||||||
|
- VINE
|
||||||
sapling: DARK_OAK_SAPLING
|
sapling: DARK_OAK_SAPLING
|
||||||
plantable-soil: []
|
plantable-soil: [ ]
|
||||||
max-log-distance-from-trunk: 3
|
max-log-distance-from-trunk: 3
|
||||||
max-leaf-distance-from-log: 5
|
max-leaf-distance-from-log: 5
|
||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: DARK_OAK_SAPLING
|
material: DARK_OAK_SAPLING
|
||||||
@ -318,8 +328,90 @@ trees:
|
|||||||
1:
|
1:
|
||||||
material: APPLE
|
material: APPLE
|
||||||
chance: 0.5
|
chance: 0.5
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
|
azalea:
|
||||||
|
logs:
|
||||||
|
- OAK_LOG
|
||||||
|
- STRIPPED_OAK_LOG
|
||||||
|
- OAK_WOOD
|
||||||
|
- STRIPPED_OAK_WOOD
|
||||||
|
leaves:
|
||||||
|
- AZALEA_LEAVES
|
||||||
|
- FLOWERING_AZALEA_LEAVES
|
||||||
|
- VINE
|
||||||
|
sapling: AZALEA
|
||||||
|
plantable-soil: [ ]
|
||||||
|
max-log-distance-from-trunk: 3
|
||||||
|
max-leaf-distance-from-log: 4
|
||||||
|
search-for-leaves-diagonally: true
|
||||||
|
drop-original-log: true
|
||||||
|
drop-original-leaf: false
|
||||||
|
log-loot: [ ]
|
||||||
|
leaf-loot:
|
||||||
|
0:
|
||||||
|
material: AZALEA
|
||||||
|
chance: 5
|
||||||
|
entire-tree-loot: [ ]
|
||||||
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
|
cherry:
|
||||||
|
logs:
|
||||||
|
- CHERRY_LOG
|
||||||
|
- STRIPPED_CHERRY_LOG
|
||||||
|
- CHERRY_WOOD
|
||||||
|
- STRIPPED_CHERRY_WOOD
|
||||||
|
leaves:
|
||||||
|
- CHERRY_LEAVES
|
||||||
|
sapling: CHERRY_SAPLING
|
||||||
|
plantable-soil: [ ]
|
||||||
|
max-log-distance-from-trunk: 10
|
||||||
|
max-leaf-distance-from-log: 6
|
||||||
|
search-for-leaves-diagonally: false
|
||||||
|
drop-original-log: true
|
||||||
|
drop-original-leaf: false
|
||||||
|
log-loot: [ ]
|
||||||
|
leaf-loot:
|
||||||
|
0:
|
||||||
|
material: CHERRY_SAPLING
|
||||||
|
chance: 5
|
||||||
|
1:
|
||||||
|
material: STICK
|
||||||
|
chance: 2.5
|
||||||
|
entire-tree-loot: [ ]
|
||||||
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
|
mangrove:
|
||||||
|
logs:
|
||||||
|
- MANGROVE_LOG
|
||||||
|
- STRIPPED_MANGROVE_LOG
|
||||||
|
- MANGROVE_WOOD
|
||||||
|
- STRIPPED_MANGROVE_WOOD
|
||||||
|
leaves:
|
||||||
|
- MANGROVE_LEAVES
|
||||||
|
- MANGROVE_ROOTS
|
||||||
|
- MOSS_CARPET
|
||||||
|
- MANGROVE_PROPAGULE
|
||||||
|
- VINE
|
||||||
|
sapling: MANGROVE_PROPAGULE
|
||||||
|
plantable-soil: [ ]
|
||||||
|
max-log-distance-from-trunk: 30
|
||||||
|
max-leaf-distance-from-log: 10
|
||||||
|
search-for-leaves-diagonally: true
|
||||||
|
drop-original-log: true
|
||||||
|
drop-original-leaf: false
|
||||||
|
log-loot: [ ]
|
||||||
|
leaf-loot:
|
||||||
|
0:
|
||||||
|
material: MANGROVE_PROPAGULE
|
||||||
|
chance: 5
|
||||||
|
1:
|
||||||
|
material: APPLE
|
||||||
|
chance: 0.5
|
||||||
|
entire-tree-loot: [ ]
|
||||||
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
brown_mushroom:
|
brown_mushroom:
|
||||||
logs:
|
logs:
|
||||||
- MUSHROOM_STEM
|
- MUSHROOM_STEM
|
||||||
@ -333,13 +425,14 @@ trees:
|
|||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: false
|
drop-original-log: false
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: BROWN_MUSHROOM
|
material: BROWN_MUSHROOM
|
||||||
chance: 25
|
chance: 25
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
red_mushroom:
|
red_mushroom:
|
||||||
logs:
|
logs:
|
||||||
- MUSHROOM_STEM
|
- MUSHROOM_STEM
|
||||||
@ -353,13 +446,14 @@ trees:
|
|||||||
search-for-leaves-diagonally: true
|
search-for-leaves-diagonally: true
|
||||||
drop-original-log: false
|
drop-original-log: false
|
||||||
drop-original-leaf: false
|
drop-original-leaf: false
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot:
|
leaf-loot:
|
||||||
0:
|
0:
|
||||||
material: RED_MUSHROOM
|
material: RED_MUSHROOM
|
||||||
chance: 25
|
chance: 25
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
huge_crimson_fungus:
|
huge_crimson_fungus:
|
||||||
logs:
|
logs:
|
||||||
- CRIMSON_STEM
|
- CRIMSON_STEM
|
||||||
@ -377,10 +471,11 @@ trees:
|
|||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: true
|
drop-original-leaf: true
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot: []
|
leaf-loot: [ ]
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
huge_warpped_fungus:
|
huge_warpped_fungus:
|
||||||
logs:
|
logs:
|
||||||
- WARPED_STEM
|
- WARPED_STEM
|
||||||
@ -398,10 +493,11 @@ trees:
|
|||||||
search-for-leaves-diagonally: false
|
search-for-leaves-diagonally: false
|
||||||
drop-original-log: true
|
drop-original-log: true
|
||||||
drop-original-leaf: true
|
drop-original-leaf: true
|
||||||
log-loot: []
|
log-loot: [ ]
|
||||||
leaf-loot: []
|
leaf-loot: [ ]
|
||||||
entire-tree-loot: []
|
entire-tree-loot: [ ]
|
||||||
required-tools: []
|
required-tools: [ ]
|
||||||
|
required-axe: false
|
||||||
|
|
||||||
# All soil types that the tree type's saplings can be planted on
|
# All soil types that the tree type's saplings can be planted on
|
||||||
global-plantable-soil:
|
global-plantable-soil:
|
||||||
@ -409,6 +505,7 @@ global-plantable-soil:
|
|||||||
- DIRT
|
- DIRT
|
||||||
- COARSE_DIRT
|
- COARSE_DIRT
|
||||||
- PODZOL
|
- PODZOL
|
||||||
|
- ROOTED_DIRT
|
||||||
|
|
||||||
# Custom loot that is available for all tree types
|
# Custom loot that is available for all tree types
|
||||||
# The loot applies to each log broken in the tree
|
# The loot applies to each log broken in the tree
|
||||||
@ -457,3 +554,27 @@ global-required-tools:
|
|||||||
- GOLDEN_AXE
|
- GOLDEN_AXE
|
||||||
- DIAMOND_AXE
|
- DIAMOND_AXE
|
||||||
- NETHERITE_AXE
|
- NETHERITE_AXE
|
||||||
|
|
||||||
|
# Require the custom axe
|
||||||
|
# Applies to all tree types
|
||||||
|
global-required-axe: false
|
||||||
|
|
||||||
|
# Axe item
|
||||||
|
required-axe:
|
||||||
|
type: DIAMOND_AXE
|
||||||
|
name: '&aAn Epic Axe'
|
||||||
|
lore:
|
||||||
|
- "&7This axe... it's awesome."
|
||||||
|
- "&7It can chop down trees real fast."
|
||||||
|
enchants:
|
||||||
|
- 'DURABILITY:3'
|
||||||
|
- 'DIG_SPEED:5'
|
||||||
|
# NBT to identify the axe by.
|
||||||
|
nbt: 'ultimatetimber_axe'
|
||||||
|
|
||||||
|
# If a tree lands on these blocks they will be destroyed.
|
||||||
|
fragile-blocks:
|
||||||
|
- GLASS
|
||||||
|
- ICE
|
||||||
|
- PACKED_ICE
|
||||||
|
- BLUE_ICE
|
@ -15,6 +15,10 @@ command:
|
|||||||
description: 'Toggles your chopping mode'
|
description: 'Toggles your chopping mode'
|
||||||
enabled: '&7Chopping Mode: &aEnabled'
|
enabled: '&7Chopping Mode: &aEnabled'
|
||||||
disabled: '&7Chopping Mode: &cDisabled'
|
disabled: '&7Chopping Mode: &cDisabled'
|
||||||
|
give:
|
||||||
|
not-a-player: '&cNot a player.'
|
||||||
|
given: '&fGiven to player &a%player%'
|
||||||
|
no-axe: '&cAxe could not be loaded.'
|
||||||
|
|
||||||
# Event Messages
|
# Event Messages
|
||||||
|
|
@ -1,14 +1,24 @@
|
|||||||
name: UltimateTimber
|
name: ${project.name}
|
||||||
version: maven-version-number
|
description: ${project.description}
|
||||||
authors: [Songoda, Esophose]
|
version: ${project.version}
|
||||||
main: com.songoda.ultimatetimber.UltimateTimber
|
|
||||||
api-version: 1.13
|
api-version: 1.13
|
||||||
softdepend: [mcMMO, Jobs, CoreProtect]
|
|
||||||
|
main: com.craftaro.ultimatetimber.UltimateTimber
|
||||||
|
softdepend:
|
||||||
|
- mcMMO
|
||||||
|
- Jobs
|
||||||
|
- CoreProtect
|
||||||
|
|
||||||
|
author: Craftaro
|
||||||
|
website: ${project.url}
|
||||||
|
|
||||||
|
# TODO: cleanup commands and permissions sections
|
||||||
commands:
|
commands:
|
||||||
ut:
|
ut:
|
||||||
description: Reloads the configuration file
|
description: Reloads the configuration file
|
||||||
usage: /ultimatetimber reload
|
usage: /ultimatetimber reload
|
||||||
aliases: [ultimatetimber]
|
aliases: [ ultimatetimber ]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
ultimatetimber.*:
|
ultimatetimber.*:
|
||||||
description: Inherits all plugin permissions
|
description: Inherits all plugin permissions
|
||||||
@ -17,15 +27,19 @@ permissions:
|
|||||||
ultimatetimber.bonusloot: true
|
ultimatetimber.bonusloot: true
|
||||||
ultimatetimber.reload: true
|
ultimatetimber.reload: true
|
||||||
ultimatetimber.bypasscooldown: true
|
ultimatetimber.bypasscooldown: true
|
||||||
|
|
||||||
ultimatetimber.chop:
|
ultimatetimber.chop:
|
||||||
description: Allows players to trigger the trees toppling down effect
|
description: Allows players to trigger the trees toppling down effect
|
||||||
default: op
|
default: op
|
||||||
|
|
||||||
ultimatetimber.bonusloot:
|
ultimatetimber.bonusloot:
|
||||||
description: Doubles the loot obtained from trees
|
description: Doubles the loot obtained from trees
|
||||||
default: op
|
default: op
|
||||||
|
|
||||||
ultimatetimber.reload:
|
ultimatetimber.reload:
|
||||||
description: Reloads the configuration file
|
description: Reloads the configuration file
|
||||||
default: op
|
default: op
|
||||||
|
|
||||||
ultimatetimber.bypasscooldown:
|
ultimatetimber.bypasscooldown:
|
||||||
description: Allows a player to bypass the tree topple cooldown
|
description: Allows a player to bypass the tree topple cooldown
|
||||||
default: op
|
default: op
|
Loading…
Reference in New Issue
Block a user