Version 1.20.1 (#1966)

* Version 1.20.1

* Added name of the addon causing the issue.

https://github.com/BentoBoxWorld/BentoBox/issues/1944

* Use world min-height for island bounding box.

* Fixes a bug when fallback could not use reusable

There was an issue in PanelItemTemplate that prevented fallback buttons to be "reusable" things.
The issue was that reusable items were not passed to the panel item reader.

* Adjusted test to try to avoid errors

* Fix for random test failures.

* Added 1.18.2 support

* Address unnecessary PVP reports on each teleport (#1948)

If a player is teleporting on the same island in the same dimension, it keeps spamming that PVP is enabled in dimension. 
It should be enough with sending messages when the player teleports to the island.

Fixes #1885

* Fixes bug with Safe Spot Teleport (#1951)

There was a bug that prevented finding a safe spot if all valid blocks were in height with the `startY` location.

Reported via discord.

* Fix Exception error reported by IDE

I am not sure why Eclipse is saying this is an error.

* Fix for kicking offline players

https://github.com/BentoBoxWorld/BentoBox/issues/1950

* Add an option in SafeSpotTeleport to cancel if fail (#1952)

There was no option to cancel teleportation if SafeSpotTeleport could not find a valid spot. This option could be used to avoid creating "backup" blocks in situations when teleportation is avoidable, f.e. visiting an island.

* Replace peplaceAll with replace

It does the same thing if the first argument is not a regex.

* Use constants for common strings

* Use constants for common strings

* Go back to replaceAll

This is required.

* Clearer paster (#1953)

* WIP - make easier to understand.

* Small refactor of paster to make it easier to understand

* Fix tabs to spaces. Sorry - new editor!

* Fix tabs to spaces

* Fix tab to spaces

* Improve team kick command (#1957)

The kick command has an unnecessary owner check. As command should be configurable by island owners, then limiting it to an owner is wrong.
Add a code that allows kicking only lower-ranked players.

Add message that shows who kicked from the island.
Add message that shows that rank does not allow to kick.

* Solve crashes with Addon#allLoaded call (#1959)

If some addon has code in Addon#allLoaded that crashes the call, then it did not disable addon as well as did not call allLoaded for every other addon that was left in the list.

This should be solved by adding an extra try-catch.

* using java 16 syntax (#1958)

* Fixes kick command (#1960)

PR #1957 broke kick command and noone could kick players from teams.
This should fix it.

* Fixes a bug with blueprint height (#1961)

Blueprint clipboard was preventing setting Y below 0 or above 255. 

The code was not adjusted to 1.18 changes.
Reported via discord.

* Fixes Lava Duplication Glitch (#1964)

Due to the fact, that Obsidian Scooping uses one tick delay to remove obsidian, a player with a bucket in hand and offhand duplicated lava. 
To avoid that, added an extra check that ignores the interact event if a player holds a bucket in both hands, and interacted hand is offhand.

Fixes #1963

* Fixes failures in obsidian cooping listener. (#1965)

Failures happened after implementing #1964

Co-authored-by: BONNe <bonne@bonne.id.lv>
Co-authored-by: Invvk <70810073+Invvk@users.noreply.github.com>
This commit is contained in:
tastybento 2022-04-17 09:04:37 -07:00 committed by GitHub
parent 73a432d75c
commit 928f1eb1eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 380 additions and 184 deletions

View File

@ -83,7 +83,7 @@
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>1.20.0</build.version>
<build.version>1.20.1</build.version>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
</properties>

View File

@ -20,6 +20,7 @@ import world.bentobox.bentobox.util.Util;
*/
public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
private static final String INVALID_INVITE = "commands.island.team.invite.errors.invalid-invite";
private final IslandTeamCommand itc;
private UUID playerUUID;
private UUID prospectiveOwnerUUID;
@ -47,7 +48,7 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
// Get the island owner
prospectiveOwnerUUID = itc.getInviter(playerUUID);
if (prospectiveOwnerUUID == null) {
user.sendMessage("commands.island.team.invite.errors.invalid-invite");
user.sendMessage(INVALID_INVITE);
return false;
}
Invite invite = itc.getInvite(playerUUID);
@ -56,7 +57,7 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
Island island = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
String inviteUsage = getParent().getSubCommand("invite").map(CompositeCommand::getUsage).orElse("");
if (island == null || island.getRank(prospectiveOwnerUUID) < island.getRankCommand(inviteUsage)) {
user.sendMessage("commands.island.team.invite.errors.invalid-invite");
user.sendMessage(INVALID_INVITE);
itc.removeInvite(playerUUID);
return false;
}
@ -149,7 +150,7 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
// Get the team's island
Island teamIsland = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
if (teamIsland == null) {
user.sendMessage("commands.island.team.invite.errors.invalid-invite");
user.sendMessage(INVALID_INVITE);
return;
}
if (teamIsland.getMemberSet(RanksManager.MEMBER_RANK, true).size() > getIslands().getMaxMembers(teamIsland, RanksManager.MEMBER_RANK)) {

View File

@ -42,10 +42,6 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
user.sendMessage("general.errors.no-team");
return false;
}
if (!user.getUniqueId().equals(getOwner(getWorld(), user))) {
user.sendMessage("general.errors.not-owner");
return false;
}
// Check rank to use command
Island island = getIslands().getIsland(getWorld(), user);
int rank = Objects.requireNonNull(island).getRank(user);
@ -72,6 +68,14 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
user.sendMessage("general.errors.not-in-team");
return false;
}
int targetRank = Objects.requireNonNull(island).getRank(targetUUID);
if (rank <= targetRank) {
user.sendMessage("commands.island.team.kick.cannot-kick-rank",
TextVariables.NAME, getPlayers().getName(targetUUID));
return false;
}
if (!getSettings().isKickConfirmation()) {
kick(user, targetUUID);
return true;
@ -93,7 +97,9 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
if (event.isCancelled()) {
return;
}
target.sendMessage("commands.island.team.kick.owner-kicked", TextVariables.GAMEMODE, getAddon().getDescription().getName());
target.sendMessage("commands.island.team.kick.player-kicked",
TextVariables.GAMEMODE, getAddon().getDescription().getName(),
TextVariables.NAME, user.getName());
getIslands().removePlayer(getWorld(), targetUUID);
// Clean the target player

View File

@ -41,6 +41,12 @@ public class TemplateReader
private static final String BORDER = "border";
private static final String FORCE_SHOWN = "force-shown";
private static final String FALLBACK = "fallback";
private static final String YML = ".yml";
private static final String ACTIONS = "actions";
private static final String TOOLTIP = "tooltip";
private static final String CLICK_TYPE = "click-type";
private static final String CONTENT = "content";
private static final String TYPE = "type";
/**
@ -73,7 +79,7 @@ public class TemplateReader
return null;
}
File file = new File(panelLocation, templateName.endsWith(".yml") ? templateName : templateName + ".yml");
File file = new File(panelLocation, templateName.endsWith(YML) ? templateName : templateName + YML);
if (!file.exists())
{
@ -82,7 +88,7 @@ public class TemplateReader
}
final String panelKey = file.getAbsolutePath() + ":" + panelName;
// Check if panel is already crafted.
if (TemplateReader.loadedPanels.containsKey(panelKey))
{
@ -125,7 +131,7 @@ public class TemplateReader
String title = configurationSection.getString(TITLE);
Panel.Type type =
Enums.getIfPresent(Panel.Type.class, configurationSection.getString("type", "INVENTORY")).
Enums.getIfPresent(Panel.Type.class, configurationSection.getString(TYPE, "INVENTORY")).
or(Panel.Type.INVENTORY);
PanelTemplateRecord.TemplateItem borderItem = null;
@ -194,7 +200,7 @@ public class TemplateReader
PanelTemplateRecord template = new PanelTemplateRecord(type, title, borderItem, backgroundItem, forcedRows);
// Read content
ConfigurationSection content = configurationSection.getConfigurationSection("content");
ConfigurationSection content = configurationSection.getConfigurationSection(CONTENT);
if (content == null)
{
@ -219,7 +225,7 @@ public class TemplateReader
// If it contains a section, then build a new button template from it.
template.addButtonTemplate(rowIndex,
columnIndex,
readPanelItemTemplate(line.getConfigurationSection(String.valueOf(columnIndex + 1))));
readPanelItemTemplate(line.getConfigurationSection(String.valueOf(columnIndex + 1)), null, panelItemDataMap));
}
else if (line.isString(String.valueOf(columnIndex + 1)))
{
@ -337,9 +343,9 @@ public class TemplateReader
}
// Read Click data
if (section.isConfigurationSection("actions"))
if (section.isConfigurationSection(ACTIONS))
{
ConfigurationSection actionSection = section.getConfigurationSection("actions");
ConfigurationSection actionSection = section.getConfigurationSection(ACTIONS);
if (actionSection != null)
{
@ -354,9 +360,9 @@ public class TemplateReader
{
ItemTemplateRecord.ActionRecords actionData =
new ItemTemplateRecord.ActionRecords(clickType,
actionDataSection.getString("type"),
actionDataSection.getString("content"),
actionDataSection.getString("tooltip"));
actionDataSection.getString(TYPE),
actionDataSection.getString(CONTENT),
actionDataSection.getString(TOOLTIP));
itemRecord.addAction(actionData);
}
}
@ -364,42 +370,42 @@ public class TemplateReader
{
ConfigurationSection actionDataSection = actionSection.getConfigurationSection(actionKey);
if (actionDataSection != null && actionDataSection.contains("click-type"))
if (actionDataSection != null && actionDataSection.contains(CLICK_TYPE))
{
clickType = Enums.getIfPresent(ClickType.class,
actionDataSection.getString("click-type", "UNKNOWN").toUpperCase()).
or(ClickType.UNKNOWN);
actionDataSection.getString(CLICK_TYPE, "UNKNOWN").toUpperCase()).
or(ClickType.UNKNOWN);
ItemTemplateRecord.ActionRecords actionData =
new ItemTemplateRecord.ActionRecords(clickType,
actionKey,
actionDataSection.getString("content"),
actionDataSection.getString("tooltip"));
new ItemTemplateRecord.ActionRecords(clickType,
actionKey,
actionDataSection.getString(CONTENT),
actionDataSection.getString(TOOLTIP));
itemRecord.addAction(actionData);
}
}
});
}
}
else if (section.isList("actions"))
else if (section.isList(ACTIONS))
{
// Read Click data as list which allows to have duplicate click types.
List<Map<?, ?>> actionList = section.getMapList("actions");
List<Map<?, ?>> actionList = section.getMapList(ACTIONS);
if (!actionList.isEmpty())
{
actionList.forEach(valueMap -> {
ClickType clickType = Enums.getIfPresent(ClickType.class,
String.valueOf(valueMap.get("click-type")).toUpperCase()).orNull();
String.valueOf(valueMap.get(CLICK_TYPE)).toUpperCase()).orNull();
if (clickType != null)
{
ItemTemplateRecord.ActionRecords actionData =
new ItemTemplateRecord.ActionRecords(clickType,
valueMap.containsKey("type") ? String.valueOf(valueMap.get("type")) : null,
valueMap.containsKey("content") ? String.valueOf(valueMap.get("content")) : null,
valueMap.containsKey("tooltip") ? String.valueOf(valueMap.get("tooltip")) : null);
new ItemTemplateRecord.ActionRecords(clickType,
valueMap.containsKey(TYPE) ? String.valueOf(valueMap.get(TYPE)) : null,
valueMap.containsKey(CONTENT) ? String.valueOf(valueMap.get(CONTENT)) : null,
valueMap.containsKey(TOOLTIP) ? String.valueOf(valueMap.get(TOOLTIP)) : null);
itemRecord.addAction(actionData);
}
});

View File

@ -257,8 +257,8 @@ public class BlueprintClipboard {
}
// Banners
if (blockState instanceof Banner) {
b.setBannerPatterns(((Banner) blockState).getPatterns());
if (blockState instanceof Banner banner) {
b.setBannerPatterns(banner.getPatterns());
}
return b;
@ -282,8 +282,8 @@ public class BlueprintClipboard {
BlueprintEntity bpe = new BlueprintEntity();
bpe.setType(entity.getType());
bpe.setCustomName(entity.getCustomName());
if (entity instanceof Villager) {
setVillager(entity, bpe);
if (entity instanceof Villager villager) {
setVillager(villager, bpe);
}
if (entity instanceof Colorable c) {
if (c.getColor() != null) {
@ -321,11 +321,10 @@ public class BlueprintClipboard {
/**
* Set the villager stats
* @param entity - villager
* @param v - villager
* @param bpe - Blueprint Entity
*/
private void setVillager(LivingEntity entity, BlueprintEntity bpe) {
Villager v = (Villager)entity;
private void setVillager(Villager v, BlueprintEntity bpe) {
bpe.setExperience(v.getVillagerExperience());
bpe.setLevel(v.getVillagerLevel());
bpe.setProfession(v.getProfession());
@ -371,11 +370,17 @@ public class BlueprintClipboard {
public void setPos1(@Nullable Location pos1) {
origin = null;
if (pos1 != null) {
if (pos1.getBlockY() < 0) {
pos1.setY(0);
final int minHeight = pos1.getWorld() == null ? 0 : pos1.getWorld().getMinHeight();
final int maxHeight = pos1.getWorld() == null ? 255 : pos1.getWorld().getMaxHeight();
if (pos1.getBlockY() < minHeight)
{
pos1.setY(minHeight);
}
if (pos1.getBlockY() > 255) {
pos1.setY(255);
if (pos1.getBlockY() > maxHeight)
{
pos1.setY(maxHeight);
}
}
this.pos1 = pos1;
@ -387,11 +392,17 @@ public class BlueprintClipboard {
public void setPos2(@Nullable Location pos2) {
origin = null;
if (pos2 != null) {
if (pos2.getBlockY() < 0) {
pos2.setY(0);
final int minHeight = pos2.getWorld() == null ? 0 : pos2.getWorld().getMinHeight();
final int maxHeight = pos2.getWorld() == null ? 255 : pos2.getWorld().getMaxHeight();
if (pos2.getBlockY() < minHeight)
{
pos2.setY(minHeight);
}
if (pos2.getBlockY() > 255) {
pos2.setY(255);
if (pos2.getBlockY() > maxHeight)
{
pos2.setY(maxHeight);
}
}
this.pos2 = pos2;

View File

@ -134,99 +134,110 @@ public class BlueprintPaster {
this.location = island.getProtectionCenter().toVector().subtract(off).toLocation(world);
}
private record Bits(Map<Vector, BlueprintBlock> blocks,
Map<Vector, BlueprintBlock> attached,
Map<Vector, List<BlueprintEntity>> entities,
Iterator<Entry<Vector, BlueprintBlock>> it,
Iterator<Entry<Vector, BlueprintBlock>> it2,
Iterator<Entry<Vector, List<BlueprintEntity>>> it3,
int pasteSpeed) {}
/**
* The main pasting method
*/
public CompletableFuture<Boolean> paste() {
CompletableFuture<Boolean> result = new CompletableFuture<>();
// Iterators for the various maps to paste
Map<Vector, BlueprintBlock> blocks = blueprint.getBlocks() == null ? Collections.emptyMap() : blueprint.getBlocks();
Map<Vector, BlueprintBlock> attached = blueprint.getAttached() == null ? Collections.emptyMap() : blueprint.getAttached();
Map<Vector, List<BlueprintEntity>> entities = blueprint.getEntities() == null ? Collections.emptyMap() : blueprint.getEntities();
Iterator<Entry<Vector, BlueprintBlock>> it = blocks.entrySet().iterator();
Iterator<Entry<Vector, BlueprintBlock>> it2 = attached.entrySet().iterator();
Iterator<Entry<Vector, List<BlueprintEntity>>> it3 = entities.entrySet().iterator();
final Map<Vector, BlueprintBlock> blocks = blueprint.getBlocks() == null ? Collections.emptyMap() : blueprint.getBlocks();
final Map<Vector, BlueprintBlock> attached = blueprint.getAttached() == null ? Collections.emptyMap() : blueprint.getAttached();
final Map<Vector, List<BlueprintEntity>> entities = blueprint.getEntities() == null ? Collections.emptyMap() : blueprint.getEntities();
// Initial state & speed
pasteState = PasteState.CHUNK_LOAD;
final int pasteSpeed = plugin.getSettings().getPasteSpeed();
// If this is an island OVERWORLD paste, get the island owner.
final Optional<User> owner = Optional.ofNullable(island)
.filter(i -> location.getWorld().getEnvironment().equals(World.Environment.NORMAL))
.map(i -> User.getInstance(i.getOwner()));
// Tell the owner we're pasting blocks and how much time it might take
owner.ifPresent(user -> {
// Estimated time:
double total = (double) blocks.size() + attached.size() + entities.size();
BigDecimal time = BigDecimal.valueOf(total / (pasteSpeed * 20.0D) + (chunkLoadTime / 1000.0D)).setScale(1, RoundingMode.UP);
user.sendMessage("commands.island.create.pasting.estimated-time", TextVariables.NUMBER, String.valueOf(time.doubleValue()));
// We're pasting blocks!
user.sendMessage("commands.island.create.pasting.blocks", TextVariables.NUMBER, String.valueOf(blocks.size() + attached.size()));
});
pastingTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
long timer = System.currentTimeMillis();
int count = 0;
if (pasteState.equals(PasteState.CHUNK_LOAD)) {
pasteState = PasteState.CHUNK_LOADING;
// Load chunk
Util.getChunkAtAsync(location).thenRun(() -> {
pasteState = PasteState.BLOCKS;
long duration = System.currentTimeMillis() - timer;
if (duration > chunkLoadTime) {
chunkLoadTime = duration;
}
});
}
while (pasteState.equals(PasteState.BLOCKS) && count < pasteSpeed && it.hasNext()) {
pasteBlock(location, it.next());
count++;
}
while (pasteState.equals(PasteState.ATTACHMENTS) && count < pasteSpeed && it2.hasNext()) {
pasteBlock(location, it2.next());
count++;
}
while (pasteState.equals(PasteState.ENTITIES) && count < pasteSpeed && it3.hasNext()) {
pasteEntity(location, it3.next());
count++;
}
// STATE SHIFT
if (pasteState.equals(PasteState.BLOCKS) && !it.hasNext()) {
// Blocks done
// Next paste attachments
pasteState = PasteState.ATTACHMENTS;
}
else if (pasteState.equals(PasteState.ATTACHMENTS) && !it2.hasNext()) {
// Attachments done. Next paste entities
pasteState = PasteState.ENTITIES;
if (entities.size() != 0) {
owner.ifPresent(user -> user.sendMessage("commands.island.create.pasting.entities", TextVariables.NUMBER, String.valueOf(entities.size())));
}
}
else if (pasteState.equals(PasteState.ENTITIES) && !it3.hasNext()) {
pasteState = PasteState.DONE;
owner.ifPresent(user -> user.sendMessage("commands.island.create.pasting.done"));
}
else if (pasteState.equals(PasteState.DONE)) {
// All done. Cancel task
// Set pos1 and 2 if this was a clipboard paste
if (island == null && clipboard != null) {
clipboard.setPos1(pos1);
clipboard.setPos2(pos2);
}
result.complete(true);
pasteState = PasteState.CANCEL;
} else if (pasteState.equals(PasteState.CANCEL)) {
// This state makes sure the follow-on task only ever runs once
pastingTask.cancel();
result.complete(true);
}
}, 0L, 1L);
owner.ifPresent(user -> tellOwner(user, blocks.size(), attached.size(), entities.size(), plugin.getSettings().getPasteSpeed()));
Bits bits = new Bits(blocks, attached, entities,
blocks.entrySet().iterator(), attached.entrySet().iterator(), entities.entrySet().iterator(),
plugin.getSettings().getPasteSpeed());
pastingTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> pasterTask(result, owner, bits), 0L, 1L);
return result;
}
private void pasterTask(CompletableFuture<Boolean> result, Optional<User> owner, Bits bits) {
final int pasteSpeed = plugin.getSettings().getPasteSpeed();
long timer = System.currentTimeMillis();
int count = 0;
if (pasteState.equals(PasteState.CHUNK_LOAD)) {
pasteState = PasteState.CHUNK_LOADING;
// Load chunk
Util.getChunkAtAsync(location).thenRun(() -> {
pasteState = PasteState.BLOCKS;
long duration = System.currentTimeMillis() - timer;
if (duration > chunkLoadTime) {
chunkLoadTime = duration;
}
});
}
while (pasteState.equals(PasteState.BLOCKS) && count < pasteSpeed && bits.it.hasNext()) {
pasteBlock(location, bits.it.next());
count++;
}
while (pasteState.equals(PasteState.ATTACHMENTS) && count < pasteSpeed && bits.it2.hasNext()) {
pasteBlock(location, bits.it2.next());
count++;
}
while (pasteState.equals(PasteState.ENTITIES) && count < pasteSpeed && bits.it3.hasNext()) {
pasteEntity(location, bits.it3.next());
count++;
}
// STATE SHIFT
if (pasteState.equals(PasteState.BLOCKS) && !bits.it.hasNext()) {
// Blocks done
// Next paste attachments
pasteState = PasteState.ATTACHMENTS;
}
else if (pasteState.equals(PasteState.ATTACHMENTS) && !bits.it2.hasNext()) {
// Attachments done. Next paste entities
pasteState = PasteState.ENTITIES;
if (bits.entities.size() != 0) {
owner.ifPresent(user -> user.sendMessage("commands.island.create.pasting.entities", TextVariables.NUMBER, String.valueOf(bits.entities.size())));
}
}
else if (pasteState.equals(PasteState.ENTITIES) && !bits.it3.hasNext()) {
pasteState = PasteState.DONE;
owner.ifPresent(user -> user.sendMessage("commands.island.create.pasting.done"));
}
else if (pasteState.equals(PasteState.DONE)) {
// All done. Cancel task
// Set pos1 and 2 if this was a clipboard paste
if (island == null && clipboard != null) {
clipboard.setPos1(pos1);
clipboard.setPos2(pos2);
}
pasteState = PasteState.CANCEL;
result.complete(true);
} else if (pasteState.equals(PasteState.CANCEL)) {
// This state makes sure the follow-on task only ever runs once
pastingTask.cancel();
result.complete(true);
}
}
private void tellOwner(User user, int blocksSize, int attachedSize, int entitiesSize, int pasteSpeed) {
// Estimated time:
double total = (double) blocksSize + attachedSize + entitiesSize;
BigDecimal time = BigDecimal.valueOf(total / (pasteSpeed * 20.0D) + (chunkLoadTime / 1000.0D)).setScale(1, RoundingMode.UP);
user.sendMessage("commands.island.create.pasting.estimated-time", TextVariables.NUMBER, String.valueOf(time.doubleValue()));
// We're pasting blocks!
user.sendMessage("commands.island.create.pasting.blocks", TextVariables.NUMBER, String.valueOf(blocksSize + attachedSize));
}
private void pasteBlock(Location location, Entry<Vector, BlueprintBlock> entry) {
World world = location.getWorld();
Location pasteTo = location.clone().add(entry.getKey());
@ -294,8 +305,8 @@ public class BlueprintPaster {
writeSign(block, bpBlock.getSignLines(), bpBlock.isGlowingText());
}
// Chests, in general
if (bs instanceof InventoryHolder) {
Inventory ih = ((InventoryHolder)bs).getInventory();
if (bs instanceof InventoryHolder holder) {
Inventory ih = holder.getInventory();
// Double chests are pasted as two blocks so inventory is filled twice.
// This code stops over-filling for the first block.
bpBlock.getInventory().forEach(ih::setItem);

View File

@ -56,23 +56,23 @@ public class BlueprintEntity {
* @since 1.8.0
*/
public void configureEntity(Entity e) {
if (e instanceof Villager) {
setVillager(e);
if (e instanceof Villager villager) {
setVillager(villager);
}
if (e instanceof Colorable) {
((Colorable) e).setColor(color);
if (e instanceof Colorable c) {
c.setColor(color);
}
if (tamed != null && e instanceof Tameable) {
((Tameable)e).setTamed(tamed);
if (tamed != null && e instanceof Tameable tameable) {
tameable.setTamed(tamed);
}
if (chest != null && e instanceof ChestedHorse) {
((ChestedHorse)e).setCarryingChest(chest);
if (chest != null && e instanceof ChestedHorse chestedHorse) {
chestedHorse.setCarryingChest(chest);
}
if (adult != null && e instanceof Ageable) {
if (adult != null && e instanceof Ageable ageable) {
if (adult) {
((Ageable)e).setAdult();
ageable.setAdult();
} else {
((Ageable)e).setBaby();
ageable.setBaby();
}
}
if (e instanceof AbstractHorse horse) {
@ -81,18 +81,17 @@ public class BlueprintEntity {
inventory.forEach(horse.getInventory()::setItem);
}
}
if (style != null && e instanceof Horse) {
((Horse)e).setStyle(style);
if (style != null && e instanceof Horse horse) {
horse.setStyle(style);
}
}
/**
* @param e - villager
* @param v - villager
* @since 1.16.0
*/
private void setVillager(Entity e) {
Villager v = (Villager)e;
private void setVillager(Villager v) {
v.setProfession(profession == null ? Profession.NONE : profession);
v.setVillagerExperience(experience == null ? 0 : experience);
v.setVillagerLevel(level == null ? 0 : level);

View File

@ -698,7 +698,7 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.5.2
*/
public BoundingBox getBoundingBox() {
return new BoundingBox(getMinX(), 0.0D, getMinZ(), getMaxX(), world.getMaxHeight(), getMaxZ());
return new BoundingBox(getMinX(), world.getMinHeight(), getMinZ(), getMaxX(), world.getMaxHeight(), getMaxZ());
}
/**

View File

@ -289,7 +289,7 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
// Convert any serialized dots back to dots
// In YAML dots . cause a lot of problems, so I serialize them as :dot:
// There may be a better way to do this.
key = key.replaceAll(":dot:", ".");
key = key.replace(":dot:", ".");
Object mapKey = deserialize(key,Class.forName(keyType.getTypeName()));
if (mapKey == null) {
continue;
@ -452,7 +452,7 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
for (Entry<Object, Object> object : value.entrySet()) {
// Serialize all key and values
String key = (String)serialize(object.getKey());
key = key.replaceAll("\\.", ":dot:");
key = key.replace("\\.", ":dot:");
result.put(key, serialize(object.getValue()));
}
// Save the list in the config file

View File

@ -17,6 +17,7 @@ import world.bentobox.bentobox.api.user.User;
public class VaultHook extends Hook {
private static final String AMOUNT_MUST_BE_POSITIVE = "Amount must be positive.";
private static final String PLAYER_OR_OFFLINEPLAYER_REQUIRED = "User must be a Player or an OfflinePlayer";
private Economy economy;
public VaultHook() {
@ -109,7 +110,7 @@ public class VaultHook extends Hook {
*/
public EconomyResponse withdraw(User user, double amount, World world) {
if (!user.isOfflinePlayer()) {
throw new IllegalArgumentException("User must be a Player or an OfflinePlayer");
throw new IllegalArgumentException(PLAYER_OR_OFFLINEPLAYER_REQUIRED);
}
if (amount < 0.0D) {
throw new IllegalArgumentException(AMOUNT_MUST_BE_POSITIVE);
@ -149,7 +150,7 @@ public class VaultHook extends Hook {
*/
public EconomyResponse deposit(User user, double amount, World world) {
if (!user.isOfflinePlayer()) {
throw new IllegalArgumentException("User must be a Player or an OfflinePlayer");
throw new IllegalArgumentException(PLAYER_OR_OFFLINEPLAYER_REQUIRED);
}
if (amount < 0.0D) {
throw new IllegalArgumentException(AMOUNT_MUST_BE_POSITIVE);
@ -198,7 +199,7 @@ public class VaultHook extends Hook {
}
if (!user.isOfflinePlayer()) {
throw new IllegalArgumentException("User must be a Player or an OfflinePlayer");
throw new IllegalArgumentException(PLAYER_OR_OFFLINEPLAYER_REQUIRED);
}
if (world == null)

View File

@ -30,6 +30,7 @@ import world.bentobox.bentobox.api.events.flags.FlagSettingChangeEvent;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.FlagListener;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.RanksManager;
@ -239,10 +240,20 @@ public class PVPListener extends FlagListener {
if (e.getTo() == null) {
return;
}
// Get previous island to skip reporting if island is not changed.
Island previousIsland = this.getIslands().getIslandAt(e.getFrom()).orElse(null);
getIslands().getIslandAt(e.getTo()).ifPresent(island -> {
if (island.getMemberSet(RanksManager.COOP_RANK).contains(e.getPlayer().getUniqueId())) {
return;
}
if (e.getFrom().getWorld() == e.getTo().getWorld() && island == previousIsland) {
// do not report as it is the same world and same island.
return;
}
if (island.isAllowed(Flags.PVP_OVERWORLD)) {
alertUser(e.getPlayer(), Flags.PVP_OVERWORLD);
}

View File

@ -15,6 +15,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import world.bentobox.bentobox.BentoBox;
@ -54,6 +55,16 @@ public class ObsidianScoopingListener extends FlagListener {
|| e.getClickedBlock().getRelative(e.getBlockFace()).getType().equals(Material.WATER)) {
return false;
}
if (Material.BUCKET.equals(e.getPlayer().getInventory().getItemInOffHand().getType()) &&
Material.BUCKET.equals(e.getPlayer().getInventory().getItemInMainHand().getType()) &&
EquipmentSlot.OFF_HAND.equals(e.getHand()))
{
// If player is holding bucket in both hands, then allow to interact only with main hand.
// Prevents lava duplication glitch.
return false;
}
return lookForLava(e);
}

View File

@ -666,7 +666,28 @@ public class AddonsManager {
* @since 1.8.0
*/
public void allLoaded() {
addons.forEach(Addon::allLoaded);
this.getEnabledAddons().forEach(this::allLoaded);
}
/**
* This method calls Addon#allLoaded in safe manner. If for some reason addon crashes on Addon#allLoaded, then
* it will disable itself without harming other addons.
* @param addon Addon that should trigger Addon#allLoaded method.
*/
private void allLoaded(@NonNull Addon addon) {
try {
addon.allLoaded();
} catch (NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
// Looks like the addon is incompatible, because it tries to refer to missing classes...
this.handleAddonIncompatibility(addon, e);
// Disable addon.
this.disable(addon);
} catch (Exception e) {
// Unhandled exception. We'll give a bit of debug here.
this.handleAddonError(addon, e);
// Disable addon.
this.disable(addon);
}
}
}

View File

@ -179,7 +179,7 @@ public class LocalesManager {
} catch (InvalidConfigurationException e) {
plugin.logError("Could not update locale file '" + lf + "' due to it being malformed: " + e.getMessage());
} catch (Exception e) {
plugin.logError("Error updating locale file '" + lf + "': " + e.getMessage());
plugin.logError("Error updating locale file for " + addon.getDescription().getName() + "'s '" + lf + "': " + e.getMessage());
plugin.logStacktrace(e);
}
}

View File

@ -577,17 +577,17 @@ public class PlayersManager {
plugin.getVault().ifPresent(vault -> vault.withdraw(target, vault.getBalance(target), world));
}
// Reset the health
if (plugin.getIWM().isOnLeaveResetHealth(world)) {
if (plugin.getIWM().isOnLeaveResetHealth(world) && target.isPlayer()) {
Util.resetHealth(target.getPlayer());
}
// Reset the hunger
if (plugin.getIWM().isOnLeaveResetHunger(world)) {
if (plugin.getIWM().isOnLeaveResetHunger(world) && target.isPlayer()) {
target.getPlayer().setFoodLevel(20);
}
// Reset the XP
if (plugin.getIWM().isOnLeaveResetXP(world)) {
if (plugin.getIWM().isOnLeaveResetXP(world) && target.isPlayer()) {
target.getPlayer().setTotalExperience(0);
}
// Save player

View File

@ -196,7 +196,7 @@ public class WebManager {
@NonNull
private String getContent(@NonNull GitHubRepository repo, String fileName) {
try {
String content = repo.getContent(fileName).getContent().replaceAll("\\n", "");
String content = repo.getContent(fileName).getContent().replaceAll("\\n", ""); // replaceAll is required here
return new String(Base64.getDecoder().decode(content), StandardCharsets.UTF_8);
} catch (IllegalAccessException e) {
// Fail silently

View File

@ -21,7 +21,9 @@ import world.bentobox.bentobox.managers.RanksManager;
*/
public class IslandInfo {
private final BentoBox plugin;
private static final String XZ1 = "[xz1]";
private static final String RANGE = "[range]";
private final BentoBox plugin;
private final Island island;
private final @Nullable UUID owner;
private final World world;
@ -57,23 +59,23 @@ public class IslandInfo {
try {
String dateTimeFormat = plugin.getLocalesManager().get("commands.admin.info.last-login-date-time-format");
formattedDate = new SimpleDateFormat(dateTimeFormat).format(new Date(lastPlayed));
} catch (NullPointerException | IllegalArgumentException ignored) {
} catch (Exception ignored) {
formattedDate = new Date(lastPlayed).toString();
}
user.sendMessage("commands.admin.info.last-login","[date]", formattedDate);
user.sendMessage("commands.admin.info.deaths", "[number]", String.valueOf(plugin.getPlayers().getDeaths(world, owner)));
user.sendMessage("commands.admin.info.deaths", TextVariables.NUMBER, String.valueOf(plugin.getPlayers().getDeaths(world, owner)));
String resets = String.valueOf(plugin.getPlayers().getResets(world, owner));
String total = plugin.getIWM().getResetLimit(world) < 0 ? "Unlimited" : String.valueOf(plugin.getIWM().getResetLimit(world));
user.sendMessage("commands.admin.info.resets-left", "[number]", resets, "[total]", total);
user.sendMessage("commands.admin.info.resets-left", TextVariables.NUMBER, resets, "[total]", total);
// Show team members
showMembers(user);
}
Vector location = island.getProtectionCenter().toVector();
user.sendMessage("commands.admin.info.island-protection-center", TextVariables.XYZ, Util.xyz(location));
user.sendMessage("commands.admin.info.island-center", TextVariables.XYZ, Util.xyz(island.getCenter().toVector()));
user.sendMessage("commands.admin.info.island-coords", "[xz1]", Util.xyz(new Vector(island.getMinX(), 0, island.getMinZ())), "[xz2]", Util.xyz(new Vector(island.getMaxX(), 0, island.getMaxZ())));
user.sendMessage("commands.admin.info.protection-range", "[range]", String.valueOf(island.getProtectionRange()));
user.sendMessage("commands.admin.info.island-coords", XZ1, Util.xyz(new Vector(island.getMinX(), 0, island.getMinZ())), "[xz2]", Util.xyz(new Vector(island.getMaxX(), 0, island.getMaxZ())));
user.sendMessage("commands.admin.info.protection-range", RANGE, String.valueOf(island.getProtectionRange()));
if (!island.getBonusRanges().isEmpty()) {
user.sendMessage("commands.admin.info.protection-range-bonus-title");
}
@ -84,8 +86,8 @@ public class IslandInfo {
user.sendMessage(brb.getMessage(), TextVariables.NUMBER, String.valueOf(brb.getRange()));
}
});
user.sendMessage("commands.admin.info.max-protection-range", "[range]", String.valueOf(island.getMaxEverProtectionRange()));
user.sendMessage("commands.admin.info.protection-coords", "[xz1]", Util.xyz(new Vector(island.getMinProtectedX(), 0, island.getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(island.getMaxProtectedX() - 1, 0, island.getMaxProtectedZ() - 1)));
user.sendMessage("commands.admin.info.max-protection-range", RANGE, String.valueOf(island.getMaxEverProtectionRange()));
user.sendMessage("commands.admin.info.protection-coords", XZ1, Util.xyz(new Vector(island.getMinProtectedX(), 0, island.getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(island.getMaxProtectedX() - 1, 0, island.getMaxProtectedZ() - 1)));
if (island.isSpawn()) {
user.sendMessage("commands.admin.info.is-spawn");
}
@ -110,17 +112,17 @@ public class IslandInfo {
user.sendMessage("commands.admin.info.unowned");
} else {
user.sendMessage("commands.admin.info.owner", "[owner]", plugin.getPlayers().getName(owner), TextVariables.UUID, owner.toString());
user.sendMessage("commands.admin.info.deaths", "[number]", String.valueOf(plugin.getPlayers().getDeaths(world, owner)));
user.sendMessage("commands.admin.info.deaths", TextVariables.NUMBER, String.valueOf(plugin.getPlayers().getDeaths(world, owner)));
String resets = String.valueOf(plugin.getPlayers().getResets(world, owner));
String total = plugin.getIWM().getResetLimit(world) < 0 ? "Unlimited" : String.valueOf(plugin.getIWM().getResetLimit(world));
user.sendMessage("commands.admin.info.resets-left", "[number]", resets, "[total]", total);
user.sendMessage("commands.admin.info.resets-left", TextVariables.NUMBER, resets, "[total]", total);
// Show team members
showMembers(user);
}
Vector location = island.getProtectionCenter().toVector();
user.sendMessage("commands.admin.info.island-center", TextVariables.XYZ, Util.xyz(location));
user.sendMessage("commands.admin.info.protection-range", "[range]", String.valueOf(island.getProtectionRange()));
user.sendMessage("commands.admin.info.protection-coords", "[xz1]", Util.xyz(new Vector(island.getMinProtectedX(), 0, island.getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(island.getMaxProtectedX() - 1, 0, island.getMaxProtectedZ() - 1)));
user.sendMessage("commands.admin.info.protection-range", RANGE, String.valueOf(island.getProtectionRange()));
user.sendMessage("commands.admin.info.protection-coords", XZ1, Util.xyz(new Vector(island.getMinProtectedX(), 0, island.getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(island.getMaxProtectedX() - 1, 0, island.getMaxProtectedZ() - 1)));
if (island.isSpawn()) {
user.sendMessage("commands.admin.info.is-spawn");
}

View File

@ -51,6 +51,7 @@ public class SafeSpotTeleport {
private final AtomicBoolean checking = new AtomicBoolean();
private BukkitTask task;
private boolean portal;
private boolean cancelIfFail;
// Locations
private Location bestSpot;
private Iterator<Pair<Integer, Integer>> chunksToScanIterator;
@ -73,6 +74,7 @@ public class SafeSpotTeleport {
this.result = builder.getResult();
this.world = Objects.requireNonNull(location.getWorld());
this.maxHeight = world.getMaxHeight() - 20;
this.cancelIfFail = builder.isCancelIfFail();
// Try to go
Util.getChunkAtAsync(location).thenRun(() -> tryToGo(builder.getFailureMessage()));
}
@ -150,7 +152,7 @@ public class SafeSpotTeleport {
if (!plugin.getIWM().inWorld(entity.getLocation())) {
// Last resort
player.performCommand("spawn");
} else {
} else if (!this.cancelIfFail) {
// Create a spot for the player to be
if (world.getEnvironment().equals(Environment.NETHER)) {
makeAndTeleport(Material.NETHERRACK);
@ -226,7 +228,7 @@ public class SafeSpotTeleport {
// Check the safe spot at the current height
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
if (minY >= startY && checkBlock(chunk, x, startY, z)) {
if (minY <= startY && checkBlock(chunk, x, startY, z)) {
return true;
}
maxY = Math.max(chunk.getHighestBlockYAt(x, z), maxY);
@ -336,6 +338,7 @@ public class SafeSpotTeleport {
private Location location;
private Runnable runnable;
private Runnable failRunnable;
private boolean cancelIfFail;
public Builder(BentoBox plugin) {
this.plugin = plugin;
@ -461,6 +464,20 @@ public class SafeSpotTeleport {
return new SafeSpotTeleport(this);
}
/**
* This method allows stopping "safe" block generation if teleportation fails.
* @param cancelIfFail - value for canceling
* @return Builder
* @since 1.20.1
*/
public Builder cancelIfFail(boolean cancelIfFail)
{
this.cancelIfFail = cancelIfFail;
return this;
}
/**
* The task to run after the player is safely teleported.
*
@ -557,5 +574,13 @@ public class SafeSpotTeleport {
}
/**
* @return the cancelIfFail
* @since 1.20.1
*/
public boolean isCancelIfFail()
{
return this.cancelIfFail;
}
}
}

View File

@ -194,6 +194,10 @@ public class ServerCompatibility {
* @since 1.19.0
*/
V1_18_1(Compatibility.COMPATIBLE),
/**
* @since 1.20.1
*/
V1_18_2(Compatibility.COMPATIBLE),
;
private final Compatibility compatibility;

View File

@ -652,8 +652,9 @@ commands:
kick:
description: "remove a member from your island"
parameters: "<player>"
owner-kicked: "&c The owner kicked you from the island in [gamemode]!"
player-kicked: "&c The [name] kicked you from the island in [gamemode]!"
cannot-kick: "&c You cannot kick yourself!"
cannot-kick-rank: "&c Your rank does not allow to kick [name]!"
success: "&b [name] &a has been kicked from your island."
demote:
description: "demote a player on your island down a rank"

View File

@ -184,6 +184,10 @@ public class IslandTeamKickCommandTest {
RanksManager rm = new RanksManager();
when(plugin.getRanksManager()).thenReturn(rm);
// Ranks
when(island.getRank(uuid)).thenReturn(RanksManager.OWNER_RANK);
when(island.getRank(user)).thenReturn(RanksManager.OWNER_RANK);
when(island.getRank(notUUID)).thenReturn(RanksManager.MEMBER_RANK);
}
@After
@ -206,11 +210,75 @@ public class IslandTeamKickCommandTest {
* Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)}
*/
@Test
public void testExecuteNotTeamOwner() {
when(im.getOwner(any(), any())).thenReturn(notUUID);
public void testExecuteLowerTeamRank() {
when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK);
when(island.getRank(notUUID)).thenReturn(RanksManager.SUB_OWNER_RANK);
when(pm.getUUID(any())).thenReturn(notUUID);
when(pm.getName(notUUID)).thenReturn("poslovitch");
Set<UUID> members = new HashSet<>();
members.add(notUUID);
when(im.getMembers(any(), any())).thenReturn(members);
IslandTeamKickCommand itl = new IslandTeamKickCommand(ic);
assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch")));
verify(user).sendMessage(eq("commands.island.team.kick.cannot-kick-rank"), eq(TextVariables.NAME), eq("poslovitch"));
}
/**
* Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)}
*/
@Test
public void testExecuteEqualTeamRank() {
when(island.getRank(user)).thenReturn(RanksManager.SUB_OWNER_RANK);
when(island.getRank(notUUID)).thenReturn(RanksManager.SUB_OWNER_RANK);
when(pm.getUUID(any())).thenReturn(notUUID);
when(pm.getName(notUUID)).thenReturn("poslovitch");
Set<UUID> members = new HashSet<>();
members.add(notUUID);
when(im.getMembers(any(), any())).thenReturn(members);
IslandTeamKickCommand itl = new IslandTeamKickCommand(ic);
assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch")));
verify(user).sendMessage(eq("commands.island.team.kick.cannot-kick-rank"), eq(TextVariables.NAME), eq("poslovitch"));
}
/**
* Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)}
*/
@Test
public void testExecuteLargerTeamRank() {
when(island.getRank(user)).thenReturn(RanksManager.SUB_OWNER_RANK);
when(island.getRank(notUUID)).thenReturn(RanksManager.MEMBER_RANK);
when(pm.getUUID(any())).thenReturn(notUUID);
when(pm.getName(notUUID)).thenReturn("poslovitch");
Set<UUID> members = new HashSet<>();
members.add(notUUID);
when(im.getMembers(any(), any())).thenReturn(members);
IslandTeamKickCommand itl = new IslandTeamKickCommand(ic);
assertTrue(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch")));
verify(im).removePlayer(any(), eq(notUUID));
verify(user).sendMessage("commands.island.team.kick.success", TextVariables.NAME, "poslovitch");
}
/**
* Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)}
*/
@Test
public void testExecuteNoCommandRank() {
when(island.getRankCommand(anyString())).thenReturn(RanksManager.SUB_OWNER_RANK);
when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK);
IslandTeamKickCommand itl = new IslandTeamKickCommand(ic);
assertFalse(itl.execute(user, itl.getLabel(), Collections.emptyList()));
verify(user).sendMessage(eq("general.errors.not-owner"));
verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member"));
}
/**

View File

@ -21,10 +21,12 @@ import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.PluginManager;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import com.google.common.collect.ImmutableSet;
@ -57,6 +59,7 @@ import world.bentobox.bentobox.util.Util;
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
public abstract class AbstractCommonSetup {
protected UUID uuid = UUID.randomUUID();
@ -136,7 +139,7 @@ public abstract class AbstractCommonSetup {
// Island - nothing is allowed by default
when(island.isAllowed(any())).thenReturn(false);
when(island.isAllowed(any(), any())).thenReturn(false);
when(island.isAllowed(any(User.class), any())).thenReturn(false);
when(island.getOwner()).thenReturn(uuid);
when(island.getMemberSet()).thenReturn(ImmutableSet.of(uuid));

View File

@ -69,6 +69,10 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
position = new Vector(10,10,10);
when(inv.getItemInMainHand()).thenReturn(new ItemStack(Material.NAME_TAG));
// Initialize the Flags class. This is a workaround to prevent weird errors when mocking
// I think it's because the flag class needs to be initialized before use in argument matchers
Flags.TRADING.setDefaultSetting(false);
// Class under test
eil = new EntityInteractListener();
}
@ -91,7 +95,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractAtEntityArmorStandAllowed() {
when(island.isAllowed(any(), any())).thenReturn(true);
when(island.isAllowed(any(User.class), any())).thenReturn(true);
clickedEntity = mock(ArmorStand.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractAtEntityEvent e = new PlayerInteractAtEntityEvent(player, clickedEntity, position, hand);
@ -118,7 +122,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractEntityHorseAllowed() {
when(island.isAllowed(any(), any())).thenReturn(true);
when(island.isAllowed(any(User.class), any())).thenReturn(true);
clickedEntity = mock(Horse.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, clickedEntity, hand);
@ -145,7 +149,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractEntityMinecartAllowed() {
when(island.isAllowed(any(), any())).thenReturn(true);
when(island.isAllowed(any(User.class), any())).thenReturn(true);
clickedEntity = mock(RideableMinecart.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, clickedEntity, hand);
@ -172,7 +176,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractEntityBoatAllowed() {
when(island.isAllowed(any(), any())).thenReturn(true);
when(island.isAllowed(any(User.class), any())).thenReturn(true);
clickedEntity = mock(Boat.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, clickedEntity, hand);
@ -199,7 +203,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractAtEntityVillagerAllowed() {
when(island.isAllowed(any(), any())).thenReturn(true);
when(island.isAllowed(any(User.class), any())).thenReturn(true);
clickedEntity = mock(Villager.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, clickedEntity, hand);
@ -212,9 +216,10 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.EntityInteractListener#onPlayerInteractEntity(org.bukkit.event.player.PlayerInteractAtEntityEvent)}.
*/
@Test
public void testOnPlayerInteractEntityNamingVillagerAllowedNoTrading() {
when(island.isAllowed(any(), eq(Flags.TRADING))).thenReturn(false);
when(island.isAllowed(any(), eq(Flags.NAME_TAG))).thenReturn(true);
when(island.isAllowed(any(User.class), eq(Flags.TRADING))).thenReturn(false);
when(island.isAllowed(any(User.class), eq(Flags.NAME_TAG))).thenReturn(true);
clickedEntity = mock(Villager.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, clickedEntity, hand);
@ -228,8 +233,8 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractEntityNamingVillagerAllowedTradingNoNaming() {
when(island.isAllowed(any(), eq(Flags.TRADING))).thenReturn(true);
when(island.isAllowed(any(), eq(Flags.NAME_TAG))).thenReturn(false);
when(island.isAllowed(any(User.class), eq(Flags.TRADING))).thenReturn(true);
when(island.isAllowed(any(User.class), eq(Flags.NAME_TAG))).thenReturn(false);
clickedEntity = mock(Villager.class);
when(clickedEntity.getLocation()).thenReturn(location);
PlayerInteractEntityEvent e = new PlayerInteractEntityEvent(player, clickedEntity, hand);
@ -257,7 +262,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
*/
@Test
public void testOnPlayerInteractAtEntityWanderingTraderAllowed() {
when(island.isAllowed(any(), any())).thenReturn(true);
when(island.isAllowed(any(User.class), any())).thenReturn(true);
clickedEntity = mock(WanderingTrader.class);
when(clickedEntity.getType()).thenReturn(EntityType.WANDERING_TRADER);
when(clickedEntity.getLocation()).thenReturn(location);
@ -271,9 +276,12 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.EntityInteractListener#onPlayerInteractEntity(org.bukkit.event.player.PlayerInteractAtEntityEvent)}.
*/
@Test
public void testOnPlayerInteractEntityNamingWanderingTraderAllowedNoTrading() {
when(island.isAllowed(any(User.class), eq(Flags.TRADING))).thenReturn(false);
when(island.isAllowed(any(User.class), eq(Flags.NAME_TAG))).thenReturn(true);
when(island.isAllowed(any(),
eq(Flags.TRADING))).thenReturn(false);
when(island.isAllowed(any(User.class),
eq(Flags.NAME_TAG))).thenReturn(true);
clickedEntity = mock(WanderingTrader.class);
when(clickedEntity.getType()).thenReturn(EntityType.WANDERING_TRADER);
when(clickedEntity.getLocation()).thenReturn(location);
@ -287,6 +295,7 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.EntityInteractListener#onPlayerInteractEntity(org.bukkit.event.player.PlayerInteractAtEntityEvent)}.
*/
@Test
public void testOnPlayerInteractEntityNamingWanderingTraderAllowedTradingNoNaming() {
when(island.isAllowed(any(User.class), eq(Flags.TRADING))).thenReturn(true);
when(island.isAllowed(any(User.class), eq(Flags.NAME_TAG))).thenReturn(false);

View File

@ -153,6 +153,11 @@ public class ObsidianScoopingListenerTest {
map.put("OBSIDIAN_SCOOPING", true);
when(ws.getWorldFlags()).thenReturn(map);
PlayerInventory playerInventory = mock(PlayerInventory.class);
when(playerInventory.getItemInMainHand()).thenReturn(item);
when(playerInventory.getItemInOffHand()).thenReturn(new ItemStack(Material.AIR));
when(p.getInventory()).thenReturn(playerInventory);
// Addon
when(iwm.getAddon(Mockito.any())).thenReturn(Optional.empty());
}

View File

@ -169,6 +169,7 @@ public class PlayersManagerTest {
when(user.getPlayer()).thenReturn(p);
when(user.getName()).thenReturn("tastybento");
when(user.isOnline()).thenReturn(true);
when(user.isPlayer()).thenReturn(true);
User.setPlugin(plugin);