Compare commits

..

No commits in common. "master" and "v2.2.1b" have entirely different histories.

51 changed files with 1046 additions and 1641 deletions

39
.gitignore vendored
View File

@ -1,10 +1,31 @@
## JetBrains IDEs # Compiled class file
/.idea/ *.class
# 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
View File

@ -1,327 +1,9 @@
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Copyright (c) 2019 Brianna OKeefe
International Public License
By exercising the Licensed Rights (defined below), You accept and agree 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:
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.
Section 1 -- Definitions. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
a. Adapted Material means material subject to Copyright and Similar 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.
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.
=======================================================================

View File

@ -1,44 +0,0 @@
<!--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

View File

@ -0,0 +1,29 @@
<project xmlns="http://maven.apache.org/POM/4.0.0">
<parent>
<groupId>com.songoda</groupId>
<artifactId>UltimateTimber</artifactId>
<version>2.1.1b</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.16.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore</artifactId>
<version>LATEST</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,20 @@
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;
}
}

View File

@ -1,10 +1,11 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.ultimatetimber.tree;
import org.bukkit.block.Block; import org.bukkit.block.Block;
public class DetectedTree { public class DetectedTree {
private final TreeDefinition treeDefinition;
private final TreeBlockSet<Block> detectedTreeBlocks; private TreeDefinition treeDefinition;
private TreeBlockSet<Block> detectedTreeBlocks;
public DetectedTree(TreeDefinition treeDefinition, TreeBlockSet<Block> detectedTreeBlocks) { public DetectedTree(TreeDefinition treeDefinition, TreeBlockSet<Block> detectedTreeBlocks) {
this.treeDefinition = treeDefinition; this.treeDefinition = treeDefinition;
@ -28,4 +29,5 @@ public class DetectedTree {
public TreeBlockSet<Block> getDetectedTreeBlocks() { public TreeBlockSet<Block> getDetectedTreeBlocks() {
return this.detectedTreeBlocks; return this.detectedTreeBlocks;
} }
} }

View File

@ -1,9 +1,10 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.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;
@ -26,4 +27,5 @@ public class FallingTreeBlock implements ITreeBlock<FallingBlock> {
public TreeBlockType getTreeBlockType() { public TreeBlockType getTreeBlockType() {
return this.treeBlockType; return this.treeBlockType;
} }
} }

View File

@ -1,8 +1,9 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.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
* *
@ -23,4 +24,5 @@ public interface ITreeBlock<BlockType> {
* @return The TreeBlockType * @return The TreeBlockType
*/ */
TreeBlockType getTreeBlockType(); TreeBlockType getTreeBlockType();
} }

View File

@ -1,4 +1,4 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.ultimatetimber.tree;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -6,6 +6,7 @@ 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;
@ -35,15 +36,11 @@ public class TreeBlock implements ITreeBlock<Block> {
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object o) {
if (!(obj instanceof TreeBlock)) { if (!(o instanceof TreeBlock)) return false;
return false; if (o == this) return true;
} TreeBlock oTreeBlock = (TreeBlock)o;
if (obj == this) { return oTreeBlock.block.equals(this.block) && oTreeBlock.treeBlockType.equals(this.treeBlockType);
return true;
} }
TreeBlock oTreeBlock = (TreeBlock) obj;
return oTreeBlock.block.equals(this.block) && oTreeBlock.treeBlockType == this.treeBlockType;
}
} }

View File

@ -1,35 +1,30 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.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 List<ITreeBlock<BlockType>> logBlocks; private final Set<ITreeBlock<BlockType>> logBlocks, leafBlocks;
private final List<ITreeBlock<BlockType>> leafBlocks;
public TreeBlockSet() { public TreeBlockSet() {
this.initialLogBlock = null; this.initialLogBlock = null;
this.logBlocks = new LinkedList<>(); this.logBlocks = new HashSet<>();
this.leafBlocks = new LinkedList<>(); this.leafBlocks = new HashSet<>();
} }
public TreeBlockSet(ITreeBlock<BlockType> initialLogBlock) { public TreeBlockSet(ITreeBlock<BlockType> initialLogBlock) {
this.initialLogBlock = initialLogBlock; this.initialLogBlock = initialLogBlock;
this.logBlocks = new LinkedList<>(); this.logBlocks = new HashSet<>();
this.leafBlocks = new LinkedList<>(); this.leafBlocks = new HashSet<>();
if (initialLogBlock != null) { if (initialLogBlock != null)
this.logBlocks.add(initialLogBlock); this.logBlocks.add(initialLogBlock);
} }
}
/** /**
* Gets the TreeBlock that initiated the tree topple * Gets the TreeBlock that initiated the tree topple
@ -45,8 +40,8 @@ public class TreeBlockSet<BlockType> implements Collection {
* *
* @return A Set of TreeBlocks * @return A Set of TreeBlocks
*/ */
public List<ITreeBlock<BlockType>> getLogBlocks() { public Set<ITreeBlock<BlockType>> getLogBlocks() {
return Collections.unmodifiableList(this.logBlocks); return Collections.unmodifiableSet(this.logBlocks);
} }
/** /**
@ -54,8 +49,8 @@ public class TreeBlockSet<BlockType> implements Collection {
* *
* @return A Set of TreeBlocks * @return A Set of TreeBlocks
*/ */
public List<ITreeBlock<BlockType>> getLeafBlocks() { public Set<ITreeBlock<BlockType>> getLeafBlocks() {
return Collections.unmodifiableList(this.leafBlocks); return Collections.unmodifiableSet(this.leafBlocks);
} }
/** /**
@ -98,9 +93,7 @@ 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)) { if (!(o instanceof ITreeBlock)) return false;
return false;
}
ITreeBlock treeBlock = (ITreeBlock) o; ITreeBlock treeBlock = (ITreeBlock) o;
switch (treeBlock.getTreeBlockType()) { switch (treeBlock.getTreeBlockType()) {
case LOG: case LOG:
@ -113,9 +106,7 @@ public class TreeBlockSet<BlockType> implements Collection {
@Override @Override
public boolean remove(Object o) { public boolean remove(Object o) {
if (!(o instanceof ITreeBlock)) { if (!(o instanceof ITreeBlock)) return false;
return false;
}
ITreeBlock treeBlock = (ITreeBlock) o; ITreeBlock treeBlock = (ITreeBlock) o;
switch (treeBlock.getTreeBlockType()) { switch (treeBlock.getTreeBlockType()) {
case LOG: case LOG:
@ -169,25 +160,6 @@ 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
* *
@ -195,12 +167,11 @@ 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 == TreeBlockType.LOG) { if (treeBlockType.equals(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;
@ -210,11 +181,9 @@ 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;
} }
@ -222,12 +191,10 @@ 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();
} }
} }

View File

@ -0,0 +1,9 @@
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
}

View File

@ -1,15 +1,16 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.ultimatetimber.tree;
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
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<XMaterial> logMaterial, leafMaterial, plantableSoilMaterial; private final Set<CompatibleMaterial> logMaterial, leafMaterial, plantableSoilMaterial;
private final XMaterial saplingMaterial; private final CompatibleMaterial 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;
@ -18,8 +19,8 @@ public class TreeDefinition {
private final Set<ItemStack> requiredTools; private final Set<ItemStack> requiredTools;
private final boolean requiredAxe; private final boolean requiredAxe;
public TreeDefinition(String key, Set<XMaterial> logMaterial, Set<XMaterial> leafMaterial, XMaterial saplingMaterial, public TreeDefinition(String key, Set<CompatibleMaterial> logMaterial, Set<CompatibleMaterial> leafMaterial, CompatibleMaterial saplingMaterial,
Set<XMaterial> plantableSoilMaterial, double maxLogDistanceFromTrunk, int maxLeafDistanceFromLog, Set<CompatibleMaterial> 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, boolean requiredAxe) { Set<TreeLoot> leafLoot, Set<TreeLoot> entireTreeLoot, Set<ItemStack> requiredTools, boolean requiredAxe) {
this.key = key; this.key = key;
@ -53,7 +54,7 @@ public class TreeDefinition {
* *
* @return A Set of CompatibleMaterial * @return A Set of CompatibleMaterial
*/ */
public Set<XMaterial> getLogMaterial() { public Set<CompatibleMaterial> getLogMaterial() {
return Collections.unmodifiableSet(this.logMaterial); return Collections.unmodifiableSet(this.logMaterial);
} }
@ -62,7 +63,7 @@ public class TreeDefinition {
* *
* @return A Set of CompatibleMaterial * @return A Set of CompatibleMaterial
*/ */
public Set<XMaterial> getLeafMaterial() { public Set<CompatibleMaterial> getLeafMaterial() {
return Collections.unmodifiableSet(this.leafMaterial); return Collections.unmodifiableSet(this.leafMaterial);
} }
@ -71,7 +72,7 @@ public class TreeDefinition {
* *
* @return An CompatibleMaterial instance for the sapling * @return An CompatibleMaterial instance for the sapling
*/ */
public XMaterial getSaplingMaterial() { public CompatibleMaterial getSaplingMaterial() {
return this.saplingMaterial; return this.saplingMaterial;
} }
@ -80,7 +81,7 @@ public class TreeDefinition {
* *
* @return A Set of CompatibleMaterial * @return A Set of CompatibleMaterial
*/ */
public Set<XMaterial> getPlantableSoilMaterial() { public Set<CompatibleMaterial> getPlantableSoilMaterial() {
return Collections.unmodifiableSet(this.plantableSoilMaterial); return Collections.unmodifiableSet(this.plantableSoilMaterial);
} }
@ -166,11 +167,11 @@ public class TreeDefinition {
} }
/** /**
* Returns whether this TreeDefinition requires a custom axe. * Returns whether or not does this TreeDefinition require a custom axe.
* *
* @return True if the TreeDefinition requires a custom axe * @return True if the TreeDefinition requires a custom axe
*/ */
public boolean isRequiredAxe() { public boolean isRequiredAxe() {
return this.requiredAxe; return requiredAxe;
} }
} }

View File

