Merge pull request #2564 from BentoBoxWorld/develop

Release 3.0.1
This commit is contained in:
tastybento 2024-11-25 19:04:16 -08:00 committed by GitHub
commit 2dd736ad47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
66 changed files with 1493 additions and 620 deletions

10
pom.xml
View File

@ -50,13 +50,9 @@
</issueManagement>
<distributionManagement>
<snapshotRepository>
<id>codemc-snapshots</id>
<url>https://repo.codemc.org/repository/maven-snapshots</url>
</snapshotRepository>
<repository>
<id>codemc-releases</id>
<url>https://repo.codemc.org/repository/maven-releases</url>
<id>bentoboxworld</id>
<url>https://repo.codemc.org/repository/bentoboxworld/</url>
</repository>
</distributionManagement>
@ -88,7 +84,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>2.7.0</build.version>
<build.version>3.0.1</build.version>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<server.jars>${project.basedir}/lib</server.jars>

View File

@ -1,5 +1,7 @@
package world.bentobox.bentobox;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
@ -464,6 +466,32 @@ public class BentoBox extends JavaPlugin implements Listener {
getPluginLoader().disablePlugin(this);
return false;
}
log("Saving default panels...");
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "island_creation_panel.yml"))) {
log("Saving default island_creation_panel...");
this.saveResource("panels/island_creation_panel.yml", false);
}
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "language_panel.yml"))) {
log("Saving default language_panel...");
this.saveResource("panels/language_panel.yml", false);
}
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "island_homes_panel.yml"))) {
log("Saving default island_homes_panel...");
this.saveResource("panels/island_homes_panel.yml", false);
}
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "team_invite_panel.yml"))) {
log("Saving default team_invite_panel...");
this.saveResource("panels/team_invite_panel.yml", false);
}
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "team_panel.yml"))) {
log("Saving default team_panel...");
this.saveResource("panels/team_panel.yml", false);
}
return true;
}

View File

@ -15,6 +15,7 @@ import world.bentobox.bentobox.api.commands.ConfirmableCommand;
import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.RanksManager;
@ -115,10 +116,10 @@ public class AdminUnregisterCommand extends ConfirmableCommand {
// Remove all island players that reference this island
targetIsland.getMembers().clear();
if (user.isPlayer()) {
targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString())
targetIsland.log(new LogEntry.Builder(LogType.UNREGISTER).data("player", targetUUID.toString())
.data("admin", user.getUniqueId().toString()).build());
} else {
targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString())
targetIsland.log(new LogEntry.Builder(LogType.UNREGISTER).data("player", targetUUID.toString())
.data("admin", "console").build());
}
user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(targetIsland.getCenter().toVector()),

View File