@ -1,8 +1,9 @@
package com.craftaro.ultimatetimber.tree; package com.songoda.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;
@ -72,10 +73,10 @@ public class TreeLoot {
@Override @Override
public String toString() { public String toString() {
return "TreeLoot{" + return "TreeLoot{" +
"treeBlockType=" + this.treeBlockType + "treeBlockType=" + treeBlockType +
", item=" + this.item + ", item=" + item +
", command='" + this.command + '\'' + ", command='" + command + '\'' +
", chance=" + this.chance + ", chance=" + chance +
'}'; '}';
} }
} }

View File

@ -0,0 +1,118 @@
<project xmlns="http://maven.apache.org/POM/4.0.0">
<parent>
<groupId>com.songoda</groupId>
<artifactId>UltimateTimber</artifactId>
<version>2.1.1b</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>
</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}.ultimatetimber.core</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.16.2</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>
</dependencies>
</project>

View File

@ -190,7 +190,6 @@ 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
@ -217,7 +216,6 @@ 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
@ -241,7 +239,6 @@ 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
@ -265,7 +262,6 @@ 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
@ -312,7 +308,6 @@ 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
@ -331,87 +326,6 @@ trees:
entire-tree-loot: [] entire-tree-loot: []
required-tools: [] required-tools: []
required-axe: false 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
@ -505,7 +419,6 @@ 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
@ -571,10 +484,3 @@ required-axe:
- 'DIG_SPEED:5' - 'DIG_SPEED:5'
# NBT to identify the axe by. # NBT to identify the axe by.
nbt: 'ultimatetimber_axe' nbt: 'ultimatetimber_axe'
# If a tree lands on these blocks they will be destroyed.
fragile-blocks:
- GLASS
- ICE
- PACKED_ICE
- BLUE_ICE

View File

@ -1,24 +1,14 @@
name: ${project.name} name: UltimateTimber
description: ${project.description} version: maven-version-number
version: ${project.version} authors: [Songoda]
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
@ -27,19 +17,15 @@ 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

View File

@ -1,35 +1,36 @@
package com.craftaro.ultimatetimber; package com.songoda.ultimatetimber;
import com.craftaro.core.SongodaCore; import com.songoda.core.SongodaCore;
import com.craftaro.core.SongodaPlugin; import com.songoda.core.SongodaPlugin;
import com.craftaro.core.commands.CommandManager; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.core.configuration.Config; import com.songoda.core.configuration.Config;
import com.craftaro.core.dependency.Dependency; import com.songoda.core.hooks.LogManager;
import com.craftaro.core.hooks.LogManager; import com.songoda.ultimatetimber.commands.CommandGiveAxe;
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import com.songoda.ultimatetimber.commands.CommandReload;
import com.craftaro.ultimatetimber.commands.CommandGiveAxe; import com.songoda.ultimatetimber.commands.CommandToggle;
import com.craftaro.ultimatetimber.commands.CommandReload; import com.songoda.ultimatetimber.manager.ChoppingManager;
import com.craftaro.ultimatetimber.commands.CommandToggle; import com.songoda.ultimatetimber.manager.ConfigurationManager;
import com.craftaro.ultimatetimber.manager.PlacedBlockManager; import com.songoda.ultimatetimber.manager.Manager;
import com.craftaro.ultimatetimber.manager.TreeDetectionManager; import com.songoda.ultimatetimber.manager.PlacedBlockManager;
import com.craftaro.ultimatetimber.manager.ChoppingManager; import com.songoda.ultimatetimber.manager.SaplingManager;
import com.craftaro.ultimatetimber.manager.ConfigurationManager; import com.songoda.ultimatetimber.manager.TreeAnimationManager;
import com.craftaro.ultimatetimber.manager.Manager; import com.songoda.ultimatetimber.manager.TreeDefinitionManager;
import com.craftaro.ultimatetimber.manager.SaplingManager; import com.songoda.ultimatetimber.manager.TreeDetectionManager;
import com.craftaro.ultimatetimber.manager.TreeAnimationManager; import com.songoda.ultimatetimber.manager.TreeFallManager;
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;
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 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,34 +38,26 @@ 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 getPlugin(UltimateTimber.class); return INSTANCE;
}
@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, XMaterial.IRON_AXE); SongodaCore.registerPlugin(this, 18, CompatibleMaterial.IRON_AXE);
// Load hooks // Load hooks
LogManager.load(); LogManager.load();
// Setup plugin commands // Setup plugin commands
CommandManager commandManager = new CommandManager(this); this.commandManager = new com.songoda.core.commands.CommandManager(this);
commandManager.addMainCommand("ut") this.commandManager.addMainCommand("ut")
.addSubCommands( .addSubCommands(
new CommandReload(this), new CommandReload(this),
new CommandToggle(this), new CommandToggle(this),
@ -72,6 +65,7 @@ public class UltimateTimber extends SongodaPlugin {
); );
// 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);
@ -81,13 +75,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.reloadConfig(); this.reloadConfig();
} }
@Override @Override
public void onPluginDisable() { public void onPluginDisable() {
this.configurationManager.disable(); this.disable();
this.managers.forEach(Manager::disable);
} }
@Override @Override
@ -103,7 +97,15 @@ public class UltimateTimber extends SongodaPlugin {
@Override @Override
public List<Config> getExtraConfig() { public List<Config> getExtraConfig() {
return Collections.emptyList(); return null;
}
/**
* Disables most of the plugin
*/
public void disable() {
this.configurationManager.disable();
this.managers.forEach(Manager::disable);
} }
/** /**
@ -124,35 +126,76 @@ public class UltimateTimber extends SongodaPlugin {
} }
} }
/**
* 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;
} }
} }

View File

@ -1,15 +1,15 @@
package com.craftaro.ultimatetimber.animation; package com.songoda.ultimatetimber.animation;
import com.craftaro.core.compatibility.CompatibleHand; import com.songoda.core.compatibility.CompatibleHand;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import com.songoda.ultimatetimber.UltimateTimber;
import com.craftaro.ultimatetimber.UltimateTimber; 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.utils.BlockUtils;
import com.craftaro.ultimatetimber.utils.BlockUtils; import org.bukkit.Bukkit;
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;
@ -19,6 +19,7 @@ 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;
@ -98,8 +99,9 @@ public abstract class TreeAnimation {
protected FallingTreeBlock convertToFallingBlock(TreeBlock treeBlock) { protected FallingTreeBlock convertToFallingBlock(TreeBlock treeBlock) {
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(); CompatibleMaterial material = CompatibleMaterial.getMaterial(block);
if (CompatibleMaterial.isAir(material)) {
if (material.isAir()) {
this.replaceBlock(treeBlock); this.replaceBlock(treeBlock);
return null; return null;
} }

View File

@ -1,18 +1,18 @@
package com.craftaro.ultimatetimber.animation; package com.songoda.ultimatetimber.animation;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
import com.craftaro.ultimatetimber.manager.ConfigurationManager; import com.songoda.ultimatetimber.manager.ConfigurationManager;
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.tree.TreeBlockType; import com.songoda.ultimatetimber.tree.TreeBlockType;
import com.craftaro.ultimatetimber.tree.TreeDefinition; import com.songoda.ultimatetimber.tree.TreeDefinition;
import com.craftaro.ultimatetimber.utils.BlockUtils; import com.songoda.ultimatetimber.utils.BlockUtils;
import com.craftaro.ultimatetimber.utils.ParticleUtils; import com.songoda.ultimatetimber.utils.ParticleUtils;
import com.craftaro.ultimatetimber.utils.SoundUtils; import com.songoda.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;
@ -24,6 +24,7 @@ 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);
} }
@ -63,36 +64,30 @@ 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() == TreeBlockType.LOG) { if (treeBlock.getTreeBlockType().equals(TreeBlockType.LOG)) {
if (td.getLogMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) { if (td.getLogMaterial().stream().noneMatch(x -> x.equals(CompatibleMaterial.getMaterial(treeBlock.getBlock()))))
continue; continue;
} } else if (treeBlock.getTreeBlockType().equals(TreeBlockType.LEAF)) {
} else if (treeBlock.getTreeBlockType() == TreeBlockType.LEAF) { if (td.getLeafMaterial().stream().noneMatch(x -> x.equals(CompatibleMaterial.getMaterial(treeBlock.getBlock()))))
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;
}
BlockUtils.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)
SoundUtils.playLandingSound(treeBlock); SoundUtils.playLandingSound(treeBlock);
} if (useCustomParticles)
if (useCustomParticles) {
ParticleUtils.playFallingParticles(treeBlock); ParticleUtils.playFallingParticles(treeBlock);
} }
}
if (partition.isEmpty()) { if (partition.isEmpty()) {
treeBlocks.remove(0); treeBlocks.remove(0);
@ -107,3 +102,4 @@ public class TreeAnimationCrumble extends TreeAnimation {
}.runTaskTimer(ultimateTimber, 0, 1); }.runTaskTimer(ultimateTimber, 0, 1);
} }
} }

View File

@ -1,16 +1,16 @@
package com.craftaro.ultimatetimber.animation; package com.songoda.ultimatetimber.animation;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
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.tree.TreeBlockType; import com.songoda.ultimatetimber.tree.TreeBlockType;
import com.craftaro.ultimatetimber.tree.TreeDefinition; import com.songoda.ultimatetimber.tree.TreeDefinition;
import com.craftaro.ultimatetimber.utils.ParticleUtils; import com.songoda.ultimatetimber.utils.ParticleUtils;
import com.craftaro.ultimatetimber.utils.SoundUtils; import com.songoda.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;
@ -23,6 +23,7 @@ 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);
} }
@ -70,24 +71,20 @@ 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)
SoundUtils.playLandingSound(first); SoundUtils.playLandingSound(first);
}
for (ITreeBlock<Block> treeBlock : toDestroy) { for (ITreeBlock<Block> treeBlock : toDestroy) {
if (treeBlock.getTreeBlockType() == TreeBlockType.LOG) { if (treeBlock.getTreeBlockType().equals(TreeBlockType.LOG)) {
if (td.getLogMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) { if (td.getLogMaterial().stream().noneMatch(x -> x.equals(CompatibleMaterial.getMaterial(treeBlock.getBlock()))))
continue; continue;
} } else if (treeBlock.getTreeBlockType().equals(TreeBlockType.LEAF)) {
} else if (treeBlock.getTreeBlockType() == TreeBlockType.LEAF) { if (td.getLeafMaterial().stream().noneMatch(x -> x.equals(CompatibleMaterial.getMaterial(treeBlock.getBlock()))))
if (td.getLeafMaterial().stream().noneMatch(x -> x == CompatibleMaterial.getMaterial(treeBlock.getBlock().getType()).orElse(null))) {
continue; continue;
} }
}
if (useCustomParticles) { if (useCustomParticles)
ParticleUtils.playFallingParticles(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);
} }
@ -98,4 +95,5 @@ public class TreeAnimationDisintegrate extends TreeAnimation {
} }
}.runTaskTimer(ultimateTimber, 0, 1); }.runTaskTimer(ultimateTimber, 0, 1);
} }
} }

View File

@ -1,16 +1,16 @@
package com.craftaro.ultimatetimber.animation; package com.songoda.ultimatetimber.animation;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
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.songoda.ultimatetimber.utils.BlockUtils;
import com.craftaro.ultimatetimber.utils.ParticleUtils; import com.songoda.ultimatetimber.utils.ParticleUtils;
import com.craftaro.ultimatetimber.utils.SoundUtils; import com.songoda.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;
@ -18,6 +18,7 @@ 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);
} }
@ -32,25 +33,22 @@ public class TreeAnimationFancy extends TreeAnimation {
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)
SoundUtils.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)
ParticleUtils.playFallingParticles(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));
@ -85,13 +83,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);
} }
} }

View File

@ -1,17 +1,18 @@
package com.craftaro.ultimatetimber.animation; package com.songoda.ultimatetimber.animation;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
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.songoda.ultimatetimber.utils.ParticleUtils;
import com.craftaro.ultimatetimber.utils.SoundUtils; import com.songoda.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);
} }
@ -34,4 +35,5 @@ public class TreeAnimationNone extends TreeAnimation {
whenFinished.run(); whenFinished.run();
} }
} }

View File

@ -1,10 +1,13 @@
package com.craftaro.ultimatetimber.animation; package com.songoda.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, DISINTEGRATE, CRUMBLE, NONE; FANCY,
DISINTEGRATE,
CRUMBLE,
NONE;
/** /**
* Gets a TreeAnimationType from a given string * Gets a TreeAnimationType from a given string
@ -13,12 +16,9 @@ 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;
} }
} }

View File

@ -1,8 +1,8 @@
package com.craftaro.ultimatetimber.commands; package com.songoda.ultimatetimber.commands;
import com.craftaro.core.commands.AbstractCommand; import com.songoda.core.commands.AbstractCommand;
import com.craftaro.core.utils.PlayerUtils; import com.songoda.core.utils.PlayerUtils;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
public class CommandGiveAxe extends AbstractCommand { public class CommandGiveAxe extends AbstractCommand {
private final UltimateTimber plugin; private final UltimateTimber plugin;
public CommandGiveAxe(UltimateTimber plugin) { public CommandGiveAxe(UltimateTimber plugin) {
@ -20,44 +21,43 @@ public class CommandGiveAxe extends AbstractCommand {
@Override @Override
protected ReturnType runCommand(CommandSender sender, String... args) { protected ReturnType runCommand(CommandSender sender, String... args) {
if (args.length < 1) {
if (args.length < 1)
return ReturnType.SYNTAX_ERROR; return ReturnType.SYNTAX_ERROR;
}
Player player = Bukkit.getPlayer(args[0]); Player player = Bukkit.getPlayer(args[0]);
if (player == null) { if (player == null) {
if (args[0].trim().equalsIgnoreCase("me")) { if (args[0].trim().equalsIgnoreCase("me")) {
if (!(sender instanceof Player)) { if (!(sender instanceof Player))
return ReturnType.NEEDS_PLAYER; return ReturnType.NEEDS_PLAYER;
}
player = (Player) sender; player = (Player) sender;
} else { } else {
this.plugin.getLocale().getMessageOrDefault("command.give.not-a-player", "&cNot a player.") plugin.getLocale().getMessageOrDefault("command.give.not-a-player", "&cNot a player.")
.sendPrefixedMessage(sender); .sendPrefixedMessage(sender);
return ReturnType.FAILURE; return ReturnType.FAILURE;
} }
} }
ItemStack axe = this.plugin.getTreeDefinitionManager().getRequiredAxe(); ItemStack axe = plugin.getTreeDefinitionManager().getRequiredAxe();
if (axe == null) { if (axe == null) {
this.plugin.getLocale().getMessageOrDefault("command.give.no-axe", "&cThe axe could not be loaded.") plugin.getLocale().getMessageOrDefault("command.give.no-axe", "&cThe axe could not be loaded.")
.sendPrefixedMessage(sender); .sendPrefixedMessage(sender);
return ReturnType.FAILURE; return ReturnType.FAILURE;
} }
player.getInventory().addItem(axe); player.getInventory().addItem(axe);
this.plugin.getLocale().getMessageOrDefault("command.give.given", "&fAxe given to &a%player%") plugin.getLocale().getMessageOrDefault("command.give.given", "&fAxe given to &a%player%")
.processPlaceholder("player", player.getName()) .processPlaceholder("player", player.getName())
.sendPrefixedMessage(sender); .sendPrefixedMessage(sender);
return ReturnType.SUCCESS; return ReturnType.SUCCESS;
} }
@Override @Override
protected List<String> onTab(CommandSender sender, String... args) { protected List<String> onTab(CommandSender commandSender, String... args) {
List<String> suggestions = null; List<String> suggestions = null;
if (args.length == 1) { if (args.length == 1) {
suggestions = PlayerUtils.getVisiblePlayerNames(sender, args[0]); suggestions = PlayerUtils.getVisiblePlayerNames(commandSender, args[0]);
suggestions.add("me"); suggestions.add("me");
} }
return suggestions; return suggestions;

View File

@ -1,12 +1,13 @@
package com.craftaro.ultimatetimber.commands; package com.songoda.ultimatetimber.commands;
import com.craftaro.core.commands.AbstractCommand; import com.songoda.core.commands.AbstractCommand;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.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) {
@ -16,8 +17,8 @@ public class CommandReload extends AbstractCommand {
@Override @Override
protected ReturnType runCommand(CommandSender sender, String... args) { protected ReturnType runCommand(CommandSender sender, String... args) {
this.plugin.reloadConfig(); plugin.reloadConfig();
this.plugin.getLocale().getMessage("command.reload.reloaded").sendPrefixedMessage(sender); plugin.getLocale().getMessage("command.reload.reloaded").sendPrefixedMessage(sender);
return ReturnType.SUCCESS; return ReturnType.SUCCESS;
} }
@ -38,6 +39,7 @@ public class CommandReload extends AbstractCommand {
@Override @Override
public String getDescription() { public String getDescription() {
return this.plugin.getLocale().getMessage("command.reload.description").getMessage().toString(); return plugin.getLocale().getMessage("command.reload.description").getMessage();
} }
} }

View File

@ -1,13 +1,14 @@
package com.craftaro.ultimatetimber.commands; package com.songoda.ultimatetimber.commands;
import com.craftaro.core.commands.AbstractCommand; import com.songoda.core.commands.AbstractCommand;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.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) {
@ -17,10 +18,10 @@ public class CommandToggle extends AbstractCommand {
@Override @Override
protected ReturnType runCommand(CommandSender sender, String... args) { protected ReturnType runCommand(CommandSender sender, String... args) {
if (this.plugin.getChoppingManager().togglePlayer((Player) sender)) { if (UltimateTimber.getInstance().getChoppingManager().togglePlayer((Player) sender)) {
this.plugin.getLocale().getMessage("command.toggle.enabled").sendPrefixedMessage(sender); plugin.getLocale().getMessage("command.toggle.enabled").sendPrefixedMessage(sender);
} else { } else {
this.plugin.getLocale().getMessage("command.toggle.disabled").sendPrefixedMessage(sender); plugin.getLocale().getMessage("command.toggle.disabled").sendPrefixedMessage(sender);
} }
return ReturnType.SUCCESS; return ReturnType.SUCCESS;
} }
@ -42,7 +43,7 @@ public class CommandToggle extends AbstractCommand {
@Override @Override
public String getDescription() { public String getDescription() {
return this.plugin.getLocale().getMessage("command.toggle.description").getMessage().toString(); return plugin.getLocale().getMessage("command.toggle.description").getMessage();
} }
} }

View File

@ -1,6 +1,6 @@
package com.craftaro.ultimatetimber.events; package com.songoda.ultimatetimber.events;
import com.craftaro.ultimatetimber.tree.DetectedTree; import com.songoda.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,10 +8,11 @@ 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) { public TreeEvent(Player player, DetectedTree detectedTree) {
super(who); super(player);
this.detectedTree = detectedTree; this.detectedTree = detectedTree;
} }
@ -23,4 +24,5 @@ public abstract class TreeEvent extends PlayerEvent {
public DetectedTree getDetectedTree() { public DetectedTree getDetectedTree() {
return this.detectedTree; return this.detectedTree;
} }
} }

View File

@ -0,0 +1,40 @@
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;
}
}

View File

@ -0,0 +1,27 @@
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;
}
}

View File

@ -1,6 +1,6 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -11,13 +11,14 @@ 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 final Set<UUID> disabledPlayers;
private final Map<UUID, Boolean> cooldownedPlayers; private final Map<UUID, Boolean> cooldownedPlayers;
private boolean useCooldown; private boolean useCooldown;
private int cooldownAmount; private int cooldownAmount;
public ChoppingManager(UltimateTimber plugin) { public ChoppingManager(UltimateTimber ultimateTimber) {
super(plugin); super(ultimateTimber);
this.disabledPlayers = new HashSet<>(); this.disabledPlayers = new HashSet<>();
this.cooldownedPlayers = new HashMap<>(); this.cooldownedPlayers = new HashMap<>();
} }
@ -71,7 +72,8 @@ public class ChoppingManager extends Manager {
this.cooldownedPlayers.put(player.getUniqueId(), false); this.cooldownedPlayers.put(player.getUniqueId(), false);
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.cooldownedPlayers.remove(player.getUniqueId()), this.cooldownAmount * 20L); Bukkit.getScheduler().scheduleSyncDelayedTask(UltimateTimber.getInstance(), () ->
this.cooldownedPlayers.remove(player.getUniqueId()), this.cooldownAmount * 20L);
} }
/** /**
@ -88,4 +90,5 @@ public class ChoppingManager extends Manager {
} }
return cooldowned; return cooldowned;
} }
} }

View File

@ -1,6 +1,6 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
@ -8,6 +8,7 @@ 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),
@ -45,10 +46,9 @@ 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 final SettingType settingType; private SettingType settingType;
private Object value = null; private Object value = null;
Setting(SettingType settingType) { Setting(SettingType settingType) {
@ -117,11 +117,10 @@ 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.getPlugin(UltimateTimber.class).getConfigurationManager().getConfig(); FileConfiguration config = UltimateTimber.getInstance().getConfigurationManager().getConfig();
switch (this.settingType) { switch (this.settingType) {
case BOOLEAN: case BOOLEAN:
this.value = config.getBoolean(this.getNameAsKey()); this.value = config.getBoolean(this.getNameAsKey());
@ -161,8 +160,8 @@ public class ConfigurationManager extends Manager {
private YamlConfiguration configuration; private YamlConfiguration configuration;
public ConfigurationManager(UltimateTimber plugin) { public ConfigurationManager(UltimateTimber ultimateTimber) {
super(plugin); super(ultimateTimber);
} }
@Override @Override
@ -171,7 +170,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);
@ -188,17 +187,15 @@ 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();
} }
}
/** /**
* Gets the config.yml as a YamlConfiguration * Gets the config.yml as a YamlConfiguration
@ -208,4 +205,5 @@ public class ConfigurationManager extends Manager {
public YamlConfiguration getConfig() { public YamlConfiguration getConfig() {
return this.configuration; return this.configuration;
} }
} }

View File

@ -1,8 +1,9 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.UltimateTimber;
public abstract class Manager { public abstract class Manager {
protected UltimateTimber plugin; protected UltimateTimber plugin;
Manager(UltimateTimber plugin) { Manager(UltimateTimber plugin) {
@ -18,4 +19,5 @@ public abstract class Manager {
* Cleans up the Manager's resources * Cleans up the Manager's resources
*/ */
public abstract void disable(); public abstract void disable();
} }