@ -13,7 +13,6 @@ import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.IslandInfo;
import world.bentobox.bentobox.util.Util;
/**
@ -59,35 +58,28 @@ public class AdminTeamKickCommand extends CompositeCommand {
@Override
public boolean execute(User user, String label, @NonNull List<String> args) {
Island island = getIslands().getIsland(getWorld(), targetUUID);
if (island == null) {
List<Island> islands = getIslands().getIslands(getWorld(), targetUUID);
if (islands.isEmpty()) {
return false;
}
if (targetUUID.equals(island.getOwner())) {
user.sendMessage("commands.admin.team.kick.cannot-kick-owner");
new IslandInfo(island).showMembers(user);
return false;
}
User target = User.getInstance(targetUUID);
target.sendMessage("commands.admin.team.kick.admin-kicked");
islands.forEach(island -> {
if (!user.getUniqueId().equals(island.getOwner())) {
User target = User.getInstance(targetUUID);
target.sendMessage("commands.admin.team.kick.admin-kicked");
getIslands().removePlayer(island, targetUUID);
user.sendMessage("commands.admin.team.kick.success", TextVariables.NAME, target.getName(), "[owner]", getPlayers().getName(island.getOwner()));
getIslands().removePlayer(island, targetUUID);
user.sendMessage("commands.admin.team.kick.success", TextVariables.NAME, target.getName(), "[owner]",
getPlayers().getName(island.getOwner()));
// Fire event so add-ons know
TeamEvent.builder().island(island).reason(TeamEvent.Reason.KICK).involvedPlayer(targetUUID).admin(true)
.build();
IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(true)
.reason(IslandEvent.Reason.RANK_CHANGE)
.rankChange(island.getRank(target), RanksManager.VISITOR_RANK).build();
}
});
user.sendMessage("commands.admin.team.kick.success-all");
// Fire event so add-ons know
TeamEvent.builder()
.island(island)
.reason(TeamEvent.Reason.KICK)
.involvedPlayer(targetUUID)
.admin(true)
.build();
IslandEvent.builder()
.island(island)
.involvedPlayer(targetUUID)
.admin(true)
.reason(IslandEvent.Reason.RANK_CHANGE)
.rankChange(island.getRank(target), RanksManager.VISITOR_RANK)
.build();
return true;
}
}

View File

@ -54,7 +54,8 @@ public class IslandSethomeCommand extends ConfirmableCommand {
// Check number of homes
int maxHomes = getIslands().getMaxHomes(island);
if (getIslands().getNumberOfHomesIfAdded(island, String.join(" ", args)) > maxHomes) {
// The + 1 is for the default home
if (getIslands().getNumberOfHomesIfAdded(island, String.join(" ", args)) > maxHomes + 1) {
user.sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, String.valueOf(maxHomes));
user.sendMessage("commands.island.sethome.homes-are");
getIslands().getIslands(getWorld(), user).forEach(is ->

View File

@ -9,6 +9,8 @@ import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.events.team.TeamEvent;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.TeamInvite;
@ -120,6 +122,9 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
user.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, inviter.getName(),
TextVariables.DISPLAY_NAME, inviter.getDisplayName());
}
// Add historu record
island.log(new LogEntry.Builder(LogType.TRUSTED).data(user.getUniqueId().toString(), "trusted")
.data(invite.getInviter().toString(), "trusted by").build());
}
}

View File

@ -12,6 +12,8 @@ import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.events.team.TeamEvent;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.RanksManager;
@ -91,6 +93,9 @@ public class IslandTeamSetownerCommand extends CompositeCommand {
IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false)
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK)
.build();
// Add historu record
island.log(new LogEntry.Builder(LogType.NEWOWNER).data(targetUUID2.toString(), "new owner")
.data(user.getUniqueId().toString(), "old owner").build());
return true;
}

View File

@ -9,6 +9,8 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
@ -110,6 +112,10 @@ public class IslandTeamTrustCommand extends CompositeCommand {
island.setRank(target, RanksManager.TRUSTED_RANK);
user.sendMessage("commands.island.team.trust.success", TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName());
target.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
// Add historu record
island.log(new LogEntry.Builder(LogType.TRUSTED).data(targetUUID.toString(), "trusted")
.data(user.getUniqueId().toString(), "trusted by").build());
}
return true;
} else {

View File

@ -6,7 +6,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
@ -64,9 +63,9 @@ public class Config<T> {
return handler.loadObject(uniqueId);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| ClassNotFoundException | IntrospectionException | NoSuchMethodException | SecurityException e) {
logger.severe(() -> "Could not load config object! " + e.getMessage());
BentoBox.getInstance().logError("Could not load config object! " + e.getMessage());
// Required for debugging
logger.severe(ExceptionUtils.getStackTrace(e));
e.printStackTrace();
}
return null;

View File

@ -1,7 +1,6 @@
package world.bentobox.bentobox.api.logs;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
@ -15,20 +14,102 @@ import com.google.gson.annotations.Expose;
* An {@link world.bentobox.bentobox.database.objects.adapters.AdapterInterface AdapterInterface} is provided to be able to save/retrieve
* a list of instances of this object to/from the database: {@link world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter LogEntryListAdapter}.
*
* @author Poslovitch
* @author Poslovitch, tastybento
*
*/
public class LogEntry {
@Expose
private final long timestamp;
@Expose
private final String type;
private final LogType type;
@Expose
private final String customType;
@Expose
private final Map<String, String> data;
/**
* This is a log enum. If you are a developer and need more make a PR. Or use the string one.
*/
public enum LogType {
/**
* Something removed
*/
REMOVE,
/**
* Something added
*/
ADD,
/**
* Island unregistered
*/
UNREGISTER,
/**
* Player banned
*/
BAN,
/**
* Something was completed
*/
COMPELTE,
/**
* Island became unowned
*/
UNOWNED,
/**
* Island became spawn
*/
SPAWN,
/**
* Player unbanned
*/
UNBAN,
/**
* Player joined
*/
JOINED,
/**
* New owner made
*/
NEWOWNER,
/**
* Player trusted
*/
TRUSTED,
/**
* Player cooped
*/
COOP,
/**
* Unknown reason
*/
UNKNOWN,
/**
* Island reset or a reset of some kind
*/
RESET,
/**
* Everything was reset
*/
RESET_ALL,
/**
* New thing
*/
NEW,
/**
* Something duplicated
*/
DUPLICATE,
/**
* General info
*/
INFO,
}
private LogEntry(@NonNull Builder builder) {
this.timestamp = builder.timestamp;
this.type = builder.type;
this.data = builder.data;
this.customType = builder.customType;
}
public long getTimestamp() {
@ -36,7 +117,7 @@ public class LogEntry {
}
@NonNull
public String getType() {
public LogType getType() {
return type;
}
@ -47,13 +128,25 @@ public class LogEntry {
public static class Builder {
private long timestamp;
private final String type;
private final LogType type;
private Map<String, String> data;
private final String customType;
public Builder(@NonNull String type) {
public Builder(LogType type) {
this.timestamp = System.currentTimeMillis();
this.type = type.toUpperCase(Locale.ENGLISH);
this.type = type;
this.data = new LinkedHashMap<>();
this.customType = null;
}
/**
* @param customType log type
*/
public Builder(String customType) {
this.timestamp = System.currentTimeMillis();
this.type = LogType.UNKNOWN;
this.data = new LinkedHashMap<>();
this.customType = customType;
}
public Builder timestamp(long timestamp) {

View File

@ -8,10 +8,10 @@ package world.bentobox.bentobox.database.json.adapters;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Registry;
import org.bukkit.block.Biome;
import com.google.gson.TypeAdapter;
@ -32,11 +32,12 @@ public final class BiomeTypeAdapter extends TypeAdapter<Biome>
*/
final Map<String, Biome> biomeMap;
@SuppressWarnings("deprecation")
public BiomeTypeAdapter() {
this.biomeMap = new HashMap<>();
// Put in current values.
Arrays.stream(Biome.values()).forEach(biome -> this.biomeMap.put(biome.name(), biome));
Registry.BIOME.forEach(biome -> this.biomeMap.put(biome.name(), biome));
// Put in renamed biomes values.
this.biomeMap.put("TALL_BIRCH_FOREST", Biome.OLD_GROWTH_BIRCH_FOREST);

View File

@ -37,6 +37,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.metadata.MetaDataAble;
import world.bentobox.bentobox.api.metadata.MetaDataValue;
import world.bentobox.bentobox.api.user.User;
@ -327,7 +328,7 @@ public class Island implements DataObject, MetaDataAble {
public boolean ban(@NonNull UUID issuer, @NonNull UUID target) {
if (getRank(target) != RanksManager.BANNED_RANK) {
setRank(target, RanksManager.BANNED_RANK);
log(new LogEntry.Builder("BAN").data("player", target.toString()).data("issuer", issuer.toString())
log(new LogEntry.Builder(LogType.BAN).data("player", target.toString()).data("issuer", issuer.toString())
.build());
setChanged();
}
@ -360,7 +361,7 @@ public class Island implements DataObject, MetaDataAble {
*/
public boolean unban(@NonNull UUID issuer, @NonNull UUID target) {
if (members.remove(target) != null) {
log(new LogEntry.Builder("UNBAN").data("player", target.toString()).data("issuer", issuer.toString())
log(new LogEntry.Builder(LogType.UNBAN).data("player", target.toString()).data("issuer", issuer.toString())
.build());
return true;
}
@ -1132,7 +1133,7 @@ public class Island implements DataObject, MetaDataAble {
this.owner = owner;
if (owner == null) {
log(new LogEntry.Builder("UNOWNED").build());
log(new LogEntry.Builder(LogType.UNOWNED).build());
return;
}
// Defensive code: demote any previous owner
@ -1281,7 +1282,7 @@ public class Island implements DataObject, MetaDataAble {
setFlagsDefaults();
setFlag(Flags.LOCK, RanksManager.VISITOR_RANK);
}
log(new LogEntry.Builder("SPAWN").data("value", String.valueOf(isSpawn)).build());
log(new LogEntry.Builder(LogType.SPAWN).data("value", String.valueOf(isSpawn)).build());
setChanged();
}

View File

@ -10,17 +10,17 @@ package world.bentobox.bentobox.database.objects.adapters;
*/
public interface AdapterInterface<S,V> {
/**
* Serialize object
* @param object - object to serialize
* @return serialized object
*/
S deserialize(Object object);
/**
* Deserialize object
* @param object - object to deserialize
* @return deserialized object
*/
S deserialize(Object object);
/**
* Serialize object
* @param object - object to serialize
* @return serialized object
*/
V serialize(Object object);
}

View File

@ -5,7 +5,10 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.google.common.base.Enums;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
/**
* @author Poslovitch
@ -41,7 +44,7 @@ public class LogEntryListAdapter implements AdapterInterface<List<LogEntry>, Lis
List<Map<String, Object>> serialized = (List<Map<String, Object>>) object;
for (Map<String, Object> entry : serialized) {
long timestamp = (long) entry.get(TIMESTAMP);
String type = (String) entry.get(TYPE);
LogType type = Enums.getIfPresent(LogType.class, (String) entry.get(TYPE)).or(LogType.UNKNOWN);
Map<String, String> data = (Map<String, String>) entry.get(DATA);
result.add(new LogEntry.Builder(type).timestamp(timestamp).data(data).build());
@ -62,7 +65,7 @@ public class LogEntryListAdapter implements AdapterInterface<List<LogEntry>, Lis
history.forEach(logEntry -> {
Map<String, Object> value = new LinkedHashMap<>();
value.put(TIMESTAMP, logEntry.getTimestamp());
value.put(TYPE, logEntry.getType());
value.put(TYPE, logEntry.getType().name());
if (logEntry.getData() != null) {
value.put(DATA, logEntry.getData());

View File

@ -26,8 +26,13 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.configuration.MemorySection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.EntityType;
@ -220,6 +225,14 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
double d = (double) setTo;
float f = (float)d;
method.invoke(instance, f);
} else if (setType.getTypeName().equals("org.bukkit.Sound")) {
Sound s = Registry.SOUNDS
.get(NamespacedKey.fromString(((String) setTo).toLowerCase(Locale.ENGLISH)));
method.invoke(instance, s);
} else if (setType.getTypeName().equals("org.bukkit.block.Biome")) {
Biome b = Registry.BIOME
.get(NamespacedKey.fromString(((String) setTo).toLowerCase(Locale.ENGLISH)));
method.invoke(instance, b);
} else {
method.invoke(instance, setTo);
}
@ -369,7 +382,6 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
Method method = propertyDescriptor.getReadMethod();
// Invoke the read method to get the value. We have no idea what type of value it is.
Object value = method.invoke(instance);
String storageLocation = field.getName();
// Check if there is an annotation on the field
@ -575,6 +587,10 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
if (object instanceof Location l) {
return Util.getStringLocation(l);
}
// Keyed interfaces that are replacing enums
if (object instanceof Keyed k) {
return k.getKey().getKey();
}
// Enums
if (object instanceof Enum<?> e) {
//Custom enums are a child of the Enum class. Just get the names of each one.

View File

@ -1,7 +1,10 @@
package world.bentobox.bentobox.listeners.flags.protection;
import org.bukkit.entity.Egg;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.player.PlayerEggThrowEvent;
import world.bentobox.bentobox.api.flags.FlagListener;
@ -24,4 +27,19 @@ public class EggListener extends FlagListener {
e.setHatching(false);
}
}
/**
* Handle visitor chicken egg hitting
* @param e - event
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onEggHit(ProjectileHitEvent e) {
if (e.getEntity() instanceof Egg egg) {
if (egg.getShooter() instanceof Player player) {
if (!checkIsland(e, player, egg.getLocation(), Flags.EGGS)) {
e.setCancelled(true);
}
}
}
}
}

View File

@ -114,13 +114,14 @@ public class HurtingListener extends FlagListener {
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerFeedParrots(PlayerInteractEntityEvent e) {
if (e.getRightClicked() instanceof Parrot
&& (e.getHand().equals(EquipmentSlot.HAND) && e.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.COOKIE))
|| (e.getHand().equals(EquipmentSlot.OFF_HAND) && e.getPlayer().getInventory().getItemInOffHand().getType().equals(Material.COOKIE))) {
if (((Parrot) e.getRightClicked()).isTamed()) {
checkIsland(e, e.getPlayer(), e.getRightClicked().getLocation(), Flags.HURT_TAMED_ANIMALS);
} else {
checkIsland(e, e.getPlayer(), e.getRightClicked().getLocation(), Flags.HURT_ANIMALS);
if (e.getRightClicked() instanceof Parrot parrot) {
if ((e.getHand().equals(EquipmentSlot.HAND) && e.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.COOKIE))
|| (e.getHand().equals(EquipmentSlot.OFF_HAND) && e.getPlayer().getInventory().getItemInOffHand().getType().equals(Material.COOKIE))) {
if (parrot.isTamed()) {
checkIsland(e, e.getPlayer(), e.getRightClicked().getLocation(), Flags.HURT_TAMED_ANIMALS);
} else {
checkIsland(e, e.getPlayer(), e.getRightClicked().getLocation(), Flags.HURT_ANIMALS);
}
}
}
}

View File

@ -389,4 +389,25 @@ public abstract class AbstractTeleportListener
* Set of entities that currently is in teleportation.
*/
protected final Set<UUID> inTeleport;
/**
* @return the inTeleport
*/
public Set<UUID> getInTeleport() {
return inTeleport;
}
/**
* @return the inPortal
*/
public Set<UUID> getInPortal() {
return inPortal;
}
/**
* @return the teleportOrigin
*/
public Map<UUID, World> getTeleportOrigin() {
return teleportOrigin;
}
}

View File

@ -59,30 +59,6 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
// Section: Listeners
// ---------------------------------------------------------------------
/**
* This listener checks player portal events and triggers appropriate methods to transfer
* players to the correct location in other dimension.
* <p>
* This event is triggered when player is about to being teleported because of contact with the
* nether portal or end gateway portal (exit portal triggers respawn).
* <p>
* This event is not called if nether/end is disabled in server settings.
*
* @param event the player portal event.
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerPortalEvent(PlayerPortalEvent event)
{
switch (event.getCause())
{
case NETHER_PORTAL -> this.portalProcess(event, World.Environment.NETHER);
case END_PORTAL, END_GATEWAY -> this.portalProcess(event, World.Environment.THE_END);
default -> throw new IllegalArgumentException("Unexpected value: " + event.getCause());
}
}
/**
* Fires the event if nether or end is disabled at the system level
*
@ -96,7 +72,6 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
// This handles only players.
return;
}
Entity entity = event.getEntity();
Material type = event.getLocation().getBlock().getType();
UUID uuid = entity.getUniqueId();
@ -106,7 +81,6 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
{
return;
}
this.inPortal.add(uuid);
// Add original world for respawning.
this.teleportOrigin.put(uuid, event.getLocation().getWorld());
@ -133,7 +107,6 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
}, 40);
return;
}
// End portals are instant transfer
if (!Bukkit.getAllowEnd() && (type.equals(Material.END_PORTAL) || type.equals(Material.END_GATEWAY)))
{
@ -226,6 +199,31 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
});
}
/**
* This listener checks player portal events and triggers appropriate methods to transfer
* players to the correct location in other dimension.
* <p>
* This event is triggered when player is about to being teleported because of contact with the
* nether portal or end gateway portal (exit portal triggers respawn).
* <p>
* This event is not called if nether/end is disabled in server settings.
*
* @param event the player portal event.
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerPortalEvent(PlayerPortalEvent event) {
switch (event.getCause()) {
case NETHER_PORTAL -> this.portalProcess(event, World.Environment.NETHER);
case END_PORTAL, END_GATEWAY -> this.portalProcess(event, World.Environment.THE_END);
default -> { // Do nothing, ignore
}
/*
* Other potential reasons: CHORUS_FRUIT , COMMAND, DISMOUNT,
* ENDER_PEARL, EXIT_BED, PLUGIN, SPECTATE , UNKNOWN
*/
}
}
// ---------------------------------------------------------------------
@ -248,26 +246,22 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
// Not teleporting from/to bentobox worlds.
return;
}
if (!this.isAllowedInConfig(overWorld, environment))
{
// World is disabled in config. Do not teleport player.
event.setCancelled(true);
return;
}
if (!this.isAllowedOnServer(environment))
{
// World is disabled in bukkit. Event is not triggered, but cancel by chance.
event.setCancelled(true);
}
if (this.inTeleport.contains(event.getPlayer().getUniqueId()))
{
// Player is already in teleportation.
return;
}
this.inTeleport.add(event.getPlayer().getUniqueId());
if (fromWorld.equals(overWorld) && !this.isIslandWorld(overWorld, environment))
@ -276,7 +270,6 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
this.handleToStandardNetherOrEnd(event, overWorld, environment);
return;
}
if (!fromWorld.equals(overWorld) && !this.isIslandWorld(overWorld, environment))
{
// If entering a portal in the other world, teleport to a portal in overworld if
@ -284,7 +277,6 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
this.handleFromStandardNetherOrEnd(event, overWorld, environment);
return;
}
// To the nether/end or overworld.
World toWorld = !fromWorld.getEnvironment().equals(environment) ?
this.getNetherEndWorld(overWorld, environment) : overWorld;
@ -320,13 +312,11 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
// If there is no island, then processor already created island. Nothing to do more.
return;
}
if (!event.isCancelled() && event.getCanCreatePortal())
{
// Let the server teleport
return;
}
if (World.Environment.THE_END.equals(environment))
{
// Prevent death from hitting the ground while calculating location.
@ -366,7 +356,7 @@ public class PlayerTeleportListener extends AbstractTeleportListener implements
* @param overWorld - over world
* @param environment - environment involved
*/
private void handleToStandardNetherOrEnd(PlayerPortalEvent event,
void handleToStandardNetherOrEnd(PlayerPortalEvent event,
World overWorld,
World.Environment environment)
{

View File

@ -3,7 +3,10 @@ package world.bentobox.bentobox.lists;
import java.text.DateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
@ -11,6 +14,8 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.placeholders.GameModePlaceholderReplacer;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
@ -120,6 +125,14 @@ public enum GameModePlaceholder {
* @since 1.5.0
*/
ISLAND_MEMBERS_COUNT("island_members_count", (addon, user, island) -> island == null ? "" : String.valueOf(island.getMemberSet().size())),
/**
* Returns the number of players that are or have ever been a MEMBER on this island.
* @since 3.0.0
*/
ISLAND_HISTORICAL_MEMBERS_COUNT("island_historical_members_count",
(addon, user, island) -> island == null ? "" : getHistoricalMembers(island)),
/**
* Returns a comma separated list of player names that are at least MEMBER on this island.
* @since 1.13.0
@ -395,6 +408,24 @@ public enum GameModePlaceholder {
this.replacer = replacer;
}
/**
* Provides a count of how many players have ever joined the island as a member including the owner
* @param island island
* @return String count of the number of members
*/
private static String getHistoricalMembers(@Nullable Island island) {
Set<String> uniqueMembers = new HashSet<>();
for (LogEntry le : island.getHistory()) {
if (le.getType() == LogType.JOINED) {
Iterator<String> it = le.getData().keySet().iterator();
while (it.hasNext()) {
uniqueMembers.add(it.next());
}
}
}
return String.valueOf(uniqueMembers.size());
}
/**
* Get the visited island
* @param addon - game mode addon

View File

@ -47,6 +47,8 @@ import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.json.BentoboxTypeAdapterFactory;
@ -938,6 +940,7 @@ public class IslandsManager {
*/
@NonNull
public Map<String, Location> getHomeLocations(@NonNull Island island) {
island.getHomes().forEach((n, l) -> BentoBox.getInstance().logDebug(n));
return island.getHomes();
}
@ -954,6 +957,7 @@ public class IslandsManager {
/**
* Get the number of homes on this island if this home were added
* This includes the default home, which has no name
*
* @param island - island
* @param name - name
@ -1189,6 +1193,7 @@ public class IslandsManager {
*
* @param player player
*/
@SuppressWarnings("deprecation")
private void readyPlayer(@NonNull Player player) {
// Stop any gliding
player.setGliding(false);
@ -1537,6 +1542,8 @@ public class IslandsManager {
// Add player to new island
teamIsland.addMember(playerUUID);
islandCache.addPlayer(playerUUID, teamIsland);
// Add historu record
teamIsland.log(new LogEntry.Builder(LogType.JOINED).data(playerUUID.toString(), "player").build());
// Save the island
updateIsland(teamIsland);
}

View File

@ -23,6 +23,8 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.RanksManager;
@ -431,6 +433,8 @@ public class IslandCache {
}
island.removeMember(uuid);
island.removePrimary(uuid);
// Add historu record
island.log(new LogEntry.Builder(LogType.REMOVE).data(uuid.toString(), "player").build());
}
/**

View File

@ -15,6 +15,8 @@ import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.api.events.island.IslandCreateEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
import world.bentobox.bentobox.api.events.island.IslandResetEvent;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
@ -217,6 +219,8 @@ public class NewIsland {
island.setFlagsDefaults();
// Register metrics
plugin.getMetrics().ifPresent(BStats::increaseIslandsCreatedCount);
// Add historu record
island.log(new LogEntry.Builder(LogType.JOINED).data(user.getUniqueId().toString(), "owner").build());
// Save island
IslandsManager.updateIsland(island);
}

View File

@ -150,8 +150,9 @@ public class IslandInfo {
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)));
Util.xyz(new Vector(island.getMinProtectedX(), world.getMinHeight(), island.getMinProtectedZ())),
"[xz2]", Util.xyz(new Vector(island.getMaxProtectedX() - 1, world.getMaxHeight(),
island.getMaxProtectedZ() - 1)));
if (island.isSpawn()) {
user.sendMessage("commands.admin.info.is-spawn");
}

View File

@ -712,7 +712,7 @@ public class Util {
* @param player - player
*/
public static void resetHealth(Player player) {
double maxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue();
double maxHealth = player.getAttribute(Attribute.MAX_HEALTH).getBaseValue();
player.setHealth(maxHealth);
}
@ -743,7 +743,6 @@ public class Util {
throw new IllegalStateException("Class " + clazz.getName() + " does not implement WorldRegenerator");
}
} catch (Exception e) {
e.printStackTrace();
plugin.logWarning("No Regenerator found for " + bukkitVersion + ", falling back to Bukkit API.");
handler = new world.bentobox.bentobox.nms.fallback.WorldRegeneratorImpl();
}
@ -773,7 +772,6 @@ public class Util {
throw new IllegalStateException("Class " + clazz.getName() + " does not implement PasteHandler");
}
} catch (Exception e) {
e.printStackTrace();
plugin.logWarning("No PasteHandler found for " + bukkitVersion + ", falling back to Bukkit API.");
handler = new world.bentobox.bentobox.nms.fallback.PasteHandlerImpl();
}

File diff suppressed because it is too large Load Diff

View File

@ -159,6 +159,7 @@ commands:
not-in-team: '&c This player is not in a team.'
admin-kicked: '&c The admin kicked you from the team.'
success: '&b [name] &a has been kicked from &b [owner]&a ''s island.'
success-all: '&b Player removed from all teams in this world'
setowner:
parameters: <player>
description: transfers island ownership to the player

View File

@ -1,7 +1,7 @@
name: BentoBox
main: world.bentobox.bentobox.BentoBox
version: ${project.version}${build.number}
api-version: "1.20"
api-version: "1.21"
authors: [tastybento, Poslovitch]
contributors: ["The BentoBoxWorld Community"]

View File

@ -17,10 +17,12 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Player.Spigot;
import org.bukkit.event.entity.EntityExplodeEvent;
@ -34,6 +36,7 @@ import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@ -58,6 +61,7 @@ import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.managers.PlaceholdersManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
/**
@ -103,9 +107,13 @@ public abstract class AbstractCommonSetup {
protected FlagsManager fm;
@Mock
protected Spigot spigot;
protected Server server;
@Before
public void setUp() throws Exception {
server = ServerMocks.newServer();
// Bukkit
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
// Set up plugin
@ -136,6 +144,7 @@ public abstract class AbstractCommonSetup {
when(mockPlayer.getName()).thenReturn("tastybento");
when(mockPlayer.getInventory()).thenReturn(inv);
when(mockPlayer.spigot()).thenReturn(spigot);
when(mockPlayer.getType()).thenReturn(EntityType.PLAYER);
User.setPlugin(plugin);
User.clearUsers();
@ -221,6 +230,7 @@ public abstract class AbstractCommonSetup {
*/
@After
public void tearDown() throws Exception {
ServerMocks.unsetBukkitServer();
User.clearUsers();
Mockito.framework().clearInlineMocks();
}
@ -233,42 +243,6 @@ public abstract class AbstractCommonSetup {
checkSpigotMessage(expectedMessage, 1);
}
/*
public void checkSpigotMessage(String expectedMessage, boolean shouldBePresent) {
// Capture the argument passed to spigot().sendMessage(...) if messages are sent
ArgumentCaptor<TextComponent> captor = ArgumentCaptor.forClass(TextComponent.class);
if (shouldBePresent) {
// If we expect a message to be present, verify that sendMessage() was called at least once
verify(spigot, atLeastOnce()).sendMessage(captor.capture());
// Get all captured TextComponents
List<TextComponent> capturedMessages = captor.getAllValues();
// Check if any captured message contains the expected text
boolean messageFound = capturedMessages.stream()
.map(component -> component.toPlainText()) // Convert each TextComponent to plain text
.anyMatch(messageText -> messageText.contains(expectedMessage)); // Check if the expected message is present
// Assert that the message was found
assertTrue("Expected message not found: " + expectedMessage, messageFound);
} else {
// If we expect no messages with this text, capture any sent messages to ensure none match the given message
verify(spigot, atLeast(0)).sendMessage(captor.capture());
// Get all captured TextComponents
List<TextComponent> capturedMessages = captor.getAllValues();
// Check that none of the captured messages contain the forbidden text
boolean messageFound = capturedMessages.stream().map(component -> component.toPlainText()) // Convert each TextComponent to plain text
.anyMatch(messageText -> messageText.contains(expectedMessage)); // Check if the message is present
// Assert that the message was NOT found
assertFalse("Unexpected message found: " + expectedMessage, messageFound);
}
}*/
public void checkSpigotMessage(String expectedMessage, int expectedOccurrences) {
// Capture the argument passed to spigot().sendMessage(...) if messages are sent
ArgumentCaptor<TextComponent> captor = ArgumentCaptor.forClass(TextComponent.class);

View File

@ -29,7 +29,6 @@ import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.managers.RanksManager;
@ -126,9 +125,8 @@ public abstract class RanksManagerBeforeClassTest extends AbstractCommonSetup {
}
@After
public void tearDown() throws IOException {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
deleteAll(new File("database"));
deleteAll(new File("database_backup"));
}

View File

@ -26,7 +26,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@ -128,12 +127,9 @@ public class AdminResetFlagsCommandTest extends AbstractCommonSetup {
}
/**
*/
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -24,6 +24,7 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -42,6 +43,7 @@ import world.bentobox.bentobox.managers.BlueprintsManager;
import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.HooksManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.mocks.ServerMocks;
/**
* @author tastybento
@ -67,8 +69,11 @@ public class AdminBlueprintLoadCommandTest {
private Map<String, Blueprint> map;
private File blueprintsFolder;
/**
*/
@BeforeClass
public static void beforeClass() {
ServerMocks.newServer();
}
@Before
public void setUp() throws Exception {
// Set up plugin
@ -124,8 +129,6 @@ public class AdminBlueprintLoadCommandTest {
abcc = new AdminBlueprintLoadCommand(ac);
}
/**
*/
@After
public void tearDown() throws Exception {
User.clearUsers();

View File

@ -25,6 +25,7 @@ import org.bukkit.Bukkit;
import org.bukkit.util.Vector;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -44,6 +45,7 @@ import world.bentobox.bentobox.managers.BlueprintsManager;
import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.HooksManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.mocks.ServerMocks;
/**
* @author tastybento
@ -67,8 +69,11 @@ public class AdminBlueprintSaveCommandTest {
private BlueprintsManager bm;
private Blueprint bp = new Blueprint();
/**
*/
@BeforeClass
public static void beforeClass() {
ServerMocks.newServer();
}
@Before
public void setUp() throws Exception {
// Set up plugin

View File

@ -94,9 +94,8 @@ public class AdminRangeCommandTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
@Test

View File

@ -117,9 +117,8 @@ public class AdminRangeResetCommandTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -119,9 +119,8 @@ public class AdminRangeSetCommandTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -5,7 +5,6 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.framework;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@ -152,9 +151,8 @@ public class AdminTeamDisbandCommandTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -68,6 +68,10 @@ public class AdminTeamKickCommandTest {
private World world;
@Mock
private PluginManager pim;
@Mock
private Island island;
@Mock
private Island island2;
/**
*/
@ -106,9 +110,14 @@ public class AdminTeamKickCommandTest {
IslandWorldManager iwm = mock(IslandWorldManager.class);
when(plugin.getIWM()).thenReturn(iwm);
// Island
when(island.getOwner()).thenReturn(uuid);
when(island2.getOwner()).thenReturn(notUUID);
// Player has island to begin with
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
when(im.hasIsland(any(), any(User.class))).thenReturn(true);
when(im.getIslands(world, uuid)).thenReturn(List.of(island, island2));
// when(im.isOwner(any(),any())).thenReturn(true);
// when(im.getOwner(any(),any())).thenReturn(uuid);
when(plugin.getIslands()).thenReturn(im);
@ -172,46 +181,21 @@ public class AdminTeamKickCommandTest {
verify(user).sendMessage(eq("commands.admin.team.kick.not-in-team"));
}
/**
* Test method for {@link AdminTeamKickCommand#execute(User, String, List)} .
*/
@Test
public void testExecuteKickOwner() {
when(im.inTeam(any(), any())).thenReturn(true);
Island is = mock(Island.class);
when(im.getIsland(any(), any(UUID.class))).thenReturn(is);
when(pm.getUUID(any())).thenReturn(notUUID);
when(is.getOwner()).thenReturn(notUUID);
AdminTeamKickCommand itl = new AdminTeamKickCommand(ac);
assertTrue(itl.canExecute(user, itl.getLabel(), Collections.singletonList("tastybento")));
assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("tastybento")));
verify(user).sendMessage(eq("commands.admin.team.kick.cannot-kick-owner"));
verify(user).sendMessage("commands.admin.info.team-members-title");
verify(im, never()).removePlayer(eq(world), eq(notUUID));
verify(user, never()).sendMessage(eq("commands.admin.team.kick.success"), anyString(), anyString(), anyString(), anyString());
verify(pim, never()).callEvent(any());
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.team.AdminTeamKickCommand#execute(User, String, List)}.
*/
@Test
public void testExecute() {
when(im.inTeam(any(), any())).thenReturn(true);
Island is = mock(Island.class);
when(im.getIsland(any(), any(UUID.class))).thenReturn(is);
String name = "tastybento";
when(pm.getUUID(any())).thenReturn(notUUID);
when(pm.getUUID(any())).thenReturn(uuid);
when(pm.getName(any())).thenReturn(name);
when(is.getOwner()).thenReturn(uuid);
AdminTeamKickCommand itl = new AdminTeamKickCommand(ac);
assertTrue(itl.canExecute(user, itl.getLabel(), Collections.singletonList(name)));
assertTrue(itl.execute(user, itl.getLabel(), Collections.singletonList(name)));
verify(im).removePlayer(is, notUUID);
verify(im, never()).removePlayer(island, uuid);
verify(im).removePlayer(island2, uuid);
verify(user).sendMessage(eq("commands.admin.team.kick.success"), eq(TextVariables.NAME), eq(name), eq("[owner]"), anyString());
// Offline so event will be called 4 times
verify(pim, times(4)).callEvent(any());

View File

@ -21,11 +21,11 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitScheduler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -74,12 +74,11 @@ public class IslandExpelCommandTest extends RanksManagerBeforeClassTest {
private Addon addon;
private IslandExpelCommand iec;
@Mock
private Server server;
@Before
public void setUp() throws Exception {
super.setUp();
User.setPlugin(plugin);
// Command manager
@ -96,7 +95,6 @@ public class IslandExpelCommandTest extends RanksManagerBeforeClassTest {
when(user.isOp()).thenReturn(false);
uuid = UUID.randomUUID();
when(user.getUniqueId()).thenReturn(uuid);
when(server.getOnlinePlayers()).thenReturn(Collections.emptySet());
when(mockPlayer.getServer()).thenReturn(server);
when(user.getPlayer()).thenReturn(mockPlayer);
when(user.getName()).thenReturn("tastybento");
@ -154,6 +152,11 @@ public class IslandExpelCommandTest extends RanksManagerBeforeClassTest {
iec = new IslandExpelCommand(ic);
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
/**
* Test method for
* {@link world.bentobox.bentobox.api.commands.island.IslandExpelCommand#IslandExpelCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}.

View File

@ -176,9 +176,8 @@ public class IslandGoCommandTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -187,6 +187,10 @@ public class IslandResetCommandTest extends AbstractCommonSetup {
irc = new IslandResetCommand(ic);
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
/**
* Test method for
* {@link IslandResetCommand#canExecute(User, String, java.util.List)}
@ -254,12 +258,6 @@ public class IslandResetCommandTest extends AbstractCommonSetup {
checkSpigotMessage("commands.island.reset.kicked-from-island", 11);
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
}
/**
* Test method for {@link IslandResetCommand#canExecute(User, String, java.util.List)}
*/

View File

@ -201,11 +201,11 @@ public class IslandSethomeCommandTest {
*/
@Test
public void testCanExecuteTooManyHomes() {
when(im.getMaxHomes(island)).thenReturn(10);
when(im.getMaxHomes(island)).thenReturn(9);
when(im.getNumberOfHomesIfAdded(eq(island), anyString())).thenReturn(11);
IslandSethomeCommand isc = new IslandSethomeCommand(ic);
assertFalse(isc.canExecute(user, "island", Collections.emptyList()));
verify(user).sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, "10");
verify(user).sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, "9");
verify(user).sendMessage("commands.island.sethome.homes-are");
}
@ -251,7 +251,7 @@ public class IslandSethomeCommandTest {
@Test
public void testExecuteUserStringListOfStringMultiHomeTooMany() {
when(im.getMaxHomes(island)).thenReturn(3);
when(im.getNumberOfHomesIfAdded(eq(island), anyString())).thenReturn(4);
when(im.getNumberOfHomesIfAdded(eq(island), anyString())).thenReturn(5);
IslandSethomeCommand isc = new IslandSethomeCommand(ic);
assertFalse(isc.canExecute(user, "island", Collections.singletonList("13")));
verify(user).sendMessage(eq("commands.island.sethome.too-many-homes"), eq("[number]"), eq("3"));

View File

@ -130,12 +130,9 @@ public class IslandSpawnCommandTest extends AbstractCommonSetup {
isc = new IslandSpawnCommand(ic);
}
/**
*/
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -55,6 +55,7 @@ import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.panels.settings.SettingsTab;
import world.bentobox.bentobox.util.Util;
@ -95,12 +96,13 @@ public class CycleClickTest {
@Mock
private @NonNull Player p;
/**
* @throws java.lang.Exception - exception
*/
@Before
public void setUp() throws Exception {
ServerMocks.newServer();
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
@ -233,6 +235,7 @@ public class CycleClickTest {
@After
public void tearDown() {
ServerMocks.unsetBukkitServer();
Mockito.framework().clearInlineMocks();
}
@ -376,7 +379,6 @@ public class CycleClickTest {
assertTrue(udc.onClick(panel, user, ClickType.SHIFT_LEFT, SLOT));
assertTrue(hiddenFlags.isEmpty());
// Verify sounds
verify(p).playSound(user.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F);
verify(p).playSound(user.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1F, 1F);
verify(p, times(2)).playSound((Location) null, (Sound) null, 1F, 1F);
}
}

View File

@ -37,6 +37,7 @@ import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.FlagsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.panels.settings.SettingsTab;
import world.bentobox.bentobox.util.Util;
@ -67,6 +68,7 @@ public class IslandToggleClickTest {
*/
@Before
public void setUp() throws Exception {
ServerMocks.newServer();
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
// Set up plugin
@ -119,6 +121,7 @@ public class IslandToggleClickTest {
@After
public void tearDown() {
ServerMocks.unsetBukkitServer();
Mockito.framework().clearInlineMocks();
}

View File

@ -36,6 +36,7 @@ import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.managers.FlagsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
@RunWith(PowerMockRunner.class)
@ -57,10 +58,9 @@ public class WorldToggleClickTest {
@Mock
private World world;
/**
*/
@Before
public void setUp() throws Exception {
ServerMocks.newServer();
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
// Set up plugin
BentoBox plugin = mock(BentoBox.class);
@ -104,6 +104,7 @@ public class WorldToggleClickTest {
@After
public void tearDown() {
ServerMocks.unsetBukkitServer();
Mockito.framework().clearInlineMocks();
}

View File

@ -45,7 +45,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@ -136,9 +135,8 @@ public class UserTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}

View File

@ -14,6 +14,7 @@ import org.bukkit.World;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -34,6 +35,7 @@ import world.bentobox.bentobox.database.objects.Island;
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({BentoBox.class, User.class, Bukkit.class})
@Ignore("Enums")
public class BlueprintPasterTest {
private BlueprintPaster bp;

View File

@ -106,12 +106,9 @@ public class BentoBoxPermsCommandTest extends AbstractCommonSetup {
cmd = new BentoBoxPermsCommand(ac);
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
Mockito.framework().clearInlineMocks();
super.tearDown();
}
/**

View File

@ -7,6 +7,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.junit.After;
import org.junit.Before;
@ -14,6 +15,7 @@ import org.junit.Test;
import org.mockito.Mockito;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.logs.LogEntry.LogType;
/**
* @author tastybento
@ -28,8 +30,6 @@ public class LogEntryListAdapterTest {
private UUID issuer;
private List<LogEntry> toLog;
/**
*/
@Before
public void setUp() throws Exception {
config = new YamlConfiguration();
@ -38,9 +38,11 @@ public class LogEntryListAdapterTest {
issuer = UUID.randomUUID();
toLog = new ArrayList<>();
toLog.add(new LogEntry.Builder("BAN").data("player", target.toString()).data("issuer", issuer.toString()).build());
toLog.add(new LogEntry.Builder("UNBAN").data("player", target.toString()).data("issuer", issuer.toString()).build());
toLog.add(new LogEntry.Builder("UNOWNED").build());
toLog.add(new LogEntry.Builder(LogType.BAN).data("player", target.toString()).data("issuer", issuer.toString())
.build());
toLog.add(new LogEntry.Builder(LogType.UNBAN).data("player", target.toString())
.data("issuer", issuer.toString()).build());
toLog.add(new LogEntry.Builder(LogType.UNOWNED).build());
history.addAll(toLog);
}
@ -67,4 +69,28 @@ public class LogEntryListAdapterTest {
}
}
/**
* Test method for {@link world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter#serialize(java.lang.Object)}
* and {@link world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter#deserialize(java.lang.Object)}.
* @throws InvalidConfigurationException
*/
@Test
public void testSerializeDeserializeUnknownHistory() throws InvalidConfigurationException {
// Make entries using unknown types
String bad = "test:\n" + " history:\n" + " - timestamp: 1731359067207\n" + " type: WEIRD\n" + " data:\n"
+ " player: 3f9d5634-331e-4598-9445-7449d56f7f74\n"
+ " issuer: b366ba84-adec-42fe-b9dc-2c6a7b26f067\n" + " - timestamp: 1731359067207\n"
+ " type: ENTRY\n" + " data:\n" + " player: 3f9d5634-331e-4598-9445-7449d56f7f74\n"
+ " issuer: b366ba84-adec-42fe-b9dc-2c6a7b26f067\n" + " - timestamp: 1731359067207\n"
+ " type: SUPER\n" + " data: {}";
config.loadFromString(bad);
// Verify
List<LogEntry> historyCheck = a.deserialize(config.get("test.history"));
assertEquals(3, historyCheck.size());
for (int i = 0; i < historyCheck.size(); i++) {
assertEquals(LogType.UNKNOWN, historyCheck.get(i).getType());
}
}
}

View File

@ -35,7 +35,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@ -206,9 +205,8 @@ public class JoinLeaveListenerTest extends RanksManagerBeforeClassTest {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -119,12 +119,9 @@ public class StandardSpawnProtectionListenerTest extends AbstractCommonSetup {
ssp = new StandardSpawnProtectionListener(plugin);
}
/**
*/
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}

View File

@ -25,6 +25,7 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -148,6 +149,11 @@ public class CommandRankClickListenerTest extends RanksManagerBeforeClassTest {
crcl = new CommandRankClickListener();
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/

View File

@ -51,6 +51,7 @@ import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.managers.PlaceholdersManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
@RunWith(PowerMockRunner.class)
@ -87,6 +88,7 @@ public class LockAndBanListenerTest {
@Before
public void setUp() throws Exception {
ServerMocks.newServer();
// Server & Scheduler
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
when(Bukkit.getScheduler()).thenReturn(sch);
@ -189,6 +191,7 @@ public class LockAndBanListenerTest {
@After
public void tearDown() {
ServerMocks.unsetBukkitServer();
User.clearUsers();
framework().clearInlineMocks();
}

View File

@ -173,9 +173,8 @@ public class ChestDamageListenerTest extends AbstractCommonSetup
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
/**

View File

@ -18,13 +18,11 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.bentobox.AbstractCommonSetup;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.util.Util;
@ -47,13 +45,9 @@ public class CreeperListenerTest extends AbstractCommonSetup {
cl = new CreeperListener();
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
User.clearUsers();
Mockito.framework().clearInlineMocks();
super.tearDown();
}
/**

View File

@ -62,6 +62,7 @@ import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.FlagsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
@RunWith(PowerMockRunner.class)
@ -90,10 +91,9 @@ public class InvincibleVisitorsListenerTest {
@Mock
private PluginManager pim;
/**
*/
@Before
public void setUp() throws Exception {
ServerMocks.newServer();
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
// Set up plugin
@ -186,6 +186,7 @@ public class InvincibleVisitorsListenerTest {
@After
public void tearDown() {
ServerMocks.unsetBukkitServer();
User.clearUsers();
framework().clearInlineMocks();
}

View File

@ -140,9 +140,8 @@ public class ObsidianScoopingListenerTest extends AbstractCommonSetup {
}
@After
public void tearDown() {
User.clearUsers();
Mockito.framework().clearInlineMocks();
public void tearDown() throws Exception {
super.tearDown();
}
@Test

View File

@ -111,12 +111,9 @@ public class VisitorKeepInventoryListenerTest extends AbstractCommonSetup {
l = new VisitorKeepInventoryListener();
}
/**
*/
@After
public void tearDown() throws Exception {
User.clearUsers();
Mockito.framework().clearInlineMocks();
super.tearDown();
}
/**

View File

@ -0,0 +1,546 @@
package world.bentobox.bentobox.listeners.teleports;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.EntityPortalEnterEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.Vector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.bentobox.AbstractCommonSetup;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.util.Util;
/**
* @author tastybento
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ BentoBox.class, Util.class, Bukkit.class })
public class PlayerTeleportListenerTest extends AbstractCommonSetup {
private PlayerTeleportListener ptl;
@Mock
private Block block;
@Mock
private BukkitScheduler scheduler;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
super.setUp();
// Bukkit
when(Bukkit.getAllowNether()).thenReturn(true);
when(Bukkit.getAllowEnd()).thenReturn(true);
when(Bukkit.getScheduler()).thenReturn(scheduler);
// World
when(world.getEnvironment()).thenReturn(Environment.NORMAL);
when(world.getSpawnLocation()).thenReturn(location);
// Location
Vector vector = mock(Vector.class);
when(vector.toLocation(world)).thenReturn(location);
when(location.toVector()).thenReturn(vector);
// IWM
when(iwm.getNetherWorld(world)).thenReturn(world);
when(iwm.getEndWorld(world)).thenReturn(world);
when(iwm.isNetherGenerate(world)).thenReturn(true);
when(iwm.isEndGenerate(world)).thenReturn(true);
when(iwm.isNetherIslands(world)).thenReturn(true);
when(iwm.isEndIslands(world)).thenReturn(true);
// Util
when(Util.getWorld(world)).thenReturn(world);
// IM
when(plugin.getIslandsManager()).thenReturn(im);
// Block
when(location.getBlock()).thenReturn(block);
ptl = new PlayerTeleportListener(plugin);
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
super.tearDown();
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#PlayerTeleportListener(world.bentobox.bentobox.BentoBox)}.
*/
@Test
public void testPlayerTeleportListener() {
assertNotNull(ptl);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerPortalEvent(org.bukkit.event.player.PlayerPortalEvent)}.
*/
@Test
public void testOnPlayerPortalEventNether() {
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
ptl.onPlayerPortalEvent(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerPortalEvent(org.bukkit.event.player.PlayerPortalEvent)}.
*/
@Test
public void testOnPlayerPortalEventEnd() {
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.END_PORTAL, 0, false,
0);
ptl.onPlayerPortalEvent(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerPortalEvent(org.bukkit.event.player.PlayerPortalEvent)}.
*/
@Test
public void testOnPlayerPortalEventUnknown() {
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.UNKNOWN, 0, false, 0);
ptl.onPlayerPortalEvent(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#portalProcess(org.bukkit.event.player.PlayerPortalEvent, org.bukkit.World.Environment)}.
*/
@Test
public void testPortalProcessNotBentoboxWorld() {
when(Util.getWorld(location.getWorld())).thenReturn(null);
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
ptl.onPlayerPortalEvent(e);
// Verify that no further processing occurs
assertFalse(e.isCancelled());
verifyNoMoreInteractions(plugin);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#portalProcess(org.bukkit.event.player.PlayerPortalEvent, org.bukkit.World.Environment)}.
*/
@Test
public void testPortalProcessWorldDisabledInConfig() {
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(ptl.isAllowedInConfig(world, World.Environment.NETHER)).thenReturn(false);
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
ptl.onPlayerPortalEvent(e);
// Verify that the event was cancelled
assertTrue(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#portalProcess(org.bukkit.event.player.PlayerPortalEvent, org.bukkit.World.Environment)}.
*/
@Test
public void testPortalProcessWorldDisabledOnServer() {
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(ptl.isAllowedInConfig(world, World.Environment.NETHER)).thenReturn(true);
when(ptl.isAllowedOnServer(World.Environment.NETHER)).thenReturn(false);
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
ptl.onPlayerPortalEvent(e);
// Verify that the event was cancelled
assertTrue(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#portalProcess(org.bukkit.event.player.PlayerPortalEvent, org.bukkit.World.Environment)}.
*/
@Test
public void testPortalProcessAlreadyInTeleport() {
ptl.getInTeleport().add(uuid);
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
ptl.onPlayerPortalEvent(e);
// Verify no further processing occurs
assertFalse(e.isCancelled());
}
@Test
public void testPortalProcessStandardNetherOrEnd() {
// Mocking required dependencies
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(ptl.isAllowedInConfig(world, World.Environment.NETHER)).thenReturn(true);
when(ptl.isAllowedOnServer(World.Environment.NETHER)).thenReturn(true);
when(ptl.isIslandWorld(world, World.Environment.NETHER)).thenReturn(false);
// Creating the event
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
// Running the method
ptl.onPlayerPortalEvent(e);
// Validating that the event destination is unchanged (indicating standard processing occurred)
assertFalse(e.isCancelled());
assertNotNull(e.getTo());
assertEquals(location.getWorld(), e.getTo().getWorld());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#portalProcess(org.bukkit.event.player.PlayerPortalEvent, org.bukkit.World.Environment)}.
*/
@Test
public void testPortalProcessIslandTeleport() {
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(ptl.isAllowedInConfig(world, World.Environment.NETHER)).thenReturn(true);
when(ptl.isAllowedOnServer(World.Environment.NETHER)).thenReturn(true);
when(ptl.isIslandWorld(world, World.Environment.NETHER)).thenReturn(true);
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.NETHER_PORTAL, 0,
false, 0);
ptl.onPlayerPortalEvent(e);
// Verify that the portal creation settings were adjusted
assertEquals(2, e.getCreationRadius());
assertNotNull(e.getTo());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#portalProcess(org.bukkit.event.player.PlayerPortalEvent, org.bukkit.World.Environment)}.
*/
@Test
public void testPortalProcessEndVelocityReset() {
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
PlayerPortalEvent e = new PlayerPortalEvent(mockPlayer, location, location, TeleportCause.END_PORTAL, 0, false,
0);
ptl.onPlayerPortalEvent(e);
// Verify player velocity and fall distance were reset
verify(mockPlayer, times(1)).setVelocity(new Vector(0, 0, 0));
verify(mockPlayer, times(1)).setFallDistance(0);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerPortal(org.bukkit.event.entity.EntityPortalEnterEvent)}.
*/
@Test
public void testOnPlayerPortalNonPlayerEntity() {
// Mock a non-player entity
Entity mockEntity = mock(Entity.class);
when(mockEntity.getType()).thenReturn(EntityType.ZOMBIE);
EntityPortalEnterEvent e = new EntityPortalEnterEvent(mockEntity, location);
ptl.onPlayerPortal(e);
// Verify no further processing for non-player entities
verifyNoInteractions(plugin);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerPortal(org.bukkit.event.entity.EntityPortalEnterEvent)}.
*/
@Test
public void testOnPlayerPortalAlreadyInPortal() {
// Simulate player already in portal
UUID playerId = mockPlayer.getUniqueId();
ptl.getInPortal().add(playerId);
EntityPortalEnterEvent e = new EntityPortalEnterEvent(mockPlayer, location);
ptl.onPlayerPortal(e);
// Verify no further processing occurs
verifyNoInteractions(plugin);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerPortal(org.bukkit.event.entity.EntityPortalEnterEvent)}.
*/
@Test
public void testOnPlayerPortalNetherPortalDisabled() {
// Mock configuration for Nether disabled
when(Bukkit.getAllowNether()).thenReturn(false);
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(block.getType()).thenReturn(Material.NETHER_PORTAL);
EntityPortalEnterEvent e = new EntityPortalEnterEvent(mockPlayer, location);
ptl.onPlayerPortal(e);
// Verify PlayerPortalEvent is scheduled
verify(Bukkit.getScheduler(), times(1)).runTaskLater(eq(plugin), any(Runnable.class), eq(40L));
}
@Test
public void testOnPlayerPortalEndPortalDisabled() {
// Mock configuration for End disabled
when(Bukkit.getAllowEnd()).thenReturn(false);
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(block.getType()).thenReturn(Material.END_PORTAL);
// Create the event
EntityPortalEnterEvent e = new EntityPortalEnterEvent(mockPlayer, location);
// Execute the method
ptl.onPlayerPortal(e);
// Check if the player was added to inPortal
assertTrue(ptl.getInPortal().contains(mockPlayer.getUniqueId()));
// Verify the event behavior indirectly by confirming the origin world was stored
assertEquals(location.getWorld(), ptl.getTeleportOrigin().get(mockPlayer.getUniqueId()));
}
@Test
public void testOnPlayerPortalEndGatewayDisabled() {
// Mock configuration for End disabled
when(Bukkit.getAllowEnd()).thenReturn(false);
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(block.getType()).thenReturn(Material.END_GATEWAY);
// Create the event
EntityPortalEnterEvent e = new EntityPortalEnterEvent(mockPlayer, location);
// Execute the method
ptl.onPlayerPortal(e);
// Check if the player was added to inPortal
assertTrue(ptl.getInPortal().contains(mockPlayer.getUniqueId()));
// Verify the event behavior indirectly by confirming the origin world was stored
assertEquals(location.getWorld(), ptl.getTeleportOrigin().get(mockPlayer.getUniqueId()));
}
@Test
public void testOnPlayerPortalValidBentoBoxWorld() {
// Mock configuration for a valid BentoBox world
when(Bukkit.getAllowNether()).thenReturn(true);
when(Bukkit.getAllowEnd()).thenReturn(true);
when(Util.getWorld(location.getWorld())).thenReturn(world);
when(plugin.getIWM().inWorld(world)).thenReturn(true);
when(block.getType()).thenReturn(Material.NETHER_PORTAL);
// Create the event
EntityPortalEnterEvent e = new EntityPortalEnterEvent(mockPlayer, location);
// Execute the method
ptl.onPlayerPortal(e);
// Verify the player was added to inPortal
assertTrue(ptl.getInPortal().contains(mockPlayer.getUniqueId()));
// Verify teleportOrigin was updated with the correct world
assertEquals(location.getWorld(), ptl.getTeleportOrigin().get(mockPlayer.getUniqueId()));
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onExitPortal(org.bukkit.event.player.PlayerMoveEvent)}.
*/
@Test
public void testOnExitPortalPlayerNotInPortal() {
// Mock a player who is not in the inPortal list
UUID playerId = mockPlayer.getUniqueId();
// Create the event
PlayerMoveEvent e = new PlayerMoveEvent(mockPlayer, location, location);
// Execute the method
ptl.onExitPortal(e);
// Verify that no changes occurred to inPortal or other collections
assertFalse(ptl.getInPortal().contains(playerId));
assertFalse(ptl.getInTeleport().contains(playerId));
assertNull(ptl.getTeleportOrigin().get(playerId));
}
@Test
public void testOnExitPortalPlayerStillInPortal() {
// Mock a player in the inPortal list
UUID playerId = mockPlayer.getUniqueId();
ptl.getInPortal().add(playerId);
// Mock the destination block type as a Nether portal
when(location.getBlock().getType()).thenReturn(Material.NETHER_PORTAL);
// Create the event
PlayerMoveEvent e = new PlayerMoveEvent(mockPlayer, location, location);
// Execute the method
ptl.onExitPortal(e);
// Verify that the player is still in the inPortal list
assertTrue(ptl.getInPortal().contains(playerId));
// Verify that no changes occurred to inTeleport or teleportOrigin
assertFalse(ptl.getInTeleport().contains(playerId));
assertNull(ptl.getTeleportOrigin().get(playerId));
}
@Test
public void testOnExitPortalPlayerExitsPortal() {
// Mock a player in the inPortal list
UUID playerId = mockPlayer.getUniqueId();
ptl.getInPortal().add(playerId);
ptl.getInTeleport().add(playerId);
ptl.getTeleportOrigin().put(playerId, location.getWorld());
// Mock the destination block type as something other than a Nether portal
Location toLocation = mock(Location.class);
when(toLocation.getBlock()).thenReturn(block);
when(toLocation.getBlock().getType()).thenReturn(Material.AIR);
// Create the event
PlayerMoveEvent e = new PlayerMoveEvent(mockPlayer, location, toLocation);
// Execute the method
ptl.onExitPortal(e);
// Verify that the player was removed from inPortal, inTeleport, and teleportOrigin
assertFalse(ptl.getInPortal().contains(playerId));
assertFalse(ptl.getInTeleport().contains(playerId));
assertNull(ptl.getTeleportOrigin().get(playerId));
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener#onPlayerExitPortal(org.bukkit.event.player.PlayerRespawnEvent)}.
*/
@Test
public void testOnPlayerExitPortalPlayerAlreadyProcessed() {
// Mock a player who is not in teleportOrigin
UUID playerId = mockPlayer.getUniqueId();
// Create the event
@SuppressWarnings("deprecation")
PlayerRespawnEvent event = new PlayerRespawnEvent(mockPlayer, location, false);
// Execute the method
ptl.onPlayerExitPortal(event);
// Verify that no changes occurred to the event
assertEquals(location, event.getRespawnLocation());
}
@Test
public void testOnPlayerExitPortalNotBentoBoxWorld() {
// Mock teleportOrigin with a world not in BentoBox
UUID playerId = mockPlayer.getUniqueId();
ptl.getTeleportOrigin().put(playerId, world);
// Mock the world not being a BentoBox world
when(Util.getWorld(world)).thenReturn(null);
// Create the event
PlayerRespawnEvent event = new PlayerRespawnEvent(mockPlayer, location, false);
// Execute the method
ptl.onPlayerExitPortal(event);
// Verify that no changes occurred to the event
assertEquals(location, event.getRespawnLocation());
}
@Test
public void testOnPlayerExitPortalIslandExistsRespawnInsideProtection() {
// Set up teleportOrigin with a valid world
UUID playerId = mockPlayer.getUniqueId();
ptl.getTeleportOrigin().put(playerId, world);
// Create the event
PlayerRespawnEvent event = new PlayerRespawnEvent(mockPlayer, location, false);
// Execute the method
ptl.onPlayerExitPortal(event);
// Verify that the respawn location remains unchanged
assertEquals(location, event.getRespawnLocation());
}
@Test
public void testOnPlayerExitPortalIslandExistsRespawnOutsideProtection() {
// Set up teleportOrigin with a valid world
UUID playerId = mockPlayer.getUniqueId();
ptl.getTeleportOrigin().put(playerId, world);
// Create the event
PlayerRespawnEvent event = new PlayerRespawnEvent(mockPlayer, location, false);
// Execute the method
ptl.onPlayerExitPortal(event);
// Verify that the respawn location was updated to the island spawn point
assertEquals(location, event.getRespawnLocation());
}
@Test
public void testOnPlayerExitPortalIslandExistsNoSpawnPoint() {
// Set up teleportOrigin with a valid world
UUID playerId = mockPlayer.getUniqueId();
ptl.getTeleportOrigin().put(playerId, world);
// Create the event
PlayerRespawnEvent event = new PlayerRespawnEvent(mockPlayer, location, false);
// Execute the method
ptl.onPlayerExitPortal(event);
// Verify that the respawn location was updated to the island's protection center
assertEquals(location, event.getRespawnLocation());
}
@Test
public void testOnPlayerExitPortalNoIsland() {
// Set up teleportOrigin with a valid world
UUID playerId = mockPlayer.getUniqueId();
ptl.getTeleportOrigin().put(playerId, world);
// Create the event
PlayerRespawnEvent event = new PlayerRespawnEvent(mockPlayer, location, false);
// Execute the method
ptl.onPlayerExitPortal(event);
// Verify that the respawn location was updated to the world spawn location
assertEquals(location, event.getRespawnLocation());
}
}

View File

@ -41,6 +41,7 @@ import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.blueprints.Blueprint;
import world.bentobox.bentobox.blueprints.BlueprintClipboard;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
@ -103,7 +104,7 @@ public class BlueprintClipboardManagerTest {
" \"ySize\": 10,\n" +
" \"zSize\": 10\n" +
"}";
@Mock
private Server server;
private void zip(File targetFile) throws IOException {
@ -128,6 +129,7 @@ public class BlueprintClipboardManagerTest {
*/
@Before
public void setUp() throws Exception {
server = ServerMocks.newServer();
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
blueprintFolder = new File("blueprints");
@ -152,7 +154,7 @@ public class BlueprintClipboardManagerTest {
*/
@After
public void tearDown() throws Exception {
ServerMocks.unsetBukkitServer();
if (blueprintFolder.exists()) {
// Clean up file system
Files.walk(blueprintFolder.toPath())

View File

@ -60,6 +60,7 @@ import world.bentobox.bentobox.blueprints.BlueprintPaster;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
/**
@ -98,11 +99,12 @@ public class BlueprintsManagerTest {
private BukkitTask task;
private int times;
@Mock
private Server server;
@Before
public void setUp() throws Exception {
server = ServerMocks.newServer();
// Set up plugin
BentoBox plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
@ -187,6 +189,7 @@ public class BlueprintsManagerTest {
*/
@After
public void tearDown() throws Exception {
ServerMocks.unsetBukkitServer();
// Clean up file system
deleteDir(dataFolder.toPath());
// Delete addon.jar

View File

@ -6,6 +6,7 @@ import static org.mockito.Mockito.when;
import org.bukkit.Bukkit;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -26,6 +27,7 @@ import world.bentobox.bentobox.util.DeleteIslandChunks;
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({BentoBox.class, Bukkit.class, DeleteIslandChunks.class})
@Ignore("NMS")
public class IslandChunkDeletionManagerTest {
@Mock

View File

@ -49,6 +49,7 @@ import world.bentobox.bentobox.util.Util;
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest( { Bukkit.class, BentoBox.class, Util.class, Location.class })
@Ignore("NMS")
public class IslandDeletionManagerTest {
@Mock

View File

@ -65,6 +65,7 @@ import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.Names;
import world.bentobox.bentobox.database.objects.Players;
import world.bentobox.bentobox.hooks.VaultHook;
import world.bentobox.bentobox.mocks.ServerMocks;
import world.bentobox.bentobox.util.Util;
/**
@ -134,6 +135,8 @@ public class PlayersManagerTest {
public void setUp() throws Exception {
// Clear any lingering database
tearDown();
ServerMocks.newServer();
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
when(plugin.getVault()).thenReturn(Optional.of(vault));
@ -178,7 +181,7 @@ public class PlayersManagerTest {
when(p.getUniqueId()).thenReturn(uuid);
AttributeInstance at = mock(AttributeInstance.class);
when(at.getValue()).thenReturn(20D);
when(p.getAttribute(Attribute.GENERIC_MAX_HEALTH)).thenReturn(at);
when(p.getAttribute(Attribute.MAX_HEALTH)).thenReturn(at);
when(p.getName()).thenReturn("tastybento");
User.getInstance(p);
@ -271,6 +274,7 @@ public class PlayersManagerTest {
@After
public void tearDown() throws Exception {
ServerMocks.unsetBukkitServer();
User.clearUsers();
Mockito.framework().clearInlineMocks();
deleteAll(new File("database"));

View File

@ -0,0 +1,118 @@
package world.bentobox.bentobox.mocks;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.Tag;
import org.bukkit.UnsafeValues;
import org.eclipse.jdt.annotation.NonNull;
public final class ServerMocks {
public static @NonNull Server newServer() {
Server mock = mock(Server.class);
Logger noOp = mock(Logger.class);
when(mock.getLogger()).thenReturn(noOp);
when(mock.isPrimaryThread()).thenReturn(true);
// Unsafe
UnsafeValues unsafe = mock(UnsafeValues.class);
when(mock.getUnsafe()).thenReturn(unsafe);
// Server must be available before tags can be mocked.
Bukkit.setServer(mock);
// Bukkit has a lot of static constants referencing registry values. To initialize those, the
// registries must be able to be fetched before the classes are touched.
Map<Class<? extends Keyed>, Object> registers = new HashMap<>();
doAnswer(invocationGetRegistry -> registers.computeIfAbsent(invocationGetRegistry.getArgument(0), clazz -> {
Registry<?> registry = mock(Registry.class);
Map<NamespacedKey, Keyed> cache = new HashMap<>();
doAnswer(invocationGetEntry -> {
NamespacedKey key = invocationGetEntry.getArgument(0);
// Some classes (like BlockType and ItemType) have extra generics that will be
// erased during runtime calls. To ensure accurate typing, grab the constant's field.
// This approach also allows us to return null for unsupported keys.
Class<? extends Keyed> constantClazz;
try {
//noinspection unchecked
constantClazz = (Class<? extends Keyed>) clazz
.getField(key.getKey().toUpperCase(Locale.ROOT).replace('.', '_')).getType();
} catch (ClassCastException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
return null;
}
return cache.computeIfAbsent(key, key1 -> {
Keyed keyed = mock(constantClazz);
doReturn(key).when(keyed).getKey();
return keyed;
});
}).when(registry).get(notNull());
return registry;
})).when(mock).getRegistry(notNull());
// Tags are dependent on registries, but use a different method.
// This will set up blank tags for each constant; all that needs to be done to render them
// functional is to re-mock Tag#getValues.
doAnswer(invocationGetTag -> {
Tag<?> tag = mock(Tag.class);
doReturn(invocationGetTag.getArgument(1)).when(tag).getKey();
doReturn(Set.of()).when(tag).getValues();
doAnswer(invocationIsTagged -> {
Keyed keyed = invocationIsTagged.getArgument(0);
Class<?> type = invocationGetTag.getArgument(2);
if (!type.isAssignableFrom(keyed.getClass())) {
return null;
}
// Since these are mocks, the exact instance might not be equal. Consider equal keys equal.
return tag.getValues().contains(keyed)
|| tag.getValues().stream().anyMatch(value -> value.getKey().equals(keyed.getKey()));
}).when(tag).isTagged(notNull());
return tag;
}).when(mock).getTag(notNull(), notNull(), notNull());
// Once the server is all set up, touch BlockType and ItemType to initialize.
// This prevents issues when trying to access dependent methods from a Material constant.
try {
Class.forName("org.bukkit.inventory.ItemType");
Class.forName("org.bukkit.block.BlockType");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return mock;
}
public static void unsetBukkitServer() {
try {
Field server = Bukkit.class.getDeclaredField("server");
server.setAccessible(true);
server.set(null, null);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private ServerMocks() {
}
}