View File

@ -1,11 +1,11 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.ultimatetimber.UltimateTimber;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.events.TreeFellEvent;
import com.craftaro.ultimatetimber.events.TreeFellEvent; import com.songoda.ultimatetimber.tree.ITreeBlock;
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,13 +22,14 @@ 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 plugin) { public PlacedBlockManager(UltimateTimber ultimateTimber) {
super(plugin); super(ultimateTimber);
Bukkit.getPluginManager().registerEvents(this, plugin); Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
} }
@Override @Override
@ -52,66 +53,57 @@ 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") && !CompatibleMaterial.isAir(CompatibleMaterial.getMaterial(event.getBlockReplacedState().getType()).get())) { if (event.getBlockPlaced().getType().name().contains("STRIPPED") && !event.getBlockReplacedState().getType().equals(Material.AIR))
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);
} }
}
/** /**
* Handles when a block is placed/broken * Handles when a block is placed/broken
*/ */
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 {
@ -128,4 +120,5 @@ 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());
} }
} }

View File

@ -1,12 +1,10 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.third_party.com.cryptomorin.xseries.XBlock; import com.songoda.ultimatetimber.UltimateTimber;
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.tree.TreeBlockType;
import com.craftaro.ultimatetimber.tree.ITreeBlock; import com.songoda.ultimatetimber.tree.TreeDefinition;
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;
@ -18,21 +16,24 @@ 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;
public SaplingManager(UltimateTimber plugin) { private Random random;
super(plugin); private Set<Location> protectedSaplings;
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() {
} }
/** /**
@ -43,14 +44,12 @@ public class SaplingManager extends Manager {
* @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() != Material.AIR || treeBlock.getTreeBlockType() == TreeBlockType.LEAF) { if (!block.getType().equals(Material.AIR) || treeBlock.getTreeBlockType().equals(TreeBlockType.LEAF))
return; return;
}
Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.internalReplant(treeDefinition, treeBlock), 1L); Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, () -> this.internalReplant(treeDefinition, treeBlock), 1L);
} }
@ -63,14 +62,12 @@ public class SaplingManager extends Manager {
* @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() || !CompatibleMaterial.isAir(CompatibleMaterial.getMaterial(treeBlock.getLocation().getBlock().getType()).get())) { if (!ConfigurationManager.Setting.FALLING_BLOCKS_REPLANT_SAPLINGS.getBoolean() || !treeBlock.getLocation().getBlock().getType().equals(Material.AIR))
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);
} }
@ -87,19 +84,18 @@ 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 (XMaterial soilMaterial : treeDefinitionManager.getPlantableSoilMaterial(treeDefinition)) { for (CompatibleMaterial soilMaterial : treeDefinitionManager.getPlantableSoilMaterial(treeDefinition)) {
if (soilMaterial == CompatibleMaterial.getMaterial(blockBelow.getType()).orElse(null)) { if (soilMaterial.equals(CompatibleMaterial.getMaterial(blockBelow))) {
isValidSoil = true; isValidSoil = true;
break; break;
} }
} }
if (!isValidSoil) { if (!isValidSoil)
return; return;
}
XMaterial material = treeDefinition.getSaplingMaterial(); CompatibleMaterial material = treeDefinition.getSaplingMaterial();
XBlock.setType(block, material); material.applyToBlock(block);
int cooldown = ConfigurationManager.Setting.REPLANT_SAPLINGS_COOLDOWN.getInt(); int cooldown = ConfigurationManager.Setting.REPLANT_SAPLINGS_COOLDOWN.getInt();
if (cooldown != 0) { if (cooldown != 0) {
@ -117,4 +113,5 @@ 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());
} }
} }

View File

@ -1,20 +1,17 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.ultimatetimber.UltimateTimber;
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.songoda.ultimatetimber.utils.ParticleUtils;
import com.craftaro.ultimatetimber.tree.ITreeBlock; import com.songoda.ultimatetimber.utils.SoundUtils;
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;
@ -31,14 +28,15 @@ 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 int taskId;
public TreeAnimationManager(UltimateTimber plugin) { private final Set<TreeAnimation> activeAnimations;
super(plugin); private int taskId;
public TreeAnimationManager(UltimateTimber ultimateTimber) {
super(ultimateTimber);
this.activeAnimations = new HashSet<>(); this.activeAnimations = new HashSet<>();
this.taskId = -1; this.taskId = -1;
Bukkit.getPluginManager().registerEvents(this, plugin); Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0, 1L); Bukkit.getScheduler().runTaskTimer(this.plugin, this, 0, 1L);
} }
@ -59,16 +57,12 @@ 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() || ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) && fallingBlock.isOnGround()) { if (fallingBlock.isDead())
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);
} }
} }
@ -103,13 +97,10 @@ 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;
} }
@ -119,13 +110,10 @@ 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;
} }
@ -135,13 +123,10 @@ 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;
} }
@ -165,18 +150,10 @@ public class TreeAnimationManager extends Manager implements Listener, Runnable
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)
ParticleUtils.playLandingParticles(treeBlock); ParticleUtils.playLandingParticles(treeBlock);
} if (useCustomSound)
if (useCustomSound) {
SoundUtils.playLandingSound(treeBlock); 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);
@ -185,28 +162,17 @@ 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() != EntityType.FALLING_BLOCK) { if (!event.getEntityType().equals(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)) { if (!(entity instanceof LivingEntity)) continue;
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); ((LivingEntity) entity).damage(damage, fallingBlock);
} }
} }

View File

@ -1,18 +1,18 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.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.google.common.base.Strings;
import com.craftaro.ultimatetimber.tree.ITreeBlock; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.ultimatetimber.tree.TreeBlockType; import com.songoda.core.compatibility.ServerVersion;
import com.craftaro.ultimatetimber.tree.TreeDefinition; import com.songoda.core.hooks.McMMOHook;
import com.craftaro.ultimatetimber.tree.TreeLoot; import com.songoda.core.nms.NmsManager;
import com.craftaro.ultimatetimber.utils.BlockUtils; import com.songoda.core.nms.nbt.NBTItem;
import com.songoda.core.utils.TextUtils;
import com.songoda.ultimatetimber.UltimateTimber;
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 com.songoda.ultimatetimber.utils.BlockUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@ -24,18 +24,14 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList; import java.util.*;
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; import java.util.stream.Collectors;
public class TreeDefinitionManager extends Manager { public class TreeDefinitionManager extends Manager {
private final Random random; private final Random random;
private final Set<TreeDefinition> treeDefinitions; private final Set<TreeDefinition> treeDefinitions;
private final Set<XMaterial> globalPlantableSoil; private final Set<CompatibleMaterial> globalPlantableSoil;
private final Set<TreeLoot> globalLogLoot, globalLeafLoot, globalEntireTreeLoot; private final Set<TreeLoot> globalLogLoot, globalLeafLoot, globalEntireTreeLoot;
private final Set<ItemStack> globalRequiredTools; private final Set<ItemStack> globalRequiredTools;
@ -43,8 +39,8 @@ public class TreeDefinitionManager extends Manager {
private ItemStack requiredAxe; private ItemStack requiredAxe;
private String requiredAxeKey; private String requiredAxeKey;
public TreeDefinitionManager(UltimateTimber plugin) { public TreeDefinitionManager(UltimateTimber ultimateTimber) {
super(plugin); super(ultimateTimber);
this.random = new Random(); this.random = new Random();
this.treeDefinitions = new HashSet<>(); this.treeDefinitions = new HashSet<>();
this.globalPlantableSoil = new HashSet<>(); this.globalPlantableSoil = new HashSet<>();
@ -72,10 +68,10 @@ public class TreeDefinitionManager extends Manager {
for (String key : treeSection.getKeys(false)) { for (String key : treeSection.getKeys(false)) {
ConfigurationSection tree = treeSection.getConfigurationSection(key); ConfigurationSection tree = treeSection.getConfigurationSection(key);
Set<XMaterial> logMaterials = new HashSet<>(); Set<CompatibleMaterial> logMaterials = new HashSet<>();
Set<XMaterial> leafMaterials = new HashSet<>(); Set<CompatibleMaterial> leafMaterials = new HashSet<>();
XMaterial saplingMaterial; CompatibleMaterial saplingMaterial;
Set<XMaterial> plantableSoilMaterial = new HashSet<>(); Set<CompatibleMaterial> plantableSoilMaterial = new HashSet<>();
double maxLogDistanceFromTrunk; double maxLogDistanceFromTrunk;
int maxLeafDistanceFromLog; int maxLeafDistanceFromLog;
boolean detectLeavesDiagonally; boolean detectLeavesDiagonally;
@ -88,29 +84,23 @@ public class TreeDefinitionManager extends Manager {
boolean requiredAxe; boolean requiredAxe;
for (String materialString : tree.getStringList("logs")) { for (String materialString : tree.getStringList("logs")) {
Optional<XMaterial> material = CompatibleMaterial.getMaterial(materialString); CompatibleMaterial material = CompatibleMaterial.getMaterial(materialString);
if (!material.isPresent() || !material.get().isSupported()) { if (material == null || material.getMaterial() == null) continue top;
continue top; logMaterials.add(material);
}
logMaterials.add(material.get());
} }
for (String materialString : tree.getStringList("leaves")) { for (String materialString : tree.getStringList("leaves")) {
Optional<XMaterial> material = CompatibleMaterial.getMaterial(materialString); CompatibleMaterial material = CompatibleMaterial.getMaterial(materialString);
if (!material.isPresent() || !material.get().isSupported()) { if (material == null || material.getMaterial() == null) continue top;
continue top; leafMaterials.add(material);
}
leafMaterials.add(material.get());
} }
saplingMaterial = CompatibleMaterial.getMaterial(tree.getString("sapling")).get(); saplingMaterial = CompatibleMaterial.getMaterial(tree.getString("sapling"));
for (String materialString : tree.getStringList("plantable-soil")) { for (String materialString : tree.getStringList("plantable-soil")) {
Optional<XMaterial> material = CompatibleMaterial.getMaterial(materialString); CompatibleMaterial material = CompatibleMaterial.getMaterial(materialString);
if (!material.isPresent() || !material.get().isSupported()) { if (material == null || material.getMaterial() == null) continue top;
continue top; plantableSoilMaterial.add(material);
}
plantableSoilMaterial.add(material.get());
} }
maxLogDistanceFromTrunk = tree.getDouble("max-log-distance-from-trunk"); maxLogDistanceFromTrunk = tree.getDouble("max-log-distance-from-trunk");
@ -120,32 +110,24 @@ public class TreeDefinitionManager extends Manager {
dropOriginalLeaf = tree.getBoolean("drop-original-leaf"); dropOriginalLeaf = tree.getBoolean("drop-original-leaf");
ConfigurationSection logLootSection = tree.getConfigurationSection("log-loot"); ConfigurationSection logLootSection = tree.getConfigurationSection("log-loot");
if (logLootSection != null) { if (logLootSection != null)
for (String lootKey : logLootSection.getKeys(false)) { for (String lootKey : logLootSection.getKeys(false))
logLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logLootSection.getConfigurationSection(lootKey))); logLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logLootSection.getConfigurationSection(lootKey)));
}
}
ConfigurationSection leafLootSection = tree.getConfigurationSection("leaf-loot"); ConfigurationSection leafLootSection = tree.getConfigurationSection("leaf-loot");
if (leafLootSection != null) { if (leafLootSection != null)
for (String lootKey : leafLootSection.getKeys(false)) { for (String lootKey : leafLootSection.getKeys(false))
leafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafLootSection.getConfigurationSection(lootKey))); leafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafLootSection.getConfigurationSection(lootKey)));
}
}
ConfigurationSection entireTreeLootSection = tree.getConfigurationSection("entire-tree-loot"); ConfigurationSection entireTreeLootSection = tree.getConfigurationSection("entire-tree-loot");
if (entireTreeLootSection != null) { if (entireTreeLootSection != null)
for (String lootKey : entireTreeLootSection.getKeys(false)) { for (String lootKey : entireTreeLootSection.getKeys(false))
entireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, entireTreeLootSection.getConfigurationSection(lootKey))); entireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, entireTreeLootSection.getConfigurationSection(lootKey)));
}
}
for (String itemStackString : tree.getStringList("required-tools")) { for (String itemStackString : tree.getStringList("required-tools")) {
Optional<XMaterial> material = CompatibleMaterial.getMaterial(itemStackString); CompatibleMaterial material = CompatibleMaterial.getMaterial(itemStackString);
if (!material.isPresent()) { if (material == null) continue top;
continue top; requiredTools.add(material.getItem());
}
requiredTools.add(material.get().parseItem());
} }
requiredAxe = tree.getBoolean("required-axe", false); requiredAxe = tree.getBoolean("required-axe", false);
@ -155,52 +137,43 @@ public class TreeDefinitionManager extends Manager {
} }
// Load global plantable soil // Load global plantable soil
for (String material : config.getStringList("global-plantable-soil")) { for (String material : config.getStringList("global-plantable-soil"))
this.globalPlantableSoil.add(CompatibleMaterial.getMaterial(material).get()); this.globalPlantableSoil.add(CompatibleMaterial.getMaterial(material));
}
// Load global log drops // Load global log drops
ConfigurationSection logSection = config.getConfigurationSection("global-log-loot"); ConfigurationSection logSection = config.getConfigurationSection("global-log-loot");
if (logSection != null) { if (logSection != null)
for (String lootKey : logSection.getKeys(false)) { for (String lootKey : logSection.getKeys(false))
this.globalLogLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logSection.getConfigurationSection(lootKey))); this.globalLogLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, logSection.getConfigurationSection(lootKey)));
}
}
// Load global leaf drops // Load global leaf drops
ConfigurationSection leafSection = config.getConfigurationSection("global-leaf-loot"); ConfigurationSection leafSection = config.getConfigurationSection("global-leaf-loot");
if (leafSection != null) { if (leafSection != null)
for (String lootKey : leafSection.getKeys(false)) { for (String lootKey : leafSection.getKeys(false))
this.globalLeafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafSection.getConfigurationSection(lootKey))); this.globalLeafLoot.add(this.getTreeLootEntry(TreeBlockType.LEAF, leafSection.getConfigurationSection(lootKey)));
}
}
// Load global entire tree drops // Load global entire tree drops
ConfigurationSection entireTreeSection = config.getConfigurationSection("global-entire-tree-loot"); ConfigurationSection entireTreeSection = config.getConfigurationSection("global-entire-tree-loot");
if (entireTreeSection != null) { if (entireTreeSection != null)
for (String lootKey : entireTreeSection.getKeys(false)) { for (String lootKey : entireTreeSection.getKeys(false))
this.globalEntireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, entireTreeSection.getConfigurationSection(lootKey))); this.globalEntireTreeLoot.add(this.getTreeLootEntry(TreeBlockType.LOG, entireTreeSection.getConfigurationSection(lootKey)));
}
}
// Load global tools // Load global tools
for (String itemStackString : config.getStringList("global-required-tools")) { for (String itemStackString : config.getStringList("global-required-tools")) {
Optional<XMaterial> tool = CompatibleMaterial.getMaterial(itemStackString); ItemStack tool = CompatibleMaterial.getMaterial(itemStackString).getItem();
if (!tool.isPresent()) { if (tool == null) continue;
continue; this.globalRequiredTools.add(tool);
}
this.globalRequiredTools.add(tool.get().parseItem());
} }
this.globalAxeRequired = config.getBoolean("global-required-axe", false); this.globalAxeRequired = config.getBoolean("global-required-axe", false);
// Load required axe // Load required axe
if (config.contains("required-axe")) { if (config.contains("required-axe"))
loadAxe(config); loadAxe(config);
} }
}
private void loadAxe(YamlConfiguration 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. // 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.requiredAxeKey = config.getString("required-axe.nbt");
this.requiredAxe = null; this.requiredAxe = null;
@ -208,17 +181,18 @@ public class TreeDefinitionManager extends Manager {
String typeString = config.getString("required-axe.type"); String typeString = config.getString("required-axe.type");
if (Strings.isNullOrEmpty(typeString)) { if (Strings.isNullOrEmpty(typeString)) {
this.plugin.getLogger().warning("Required-axe has to have a material set."); plugin.getLogger().warning("Required-axe has to have a material set.");
return; return;
} }
Optional<XMaterial> material = CompatibleMaterial.getMaterial(typeString); CompatibleMaterial material = CompatibleMaterial.getMaterial(typeString);
if (!material.isPresent()) {
this.plugin.getLogger().warning("Material " + typeString + " is invalid."); if (material == null) {
plugin.getLogger().warning("Material " + typeString + " is invalid.");
return; return;
} }
ItemStack item = material.get().parseItem(); ItemStack item = material.getItem();
// Add display name and lore // Add display name and lore
String displayName = TextUtils.formatText(config.getString("required-axe.name")); String displayName = TextUtils.formatText(config.getString("required-axe.name"));
@ -242,15 +216,13 @@ public class TreeDefinitionManager extends Manager {
enchantment = Enchantment.getByKey(key); enchantment = Enchantment.getByKey(key);
// Try to fall back to #getByName() if someone uses the old names. // Try to fall back to #getByName() if someone uses the old names.
if (enchantment == null) { if (enchantment == null)
enchantment = Enchantment.getByName(arr[0].trim()); enchantment = Enchantment.getByName(arr[0].trim());
} } else
} else {
enchantment = Enchantment.getByName(arr[0].trim()); enchantment = Enchantment.getByName(arr[0].trim());
}
if (enchantment == null) { if (enchantment == null) {
this.plugin.getLogger().warning("Enchantment " + arr[0].trim() + " is invalid."); plugin.getLogger().warning("Enchantment " + arr[0].trim() + " is invalid.");
continue; continue;
} }
@ -260,9 +232,9 @@ public class TreeDefinitionManager extends Manager {
item.setItemMeta(meta); item.setItemMeta(meta);
// Apply NBT // Apply NBT
NBTItem nbtItem = new NBTItem(item); NBTItem nbtItem = NmsManager.getNbt().of(item);
nbtItem.setBoolean(this.requiredAxeKey, true); nbtItem.set(requiredAxeKey, true);
item = nbtItem.getItem(); item = nbtItem.finish();
this.requiredAxe = item; this.requiredAxe = item;
} }
@ -280,7 +252,7 @@ public class TreeDefinitionManager extends Manager {
} }
public boolean isGlobalAxeRequired() { public boolean isGlobalAxeRequired() {
return this.globalAxeRequired; return globalAxeRequired;
} }
@Override @Override
@ -311,8 +283,8 @@ public class TreeDefinitionManager extends Manager {
switch (treeBlockType) { switch (treeBlockType) {
case LOG: case LOG:
for (TreeDefinition treeDefinition : possibleTreeDefinitions) { for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
for (XMaterial material : treeDefinition.getLogMaterial()) { for (CompatibleMaterial material : treeDefinition.getLogMaterial()) {
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) { if (material.equals(CompatibleMaterial.getMaterial(block))) {
matchingTreeDefinitions.add(treeDefinition); matchingTreeDefinitions.add(treeDefinition);
break; break;
} }
@ -321,8 +293,8 @@ public class TreeDefinitionManager extends Manager {
break; break;
case LEAF: case LEAF:
for (TreeDefinition treeDefinition : possibleTreeDefinitions) { for (TreeDefinition treeDefinition : possibleTreeDefinitions) {
for (XMaterial material : treeDefinition.getLeafMaterial()) { for (CompatibleMaterial material : treeDefinition.getLeafMaterial()) {
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) { if (material.equals(CompatibleMaterial.getMaterial(block))) {
matchingTreeDefinitions.add(treeDefinition); matchingTreeDefinitions.add(treeDefinition);
break; break;
} }
@ -341,31 +313,25 @@ public class TreeDefinitionManager extends Manager {
* @return True if the tool is allowed for toppling any trees * @return True if the tool is allowed for toppling any trees
*/ */
public boolean isToolValidForAnyTreeDefinition(ItemStack tool) { public boolean isToolValidForAnyTreeDefinition(ItemStack tool) {
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean()) { if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean())
return true; return true;
}
for (TreeDefinition treeDefinition : this.treeDefinitions) { for (TreeDefinition treeDefinition : this.treeDefinitions) {
if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) { if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) {
if (tool != null && !tool.getType().isAir() && new NBTItem(tool).hasTag(this.requiredAxeKey)) { NBTItem nbtItem = NmsManager.getNbt().of(tool);
if (nbtItem.has(requiredAxeKey))
return true; return true;
} }
} }
}
for (TreeDefinition treeDefinition : this.treeDefinitions) { for (TreeDefinition treeDefinition : this.treeDefinitions)
for (ItemStack requiredTool : treeDefinition.getRequiredTools()) { for (ItemStack requiredTool : treeDefinition.getRequiredTools())
if (tool != null && requiredTool.getType() == tool.getType()) { if (requiredTool.getType().equals(tool.getType()))
return true; return true;
}
}
}
for (ItemStack requiredTool : this.globalRequiredTools) { for (ItemStack requiredTool : this.globalRequiredTools)
if (tool != null && requiredTool.getType() == tool.getType()) { if (requiredTool.getType().equals(tool.getType()))
return true; return true;
}
}
return false; return false;
} }
@ -378,26 +344,23 @@ public class TreeDefinitionManager extends Manager {
* @return True if the tool is allowed for toppling the given TreeDefinition * @return True if the tool is allowed for toppling the given TreeDefinition
*/ */
public boolean isToolValidForTreeDefinition(TreeDefinition treeDefinition, ItemStack tool) { public boolean isToolValidForTreeDefinition(TreeDefinition treeDefinition, ItemStack tool) {
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean()) {
if (ConfigurationManager.Setting.IGNORE_REQUIRED_TOOLS.getBoolean())
return true; return true;
}
// If the tree definition requires the custom axe, don't allow any other checks to pass. // If the tree definition requires the custom axe, don't allow any other checks to pass.
if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) { if (treeDefinition.isRequiredAxe() || isGlobalAxeRequired()) {
return tool != null && !tool.getType().isAir() && new NBTItem(tool).hasTag(this.requiredAxeKey); NBTItem nbtItem = NmsManager.getNbt().of(tool);
return nbtItem.has(requiredAxeKey);
} }
for (ItemStack requiredTool : treeDefinition.getRequiredTools()) { for (ItemStack requiredTool : treeDefinition.getRequiredTools())
if (requiredTool.getType() == tool.getType()) { if (requiredTool.getType().equals(tool.getType()))
return true; return true;
}
}
for (ItemStack requiredTool : this.globalRequiredTools) { for (ItemStack requiredTool : this.globalRequiredTools)
if (requiredTool.getType() == tool.getType()) { if (requiredTool.getType().equals(tool.getType()))
return true; return true;
}
}
return false; return false;
} }
@ -423,9 +386,8 @@ public class TreeDefinitionManager extends Manager {
} else { } else {
if (ConfigurationManager.Setting.APPLY_SILK_TOUCH.getBoolean() && hasSilkTouch) { if (ConfigurationManager.Setting.APPLY_SILK_TOUCH.getBoolean() && hasSilkTouch) {
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean() if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) { && McMMOHook.hasWoodcuttingDoubleDrops(player))
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock)); lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
}
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock)); lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
} else { } else {
switch (treeBlock.getTreeBlockType()) { switch (treeBlock.getTreeBlockType()) {
@ -434,9 +396,8 @@ public class TreeDefinitionManager extends Manager {
toTry.addAll(this.globalLogLoot); toTry.addAll(this.globalLogLoot);
if (treeDefinition.shouldDropOriginalLog()) { if (treeDefinition.shouldDropOriginalLog()) {
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean() if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) { && McMMOHook.hasWoodcuttingDoubleDrops(player))
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock)); lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
}
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock)); lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
} }
break; break;
@ -445,9 +406,8 @@ public class TreeDefinitionManager extends Manager {
toTry.addAll(this.globalLeafLoot); toTry.addAll(this.globalLeafLoot);
if (treeDefinition.shouldDropOriginalLeaf()) { if (treeDefinition.shouldDropOriginalLeaf()) {
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean() if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) { && McMMOHook.hasWoodcuttingDoubleDrops(player))
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock)); lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
}
lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock)); lootedItems.addAll(BlockUtils.getBlockDrops(treeBlock));
} }
break; break;
@ -458,27 +418,22 @@ public class TreeDefinitionManager extends Manager {
// Roll the dice // Roll the dice
double bonusLootMultiplier = ConfigurationManager.Setting.BONUS_LOOT_MULTIPLIER.getDouble(); double bonusLootMultiplier = ConfigurationManager.Setting.BONUS_LOOT_MULTIPLIER.getDouble();
for (TreeLoot treeLoot : toTry) { for (TreeLoot treeLoot : toTry) {
if (treeLoot == null) { if (treeLoot == null) continue;
continue;
}
double chance = hasBonusChance ? treeLoot.getChance() * bonusLootMultiplier : treeLoot.getChance(); double chance = hasBonusChance ? treeLoot.getChance() * bonusLootMultiplier : treeLoot.getChance();
if (this.random.nextDouble() > chance / 100) { if (this.random.nextDouble() > chance / 100)
continue; continue;
}
if (treeLoot.hasItem()) { if (treeLoot.hasItem()) {
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean() if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) { && McMMOHook.hasWoodcuttingDoubleDrops(player))
lootedItems.add(treeLoot.getItem()); lootedItems.add(treeLoot.getItem());
}
lootedItems.add(treeLoot.getItem()); lootedItems.add(treeLoot.getItem());
} }
if (treeLoot.hasCommand()) { if (treeLoot.hasCommand()) {
if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean() if (ConfigurationManager.Setting.HOOKS_APPLY_EXTRA_DROPS.getBoolean()
&& McMMOHook.hasWoodcuttingDoubleDrops(player)) { && McMMOHook.hasWoodcuttingDoubleDrops(player))
lootedCommands.add(treeLoot.getCommand()); lootedCommands.add(treeLoot.getCommand());
}
lootedCommands.add(treeLoot.getCommand()); lootedCommands.add(treeLoot.getCommand());
} }
} }
@ -486,29 +441,25 @@ public class TreeDefinitionManager extends Manager {
// Add to inventory or drop on ground // Add to inventory or drop on ground
if (addToInventory && player.getWorld().equals(treeBlock.getLocation().getWorld())) { if (addToInventory && player.getWorld().equals(treeBlock.getLocation().getWorld())) {
List<ItemStack> extraItems = new ArrayList<>(); List<ItemStack> extraItems = new ArrayList<>();
for (ItemStack lootedItem : lootedItems) { for (ItemStack lootedItem : lootedItems)
extraItems.addAll(player.getInventory().addItem(lootedItem).values()); extraItems.addAll(player.getInventory().addItem(lootedItem).values());
}
Location location = player.getLocation().clone().subtract(0.5, 0, 0.5); Location location = player.getLocation().clone().subtract(0.5, 0, 0.5);
for (ItemStack extraItem : extraItems) { for (ItemStack extraItem : extraItems)
location.getWorld().dropItemNaturally(location, extraItem); location.getWorld().dropItemNaturally(location, extraItem);
}
} else { } else {
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5); Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
for (ItemStack lootedItem : lootedItems) { for (ItemStack lootedItem : lootedItems)
location.getWorld().dropItemNaturally(location, lootedItem); location.getWorld().dropItemNaturally(location, lootedItem);
} }
}
// Run looted commands // Run looted commands
for (String lootedCommand : lootedCommands) { for (String lootedCommand : lootedCommands)
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(),
lootedCommand.replace("%player%", player.getName()) lootedCommand.replace("%player%", player.getName())
.replace("%type%", treeDefinition.getKey()) .replace("%type%", treeDefinition.getKey())
.replace("%xPos%", String.valueOf(treeBlock.getLocation().getBlockX())) .replace("%xPos%", treeBlock.getLocation().getBlockX() + "")
.replace("%yPos%", String.valueOf(treeBlock.getLocation().getBlockY())) .replace("%yPos%", treeBlock.getLocation().getBlockY() + "")
.replace("%zPos%", String.valueOf(treeBlock.getLocation().getBlockZ()))); .replace("%zPos%", treeBlock.getLocation().getBlockZ() + ""));
}
} }
/** /**
@ -517,8 +468,8 @@ public class TreeDefinitionManager extends Manager {
* @param treeDefinition The TreeDefinition * @param treeDefinition The TreeDefinition
* @return A Set of IBlockData of plantable soil * @return A Set of IBlockData of plantable soil
*/ */
public Set<XMaterial> getPlantableSoilMaterial(TreeDefinition treeDefinition) { public Set<CompatibleMaterial> getPlantableSoilMaterial(TreeDefinition treeDefinition) {
Set<XMaterial> plantableSoilBlockData = new HashSet<>(); Set<CompatibleMaterial> plantableSoilBlockData = new HashSet<>();
plantableSoilBlockData.addAll(treeDefinition.getPlantableSoilMaterial()); plantableSoilBlockData.addAll(treeDefinition.getPlantableSoilMaterial());
plantableSoilBlockData.addAll(this.globalPlantableSoil); plantableSoilBlockData.addAll(this.globalPlantableSoil);
return plantableSoilBlockData; return plantableSoilBlockData;
@ -533,9 +484,9 @@ public class TreeDefinitionManager extends Manager {
*/ */
private TreeLoot getTreeLootEntry(TreeBlockType treeBlockType, ConfigurationSection configurationSection) { private TreeLoot getTreeLootEntry(TreeBlockType treeBlockType, ConfigurationSection configurationSection) {
String material = configurationSection.getString("material"); String material = configurationSection.getString("material");
Optional<XMaterial> compatibleMaterial = material == null ? Optional.empty() : CompatibleMaterial.getMaterial(material); CompatibleMaterial compatibleMaterial = material == null ? null : CompatibleMaterial.getMaterial(material);
ItemStack item = compatibleMaterial.map(XMaterial::parseItem).orElse(null); ItemStack item = compatibleMaterial == null ? null : compatibleMaterial.getItem();
String command = configurationSection.getString("command"); String command = configurationSection.getString("command");
double chance = configurationSection.getDouble("chance"); double chance = configurationSection.getDouble("chance");
return new TreeLoot(treeBlockType, item, command, chance); return new TreeLoot(treeBlockType, item, command, chance);

View File

@ -1,57 +1,42 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import com.songoda.ultimatetimber.UltimateTimber;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.tree.*;
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.ArrayList; import java.util.*;
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 numLeavesRequiredForTree; private int maxLogBlocksAllowed, numLeavesRequiredForTree;
private boolean onlyBreakLogsUpwards, entireTreeBase, destroyLeaves; private boolean onlyBreakLogsUpwards, entireTreeBase, destroyLeaves;
public TreeDetectionManager(UltimateTimber plugin) { public TreeDetectionManager(UltimateTimber ultimateTimber) {
super(plugin); super(ultimateTimber);
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) {
@ -65,6 +50,7 @@ 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();
@ -73,6 +59,7 @@ public class TreeDetectionManager extends Manager {
@Override @Override
public void disable() { public void disable() {
} }
/** /**
@ -88,9 +75,8 @@ 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<>();
@ -113,54 +99,47 @@ 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 (XMaterial material : treeDefinitionManager.getPlantableSoilMaterial(actualTreeDefinition)) { for (CompatibleMaterial material : treeDefinitionManager.getPlantableSoilMaterial(actualTreeDefinition)) {
if (material == CompatibleMaterial.getMaterial(blockBelow.getType()).orElse(null)) { if (material.equals(CompatibleMaterial.getMaterial(blockBelow))) {
blockBelowIsSoil = true; blockBelowIsSoil = true;
break; break;
} }
} }
if (blockBelowIsLog || blockBelowIsSoil) { if (blockBelowIsLog || blockBelowIsSoil)
return null; return null;
} }
} }
}
return new DetectedTree(actualTreeDefinition, detectedTreeBlocks); return new DetectedTree(actualTreeDefinition, detectedTreeBlocks);
} }
@ -175,18 +154,20 @@ 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);
} }
} }
} }
}
/** /**
* Recursively searches for leaves that are next to this tree * Recursively searches for leaves that are next to this tree
@ -200,9 +181,8 @@ 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);
@ -225,10 +205,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;
} }
@ -242,43 +221,36 @@ 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 (XMaterial material : treeDefinition.getLogMaterial()) { for (CompatibleMaterial material : treeDefinition.getLogMaterial()) {
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) { if (material.equals(CompatibleMaterial.getMaterial(block))) {
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)
for (Block trunkBlock : trunkBlocks) { if (location.distanceSquared(trunkBlock.getLocation()) < maxDistance)
if (location.distanceSquared(trunkBlock.getLocation()) < maxDistance) {
return true; return true;
} }
}
}
return false; return false;
} }
@ -293,31 +265,29 @@ 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 (XMaterial material : treeDefinition.getLeafMaterial()) { for (CompatibleMaterial material : treeDefinition.getLeafMaterial()) {
if (material == CompatibleMaterial.getMaterial(block.getType()).orElse(null)) { if (material.equals(CompatibleMaterial.getMaterial(block))) {
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);
} }
} }

View File

@ -1,19 +1,17 @@
package com.craftaro.ultimatetimber.manager; package com.songoda.ultimatetimber.manager;
import com.craftaro.core.compatibility.CompatibleHand; import com.songoda.core.compatibility.CompatibleHand;
import com.craftaro.core.compatibility.ServerVersion; import com.songoda.core.hooks.JobsHook;
import com.craftaro.core.hooks.JobsHook; import com.songoda.core.hooks.LogManager;
import com.craftaro.core.hooks.LogManager; import com.songoda.core.hooks.McMMOHook;
import com.craftaro.core.hooks.McMMOHook; import com.songoda.core.utils.ItemUtils;
import com.craftaro.core.utils.ItemUtils; import com.songoda.ultimatetimber.UltimateTimber;
import com.craftaro.core.world.SItemStack; import com.songoda.ultimatetimber.events.TreeFallEvent;
import com.craftaro.ultimatetimber.UltimateTimber; import com.songoda.ultimatetimber.events.TreeFellEvent;
import com.craftaro.ultimatetimber.events.TreeFallEvent; import com.songoda.ultimatetimber.misc.OnlyToppleWhile;
import com.craftaro.ultimatetimber.events.TreeFellEvent; 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.TreeBlockSet;
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;
@ -25,26 +23,24 @@ 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 plugin) { public TreeFallManager(UltimateTimber ultimateTimber) {
super(plugin); super(ultimateTimber);
Bukkit.getPluginManager().registerEvents(this, plugin); Bukkit.getPluginManager().registerEvents(this, ultimateTimber);
} }
@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)
@ -68,141 +64,92 @@ 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() && !McMMOHook.isUsingTreeFeller(player)) { if (ConfigurationManager.Setting.HOOKS_REQUIRE_ABILITY_ACTIVE.getBoolean()
&& 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;
}
}
if (!treeDefinitionManager.isToolValidForTreeDefinition(detectedTree.getTreeDefinition(), tool)) {
return; return;
} }
short toolDamage = this.getToolDamage(detectedTree.getDetectedTreeBlocks(), tool.containsEnchantment(Enchantment.SILK_TOUCH)); if (!treeDefinitionManager.isToolValidForTreeDefinition(detectedTree.getTreeDefinition(), tool))
if (ConfigurationManager.Setting.PROTECT_TOOL.getBoolean() && !ItemUtils.hasEnoughDurability(tool, toolDamage)) { return;
int toolDamage = this.getToolDamage(detectedTree.getDetectedTreeBlocks(), tool.containsEnchantment(Enchantment.SILK_TOUCH));
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());
} }
boolean isCreative = player.getGameMode() == GameMode.CREATIVE; boolean isCreative = player.getGameMode().equals(GameMode.CREATIVE);
if (!isCreative) { if (!isCreative)
SItemStack sstack = new SItemStack(tool); ItemUtils.addDamage(tool, toolDamage);
sstack.addDamage(player, toolDamage, true);
//Destroy item if durability is less than 0
ItemStack itemStack = sstack.getItem();
ItemMeta meta = itemStack.getItemMeta();
boolean isDamageableAvailable = false;
try {
Class.forName("org.bukkit.inventory.meta.Damageable");
isDamageableAvailable = true;
} catch (ClassNotFoundException e) {
isDamageableAvailable = false;
}
if (isDamageableAvailable && meta instanceof org.bukkit.inventory.meta.Damageable) {
org.bukkit.inventory.meta.Damageable damageable = (org.bukkit.inventory.meta.Damageable) meta;
int damage = damageable.getDamage();
if (damage >= itemStack.getType().getMaxDurability()) {
player.getInventory().setItemInMainHand(null);
} else {
itemStack.setItemMeta(meta);
}
} else {
short currentDurability = itemStack.getDurability();
short maxDurability = itemStack.getType().getMaxDurability();
if (currentDurability >= maxDurability) {
player.getInventory().setItemInMainHand(null);
} else {
itemStack.setDurability(currentDurability);
}
}
}
if (ConfigurationManager.Setting.HOOKS_APPLY_EXPERIENCE.getBoolean()) { if (ConfigurationManager.Setting.HOOKS_APPLY_EXPERIENCE.getBoolean()) {
McMMOHook.addWoodcutting(player, detectedTree.getDetectedTreeBlocks().getAllTreeBlocks().stream() McMMOHook.addWoodcutting(player, detectedTree.getDetectedTreeBlocks().getAllTreeBlocks().stream()
.map(ITreeBlock::getBlock).collect(Collectors.toList())); .map(ITreeBlock::getBlock).collect(Collectors.toList()));
if (!isCreative && JobsHook.isEnabled()) { if (!isCreative && JobsHook.isEnabled())
for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getLogBlocks()) { for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getLogBlocks())
JobsHook.breakBlock(player, treeBlock.getBlock()); JobsHook.breakBlock(player, treeBlock.getBlock());
} }
}
}
for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getAllTreeBlocks()) { for (ITreeBlock<Block> treeBlock : detectedTree.getDetectedTreeBlocks().getAllTreeBlocks())
LogManager.logRemoval(player, treeBlock.getBlock()); LogManager.logRemoval(player, treeBlock.getBlock());
}
treeAnimationManager.runAnimation(detectedTree, player); treeAnimationManager.runAnimation(detectedTree, player);
treeDefinitionManager.dropTreeLoot(detectedTree.getTreeDefinition(), detectedTree.getDetectedTreeBlocks().getInitialLogBlock(), player, false, true); treeDefinitionManager.dropTreeLoot(detectedTree.getTreeDefinition(), detectedTree.getDetectedTreeBlocks().getInitialLogBlock(), player, false, true);
@ -229,15 +176,15 @@ public class TreeFallManager extends Manager implements Listener {
} }
} }
private short getToolDamage(TreeBlockSet<Block> treeBlocks, boolean hasSilkTouch) { private int 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 (short) treeBlocks.size(); return treeBlocks.size();
} else { } else {
return (short) treeBlocks.getLogBlocks().size(); return treeBlocks.getLogBlocks().size();
} }
} }
} }

View File

@ -1,9 +1,8 @@
package com.craftaro.ultimatetimber.utils; package com.songoda.ultimatetimber.utils;
import com.craftaro.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.craftaro.core.compatibility.ServerVersion; import com.songoda.core.compatibility.ServerVersion;
import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.craftaro.ultimatetimber.tree.ITreeBlock;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.FallingBlock; import org.bukkit.entity.FallingBlock;
@ -11,37 +10,34 @@ import org.bukkit.inventory.ItemStack;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional;
import java.util.Set; import java.util.Set;
public class BlockUtils { public class BlockUtils {
public static Collection<ItemStack> getBlockDrops(ITreeBlock treeBlock) { public static Collection<ItemStack> getBlockDrops(ITreeBlock treeBlock) {
Set<ItemStack> drops = new HashSet<>(); Set<ItemStack> drops = new HashSet<>();
if (treeBlock.getBlock() instanceof Block) { if (treeBlock.getBlock() instanceof Block) {
Block block = (Block)treeBlock.getBlock(); Block block = (Block)treeBlock.getBlock();
Optional<XMaterial> material = CompatibleMaterial.getMaterial(block.getType()); CompatibleMaterial material = CompatibleMaterial.getMaterial(block);
if (!material.isPresent() || CompatibleMaterial.isAir(material.get())) { if (material.isAir())
return drops; return drops;
} drops.add(CompatibleMaterial.getMaterial(block).getItem());
drops.add(material.get().parseItem());
} else if (treeBlock.getBlock() instanceof FallingBlock) { } else if (treeBlock.getBlock() instanceof FallingBlock) {
Optional<XMaterial> material = CompatibleMaterial.getMaterial(((FallingBlock) treeBlock.getBlock()).getBlockData().getMaterial()); CompatibleMaterial material = CompatibleMaterial.getMaterial((FallingBlock)treeBlock.getBlock());
if (!material.isPresent()) { if (material == null)
return drops; return drops;
} drops.add(material.getItem());
drops.add(material.get().parseItem());
} }
return drops; return drops;
} }
public static void toggleGravityFallingBlock(FallingBlock fallingBlock, boolean applyGravity) { public static void toggleGravityFallingBlock(FallingBlock fallingBlock, boolean applyGravity) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) { if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9))
fallingBlock.setGravity(applyGravity); fallingBlock.setGravity(applyGravity);
} }
}
public static FallingBlock spawnFallingBlock(Location location, XMaterial material) { public static FallingBlock spawnFallingBlock(Location location, CompatibleMaterial material) {
return location.getWorld().spawnFallingBlock(location, material.parseMaterial(), material.getData()); return location.getWorld().spawnFallingBlock(location, material.getMaterial(), material.getData());
} }
public static void configureFallingBlock(FallingBlock fallingBlock) { public static void configureFallingBlock(FallingBlock fallingBlock) {
@ -49,4 +45,5 @@ public class BlockUtils {
fallingBlock.setDropItem(false); fallingBlock.setDropItem(false);
fallingBlock.setHurtEntities(false); fallingBlock.setHurtEntities(false);
} }
} }

View File

@ -1,7 +1,8 @@
package com.craftaro.ultimatetimber.utils; package com.songoda.ultimatetimber.utils;
import com.craftaro.core.compatibility.ServerVersion; import com.songoda.core.compatibility.ServerVersion;
import com.craftaro.ultimatetimber.tree.ITreeBlock; import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.ultimatetimber.tree.TreeDefinition;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Particle; import org.bukkit.Particle;
@ -13,6 +14,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.Collection; import java.util.Collection;
public class ParticleUtils { public class ParticleUtils {
public static void playFallingParticles(ITreeBlock treeBlock) { public static void playFallingParticles(ITreeBlock treeBlock) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) { if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
BlockData blockData; BlockData blockData;
@ -20,20 +22,15 @@ public class ParticleUtils {
blockData = ((Block) treeBlock.getBlock()).getBlockData(); blockData = ((Block) treeBlock.getBlock()).getBlockData();
} else if (treeBlock.getBlock() instanceof FallingBlock) { } else if (treeBlock.getBlock() instanceof FallingBlock) {
blockData = ((FallingBlock) treeBlock.getBlock()).getBlockData(); blockData = ((FallingBlock) treeBlock.getBlock()).getBlockData();
} else { } else return;
return;
}
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5); Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockData); location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockData);
} else {
return;
}
Collection<ItemStack> blockDrops = BlockUtils.getBlockDrops(treeBlock); Collection<ItemStack> blockDrops = BlockUtils.getBlockDrops(treeBlock);
if (!blockDrops.iterator().hasNext()) { if (!blockDrops.iterator().hasNext())
return; return;
}
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5); Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
if (ServerVersion.isServerVersion(ServerVersion.V1_8)) { if (ServerVersion.isServerVersion(ServerVersion.V1_8)) {
@ -42,6 +39,7 @@ public class ParticleUtils {
location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockDrops.iterator().next().getData()); location.getWorld().spawnParticle(Particle.BLOCK_DUST, location, 10, blockDrops.iterator().next().getData());
} }
} }
}
public static void playLandingParticles(ITreeBlock treeBlock) { public static void playLandingParticles(ITreeBlock treeBlock) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) { if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
@ -50,20 +48,14 @@ public class ParticleUtils {
blockData = ((Block) treeBlock.getBlock()).getBlockData(); blockData = ((Block) treeBlock.getBlock()).getBlockData();
} else if (treeBlock.getBlock() instanceof FallingBlock) { } else if (treeBlock.getBlock() instanceof FallingBlock) {
blockData = ((FallingBlock) treeBlock.getBlock()).getBlockData(); blockData = ((FallingBlock) treeBlock.getBlock()).getBlockData();
} else { } else return;
return;
}
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5); Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
location.getWorld().spawnParticle(Particle.BLOCK_CRACK, location, 10, blockData); location.getWorld().spawnParticle(Particle.BLOCK_CRACK, location, 10, blockData);
} else {
return;
}
Collection<ItemStack> blockDrops = BlockUtils.getBlockDrops(treeBlock); Collection<ItemStack> blockDrops = BlockUtils.getBlockDrops(treeBlock);
if (!blockDrops.iterator().hasNext()) { if (!blockDrops.iterator().hasNext())
return; return;
}
Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5); Location location = treeBlock.getLocation().clone().add(0.5, 0.5, 0.5);
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) { if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
@ -73,3 +65,4 @@ public class ParticleUtils {
} }
} }
} }
}

View File

@ -0,0 +1,27 @@
package com.songoda.ultimatetimber.utils;
import com.songoda.core.compatibility.CompatibleSound;
import com.songoda.ultimatetimber.tree.ITreeBlock;
import com.songoda.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;
CompatibleSound.BLOCK_CHEST_OPEN.play(location.getWorld(), location, 2F, 0.1F);
}
public static void playLandingSound(ITreeBlock block) {
Location location = block.getLocation();
if (location.getWorld() == null) return;
if (block.getTreeBlockType().equals(TreeBlockType.LOG)) {
CompatibleSound.BLOCK_WOOD_FALL.play(location.getWorld(), location, 2F, 0.1F);
} else {
CompatibleSound.BLOCK_GRASS_BREAK.play(location.getWorld(), location, 0.5F, 0.75F);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

181
pom.xml
View File

@ -1,133 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.craftaro</groupId> <groupId>com.songoda</groupId>
<artifactId>UltimateTimber</artifactId> <artifactId>UltimateTimber</artifactId>
<version>3.2.0</version> <version>2.1.1b</version>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<name>UltimateTimber</name> <modules>
<description>Give your players a new and exciting way to chop down trees</description> <module>UltimateTimber/Core</module>
<url>https://craftaro.com/marketplace/product/18</url> <module>UltimateTimber/Plugin</module>
</modules>
<properties> <repositories>
<maven.compiler.release>8</maven.compiler.release> <repository>
<maven.compiler.target>1.8</maven.compiler.target> <id>public</id>
<maven.compiler.source>1.8</maven.compiler.source> <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>
<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-shade-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.5.3</version> <version>3.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>package</phase> <phase>validate</phase>
<goals> <goals>
<goal>shade</goal> <goal>run</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>
<include>**/third_party/net/kyori/**</include>
</includes>
<excludes>
<exclude>**/third_party/org/apache/**</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>src/main/resources</directory> <directory>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.5.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>

View File

@ -1,67 +0,0 @@
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;}
}

View File

@ -1,39 +0,0 @@
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;
}
}

View File

@ -1,25 +0,0 @@
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;
}
}

View File

@ -1,20 +0,0 @@
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;
}
}

View File

@ -1,5 +0,0 @@
package com.craftaro.ultimatetimber.tree;
public enum TreeBlockType {
LOG, LEAF
}

View File

@ -1,29 +0,0 @@
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);
}
}
}

View File

@ -1,29 +0,0 @@
#########################################################
# 参考 By https://www.mcbbs.net/thread-1297859-1-1.html #
# command.give.not-a-player #
# command.give.given #
# command.give.no-axe #
#########################################################
# 一般信息
general:
nametag:
prefix: '&8[&6UltimateTimber&8] '
nopermission: '&c你没有权限'
# 命令消息
command:
reload:
description: '&8 - &a/ut reload &7 - 配置已重载'
reloaded: '&7配置和语言环境文件已重新加载'
toggle:
description: '&8 - &a/ut toggle &7 - 切换砍树模式'
enabled: '&7Chopping Mode: &a开启'
disabled: '&7Chopping Mode: &c关闭'
give:
not-a-player: '&c你貌似并非一个玩家'
given: '&f给予玩家 &a%player%'
no-axe: '&cAxe 加载失败惹'
# 事件消息
event:
'on':
cooldown: '&e冷却中, 暂不能砍树哦'