Merge branch 'develop' into 1.16.5_lts
This commit is contained in:
parent
4683f7f9af
commit
260635e31e
|
@ -30,19 +30,7 @@ import world.bentobox.bentobox.listeners.JoinLeaveListener;
|
|||
import world.bentobox.bentobox.listeners.PanelListenerManager;
|
||||
import world.bentobox.bentobox.listeners.PortalTeleportationListener;
|
||||
import world.bentobox.bentobox.listeners.StandardSpawnProtectionListener;
|
||||
import world.bentobox.bentobox.managers.AddonsManager;
|
||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
import world.bentobox.bentobox.managers.CommandsManager;
|
||||
import world.bentobox.bentobox.managers.FlagsManager;
|
||||
import world.bentobox.bentobox.managers.HooksManager;
|
||||
import world.bentobox.bentobox.managers.IslandDeletionManager;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
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.managers.RanksManager;
|
||||
import world.bentobox.bentobox.managers.WebManager;
|
||||
import world.bentobox.bentobox.managers.*;
|
||||
import world.bentobox.bentobox.util.heads.HeadGetter;
|
||||
import world.bentobox.bentobox.versions.ServerCompatibility;
|
||||
|
||||
|
@ -69,6 +57,7 @@ public class BentoBox extends JavaPlugin {
|
|||
private HooksManager hooksManager;
|
||||
private PlaceholdersManager placeholdersManager;
|
||||
private IslandDeletionManager islandDeletionManager;
|
||||
private IslandChunkDeletionManager islandChunkDeletionManager;
|
||||
private WebManager webManager;
|
||||
|
||||
// Settings
|
||||
|
@ -157,7 +146,6 @@ public class BentoBox extends JavaPlugin {
|
|||
|
||||
// Load hooks
|
||||
hooksManager = new HooksManager(this);
|
||||
hooksManager.registerHook(new VaultHook());
|
||||
|
||||
// Load addons. Addons may load worlds, so they must go before islands are loaded.
|
||||
addonsManager = new AddonsManager(this);
|
||||
|
@ -177,6 +165,8 @@ public class BentoBox extends JavaPlugin {
|
|||
|
||||
private void completeSetup(long loadTime) {
|
||||
final long enableStart = System.currentTimeMillis();
|
||||
hooksManager.registerHook(new VaultHook());
|
||||
|
||||
hooksManager.registerHook(new PlaceholderAPIHook());
|
||||
// Setup the Placeholders manager
|
||||
placeholdersManager = new PlaceholdersManager(this);
|
||||
|
@ -294,6 +284,7 @@ public class BentoBox extends JavaPlugin {
|
|||
// Death counter
|
||||
manager.registerEvents(new DeathListener(this), this);
|
||||
// Island Delete Manager
|
||||
islandChunkDeletionManager = new IslandChunkDeletionManager(this);
|
||||
islandDeletionManager = new IslandDeletionManager(this);
|
||||
manager.registerEvents(islandDeletionManager, this);
|
||||
}
|
||||
|
@ -523,6 +514,13 @@ public class BentoBox extends JavaPlugin {
|
|||
return islandDeletionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the islandChunkDeletionManager
|
||||
*/
|
||||
public IslandChunkDeletionManager getIslandChunkDeletionManager() {
|
||||
return islandChunkDeletionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an optional of the Bstats instance
|
||||
* @since 1.1
|
||||
|
|
|
@ -298,6 +298,22 @@ public class Settings implements ConfigObject {
|
|||
@ConfigEntry(path = "island.deletion.keep-previous-island-on-reset", since = "1.13.0")
|
||||
private boolean keepPreviousIslandOnReset = false;
|
||||
|
||||
@ConfigComment("Toggles how the islands are deleted.")
|
||||
@ConfigComment("* If set to 'false', all islands will be deleted at once.")
|
||||
@ConfigComment(" This is fast but may cause an impact on the performance")
|
||||
@ConfigComment(" as it'll load all the chunks of the in-deletion islands.")
|
||||
@ConfigComment("* If set to 'true', the islands will be deleted one by one.")
|
||||
@ConfigComment(" This is slower but will not cause any impact on the performance.")
|
||||
@ConfigEntry(path = "island.deletion.slow-deletion", since = "1.19.1")
|
||||
private boolean slowDeletion = false;
|
||||
|
||||
@ConfigComment("By default, If the destination is not safe, the plugin will try to search for a safe spot around the destination,")
|
||||
@ConfigComment("then it will try to expand the y-coordinate up and down from the destination.")
|
||||
@ConfigComment("This setting limits how far the y-coordinate will be expanded.")
|
||||
@ConfigComment("If set to 0 or lower, the plugin will not expand the y-coordinate.")
|
||||
@ConfigEntry(path = "island.safe-spot-search-vertical-range", since = "1.19.1")
|
||||
private int safeSpotSearchVerticalRange = 400;
|
||||
|
||||
/* WEB */
|
||||
@ConfigComment("Toggle whether BentoBox can connect to GitHub to get data about updates and addons.")
|
||||
@ConfigComment("Disabling this will result in the deactivation of the update checker and of some other")
|
||||
|
@ -890,4 +906,20 @@ public class Settings implements ConfigObject {
|
|||
public void setMinPortalSearchRadius(int minPortalSearchRadius) {
|
||||
this.minPortalSearchRadius = minPortalSearchRadius;
|
||||
}
|
||||
|
||||
public int getSafeSpotSearchVerticalRange() {
|
||||
return safeSpotSearchVerticalRange;
|
||||
}
|
||||
|
||||
public void setSafeSpotSearchVerticalRange(int safeSpotSearchVerticalRange) {
|
||||
this.safeSpotSearchVerticalRange = safeSpotSearchVerticalRange;
|
||||
}
|
||||
|
||||
public boolean isSlowDeletion() {
|
||||
return slowDeletion;
|
||||
}
|
||||
|
||||
public void setSlowDeletion(boolean slowDeletion) {
|
||||
this.slowDeletion = slowDeletion;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package world.bentobox.bentobox.api.commands.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
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.util.Util;
|
||||
|
||||
/**
|
||||
* Deletes all named homes from an island
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
public class AdminDeleteHomesCommand extends ConfirmableCommand {
|
||||
|
||||
public AdminDeleteHomesCommand(CompositeCommand parent) {
|
||||
super(parent, "deletehomes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("mod.deletehomes");
|
||||
setOnlyPlayer(false);
|
||||
setParametersHelp("commands.admin.deletehomes.parameters");
|
||||
setDescription("commands.admin.deletehomes.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
showHelp(this, user);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Get target player
|
||||
UUID targetUUID = Util.getUUID(args.get(0));
|
||||
if (targetUUID == null) {
|
||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||
return false;
|
||||
}
|
||||
// Get island
|
||||
Island island = getIslands().getIsland(getWorld(), targetUUID);
|
||||
if (island == null) {
|
||||
user.sendMessage("general.errors.player-has-no-island");
|
||||
return false;
|
||||
}
|
||||
// Confirm
|
||||
askConfirmation(user, user.getTranslation("commands.admin.deletehomes.warning"), () -> deleteHomes(user, targetUUID, island));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean deleteHomes(User user, UUID targetUUID, Island island) {
|
||||
island.removeHomes();
|
||||
user.sendMessage("general.success");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
|
||||
if (args.isEmpty()) {
|
||||
// Don't show every player on the server. Require at least the first letter
|
||||
return Optional.empty();
|
||||
}
|
||||
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
}
|
||||
}
|
|
@ -92,6 +92,8 @@ public abstract class DefaultAdminCommand extends CompositeCommand {
|
|||
new AdminSettingsCommand(this);
|
||||
// Location
|
||||
new AdminSetProtectionCenterCommand(this);
|
||||
// Delete homes
|
||||
new AdminDeleteHomesCommand(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,8 @@ import org.bukkit.Color;
|
|||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
|
||||
import com.google.common.base.Enums;
|
||||
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
|
@ -22,6 +24,8 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
private static final String DISPLAY = "display";
|
||||
private static final String SHOW = "show";
|
||||
private static final String HIDE = "hide";
|
||||
// Since 1.18, the Particle.BARRIER was replaced by BLOCK_MARKER
|
||||
private static final Particle BARRIER = Enums.getIfPresent(Particle.class, "BARRIER").or(Enums.getIfPresent(Particle.class, "BLOCK_MARKER").or(Particle.LAVA));
|
||||
|
||||
// Map of users to which ranges must be displayed
|
||||
private final Map<User, Integer> displayRanges = new HashMap<>();
|
||||
|
@ -46,15 +50,15 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
|
||||
if (!displayRanges.containsKey(user)) {
|
||||
switch (label) {
|
||||
case DISPLAY, SHOW -> showZones(user);
|
||||
case HIDE -> user.sendMessage("commands.admin.range.display.already-off");
|
||||
default -> showHelp(this, user);
|
||||
case DISPLAY, SHOW -> showZones(user);
|
||||
case HIDE -> user.sendMessage("commands.admin.range.display.already-off");
|
||||
default -> showHelp(this, user);
|
||||
}
|
||||
} else {
|
||||
switch (label) {
|
||||
case DISPLAY, HIDE -> hideZones(user);
|
||||
case SHOW -> user.sendMessage("commands.admin.range.display.already-on");
|
||||
default -> showHelp(this, user);
|
||||
case DISPLAY, HIDE -> hideZones(user);
|
||||
case SHOW -> user.sendMessage("commands.admin.range.display.already-on");
|
||||
default -> showHelp(this, user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +75,7 @@ public class AdminRangeDisplayCommand extends CompositeCommand {
|
|||
|
||||
getIslands().getIslandAt(user.getLocation()).ifPresent(island -> {
|
||||
// Draw the island protected area
|
||||
drawZone(user, Particle.BARRIER, null, island, island.getProtectionRange());
|
||||
drawZone(user, BARRIER, null, island, island.getProtectionRange());
|
||||
|
||||
// Draw the default protected area if island protected zone is different
|
||||
if (island.getProtectionRange() != getPlugin().getIWM().getIslandProtectionRange(getWorld())) {
|
||||
|
|
|
@ -34,7 +34,7 @@ public abstract class FlagListener implements Listener {
|
|||
* Reason for why flag was allowed or disallowed
|
||||
* Used by admins for debugging player actions
|
||||
*/
|
||||
enum Why {
|
||||
protected enum Why {
|
||||
UNPROTECTED_WORLD,
|
||||
OP,
|
||||
BYPASS_EVERYWHERE,
|
||||
|
@ -206,7 +206,15 @@ public abstract class FlagListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
private void report(@Nullable User user, @NonNull Event e, @NonNull Location loc, @NonNull Flag flag, @NonNull Why why) {
|
||||
/**
|
||||
* Report why something did or did not happen for the admin why command
|
||||
* @param user user involved
|
||||
* @param e associated event
|
||||
* @param loc location
|
||||
* @param flag flag
|
||||
* @param why reason enum
|
||||
*/
|
||||
protected void report(@Nullable User user, @NonNull Event e, @NonNull Location loc, @NonNull Flag flag, @NonNull Why why) {
|
||||
// A quick way to debug flag listener unit tests is to add this line here: System.out.println(why.name()); NOSONAR
|
||||
if (user != null && user.isPlayer() && user.getPlayer().getMetadata(loc.getWorld().getName() + "_why_debug").stream()
|
||||
.filter(p -> p.getOwningPlugin().equals(getPlugin())).findFirst().map(MetadataValue::asBoolean).orElse(false)) {
|
||||
|
|
|
@ -97,7 +97,7 @@ public class TemplatedPanel extends Panel
|
|||
{
|
||||
String type = String.valueOf(record.dataMap().get("type"));
|
||||
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 1);
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
|
||||
this.typeSlotMap.put(type, counter + 1);
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ public class TemplatedPanel extends Panel
|
|||
{
|
||||
String type = String.valueOf(record.dataMap().get("type"));
|
||||
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 1);
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
|
||||
this.typeSlotMap.put(type, counter + 1);
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ public class TemplatedPanel extends Panel
|
|||
{
|
||||
String type = String.valueOf(record.dataMap().get("type"));
|
||||
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 1);
|
||||
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
|
||||
this.typeSlotMap.put(type, counter + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
@ -28,11 +31,11 @@ import world.bentobox.bentobox.api.panels.Panel;
|
|||
* @since 1.17.3
|
||||
*/
|
||||
public record PanelTemplateRecord(Panel.Type type,
|
||||
@Nullable String title,
|
||||
@Nullable TemplateItem border,
|
||||
@Nullable TemplateItem background,
|
||||
boolean[] forcedRows,
|
||||
@NonNull ItemTemplateRecord[][] content)
|
||||
@Nullable String title,
|
||||
@Nullable TemplateItem border,
|
||||
@Nullable TemplateItem background,
|
||||
boolean[] forcedRows,
|
||||
@NonNull ItemTemplateRecord[][] content)
|
||||
{
|
||||
/**
|
||||
* Instantiates a new Panel template record with empty content.
|
||||
|
@ -76,4 +79,43 @@ public record PanelTemplateRecord(Panel.Type type,
|
|||
this(icon, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.deepHashCode(content);
|
||||
result = prime * result + Arrays.hashCode(forcedRows);
|
||||
result = prime * result + Objects.hash(background, border, title, type);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof PanelTemplateRecord)) {
|
||||
return false;
|
||||
}
|
||||
PanelTemplateRecord other = (PanelTemplateRecord) obj;
|
||||
return Objects.equals(background, other.background) && Objects.equals(border, other.border)
|
||||
&& Arrays.deepEquals(content, other.content) && Arrays.equals(forcedRows, other.forcedRows)
|
||||
&& Objects.equals(title, other.title) && type == other.type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PanelTemplateRecord {type=" + type +
|
||||
", title=" + title +
|
||||
", border=" + border +
|
||||
", background=" + background +
|
||||
", forcedRows=" + Arrays.toString(forcedRows) +
|
||||
", content=" + Arrays.toString(content) + "}";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.Map;
|
|||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
@ -16,14 +17,9 @@ import com.google.gson.reflect.TypeToken;
|
|||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.flags.Flag;
|
||||
import world.bentobox.bentobox.database.json.adapters.BukkitObjectTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.EnumTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.FlagTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.ItemStackTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.LocationTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.PotionEffectTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.VectorTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.WorldTypeAdapter;
|
||||
import world.bentobox.bentobox.database.json.adapters.*;
|
||||
import world.bentobox.bentobox.versions.ServerCompatibility;
|
||||
|
||||
|
||||
/**
|
||||
* Allocates type adapters based on class type.
|
||||
|
@ -52,6 +48,8 @@ public class BentoboxTypeAdapterFactory implements TypeAdapterFactory {
|
|||
if (Location.class.isAssignableFrom(rawType)) {
|
||||
// Use our current location adapter for backward compatibility
|
||||
return (TypeAdapter<T>) new LocationTypeAdapter();
|
||||
} else if (Biome.class.isAssignableFrom(rawType) && !ServerCompatibility.getInstance().isVersion(ServerCompatibility.ServerVersion.V1_17_1)) { // TODO: Any better way ?
|
||||
return (TypeAdapter<T>) new BiomeTypeAdapter();
|
||||
} else if (Enum.class.isAssignableFrom(rawType)) {
|
||||
return new EnumTypeAdapter(rawType);
|
||||
} else if (ItemStack.class.isAssignableFrom(rawType)) {
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.database.json.adapters;
|
||||
|
||||
|
||||
import com.google.common.base.Enums;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Minecraft 1.18 reworked their biomes, and a lot of things were renamed or removed.
|
||||
* This adapter will address these changes in each database object, instead of manually fining it
|
||||
* per implementation.
|
||||
*/
|
||||
public final class BiomeTypeAdapter extends TypeAdapter<Biome>
|
||||
{
|
||||
/**
|
||||
* Map that contains string value to the actual Biome enum object.
|
||||
*/
|
||||
static final Map<String, Biome> BIOMEMAP;
|
||||
static {
|
||||
Map<String, Biome> biomeMap = new HashMap<>();
|
||||
|
||||
// Put in current values.
|
||||
Arrays.stream(Biome.values()).forEach(biome -> biomeMap.put(biome.name(), biome));
|
||||
|
||||
// Put in renamed biomes values.
|
||||
biomeMap.put("TALL_BIRCH_FOREST", getBiome("OLD_GROWTH_BIRCH_FOREST", "TALL_BIRCH_FOREST"));
|
||||
biomeMap.put("GIANT_TREE_TAIGA", getBiome("OLD_GROWTH_PINE_TAIGA", "GIANT_TREE_TAIGA"));
|
||||
biomeMap.put("GIANT_SPRUCE_TAIGA", getBiome("OLD_GROWTH_SPRUCE_TAIGA", "GIANT_SPRUCE_TAIGA"));
|
||||
biomeMap.put("SNOWY_TUNDRA", getBiome("SNOWY_PLAINS", "SNOWY_TUNDRA"));
|
||||
biomeMap.put("JUNGLE_EDGE", getBiome("SPARSE_JUNGLE", "JUNGLE_EDGE"));
|
||||
biomeMap.put("STONE_SHORE", getBiome("STONY_SHORE", "STONE_SHORE"));
|
||||
biomeMap.put("MOUNTAINS", getBiome("WINDSWEPT_HILLS", "MOUNTAINS"));
|
||||
biomeMap.put("WOODED_MOUNTAINS", getBiome("WINDSWEPT_FOREST", "WOODED_MOUNTAINS"));
|
||||
biomeMap.put("GRAVELLY_MOUNTAINS", getBiome("WINDSWEPT_GRAVELLY_HILLS", "GRAVELLY_MOUNTAINS"));
|
||||
biomeMap.put("SHATTERED_SAVANNA", getBiome("WINDSWEPT_SAVANNA", "SHATTERED_SAVANNA"));
|
||||
biomeMap.put("WOODED_BADLANDS_PLATEAU", getBiome("WOODED_BADLANDS", "WOODED_BADLANDS_PLATEAU"));
|
||||
|
||||
// Put in removed biomes values. BONNe chose some close enough values.
|
||||
biomeMap.put("SNOWY_MOUNTAINS", getBiome("WINDSWEPT_HILLS", "SNOWY_MOUNTAINS"));
|
||||
biomeMap.put("DESERT_HILLS", getBiome("WINDSWEPT_HILLS", "DESERT_HILLS"));
|
||||
biomeMap.put("MOUNTAIN_EDGE", getBiome("WINDSWEPT_HILLS", "MOUNTAIN_EDGE"));
|
||||
biomeMap.put("SNOWY_TAIGA_HILLS", getBiome("WINDSWEPT_HILLS", "SNOWY_TAIGA_HILLS"));
|
||||
biomeMap.put("TAIGA_HILLS", getBiome("WINDSWEPT_HILLS", "TAIGA_HILLS"));
|
||||
biomeMap.put("TAIGA_MOUNTAINS", getBiome("WINDSWEPT_HILLS", "TAIGA_MOUNTAINS"));
|
||||
biomeMap.put("SNOWY_TAIGA_MOUNTAINS", getBiome("WINDSWEPT_HILLS", "SNOWY_TAIGA_MOUNTAINS"));
|
||||
biomeMap.put("WOODED_HILLS", getBiome("WINDSWEPT_FOREST", "WOODED_HILLS"));
|
||||
biomeMap.put("SWAMP_HILLS", getBiome("WINDSWEPT_FOREST", "SWAMP_HILLS"));
|
||||
biomeMap.put("DARK_FOREST_HILLS", getBiome("WINDSWEPT_FOREST", "DARK_FOREST_HILLS"));
|
||||
biomeMap.put("JUNGLE_HILLS", getBiome("SPARSE_JUNGLE", "JUNGLE_HILLS"));
|
||||
biomeMap.put("MODIFIED_JUNGLE", getBiome("SPARSE_JUNGLE", "MODIFIED_JUNGLE"));
|
||||
biomeMap.put("MODIFIED_JUNGLE_EDGE", getBiome("SPARSE_JUNGLE", "MODIFIED_JUNGLE_EDGE"));
|
||||
biomeMap.put("BAMBOO_JUNGLE_HILLS", getBiome("SPARSE_JUNGLE", "BAMBOO_JUNGLE_HILLS"));
|
||||
biomeMap.put("BIRCH_FOREST_HILLS", getBiome("OLD_GROWTH_BIRCH_FOREST", "BIRCH_FOREST_HILLS"));
|
||||
biomeMap.put("TALL_BIRCH_HILLS", getBiome("OLD_GROWTH_BIRCH_FOREST", "TALL_BIRCH_HILLS"));
|
||||
biomeMap.put("GIANT_TREE_TAIGA_HILLS", getBiome("OLD_GROWTH_PINE_TAIGA", "GIANT_TREE_TAIGA_HILLS"));
|
||||
biomeMap.put("GIANT_SPRUCE_TAIGA_HILLS", getBiome("OLD_GROWTH_SPRUCE_TAIGA", "GIANT_SPRUCE_TAIGA_HILLS"));
|
||||
biomeMap.put("MUSHROOM_FIELD_SHORE", getBiome("MUSHROOM_FIELDS", "MUSHROOM_FIELD_SHORE"));
|
||||
biomeMap.put("BADLANDS_PLATEAU", getBiome("BADLANDS", "BADLANDS_PLATEAU"));
|
||||
biomeMap.put("MODIFIED_WOODED_BADLANDS_PLATEAU", getBiome("BADLANDS", "MODIFIED_WOODED_BADLANDS_PLATEAU"));
|
||||
biomeMap.put("MODIFIED_BADLANDS_PLATEAU", getBiome("BADLANDS", "MODIFIED_BADLANDS_PLATEAU"));
|
||||
biomeMap.put("SHATTERED_SAVANNA_PLATEAU", getBiome("SAVANNA_PLATEAU", "SHATTERED_SAVANNA_PLATEAU"));
|
||||
biomeMap.put("DESERT_LAKES", getBiome("DESERT", "DESERT_LAKES"));
|
||||
biomeMap.put("MODIFIED_GRAVELLY_MOUNTAINS", getBiome("WINDSWEPT_GRAVELLY_HILLS", "MODIFIED_GRAVELLY_MOUNTAINS"));
|
||||
biomeMap.put("DEEP_WARM_OCEAN", getBiome("DEEP_LUKEWARM_OCEAN", "DEEP_WARM_OCEAN"));
|
||||
|
||||
BIOMEMAP = Collections.unmodifiableMap(biomeMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely gets a biome based on string values
|
||||
* @param primary - primary biome
|
||||
* @param secondary - secondary biome
|
||||
* @return Biome or null
|
||||
*/
|
||||
@Nullable
|
||||
private static Biome getBiome(String primary, String secondary) {
|
||||
return Enums.getIfPresent(Biome.class, primary).or(Enums.getIfPresent(Biome.class, secondary).orNull());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome read(JsonReader input) throws IOException
|
||||
{
|
||||
if (JsonToken.NULL.equals(input.peek())) {
|
||||
input.nextNull();
|
||||
return null;
|
||||
}
|
||||
|
||||
return BIOMEMAP.get(input.nextString().toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter output, Biome enumValue) throws IOException {
|
||||
output.value(enumValue != null ? enumValue.name() : null);
|
||||
}
|
||||
}
|
||||
|
|
@ -1444,6 +1444,16 @@ public class Island implements DataObject, MetaDataAble {
|
|||
return getHomes().remove(name.toLowerCase()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all homes from this island except the default home
|
||||
* @return true if any non-default homes removed
|
||||
* @since 1.20.0
|
||||
*/
|
||||
public boolean removeHomes() {
|
||||
setChanged();
|
||||
return getHomes().keySet().removeIf(k -> !k.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a home
|
||||
* @param oldName - old name of home
|
||||
|
@ -1542,4 +1552,6 @@ public class Island implements DataObject, MetaDataAble {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ public class Players implements DataObject, MetaDataAble {
|
|||
/**
|
||||
* Clears all home Locations in world
|
||||
* @param world - world
|
||||
* @deprecated Home locations are no longer stored for players. Use {@link IslandManager}
|
||||
* @deprecated Home locations are no longer stored for players. Use {@link world.bentobox.bentobox.managers.IslandsManager}
|
||||
*/
|
||||
@Deprecated(since="1.18.0", forRemoval=true)
|
||||
public void clearHomeLocations(World world) {
|
||||
|
|
|
@ -39,12 +39,12 @@ public class BlockEndDragon implements Listener {
|
|||
World w = location.getWorld();
|
||||
if (w == null || !plugin.getIWM().isIslandEnd(w)
|
||||
|| !Flags.REMOVE_END_EXIT_ISLAND.isSetForWorld(w)
|
||||
|| w.getBlockAt(0, 255, 0).getType().equals(Material.END_PORTAL)) {
|
||||
|| w.getBlockAt(0, w.getMaxHeight() - 1, 0).getType().equals(Material.END_PORTAL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Setting a End Portal at the top will trick dragon legacy check.
|
||||
w.getBlockAt(0, 255, 0).setType(Material.END_PORTAL, false);
|
||||
w.getBlockAt(0, w.getMaxHeight() - 1, 0).setType(Material.END_PORTAL, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,9 +68,9 @@ public class BlockEndDragon implements Listener {
|
|||
}
|
||||
|
||||
private boolean testBlock(Block block) {
|
||||
return block.getY() == 255
|
||||
&& block.getX() == 0
|
||||
return block.getX() == 0
|
||||
&& block.getZ() == 0
|
||||
&& block.getY() == block.getWorld().getMaxHeight() - 1
|
||||
&& block.getWorld().getEnvironment().equals(Environment.THE_END)
|
||||
&& Flags.REMOVE_END_EXIT_ISLAND.isSetForWorld(block.getWorld())
|
||||
&& plugin.getIWM().inWorld(block.getWorld())
|
||||
|
|
|
@ -57,7 +57,7 @@ public class CommandRankClickListener implements ClickHandler {
|
|||
|
||||
// Get the user's island
|
||||
Island island = plugin.getIslands().getIsland(panel.getWorld().orElse(user.getWorld()), user.getUniqueId());
|
||||
if (island == null || !island.getOwner().equals(user.getUniqueId())) {
|
||||
if (island == null || island.getOwner() == null || !island.getOwner().equals(user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.not-owner");
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
|
||||
return true;
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.bukkit.entity.Projectile;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
@ -50,8 +51,8 @@ public class TNTListener extends FlagListener {
|
|||
// Stop TNT from being damaged if it is being caused by a visitor with a flaming arrow
|
||||
if (e.getEntity() instanceof Projectile projectile) {
|
||||
// Find out who fired it
|
||||
if (projectile.getShooter() instanceof Player && projectile.getFireTicks() > 0
|
||||
&& !checkIsland(e, (Player)projectile.getShooter(), e.getBlock().getLocation(), Flags.TNT_PRIMING)) {
|
||||
if (projectile.getShooter() instanceof Player shooter && projectile.getFireTicks() > 0
|
||||
&& !checkIsland(e, shooter, e.getBlock().getLocation(), Flags.TNT_PRIMING)) {
|
||||
// Remove the arrow
|
||||
projectile.remove();
|
||||
e.setCancelled(true);
|
||||
|
@ -82,12 +83,17 @@ public class TNTListener extends FlagListener {
|
|||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onExplosion(final EntityExplodeEvent e) {
|
||||
// Check world and types
|
||||
if (getIWM().inWorld(e.getLocation()) && TNT_TYPES.contains(e.getEntityType())) {
|
||||
// Remove any blocks from the explosion list if required
|
||||
e.blockList().removeIf(b -> protect(b.getLocation()));
|
||||
e.setCancelled(protect(e.getLocation()));
|
||||
if (!getIWM().inWorld(e.getLocation()) || !TNT_TYPES.contains(e.getEntityType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (protect(e.getLocation())) {
|
||||
// This is protected as a whole, so just cancel the event
|
||||
e.setCancelled(true);
|
||||
} else {
|
||||
// Remove any blocks from the explosion list if required
|
||||
e.blockList().removeIf(b -> protect(b.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean protect(Location location) {
|
||||
|
@ -109,4 +115,43 @@ public class TNTListener extends FlagListener {
|
|||
e.setCancelled(protect(e.getEntity().getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean protectBlockExplode(Location location) {
|
||||
return getIslands().getProtectedIslandAt(location).map(i -> !i.isAllowed(Flags.BLOCK_EXPLODE_DAMAGE))
|
||||
.orElseGet(() -> !Flags.WORLD_BLOCK_EXPLODE_DAMAGE.isSetForWorld(location.getWorld()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents block explosion from breaking blocks
|
||||
* @param e - event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onExplosion(final BlockExplodeEvent e) {
|
||||
// Check world
|
||||
if (!getIWM().inWorld(e.getBlock().getLocation())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (protectBlockExplode(e.getBlock().getLocation())) {
|
||||
// This is protected as a whole, so just cancel the event
|
||||
e.setCancelled(true);
|
||||
} else {
|
||||
// Remove any blocks from the explosion list if required
|
||||
e.blockList().removeIf(b -> protectBlockExplode(b.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents block explosion from damaging entities.
|
||||
* @param e event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onExplosion(final EntityDamageEvent e) {
|
||||
// Check if this in world and a block explosion
|
||||
if (getIWM().inWorld(e.getEntity().getLocation())
|
||||
&& e.getCause().equals(EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)) {
|
||||
// Check if it is disallowed, then cancel it.
|
||||
e.setCancelled(protectBlockExplode(e.getEntity().getLocation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,8 +225,8 @@ public class PVPListener extends FlagListener {
|
|||
String message = "protection.flags." + flag.getID() + "." + (e.isSetTo() ? "enabled" : "disabled");
|
||||
// Send the message to visitors
|
||||
e.getIsland().getVisitors().forEach(visitor -> User.getInstance(visitor).sendMessage(message));
|
||||
// Send the message to island members (and coops and trusted)
|
||||
e.getIsland().getMemberSet(RanksManager.COOP_RANK).forEach(member -> User.getInstance(member).sendMessage(message));
|
||||
// Send the message to players on the island
|
||||
e.getIsland().getPlayersOnIsland().forEach(player -> User.getInstance(player).sendMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,10 +60,12 @@ public class IslandRespawnListener extends FlagListener {
|
|||
if (world == null) {
|
||||
return; // world no longer available
|
||||
}
|
||||
|
||||
final Location respawnLocation = getIslands().getSafeHomeLocation(Util.getWorld(world), User.getInstance(e.getPlayer().getUniqueId()), "");
|
||||
if (respawnLocation != null) {
|
||||
e.setRespawnLocation(respawnLocation);
|
||||
World w = Util.getWorld(world);
|
||||
if (w != null) {
|
||||
final Location respawnLocation = getIslands().getSafeHomeLocation(w, User.getInstance(e.getPlayer().getUniqueId()), "");
|
||||
if (respawnLocation != null) {
|
||||
e.setRespawnLocation(respawnLocation);
|
||||
}
|
||||
}
|
||||
// Run respawn commands, if any
|
||||
Util.runCommands(User.getInstance(e.getPlayer()), getIWM().getOnRespawnCommands(world), "respawn");
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.bukkit.event.EventHandler;
|
|||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
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.util.Util;
|
||||
|
@ -25,6 +26,7 @@ public class VisitorKeepInventoryListener extends FlagListener {
|
|||
World world = Util.getWorld(e.getEntity().getWorld());
|
||||
if (!getIWM().inWorld(world) || !Flags.VISITOR_KEEP_INVENTORY.isSetForWorld(world)) {
|
||||
// If the player dies outside of the island world, don't do anything
|
||||
this.report(User.getInstance(e.getEntity()), e, e.getEntity().getLocation(), Flags.VISITOR_KEEP_INVENTORY, Why.SETTING_NOT_ALLOWED_IN_WORLD);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -34,6 +36,7 @@ public class VisitorKeepInventoryListener extends FlagListener {
|
|||
e.setKeepLevel(true);
|
||||
e.getDrops().clear();
|
||||
e.setDroppedExp(0);
|
||||
this.report(User.getInstance(e.getEntity()), e, e.getEntity().getLocation(), Flags.VISITOR_KEEP_INVENTORY, Why.SETTING_ALLOWED_IN_WORLD);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -392,6 +392,14 @@ public final class Flags {
|
|||
public static final Flag TNT_DAMAGE = new Flag.Builder("TNT_DAMAGE", Material.TNT).type(Type.SETTING)
|
||||
.mode(Flag.Mode.ADVANCED).build();
|
||||
|
||||
/**
|
||||
* If {@code false}, prevents Block Explode from breaking blocks and damaging nearby entities.
|
||||
* @since 1.19.1
|
||||
* @see TNTListener
|
||||
*/
|
||||
public static final Flag BLOCK_EXPLODE_DAMAGE = new Flag.Builder("BLOCK_EXPLODE_DAMAGE", Material.TNT_MINECART).type(Type.SETTING)
|
||||
.mode(Flag.Mode.ADVANCED).build();
|
||||
|
||||
/**
|
||||
* If {@code false}, prevents TNT from breaking blocks and damaging nearby entities outside of island boundaries.
|
||||
* @since 1.15.3
|
||||
|
@ -401,6 +409,15 @@ public final class Flags {
|
|||
.type(Type.WORLD_SETTING)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* If {@code false}, prevents Block Explode from breaking blocks and damaging nearby entities outside of island boundaries.
|
||||
* @since 1.19.1
|
||||
* @see TNTListener
|
||||
*/
|
||||
public static final Flag WORLD_BLOCK_EXPLODE_DAMAGE = new Flag.Builder("WORLD_BLOCK_EXPLODE_DAMAGE", Material.TNT_MINECART)
|
||||
.type(Type.WORLD_SETTING)
|
||||
.build();
|
||||
|
||||
/*
|
||||
* World Settings - they apply to every island in the game worlds.
|
||||
*/
|
||||
|
|
|
@ -96,7 +96,7 @@ public class BlueprintClipboardManager {
|
|||
plugin.logError(LOAD_ERROR + zipFile.getName());
|
||||
throw new IOException(LOAD_ERROR + zipFile.getName());
|
||||
}
|
||||
unzip(zipFile.getAbsolutePath());
|
||||
unzip(zipFile.getCanonicalPath());
|
||||
File file = new File(blueprintFolder, BlueprintsManager.sanitizeFileName(fileName));
|
||||
if (!file.exists()) {
|
||||
plugin.logError(LOAD_ERROR + file.getName());
|
||||
|
@ -194,7 +194,7 @@ public class BlueprintClipboardManager {
|
|||
if (!entry.isDirectory()) {
|
||||
unzipFiles(zipInputStream, filePath);
|
||||
} else {
|
||||
if (!filePath.startsWith(blueprintFolder.getAbsolutePath())) {
|
||||
if (!filePath.startsWith(blueprintFolder.getCanonicalPath())) {
|
||||
throw new IOException("Entry is outside of the target directory");
|
||||
}
|
||||
Files.createDirectories(filePath);
|
||||
|
@ -207,10 +207,10 @@ public class BlueprintClipboardManager {
|
|||
}
|
||||
|
||||
private void unzipFiles(final ZipInputStream zipInputStream, final Path unzipFilePath) throws IOException {
|
||||
if (!unzipFilePath.toAbsolutePath().toString().startsWith(blueprintFolder.getAbsolutePath())) {
|
||||
if (!unzipFilePath.toFile().getCanonicalPath().startsWith(blueprintFolder.getCanonicalPath())) {
|
||||
throw new IOException("Entry is outside of the target directory");
|
||||
}
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipFilePath.toAbsolutePath().toString()))) {
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipFilePath.toFile().getCanonicalPath()))) {
|
||||
byte[] bytesIn = new byte[1024];
|
||||
int read;
|
||||
while ((read = zipInputStream.read(bytesIn)) != -1) {
|
||||
|
@ -220,7 +220,7 @@ public class BlueprintClipboardManager {
|
|||
}
|
||||
|
||||
private void zip(File targetFile) throws IOException {
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile.getAbsolutePath() + BlueprintsManager.BLUEPRINT_SUFFIX))) {
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile.getCanonicalPath() + BlueprintsManager.BLUEPRINT_SUFFIX))) {
|
||||
zipOutputStream.putNextEntry(new ZipEntry(targetFile.getName()));
|
||||
try (FileInputStream inputStream = new FileInputStream(targetFile)) {
|
||||
final byte[] buffer = new byte[1024];
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package world.bentobox.bentobox.managers;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||
import world.bentobox.bentobox.util.DeleteIslandChunks;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Manages the queue of island chunks to be deleted.
|
||||
*/
|
||||
public class IslandChunkDeletionManager implements Runnable {
|
||||
private final boolean slowDeletion;
|
||||
private final BentoBox plugin;
|
||||
private final AtomicReference<DeleteIslandChunks> currentTask;
|
||||
private final Queue<IslandDeletion> queue;
|
||||
|
||||
public IslandChunkDeletionManager(BentoBox plugin) {
|
||||
this.plugin = plugin;
|
||||
this.currentTask = new AtomicReference<>();
|
||||
this.queue = new LinkedList<>();
|
||||
this.slowDeletion = plugin.getSettings().isSlowDeletion();
|
||||
|
||||
if (slowDeletion) {
|
||||
plugin.getServer().getScheduler().runTaskTimer(plugin, this, 0L, 20L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (queue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
DeleteIslandChunks task = this.currentTask.get();
|
||||
if (task != null && !task.isCompleted()) {
|
||||
return;
|
||||
}
|
||||
IslandDeletion islandDeletion = queue.remove();
|
||||
currentTask.set(startDeleteTask(islandDeletion));
|
||||
}
|
||||
|
||||
private DeleteIslandChunks startDeleteTask(IslandDeletion islandDeletion) {
|
||||
return new DeleteIslandChunks(plugin, islandDeletion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an island deletion to the queue.
|
||||
*
|
||||
* @param islandDeletion island deletion
|
||||
*/
|
||||
public void add(IslandDeletion islandDeletion) {
|
||||
if (slowDeletion) {
|
||||
queue.add(islandDeletion);
|
||||
} else {
|
||||
startDeleteTask(islandDeletion);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@ import world.bentobox.bentobox.api.events.island.IslandDeleteChunksEvent;
|
|||
import world.bentobox.bentobox.api.events.island.IslandDeletedEvent;
|
||||
import world.bentobox.bentobox.database.Database;
|
||||
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||
import world.bentobox.bentobox.util.DeleteIslandChunks;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
|
@ -57,7 +56,7 @@ public class IslandDeletionManager implements Listener {
|
|||
} else {
|
||||
plugin.log("Resuming deletion of island at " + di.getLocation().getWorld().getName() + " " + Util.xyz(di.getLocation().toVector()));
|
||||
inDeletion.add(di.getLocation());
|
||||
new DeleteIslandChunks(plugin, di);
|
||||
plugin.getIslandChunkDeletionManager().add(di);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ import world.bentobox.bentobox.database.objects.Island;
|
|||
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.managers.island.IslandCache;
|
||||
import world.bentobox.bentobox.util.DeleteIslandChunks;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
import world.bentobox.bentobox.util.teleport.SafeSpotTeleport;
|
||||
|
||||
|
@ -346,7 +345,7 @@ public class IslandsManager {
|
|||
// Remove players from island
|
||||
removePlayersFromIsland(island);
|
||||
// Remove blocks from world
|
||||
new DeleteIslandChunks(plugin, new IslandDeletion(island));
|
||||
plugin.getIslandChunkDeletionManager().add(new IslandDeletion(island));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,7 +511,7 @@ public class IslandsManager {
|
|||
|
||||
int islandMax = island.getMaxMembers(rank) == null ? worldDefault : island.getMaxMembers(rank);
|
||||
// Update based on owner permissions if online
|
||||
if (Bukkit.getPlayer(island.getOwner()) != null) {
|
||||
if (island.getOwner() != null && Bukkit.getPlayer(island.getOwner()) != null) {
|
||||
User owner = User.getInstance(island.getOwner());
|
||||
islandMax = owner.getPermissionValue(plugin.getIWM().getPermissionPrefix(island.getWorld())
|
||||
+ perm, islandMax);
|
||||
|
@ -544,7 +543,7 @@ public class IslandsManager {
|
|||
public int getMaxHomes(@NonNull Island island) {
|
||||
int islandMax = island.getMaxHomes() == null ? plugin.getIWM().getMaxHomes(island.getWorld()) : island.getMaxHomes();
|
||||
// Update based on owner permissions if online
|
||||
if (Bukkit.getPlayer(island.getOwner()) != null) {
|
||||
if (island.getOwner() != null && Bukkit.getPlayer(island.getOwner()) != null) {
|
||||
User owner = User.getInstance(island.getOwner());
|
||||
islandMax = owner.getPermissionValue(plugin.getIWM().getPermissionPrefix(island.getWorld())
|
||||
+ "island.maxhomes", islandMax);
|
||||
|
@ -622,11 +621,11 @@ public class IslandsManager {
|
|||
return result;
|
||||
}
|
||||
|
||||
private void tryIsland(CompletableFuture<Location> result, Location islandLoc, @NonNull User user, String number) {
|
||||
private void tryIsland(CompletableFuture<Location> result, Location islandLoc, @NonNull User user, String name) {
|
||||
Util.getChunkAtAsync(islandLoc).thenRun(() -> {
|
||||
World w = islandLoc.getWorld();
|
||||
if (isSafeLocation(islandLoc)) {
|
||||
setHomeLocation(user, islandLoc, number);
|
||||
setHomeLocation(user, islandLoc, name);
|
||||
result.complete(islandLoc.clone().add(new Vector(0.5D,0,0.5D)));
|
||||
return;
|
||||
} else {
|
||||
|
@ -634,14 +633,14 @@ public class IslandsManager {
|
|||
// Try the default location
|
||||
Location dl = islandLoc.clone().add(new Vector(0.5D, 5D, 2.5D));
|
||||
if (isSafeLocation(dl)) {
|
||||
setHomeLocation(user, dl, number);
|
||||
setHomeLocation(user, dl, name);
|
||||
result.complete(dl);
|
||||
return;
|
||||
}
|
||||
// Try just above the bedrock
|
||||
dl = islandLoc.clone().add(new Vector(0.5D, 5D, 0.5D));
|
||||
if (isSafeLocation(dl)) {
|
||||
setHomeLocation(user, dl, number);
|
||||
setHomeLocation(user, dl, name);
|
||||
result.complete(dl);
|
||||
return;
|
||||
}
|
||||
|
@ -649,7 +648,7 @@ public class IslandsManager {
|
|||
for (int y = islandLoc.getBlockY(); y < w.getMaxHeight(); y++) {
|
||||
dl = new Location(w, islandLoc.getX() + 0.5D, y, islandLoc.getZ() + 0.5D);
|
||||
if (isSafeLocation(dl)) {
|
||||
setHomeLocation(user, dl, number);
|
||||
setHomeLocation(user, dl, name);
|
||||
result.complete(dl);
|
||||
return;
|
||||
}
|
||||
|
@ -705,10 +704,13 @@ public class IslandsManager {
|
|||
return l;
|
||||
} else {
|
||||
// try owner's home
|
||||
Location tlh = getHomeLocation(world, getOwner(world, user.getUniqueId()));
|
||||
if (tlh != null && isSafeLocation(tlh)) {
|
||||
setHomeLocation(user, tlh, name);
|
||||
return tlh;
|
||||
UUID owner = getOwner(world, user.getUniqueId());
|
||||
if (owner != null) {
|
||||
Location tlh = getHomeLocation(world, owner);
|
||||
if (tlh != null && isSafeLocation(tlh)) {
|
||||
setHomeLocation(user, tlh, name);
|
||||
return tlh;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -866,6 +868,7 @@ public class IslandsManager {
|
|||
return getHomeLocation(island, name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void migrateHomes(@NonNull World world, @NonNull UUID uuid, String name, Island island) {
|
||||
Map<Location, Integer> homes = plugin
|
||||
.getPlayers()
|
||||
|
@ -874,7 +877,7 @@ public class IslandsManager {
|
|||
// No migration required
|
||||
return;
|
||||
}
|
||||
if (island.getOwner().equals(uuid)) {
|
||||
if (island.getOwner() != null && island.getOwner().equals(uuid)) {
|
||||
// Owner
|
||||
island.setHomes(homes.entrySet().stream().collect(Collectors.toMap(this::getHomeName, Map.Entry::getKey)));
|
||||
plugin.getPlayers().clearHomeLocations(world, uuid);
|
||||
|
|
|
@ -547,7 +547,7 @@ public class PlayersManager {
|
|||
// Remove any tamed animals
|
||||
world.getEntitiesByClass(Tameable.class).stream()
|
||||
.filter(Tameable::isTamed)
|
||||
.filter(t -> t.getOwner() != null && t.getOwner().equals(target.getPlayer()))
|
||||
.filter(t -> t.getOwner() != null && t.getOwner().getUniqueId().equals(target.getUniqueId()))
|
||||
.forEach(t -> t.setOwner(null));
|
||||
|
||||
// Remove money inventory etc.
|
||||
|
@ -555,7 +555,10 @@ public class PlayersManager {
|
|||
if (target.isOnline()) {
|
||||
target.getPlayer().getEnderChest().clear();
|
||||
} else {
|
||||
getPlayer(target.getUniqueId()).addToPendingKick(world);
|
||||
Players p = getPlayer(target.getUniqueId());
|
||||
if (p != null) {
|
||||
p.addToPendingKick(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((kicked && plugin.getIWM().isOnLeaveResetInventory(world) && !plugin.getIWM().isKickedKeepInventory(world))
|
||||
|
@ -563,7 +566,10 @@ public class PlayersManager {
|
|||
if (target.isOnline()) {
|
||||
target.getPlayer().getInventory().clear();
|
||||
} else {
|
||||
getPlayer(target.getUniqueId()).addToPendingKick(world);
|
||||
Players p = getPlayer(target.getUniqueId());
|
||||
if (p != null) {
|
||||
p.addToPendingKick(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -141,7 +142,11 @@ public class IslandCache {
|
|||
*/
|
||||
@Nullable
|
||||
public Island get(@NonNull World world, @NonNull UUID uuid) {
|
||||
return islandsByUUID.containsKey(Util.getWorld(world)) ? islandsByUUID.get(Util.getWorld(world)).get(uuid) : null;
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return null;
|
||||
}
|
||||
return islandsByUUID.containsKey(w) ? islandsByUUID.get(w).get(uuid) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,10 +158,11 @@ public class IslandCache {
|
|||
*/
|
||||
@Nullable
|
||||
public Island getIslandAt(@NonNull Location location) {
|
||||
if (!grids.containsKey(Util.getWorld(location.getWorld()))) {
|
||||
World w = Util.getWorld(location.getWorld());
|
||||
if (w == null || !grids.containsKey(w)) {
|
||||
return null;
|
||||
}
|
||||
return grids.get(Util.getWorld(location.getWorld())).getIslandAt(location.getBlockX(), location.getBlockZ());
|
||||
return grids.get(w).getIslandAt(location.getBlockX(), location.getBlockZ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,7 +183,9 @@ public class IslandCache {
|
|||
@NonNull
|
||||
public Collection<Island> getIslands(@NonNull World world) {
|
||||
World overworld = Util.getWorld(world);
|
||||
|
||||
if (overworld == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return islandsByLocation.entrySet().stream()
|
||||
.filter(entry -> overworld.equals(Util.getWorld(entry.getKey().getWorld()))) // shouldn't make NPEs
|
||||
.map(Map.Entry::getValue).toList();
|
||||
|
@ -191,7 +199,11 @@ public class IslandCache {
|
|||
*/
|
||||
@NonNull
|
||||
public Set<UUID> getMembers(@NonNull World world, @NonNull UUID uuid, int minimumRank) {
|
||||
Island island = islandsByUUID.computeIfAbsent(Util.getWorld(world), k -> new HashMap<>()).get(uuid);
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid);
|
||||
return island != null ? island.getMemberSet(minimumRank) : new HashSet<>();
|
||||
}
|
||||
|
||||
|
@ -202,7 +214,11 @@ public class IslandCache {
|
|||
*/
|
||||
@Nullable
|
||||
public UUID getOwner(@NonNull World world, @NonNull UUID uuid) {
|
||||
Island island = islandsByUUID.computeIfAbsent(Util.getWorld(world), k -> new HashMap<>()).get(uuid);
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return null;
|
||||
}
|
||||
Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid);
|
||||
return island != null ? island.getOwner() : null;
|
||||
|
||||
}
|
||||
|
@ -213,7 +229,11 @@ public class IslandCache {
|
|||
* @return true if player has island and owns it
|
||||
*/
|
||||
public boolean hasIsland(@NonNull World world, @NonNull UUID uuid) {
|
||||
Island island = islandsByUUID.computeIfAbsent(Util.getWorld(world), k -> new HashMap<>()).get(uuid);
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return false;
|
||||
}
|
||||
Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid);
|
||||
return island != null && uuid.equals(island.getOwner());
|
||||
}
|
||||
|
||||
|
@ -226,7 +246,11 @@ public class IslandCache {
|
|||
*/
|
||||
@Nullable
|
||||
public Island removePlayer(@NonNull World world, @NonNull UUID uuid) {
|
||||
Island island = islandsByUUID.computeIfAbsent(Util.getWorld(world), k -> new HashMap<>()).get(uuid);
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return null;
|
||||
}
|
||||
Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid);
|
||||
if (island != null) {
|
||||
if (uuid.equals(island.getOwner())) {
|
||||
// Clear ownership and members
|
||||
|
@ -237,7 +261,7 @@ public class IslandCache {
|
|||
island.removeMember(uuid);
|
||||
}
|
||||
}
|
||||
islandsByUUID.get(world).remove(uuid);
|
||||
islandsByUUID.get(w).remove(uuid);
|
||||
return island;
|
||||
}
|
||||
|
||||
|
@ -267,7 +291,7 @@ public class IslandCache {
|
|||
public void setOwner(@NonNull Island island, @Nullable UUID newOwnerUUID) {
|
||||
island.setOwner(newOwnerUUID);
|
||||
if (newOwnerUUID != null) {
|
||||
islandsByUUID.computeIfAbsent(Util.getWorld(island.getWorld()), k -> new HashMap<>()).put(newOwnerUUID, island);
|
||||
islandsByUUID.computeIfAbsent(Objects.requireNonNull(Util.getWorld(island.getWorld())), k -> new HashMap<>()).put(newOwnerUUID, island);
|
||||
}
|
||||
islandsByLocation.put(island.getCenter(), island);
|
||||
islandsById.put(island.getUniqueId(), island);
|
||||
|
@ -292,11 +316,15 @@ public class IslandCache {
|
|||
public void removeIsland(@NonNull Island island) {
|
||||
islandsByLocation.values().removeIf(island::equals);
|
||||
islandsById.values().removeIf(island::equals);
|
||||
if (islandsByUUID.containsKey(Util.getWorld(island.getWorld()))) {
|
||||
islandsByUUID.get(Util.getWorld(island.getWorld())).values().removeIf(island::equals);
|
||||
World w = Util.getWorld(island.getWorld());
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
if (grids.containsKey(Util.getWorld(island.getWorld()))) {
|
||||
grids.get(Util.getWorld(island.getWorld())).removeFromGrid(island);
|
||||
if (islandsByUUID.containsKey(w)) {
|
||||
islandsByUUID.get(w).values().removeIf(island::equals);
|
||||
}
|
||||
if (grids.containsKey(w)) {
|
||||
grids.get(w).removeFromGrid(island);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,6 +335,9 @@ public class IslandCache {
|
|||
*/
|
||||
public void resetAllFlags(World world) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
islandsById.values().stream().filter(i -> i.getWorld().equals(w)).forEach(Island::setFlagsDefaults);
|
||||
}
|
||||
|
||||
|
@ -318,6 +349,9 @@ public class IslandCache {
|
|||
*/
|
||||
public void resetFlag(World world, Flag flag) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
int setting = BentoBox.getInstance().getIWM().getDefaultIslandFlags(w).getOrDefault(flag, flag.getDefaultRank());
|
||||
islandsById.values().stream().filter(i -> i.getWorld().equals(w)).forEach(i -> i.setFlag(flag, setting));
|
||||
}
|
||||
|
|
|
@ -2,9 +2,37 @@ package world.bentobox.bentobox.nms;
|
|||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
|
||||
public interface NMSAbstraction {
|
||||
|
||||
/**
|
||||
* Copy the chunk data and biome grid to the given chunk.
|
||||
* @param chunk - chunk to copy to
|
||||
* @param chunkData - chunk data to copy
|
||||
* @param biomeGrid - biome grid to copy to
|
||||
* @param limitBox - bounding box to limit the copying
|
||||
*/
|
||||
default void copyChunkDataToChunk(Chunk chunk, ChunkGenerator.ChunkData chunkData, ChunkGenerator.BiomeGrid biomeGrid, BoundingBox limitBox) {
|
||||
double baseX = chunk.getX() << 4;
|
||||
double baseZ = chunk.getZ() << 4;
|
||||
int minHeight = chunk.getWorld().getMinHeight();
|
||||
int maxHeight = chunk.getWorld().getMaxHeight();
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
if (!limitBox.contains(baseX + x, 0, baseZ + z)) {
|
||||
continue;
|
||||
}
|
||||
for (int y = minHeight; y < maxHeight; y++) {
|
||||
setBlockInNativeChunk(chunk, x, y, z, chunkData.getBlockData(x, y, z), false);
|
||||
// 3D biomes, 4 blocks separated
|
||||
if (x % 4 == 0 && y % 4 == 0 && z % 4 == 0) {
|
||||
chunk.getBlock(x, y, z).setBiome(biomeGrid.getBiome(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the low-level chunk information for the given block to the new block ID and data. This
|
||||
|
|
|
@ -183,7 +183,7 @@ public class BlueprintManagementPanel {
|
|||
// Toggle permission - default is always allowed
|
||||
pb.item(39, getNoPermissionIcon());
|
||||
} else {
|
||||
// Panel has a Trash icon. If right clicked it is discarded
|
||||
// Panel has a Trash icon. If right clicked it is discarded
|
||||
pb.item(36, getTrashIcon(addon, bb));
|
||||
// Toggle permission - default is always allowed
|
||||
pb.item(39, getPermissionIcon(addon, bb));
|
||||
|
@ -256,22 +256,22 @@ public class BlueprintManagementPanel {
|
|||
Material icon;
|
||||
String worldName;
|
||||
switch (env) {
|
||||
case NORMAL -> {
|
||||
icon = Material.GRASS_BLOCK;
|
||||
worldName = normalBlueprint.getName();
|
||||
}
|
||||
case NETHER -> {
|
||||
icon = Material.NETHERRACK;
|
||||
worldName = netherBlueprint.getName();
|
||||
}
|
||||
case THE_END -> {
|
||||
icon = Material.END_STONE;
|
||||
worldName = endBlueprint.getName();
|
||||
}
|
||||
default -> {
|
||||
icon = Material.STONE;
|
||||
worldName = Util.prettifyText(env.name());
|
||||
}
|
||||
case NORMAL -> {
|
||||
icon = Material.GRASS_BLOCK;
|
||||
worldName = normalBlueprint.getName();
|
||||
}
|
||||
case NETHER -> {
|
||||
icon = Material.NETHERRACK;
|
||||
worldName = netherBlueprint.getName();
|
||||
}
|
||||
case THE_END -> {
|
||||
icon = Material.END_STONE;
|
||||
worldName = endBlueprint.getName();
|
||||
}
|
||||
default -> {
|
||||
icon = Material.STONE;
|
||||
worldName = Util.prettifyText(env.name());
|
||||
}
|
||||
}
|
||||
|
||||
return new PanelItemBuilder()
|
||||
|
@ -297,7 +297,7 @@ public class BlueprintManagementPanel {
|
|||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
private PanelItem getNoTrashIcon() {
|
||||
return new PanelItemBuilder()
|
||||
.name(t("no-trash"))
|
||||
|
@ -321,7 +321,7 @@ public class BlueprintManagementPanel {
|
|||
return true;
|
||||
}).build();
|
||||
}
|
||||
|
||||
|
||||
private PanelItem getNoPermissionIcon() {
|
||||
return new PanelItemBuilder().icon(Material.PAINTING).name(t("no-permission"))
|
||||
.description(t("no-perm-required"))
|
||||
|
@ -350,7 +350,7 @@ public class BlueprintManagementPanel {
|
|||
return new PanelItemBuilder()
|
||||
.name(blueprint.getDisplayName() == null ? blueprint.getName() : blueprint.getDisplayName())
|
||||
.description(desc)
|
||||
.icon(blueprint.getIcon() == null ? Material.PAPER : blueprint.getIcon())
|
||||
.icon(blueprint.getIcon())
|
||||
.glow(selected != null && pos == selected.getKey())
|
||||
.clickHandler((panel, u, clickType, slot) -> {
|
||||
// Handle the world squares
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package world.bentobox.bentobox.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
@ -13,8 +10,6 @@ import org.bukkit.generator.ChunkGenerator;
|
|||
import org.bukkit.generator.ChunkGenerator.ChunkData;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import io.papermc.lib.PaperLib;
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||
|
@ -22,6 +17,13 @@ import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
|
|||
import world.bentobox.bentobox.database.objects.IslandDeletion;
|
||||
import world.bentobox.bentobox.nms.NMSAbstraction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Deletes islands chunk by chunk
|
||||
*
|
||||
|
@ -29,21 +31,23 @@ import world.bentobox.bentobox.nms.NMSAbstraction;
|
|||
*/
|
||||
public class DeleteIslandChunks {
|
||||
|
||||
private final IslandDeletion di;
|
||||
private final BentoBox plugin;
|
||||
private final World netherWorld;
|
||||
private final World endWorld;
|
||||
private final AtomicBoolean completed;
|
||||
private final NMSAbstraction nms;
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
private BukkitTask task;
|
||||
private final IslandDeletion di;
|
||||
private boolean inDelete;
|
||||
private final BentoBox plugin;
|
||||
private NMSAbstraction nms;
|
||||
private final World netherWorld;
|
||||
private final World endWorld;
|
||||
private CompletableFuture<Void> currentTask = CompletableFuture.completedFuture(null);
|
||||
|
||||
public DeleteIslandChunks(BentoBox plugin, IslandDeletion di) {
|
||||
this.plugin = plugin;
|
||||
this.chunkX = di.getMinXChunk();
|
||||
this.chunkZ = di.getMinZChunk();
|
||||
this.di = di;
|
||||
completed = new AtomicBoolean(false);
|
||||
// Nether
|
||||
if (plugin.getIWM().isNetherGenerate(di.getWorld()) && plugin.getIWM().isNetherIslands(di.getWorld())) {
|
||||
netherWorld = plugin.getIWM().getNetherWorld(di.getWorld());
|
||||
|
@ -57,9 +61,8 @@ public class DeleteIslandChunks {
|
|||
endWorld = null;
|
||||
}
|
||||
// NMS
|
||||
try {
|
||||
this.nms = Util.getNMS();
|
||||
} catch (Exception e) {
|
||||
this.nms = Util.getNMS();
|
||||
if (nms == null) {
|
||||
plugin.logError("Could not delete chunks because of NMS error");
|
||||
return;
|
||||
}
|
||||
|
@ -73,55 +76,58 @@ public class DeleteIslandChunks {
|
|||
private void regenerateChunks() {
|
||||
// Run through all chunks of the islands and regenerate them.
|
||||
task = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
if (inDelete) return;
|
||||
inDelete = true;
|
||||
if (!currentTask.isDone()) return;
|
||||
if (isEnded(chunkX)) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
List<CompletableFuture<Void>> newTasks = new ArrayList<>();
|
||||
for (int i = 0; i < plugin.getSettings().getDeleteSpeed(); i++) {
|
||||
boolean last = i == plugin.getSettings().getDeleteSpeed() -1;
|
||||
if (isEnded(chunkX)) {
|
||||
break;
|
||||
}
|
||||
final int x = chunkX;
|
||||
final int z = chunkZ;
|
||||
plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm ->
|
||||
// Overworld
|
||||
processChunk(gm, di.getWorld(), x, z).thenRun(() ->
|
||||
// Nether
|
||||
processChunk(gm, netherWorld, x, z).thenRun(() ->
|
||||
// End
|
||||
processChunk(gm, endWorld, x, z).thenRun(() -> finish(last, x)))));
|
||||
plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm -> {
|
||||
newTasks.add(processChunk(gm, di.getWorld(), x, z)); // Overworld
|
||||
newTasks.add(processChunk(gm, netherWorld, x, z)); // Nether
|
||||
newTasks.add(processChunk(gm, endWorld, x, z)); // End
|
||||
});
|
||||
chunkZ++;
|
||||
if (chunkZ > di.getMaxZChunk()) {
|
||||
chunkZ = di.getMinZChunk();
|
||||
chunkX++;
|
||||
}
|
||||
}
|
||||
currentTask = CompletableFuture.allOf(newTasks.toArray(new CompletableFuture[0]));
|
||||
}, 0L, 20L);
|
||||
|
||||
}
|
||||
|
||||
private void finish(boolean last, int x) {
|
||||
if (x > di.getMaxXChunk()) {
|
||||
// Fire event
|
||||
IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build();
|
||||
// We're done
|
||||
task.cancel();
|
||||
}
|
||||
if (last) {
|
||||
inDelete = false;
|
||||
}
|
||||
private boolean isEnded(int chunkX) {
|
||||
return chunkX > di.getMaxXChunk();
|
||||
}
|
||||
|
||||
private CompletableFuture<Boolean> processChunk(GameModeAddon gm, World world, int x, int z) {
|
||||
private void finish() {
|
||||
// Fire event
|
||||
IslandEvent.builder().deletedIslandInfo(di).reason(Reason.DELETED).build();
|
||||
// We're done
|
||||
completed.set(true);
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> processChunk(GameModeAddon gm, World world, int x, int z) {
|
||||
if (world != null) {
|
||||
CompletableFuture<Boolean> r = new CompletableFuture<>();
|
||||
PaperLib.getChunkAtAsync(world, x, z).thenAccept(chunk -> regenerateChunk(r, gm, chunk, x, z));
|
||||
return r;
|
||||
return PaperLib.getChunkAtAsync(world, x, z).thenAccept(chunk -> regenerateChunk(gm, chunk, x, z));
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
|
||||
private void regenerateChunk(CompletableFuture<Boolean> r, GameModeAddon gm, Chunk chunk, int x, int z) {
|
||||
private void regenerateChunk(GameModeAddon gm, Chunk chunk, int x, int z) {
|
||||
// Clear all inventories
|
||||
Arrays.stream(chunk.getTileEntities()).filter(te -> (te instanceof InventoryHolder))
|
||||
.filter(te -> di.inBounds(te.getLocation().getBlockX(), te.getLocation().getBlockZ()))
|
||||
.forEach(te -> ((InventoryHolder)te).getInventory().clear());
|
||||
Arrays.stream(chunk.getTileEntities()).filter(InventoryHolder.class::isInstance)
|
||||
.filter(te -> di.inBounds(te.getLocation().getBlockX(), te.getLocation().getBlockZ()))
|
||||
.forEach(te -> ((InventoryHolder) te).getInventory().clear());
|
||||
// Remove all entities
|
||||
for (Entity e : chunk.getEntities()) {
|
||||
if (!(e instanceof Player)) {
|
||||
|
@ -133,30 +139,18 @@ public class DeleteIslandChunks {
|
|||
ChunkGenerator cg = gm.getDefaultWorldGenerator(chunk.getWorld().getName(), "delete");
|
||||
// Will be null if use-own-generator is set to true
|
||||
if (cg != null) {
|
||||
|
||||
ChunkData cd = cg.generateChunkData(chunk.getWorld(), new Random(), chunk.getX(), chunk.getZ(), grid);
|
||||
createChunk(cd, chunk, grid);
|
||||
}
|
||||
r.complete(true);
|
||||
}
|
||||
|
||||
private void createChunk(ChunkData cd, Chunk chunk, MyBiomeGrid grid) {
|
||||
int baseX = chunk.getX() << 4;
|
||||
int baseZ = chunk.getZ() << 4;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
if (di.inBounds(baseX + x, baseZ + z)) {
|
||||
for (int y = 0; y < chunk.getWorld().getMaxHeight(); y++) {
|
||||
nms.setBlockInNativeChunk(chunk, x, y, z, cd.getBlockData(x, y, z), false);
|
||||
// 3D biomes, 4 blocks separated
|
||||
if (x%4 == 0 && y%4 == 0 && z%4 == 0) {
|
||||
chunk.getBlock(x, y, z).setBiome(grid.getBiome(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nms.copyChunkDataToChunk(chunk, cd, grid, di.getBox());
|
||||
// Remove all entities in chunk, including any dropped items as a result of clearing the blocks above
|
||||
Arrays.stream(chunk.getEntities()).filter(e -> !(e instanceof Player) && di.inBounds(e.getLocation().getBlockX(), e.getLocation().getBlockZ())).forEach(Entity::remove);
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return completed.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package world.bentobox.bentobox.util;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
@ -65,6 +64,7 @@ public class Util {
|
|||
private static final String THE_END = "_the_end";
|
||||
private static String serverVersion = null;
|
||||
private static BentoBox plugin = BentoBox.getInstance();
|
||||
private static NMSAbstraction nms = null;
|
||||
|
||||
private Util() {}
|
||||
|
||||
|
@ -238,7 +238,7 @@ public class Util {
|
|||
/**
|
||||
* Convert world to an overworld
|
||||
* @param world - world
|
||||
* @return over world
|
||||
* @return over world or null if world is null or a world cannot be found
|
||||
*/
|
||||
@Nullable
|
||||
public static World getWorld(@Nullable World world) {
|
||||
|
@ -284,21 +284,21 @@ public class Util {
|
|||
*/
|
||||
public static float blockFaceToFloat(BlockFace face) {
|
||||
return switch (face) {
|
||||
case EAST -> 90F;
|
||||
case EAST_NORTH_EAST -> 67.5F;
|
||||
case NORTH_EAST -> 45F;
|
||||
case NORTH_NORTH_EAST -> 22.5F;
|
||||
case NORTH_NORTH_WEST -> 337.5F;
|
||||
case NORTH_WEST -> 315F;
|
||||
case SOUTH -> 180F;
|
||||
case SOUTH_EAST -> 135F;
|
||||
case SOUTH_SOUTH_EAST -> 157.5F;
|
||||
case SOUTH_SOUTH_WEST -> 202.5F;
|
||||
case SOUTH_WEST -> 225F;
|
||||
case WEST -> 270F;
|
||||
case WEST_NORTH_WEST -> 292.5F;
|
||||
case WEST_SOUTH_WEST -> 247.5F;
|
||||
default -> 0F;
|
||||
case EAST -> 90F;
|
||||
case EAST_NORTH_EAST -> 67.5F;
|
||||
case NORTH_EAST -> 45F;
|
||||
case NORTH_NORTH_EAST -> 22.5F;
|
||||
case NORTH_NORTH_WEST -> 337.5F;
|
||||
case NORTH_WEST -> 315F;
|
||||
case SOUTH -> 180F;
|
||||
case SOUTH_EAST -> 135F;
|
||||
case SOUTH_SOUTH_EAST -> 157.5F;
|
||||
case SOUTH_SOUTH_WEST -> 202.5F;
|
||||
case SOUTH_WEST -> 225F;
|
||||
case WEST -> 270F;
|
||||
case WEST_NORTH_WEST -> 292.5F;
|
||||
case WEST_SOUTH_WEST -> 247.5F;
|
||||
default -> 0F;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -548,21 +548,21 @@ public class Util {
|
|||
if (group.length() == 6) {
|
||||
// Parses #ffffff to a color text.
|
||||
matcher.appendReplacement(buffer, ChatColor.COLOR_CHAR + "x"
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(0) + ChatColor.COLOR_CHAR + group.charAt(1)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(2) + ChatColor.COLOR_CHAR + group.charAt(3)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(4) + ChatColor.COLOR_CHAR + group.charAt(5));
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(0) + ChatColor.COLOR_CHAR + group.charAt(1)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(2) + ChatColor.COLOR_CHAR + group.charAt(3)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(4) + ChatColor.COLOR_CHAR + group.charAt(5));
|
||||
} else {
|
||||
// Parses #fff to a color text.
|
||||
matcher.appendReplacement(buffer, ChatColor.COLOR_CHAR + "x"
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(0) + ChatColor.COLOR_CHAR + group.charAt(0)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(1) + ChatColor.COLOR_CHAR + group.charAt(1)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(2) + ChatColor.COLOR_CHAR + group.charAt(2));
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(0) + ChatColor.COLOR_CHAR + group.charAt(0)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(1) + ChatColor.COLOR_CHAR + group.charAt(1)
|
||||
+ ChatColor.COLOR_CHAR + group.charAt(2) + ChatColor.COLOR_CHAR + group.charAt(2));
|
||||
}
|
||||
}
|
||||
|
||||
// transform normal codes and strip spaces after color code.
|
||||
return Util.stripSpaceAfterColorCodes(
|
||||
ChatColor.translateAlternateColorCodes('&', matcher.appendTail(buffer).toString()));
|
||||
ChatColor.translateAlternateColorCodes('&', matcher.appendTail(buffer).toString()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -689,35 +689,25 @@ public class Util {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks what version the server is running and picks the appropriate NMS handler, or fallback
|
||||
* @return an NMS accelerated class for this server, or a fallback Bukkit API based one
|
||||
* @throws ClassNotFoundException - thrown if there is no fallback class - should never be thrown
|
||||
* @throws SecurityException - thrown if security violation - should never be thrown
|
||||
* @throws NoSuchMethodException - thrown if no constructor for NMS package
|
||||
* @throws InvocationTargetException - should never be thrown
|
||||
* @throws IllegalArgumentException - should never be thrown
|
||||
* @throws IllegalAccessException - should never be thrown
|
||||
* @throws InstantiationException - should never be thrown
|
||||
* Set the NMS handler the plugin will use
|
||||
* @param nms the NMS handler
|
||||
*/
|
||||
public static NMSAbstraction getNMS() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
String serverPackageName = Bukkit.getServer().getClass().getPackage().getName();
|
||||
String pluginPackageName = plugin.getClass().getPackage().getName();
|
||||
String version = serverPackageName.substring(serverPackageName.lastIndexOf('.') + 1);
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(pluginPackageName + ".nms." + version + ".NMSHandler");
|
||||
} catch (Exception e) {
|
||||
plugin.logWarning("No NMS Handler found for " + version + ", falling back to Bukkit API.");
|
||||
clazz = Class.forName(pluginPackageName + ".nms.fallback.NMSHandler");
|
||||
}
|
||||
// Check if we have a NMSAbstraction implementing class at that location.
|
||||
if (NMSAbstraction.class.isAssignableFrom(clazz)) {
|
||||
return (NMSAbstraction) clazz.getConstructor().newInstance();
|
||||
} else {
|
||||
throw new IllegalStateException("Class " + clazz.getName() + " does not implement NMSAbstraction");
|
||||
}
|
||||
public static void setNms(NMSAbstraction nms) {
|
||||
Util.nms = nms;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the NMS handler the plugin will use
|
||||
* @return an NMS accelerated class for this server
|
||||
*/
|
||||
public static NMSAbstraction getNMS() {
|
||||
if (nms == null) {
|
||||
plugin.log("No NMS Handler was set, falling back to Bukkit API.");
|
||||
setNms(new world.bentobox.bentobox.nms.fallback.NMSHandler());
|
||||
}
|
||||
return nms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast a localized message to all players with the permission {@link Server#BROADCAST_CHANNEL_USERS}
|
||||
*
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
package world.bentobox.bentobox.util.teleport;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
@ -17,45 +8,51 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.util.Pair;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* A class that calculates finds a safe spot asynchronously and then teleports the player there.
|
||||
* @author tastybento
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
public class SafeSpotTeleport {
|
||||
|
||||
private static final int MAX_CHUNKS = 6;
|
||||
private static final long SPEED = 1;
|
||||
private static final int MAX_RADIUS = 50;
|
||||
private boolean notChecking;
|
||||
private BukkitTask task;
|
||||
|
||||
// Parameters
|
||||
private final Entity entity;
|
||||
private final Location location;
|
||||
private boolean portal;
|
||||
private final int homeNumber;
|
||||
|
||||
// Locations
|
||||
private Location bestSpot;
|
||||
|
||||
private final BentoBox plugin;
|
||||
private List<Pair<Integer, Integer>> chunksToScan;
|
||||
private final Runnable runnable;
|
||||
private final Runnable failRunnable;
|
||||
private final CompletableFuture<Boolean> result;
|
||||
private final String homeName;
|
||||
private final int maxHeight;
|
||||
private final World world;
|
||||
private final AtomicBoolean checking = new AtomicBoolean();
|
||||
private BukkitTask task;
|
||||
private boolean portal;
|
||||
// Locations
|
||||
private Location bestSpot;
|
||||
private Iterator<Pair<Integer, Integer>> chunksToScanIterator;
|
||||
private int checkedChunks = 0;
|
||||
|
||||
/**
|
||||
* Teleports and entity to a safe spot on island
|
||||
*
|
||||
* @param builder - safe spot teleport builder
|
||||
*/
|
||||
SafeSpotTeleport(Builder builder) {
|
||||
|
@ -68,12 +65,13 @@ public class SafeSpotTeleport {
|
|||
this.runnable = builder.getRunnable();
|
||||
this.failRunnable = builder.getFailRunnable();
|
||||
this.result = builder.getResult();
|
||||
this.maxHeight = location.getWorld().getMaxHeight() - 20;
|
||||
this.world = Objects.requireNonNull(location.getWorld());
|
||||
this.maxHeight = world.getMaxHeight() - 20;
|
||||
// Try to go
|
||||
Util.getChunkAtAsync(location).thenRun(()-> tryToGo(builder.getFailureMessage()));
|
||||
Util.getChunkAtAsync(location).thenRun(() -> tryToGo(builder.getFailureMessage()));
|
||||
}
|
||||
|
||||
private void tryToGo(String failureMessage) {
|
||||
void tryToGo(String failureMessage) {
|
||||
if (plugin.getIslands().isSafeLocation(location)) {
|
||||
if (portal) {
|
||||
// If the desired location is safe, then that's where you'll go if there's no portal
|
||||
|
@ -88,44 +86,47 @@ public class SafeSpotTeleport {
|
|||
}
|
||||
}
|
||||
// Get chunks to scan
|
||||
chunksToScan = getChunksToScan();
|
||||
|
||||
// Start checking
|
||||
notChecking = true;
|
||||
chunksToScanIterator = getChunksToScan().iterator();
|
||||
|
||||
// Start a recurring task until done or cancelled
|
||||
task = Bukkit.getScheduler().runTaskTimer(plugin, () -> gatherChunks(failureMessage), 0L, SPEED);
|
||||
}
|
||||
|
||||
private void gatherChunks(String failureMessage) {
|
||||
if (!notChecking) {
|
||||
return;
|
||||
boolean gatherChunks(String failureMessage) {
|
||||
// Set a flag so this is only run if it's not already in progress
|
||||
if (checking.get()) {
|
||||
return false;
|
||||
}
|
||||
notChecking = false;
|
||||
List<ChunkSnapshot> chunkSnapshot = new ArrayList<>();
|
||||
Iterator<Pair<Integer, Integer>> it = chunksToScan.iterator();
|
||||
if (!it.hasNext()) {
|
||||
checking.set(true);
|
||||
if (checkedChunks > MAX_CHUNKS || !chunksToScanIterator.hasNext()) {
|
||||
// Nothing left
|
||||
tidyUp(entity, failureMessage);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// Add chunk snapshots to the list
|
||||
while (it.hasNext() && chunkSnapshot.size() < MAX_CHUNKS) {
|
||||
Pair<Integer, Integer> pair = it.next();
|
||||
if (location.getWorld() != null) {
|
||||
boolean isLoaded = location.getWorld().getChunkAt(pair.x, pair.z).isLoaded();
|
||||
chunkSnapshot.add(location.getWorld().getChunkAt(pair.x, pair.z).getChunkSnapshot());
|
||||
if (!isLoaded) {
|
||||
location.getWorld().getChunkAt(pair.x, pair.z).unload();
|
||||
}
|
||||
|
||||
// Get the chunk
|
||||
Pair<Integer, Integer> chunkPair = chunksToScanIterator.next();
|
||||
chunksToScanIterator.remove();
|
||||
checkedChunks++;
|
||||
if (checkedChunks >= MAX_CHUNKS) {
|
||||
checking.set(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the chunk snapshot and scan it
|
||||
Util.getChunkAtAsync(world, chunkPair.x, chunkPair.z)
|
||||
.thenApply(Chunk::getChunkSnapshot)
|
||||
.whenCompleteAsync((snapshot, e) -> {
|
||||
if (snapshot != null && scanChunk(snapshot)) {
|
||||
task.cancel();
|
||||
} else {
|
||||
checking.set(false);
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
// Move to next step
|
||||
checkChunks(chunkSnapshot);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void tidyUp(Entity entity, String failureMessage) {
|
||||
void tidyUp(Entity entity, String failureMessage) {
|
||||
// Still Async!
|
||||
// Nothing left to check and still not canceled
|
||||
task.cancel();
|
||||
|
@ -133,7 +134,7 @@ public class SafeSpotTeleport {
|
|||
if (portal && bestSpot != null) {
|
||||
// Portals found, teleport to the best spot we found
|
||||
teleportEntity(bestSpot);
|
||||
} else if (entity instanceof Player) {
|
||||
} else if (entity instanceof Player player) {
|
||||
// Return to main thread and teleport the player
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
// Failed, no safe spot
|
||||
|
@ -142,15 +143,15 @@ public class SafeSpotTeleport {
|
|||
}
|
||||
if (!plugin.getIWM().inWorld(entity.getLocation())) {
|
||||
// Last resort
|
||||
((Player)entity).performCommand("spawn");
|
||||
player.performCommand("spawn");
|
||||
} else {
|
||||
// Create a spot for the player to be
|
||||
if (location.getWorld().getEnvironment().equals(Environment.NETHER)) {
|
||||
makeAndTelport(Material.NETHERRACK);
|
||||
} else if (location.getWorld().getEnvironment().equals(Environment.THE_END)) {
|
||||
makeAndTelport(Material.END_STONE);
|
||||
if (world.getEnvironment().equals(Environment.NETHER)) {
|
||||
makeAndTeleport(Material.NETHERRACK);
|
||||
} else if (world.getEnvironment().equals(Environment.THE_END)) {
|
||||
makeAndTeleport(Material.END_STONE);
|
||||
} else {
|
||||
makeAndTelport(Material.COBBLESTONE);
|
||||
makeAndTeleport(Material.COBBLESTONE);
|
||||
}
|
||||
}
|
||||
if (failRunnable != null) {
|
||||
|
@ -166,7 +167,7 @@ public class SafeSpotTeleport {
|
|||
}
|
||||
}
|
||||
|
||||
private void makeAndTelport(Material m) {
|
||||
void makeAndTeleport(Material m) {
|
||||
location.getBlock().getRelative(BlockFace.DOWN).setType(m, false);
|
||||
location.getBlock().setType(Material.AIR, false);
|
||||
location.getBlock().getRelative(BlockFace.UP).setType(Material.AIR, false);
|
||||
|
@ -179,20 +180,21 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Gets a set of chunk coords that will be scanned.
|
||||
*
|
||||
* @return - list of chunk coords to be scanned
|
||||
*/
|
||||
private List<Pair<Integer, Integer>> getChunksToScan() {
|
||||
List<Pair<Integer, Integer>> getChunksToScan() {
|
||||
List<Pair<Integer, Integer>> chunksToScan = new ArrayList<>();
|
||||
int maxRadius = plugin.getIslands().getIslandAt(location).map(Island::getProtectionRange).orElseGet(() -> plugin.getIWM().getIslandProtectionRange(location.getWorld()));
|
||||
int maxRadius = plugin.getIslands().getIslandAt(location).map(Island::getProtectionRange).orElseGet(() -> plugin.getIWM().getIslandProtectionRange(world));
|
||||
maxRadius = Math.min(MAX_RADIUS, maxRadius);
|
||||
int x = location.getBlockX();
|
||||
int z = location.getBlockZ();
|
||||
// Create ever increasing squares around the target location
|
||||
int radius = 0;
|
||||
do {
|
||||
for (int i = x - radius; i <= x + radius; i+=16) {
|
||||
for (int j = z - radius; j <= z + radius; j+=16) {
|
||||
addChunk(chunksToScan, new Pair<>(i,j), new Pair<>(i >> 4, j >> 4));
|
||||
for (int i = x - radius; i <= x + radius; i += 16) {
|
||||
for (int j = z - radius; j <= z + radius; j += 16) {
|
||||
addChunk(chunksToScan, new Pair<>(i, j), new Pair<>(i >> 4, j >> 4));
|
||||
}
|
||||
}
|
||||
radius++;
|
||||
|
@ -206,48 +208,66 @@ public class SafeSpotTeleport {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through the chunks and if a safe spot is found, fires off the teleportation
|
||||
* @param chunkSnapshot - list of chunk snapshots to check
|
||||
*/
|
||||
private void checkChunks(final List<ChunkSnapshot> chunkSnapshot) {
|
||||
// Run async task to scan chunks
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
for (ChunkSnapshot chunk: chunkSnapshot) {
|
||||
if (scanChunk(chunk)) {
|
||||
task.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Nothing happened, change state
|
||||
notChecking = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param chunk - chunk snapshot
|
||||
* @return true if a safe spot was found
|
||||
*/
|
||||
private boolean scanChunk(ChunkSnapshot chunk) {
|
||||
// Run through the chunk
|
||||
for (int x = 0; x< 16; x++) {
|
||||
boolean scanChunk(ChunkSnapshot chunk) {
|
||||
int startY = location.getBlockY();
|
||||
int minY = world.getMinHeight();
|
||||
int maxY = 60; // Just a dummy value
|
||||
|
||||
// Check the safe spot at the current height
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
// Work down from the entry point up
|
||||
for (int y = Math.min(chunk.getHighestBlockYAt(x, z), maxHeight); y >= 0; y--) {
|
||||
if (checkBlock(chunk, x,y,z)) {
|
||||
if (minY >= startY && checkBlock(chunk, x, startY, z)) {
|
||||
return true;
|
||||
}
|
||||
maxY = Math.max(chunk.getHighestBlockYAt(x, z), maxY);
|
||||
}
|
||||
}
|
||||
maxY = Math.min(maxY, maxHeight);
|
||||
|
||||
// Expand the height up and down until a safe spot is found
|
||||
int upperY = startY + 1;
|
||||
int lowerY = startY - 1;
|
||||
boolean checkUpper = upperY <= maxY;
|
||||
boolean checkLower = lowerY >= minY;
|
||||
int limitRange = plugin.getSettings().getSafeSpotSearchVerticalRange(); // Limit the y-coordinate range
|
||||
while (limitRange > 0 && (checkUpper || checkLower)) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
if (checkUpper && checkBlock(chunk, x, upperY, z)) {
|
||||
return true;
|
||||
}
|
||||
} // end y
|
||||
} //end z
|
||||
} // end x
|
||||
if (checkLower && checkBlock(chunk, x, lowerY, z)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkUpper) {
|
||||
upperY++;
|
||||
if (upperY > maxY) {
|
||||
checkUpper = false;
|
||||
}
|
||||
}
|
||||
if (checkLower) {
|
||||
lowerY--;
|
||||
if (lowerY < minY) {
|
||||
checkLower = false;
|
||||
}
|
||||
}
|
||||
limitRange--;
|
||||
}
|
||||
|
||||
// We can't find a safe spot
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teleports entity to the safe spot
|
||||
*/
|
||||
private void teleportEntity(final Location loc) {
|
||||
void teleportEntity(final Location loc) {
|
||||
task.cancel();
|
||||
// Return to main thread and teleport the player
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
|
@ -264,14 +284,14 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Returns true if the location is a safe one.
|
||||
*
|
||||
* @param chunk - chunk snapshot
|
||||
* @param x - x coordinate
|
||||
* @param y - y coordinate
|
||||
* @param z - z coordinate
|
||||
* @param x - x coordinate
|
||||
* @param y - y coordinate
|
||||
* @param z - z coordinate
|
||||
* @return true if this is a safe spot, false if this is a portal scan
|
||||
*/
|
||||
boolean checkBlock(ChunkSnapshot chunk, int x, int y, int z) {
|
||||
World world = location.getWorld();
|
||||
Material type = chunk.getBlockType(x, y, z);
|
||||
Material space1 = chunk.getBlockType(x, Math.min(y + 1, maxHeight), z);
|
||||
Material space2 = chunk.getBlockType(x, Math.min(y + 2, maxHeight), z);
|
||||
|
@ -285,7 +305,7 @@ public class SafeSpotTeleport {
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean safe(ChunkSnapshot chunk, int x, int y, int z, World world) {
|
||||
boolean safe(ChunkSnapshot chunk, int x, int y, int z, World world) {
|
||||
Vector newSpot = new Vector((chunk.getX() << 4) + x + 0.5D, y + 1.0D, (chunk.getZ() << 4) + z + 0.5D);
|
||||
if (portal) {
|
||||
if (bestSpot == null) {
|
||||
|
@ -301,6 +321,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
public static class Builder {
|
||||
private final BentoBox plugin;
|
||||
private final CompletableFuture<Boolean> result = new CompletableFuture<>();
|
||||
private Entity entity;
|
||||
private int homeNumber = 0;
|
||||
private String homeName = "";
|
||||
|
@ -309,7 +330,6 @@ public class SafeSpotTeleport {
|
|||
private Location location;
|
||||
private Runnable runnable;
|
||||
private Runnable failRunnable;
|
||||
private final CompletableFuture<Boolean> result = new CompletableFuture<>();
|
||||
|
||||
public Builder(BentoBox plugin) {
|
||||
this.plugin = plugin;
|
||||
|
@ -317,6 +337,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Set who or what is going to teleport
|
||||
*
|
||||
* @param entity entity to teleport
|
||||
* @return Builder
|
||||
*/
|
||||
|
@ -327,6 +348,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Set the island to teleport to
|
||||
*
|
||||
* @param island island destination
|
||||
* @return Builder
|
||||
*/
|
||||
|
@ -337,6 +359,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Set the home number to this number
|
||||
*
|
||||
* @param homeNumber home number
|
||||
* @return Builder
|
||||
* @deprecated use {@link #homeName}
|
||||
|
@ -349,6 +372,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Set the home name
|
||||
*
|
||||
* @param homeName - home name
|
||||
* @return Builder
|
||||
* @since 1.16.0
|
||||
|
@ -360,6 +384,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* This is a portal teleportation
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public Builder portal() {
|
||||
|
@ -369,6 +394,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Set the failure message if this teleport cannot happen
|
||||
*
|
||||
* @param failureMessage failure message to report to user
|
||||
* @return Builder
|
||||
*/
|
||||
|
@ -379,6 +405,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Set the desired location
|
||||
*
|
||||
* @param location the location
|
||||
* @return Builder
|
||||
*/
|
||||
|
@ -389,6 +416,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Try to teleport the player
|
||||
*
|
||||
* @return CompletableFuture that will become true if successful and false if not
|
||||
* @since 1.14.0
|
||||
*/
|
||||
|
@ -400,6 +428,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* Try to teleport the player
|
||||
*
|
||||
* @return SafeSpotTeleport
|
||||
*/
|
||||
@Nullable
|
||||
|
@ -415,6 +444,11 @@ public class SafeSpotTeleport {
|
|||
result.complete(null);
|
||||
return null;
|
||||
}
|
||||
if (location.getWorld() == null) {
|
||||
plugin.logError("Attempt to safe teleport to a null world!");
|
||||
result.complete(null);
|
||||
return null;
|
||||
}
|
||||
if (failureMessage.isEmpty() && entity instanceof Player) {
|
||||
failureMessage = "general.errors.no-safe-location-found";
|
||||
}
|
||||
|
@ -423,6 +457,7 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* The task to run after the player is safely teleported.
|
||||
*
|
||||
* @param runnable - task
|
||||
* @return Builder
|
||||
* @since 1.13.0
|
||||
|
@ -434,14 +469,16 @@ public class SafeSpotTeleport {
|
|||
|
||||
/**
|
||||
* The task to run if the player is not safely teleported
|
||||
*
|
||||
* @param runnable - task
|
||||
* @return Builder
|
||||
* @since 1.18.0
|
||||
*/
|
||||
public Builder ifFail(Runnable rannable) {
|
||||
public Builder ifFail(Runnable runnable) {
|
||||
this.failRunnable = runnable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the plugin
|
||||
*/
|
||||
|
|
|
@ -75,8 +75,6 @@ public class ServerCompatibility {
|
|||
GLOWSTONE(Compatibility.INCOMPATIBLE),
|
||||
SPIGOT(Compatibility.COMPATIBLE),
|
||||
PAPER(Compatibility.SUPPORTED),
|
||||
TUINITY(Compatibility.SUPPORTED),
|
||||
AIRPLANE(Compatibility.SUPPORTED),
|
||||
PURPUR(Compatibility.SUPPORTED),
|
||||
TACOSPIGOT(Compatibility.NOT_SUPPORTED),
|
||||
AKARIN(Compatibility.NOT_SUPPORTED),
|
||||
|
@ -187,7 +185,15 @@ public class ServerCompatibility {
|
|||
/**
|
||||
* @since 1.17.1
|
||||
*/
|
||||
V1_17_1(Compatibility.INCOMPATIBLE)
|
||||
V1_17_1(Compatibility.INCOMPATIBLE),
|
||||
/**
|
||||
* @since 1.19.0
|
||||
*/
|
||||
V1_18(Compatibility.INCOMPATIBLE),
|
||||
/**
|
||||
* @since 1.19.0
|
||||
*/
|
||||
V1_18_1(Compatibility.INCOMPATIBLE),
|
||||
;
|
||||
|
||||
private final Compatibility compatibility;
|
||||
|
|
|
@ -195,6 +195,20 @@ island:
|
|||
# This is the default behaviour.
|
||||
# Added since 1.13.0.
|
||||
keep-previous-island-on-reset: false
|
||||
# Toggles how the islands are deleted.
|
||||
# * If set to 'false', all islands will be deleted at once.
|
||||
# This is fast but may cause an impact on the performance
|
||||
# as it'll load all the chunks of the in-deletion islands.
|
||||
# * If set to 'true', the islands will be deleted one by one.
|
||||
# This is slower but will not cause any impact on the performance.
|
||||
# Added since 1.19.1.
|
||||
slow-deletion: false
|
||||
# By default, If the destination is not safe, the plugin will try to search for a safe spot around the destination,
|
||||
# then it will try to expand the y-coordinate up and down from the destination.
|
||||
# This setting limits how far the y-coordinate will be expanded.
|
||||
# If set to 0 or lower, the plugin will not expand the y-coordinate.
|
||||
# Added since 1.19.1.
|
||||
safe-spot-search-vertical-range: 400
|
||||
web:
|
||||
github:
|
||||
# Toggle whether BentoBox can connect to GitHub to get data about updates and addons.
|
||||
|
|
|
@ -1373,7 +1373,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 od &a tastybento &7 a &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Načteno v &e [time]&8 ms.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -391,6 +391,10 @@ commands:
|
|||
description: "deletes a player's island"
|
||||
cannot-delete-owner: "&c All island members have to be kicked from the island before deleting it."
|
||||
deleted-island: "&a Island at &e [xyz] &a has been successfully deleted."
|
||||
deletehomes:
|
||||
parameters: "<player>"
|
||||
description: "deletes all named homes from an island"
|
||||
warning: "&c All named homes will be deleted from the island!"
|
||||
why:
|
||||
parameters: "<player>"
|
||||
description: "toggle console protection debug reporting"
|
||||
|
@ -811,6 +815,12 @@ protection:
|
|||
name: "Barrels"
|
||||
description: "Toggle barrel interaction"
|
||||
hint: "Barrel access disabled"
|
||||
BLOCK_EXPLODE_DAMAGE:
|
||||
description: |-
|
||||
&a Allow Bed & Respawn Anchors
|
||||
&a to break blocks and damage
|
||||
&a entities.
|
||||
name: "Block explode damage"
|
||||
COMPOSTER:
|
||||
name: "Composters"
|
||||
description: "Toggle composter interaction"
|
||||
|
@ -1316,6 +1326,12 @@ protection:
|
|||
description: |-
|
||||
&a If active, withers can
|
||||
&a damage blocks and players
|
||||
WORLD_BLOCK_EXPLODE_DAMAGE:
|
||||
description: |-
|
||||
&a Allow Bed & Respawn Anchors
|
||||
&a to break blocks and damage
|
||||
&a entities outside of island limits.
|
||||
name: "World block explode damage"
|
||||
WORLD_TNT_DAMAGE:
|
||||
description: |-
|
||||
&a Allow TNT and TNT minecarts
|
||||
|
@ -1563,7 +1579,7 @@ successfully-loaded: |
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 by &a tastybento &7 and &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Loaded in &e [time]&8 ms.
|
||||
|
|
|
@ -1460,7 +1460,7 @@ panel:
|
|||
successfully-loaded: |-
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7Por &atastybento &7y &aPoslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ / &7Traducido por &aSrAcosta
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8Recargado en &e[time]&8ms.
|
||||
|
|
|
@ -1437,7 +1437,7 @@ ranks:
|
|||
successfully-loaded: |-
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 par &a tastybento &7 et &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Chargé en &e [time]&8 ms.
|
||||
|
|
|
@ -1392,7 +1392,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7by &atastybento &7and &aPoslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8Caricato in &e[time]&8ms.
|
||||
|
|
|
@ -1476,7 +1476,7 @@ panel:
|
|||
successfully-loaded: |-
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7by &atastybento &7and &aPoslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8Loaded in &e[time]&8ms.
|
||||
|
|
|
@ -1358,7 +1358,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 by &a tastybento &7 and &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Loaded in &e [time]&8 ms.
|
||||
|
|
|
@ -1441,7 +1441,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7veidoja &atastybento &7un &aPoslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8Ielādēts &e[time]&8ms.
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
---
|
||||
meta:
|
||||
banner: WHITE_BANNER
|
||||
authors:
|
||||
- tastybento
|
||||
-
|
||||
banner: WHITE_BANNER
|
||||
prefixes:
|
||||
bentobox: "&6 BentoBox &7 &l> &r"
|
||||
general:
|
||||
success: "&a Succes!"
|
||||
invalid: Ongeldig
|
||||
errors:
|
||||
command-cancelled: "&c Commando geannuleerd."
|
||||
no-permission: "&c U heeft geen toestemming om deze opdracht uit te voeren (&7
|
||||
|
@ -29,10 +31,9 @@ general:
|
|||
general: "&c Dat commando is nog niet klaar - neem contact op met de beheerder"
|
||||
unknown-command: "&c Onbekend commando. Doe &b /[label] help &c voor hulp."
|
||||
wrong-world: "&c Je bent niet in de juiste wereld om dat te doen!"
|
||||
you-must-wait: "&c Je moet [number]seconden wachten voordat je dat commando
|
||||
opnieuw kunt doen."
|
||||
you-must-wait: "&c Je moet [number]seconden wachten voordat je dat commando opnieuw
|
||||
kunt doen."
|
||||
must-be-positive-number: "&c [number] is geen geldig positief getal."
|
||||
invalid: Ongeldig
|
||||
worlds:
|
||||
overworld: Bovenwereld
|
||||
nether: Nether
|
||||
|
@ -59,26 +60,26 @@ commands:
|
|||
reset:
|
||||
description: reset hoe vaak deze speler zijn eiland terugzet op 0
|
||||
parameters: "<speler>"
|
||||
success-everyone: "&a Succesvol gereset &b iedereen &a 's resetten naar
|
||||
&b 0 &a."
|
||||
success-everyone: "&a Succesvol gereset &b iedereen &a 's resetten naar &b
|
||||
0 &a."
|
||||
success: "&a Succesvol gereset &b [name] &a 's resetten naar &b 0 &a."
|
||||
add:
|
||||
description: telt op bij het aantal keren dat deze speler zijn eiland reset
|
||||
parameters: "<speler> <resets>"
|
||||
success: "&a Met succes toegevoegd &b [number] &a wordt gereset naar &
|
||||
b [name], waardoor het totaal wordt verhoogd naar &b [total] &a wordt
|
||||
gereset."
|
||||
success: "&a Met succes toegevoegd &b [number] &a wordt gereset naar & b [name],
|
||||
waardoor het totaal wordt verhoogd naar &b [total] &a wordt gereset."
|
||||
remove:
|
||||
description: verwijdert uit hoe vaak deze speler zijn eiland reset
|
||||
parameters: "<speler> <resets>"
|
||||
success: "&a Succesvol verwijderd &b [number] &a wordt gereset naar &b
|
||||
[name], waardoor het totaal wordt verlaagd naar &b [total] &a wordt gereset."
|
||||
success: "&a Succesvol verwijderd &b [number] &a wordt gereset naar &b [name],
|
||||
waardoor het totaal wordt verlaagd naar &b [total] &a wordt gereset."
|
||||
purge:
|
||||
parameters: "[days]"
|
||||
description: eilanden zuiveren die al meer dan [days] zijn verlaten
|
||||
days-one-or-more: Moet minimaal 1 dag of langer duren
|
||||
purgable-islands: "&a Gevonden &b [number]&a zuiverbare eilanden."
|
||||
purge-in-progress: "&c Bezig met spoelen. Gebruik &b /[label] purge stop
|
||||
&c om te annuleren."
|
||||
purge-in-progress: "&c Bezig met spoelen. Gebruik &b /[label] purge stop &c
|
||||
om te annuleren."
|
||||
number-error: "&c Argument moet een aantal dagen zijn"
|
||||
confirm: "&d Typ &b /[label] purge confirm &d om te beginnen met purgeren"
|
||||
completed: "&a zuivering gestopt."
|
||||
|
@ -98,9 +99,8 @@ commands:
|
|||
unowned-islands: "&a Found &b [number]&a eilanden zonder eigendom."
|
||||
status:
|
||||
description: geeft de status van de zuivering weer
|
||||
status: "&b [purged] &a eilanden gezuiverd uit &b [purgeable] &7 (&
|
||||
b [percentage]% &7) &a."
|
||||
days-one-or-more: Moet minimaal 1 dag of langer duren
|
||||
status: "&b [purged] &a eilanden gezuiverd uit &b [purgeable] &7 (& b [percentage]%
|
||||
&7) &a."
|
||||
team:
|
||||
add:
|
||||
parameters: "<eigenaar> <speler>"
|
||||
|
@ -115,6 +115,16 @@ commands:
|
|||
use-disband-owner: "&c Geen eigenaar! Gebruik ontbinden [owner]."
|
||||
disbanded: "&c Admin heeft je team ontbonden!"
|
||||
success: "&b [name] &a 's team is opgeheven."
|
||||
fix:
|
||||
description: scant en repareert het lidmaatschap van meerdere eilanden in
|
||||
de database
|
||||
scanning: Database scannen ...
|
||||
duplicate-owner: "&c Speler bezit meer dan één eiland in de database: [name]"
|
||||
player-has: "&c Speler [name] heeft [number]eilanden"
|
||||
duplicate-member: "&c Speler [name] is lid van meer dan één eiland in de database"
|
||||
rank-on-island: "&c [rank] op het eiland op [xyz]"
|
||||
fixed: "&a vaste"
|
||||
done: "&a scan"
|
||||
kick:
|
||||
parameters: "<teamspeler>"
|
||||
description: schop een speler uit een team
|
||||
|
@ -127,17 +137,6 @@ commands:
|
|||
description: draagt het eilandbezit over aan de speler
|
||||
already-owner: "&c [name] is al de eigenaar van dit eiland!"
|
||||
success: "&b [name] &a is nu de eigenaar van dit eiland."
|
||||
fix:
|
||||
description: scant en repareert het lidmaatschap van meerdere eilanden in
|
||||
de database
|
||||
scanning: Database scannen ...
|
||||
duplicate-owner: "&c Speler bezit meer dan één eiland in de database: [name]"
|
||||
player-has: "&c Speler [name] heeft [number]eilanden"
|
||||
fixed: "&a vaste"
|
||||
done: "&a scan"
|
||||
duplicate-member: "&c Speler [name] is lid van meer dan één eiland in de
|
||||
database"
|
||||
rank-on-island: "&c [rank] op het eiland op [xyz]"
|
||||
range:
|
||||
description: admin eilandbereik commando
|
||||
invalid-value:
|
||||
|
@ -159,8 +158,7 @@ commands:
|
|||
set:
|
||||
parameters: "<speler> <bereik>"
|
||||
description: stelt het beschermde eilandbereik in
|
||||
success: "&a Stel het bereik van de eilandbescherming in op &b [number]
|
||||
&a."
|
||||
success: "&a Stel het bereik van de eilandbescherming in op &b [number] &a."
|
||||
reset:
|
||||
parameters: "<speler>"
|
||||
description: zet het beschermde eilandbereik terug naar de wereldstandaard
|
||||
|
@ -168,13 +166,13 @@ commands:
|
|||
add:
|
||||
description: vergroot het beschermde bereik van het eiland
|
||||
parameters: "<speler> <bereik>"
|
||||
success: "&a Met succes het beschermde bereik van &b [name] &a 's op het
|
||||
eiland vergroot tot &b [total] &7 (&b + [number]&7) &a."
|
||||
success: "&a Met succes het beschermde bereik van &b [name] &a 's op het eiland
|
||||
vergroot tot &b [total] &7 (&b + [number]&7) &a."
|
||||
remove:
|
||||
description: verkleint het beschermde bereik van het eiland
|
||||
parameters: "<speler> <bereik>"
|
||||
success: "&a Succesvol verkleind &b [name] &a 's beschermde eilandbereik
|
||||
naar &b [total] &7 (&b - [number]&7) &a."
|
||||
success: "&a Succesvol verkleind &b [name] &a 's beschermde eilandbereik naar
|
||||
&b [total] &7 (&b - [number]&7) &a."
|
||||
register:
|
||||
parameters: "<speler>"
|
||||
description: registreer speler op het eiland waar je je bevindt
|
||||
|
@ -206,6 +204,8 @@ commands:
|
|||
team-members-title: 'Leden van het team:'
|
||||
team-owner-format: "&a [name] [rank]"
|
||||
team-member-format: "&b [name] [rank]"
|
||||
island-protection-center: 'Beschermingsgebied centrum: [xyz]'
|
||||
island-center: 'Eilandcentrum: [xyz]'
|
||||
island-coords: 'Eilandcoördinaten: [xz1] tot [xz2]'
|
||||
islands-in-trash: "&d Player heeft eilanden in de prullenbak."
|
||||
protection-range: 'Beschermingsbereik: [range]'
|
||||
|
@ -216,12 +216,9 @@ commands:
|
|||
banned-players: 'Verbannen spelers:'
|
||||
banned-format: "&c [name]"
|
||||
unowned: "&c Onbeheerd"
|
||||
island-protection-center: 'Beschermingsgebied centrum: [xyz]'
|
||||
island-center: 'Eilandcentrum: [xyz]'
|
||||
switch:
|
||||
description: bescherming bypass in- / uitschakelen
|
||||
op: "&c Ops kunnen de bescherming altijd omzeilen. Deop om het commando te
|
||||
gebruiken."
|
||||
op: "&c Ops kunnen de bescherming altijd omzeilen. Deop om het commando te gebruiken."
|
||||
removing: Bypass verwijderen ...
|
||||
adding: Beveiligingsbypass toevoegen ...
|
||||
switchto:
|
||||
|
@ -240,10 +237,10 @@ commands:
|
|||
de prullenbak
|
||||
title: "&d =========== Eilanden in prullenbak ==========="
|
||||
count: "&l &d Island [number]:"
|
||||
use-switch: "&a Gebruik &l [label] switcht naar <player> <nummer> &r &a
|
||||
om speler naar eiland in prullenbak te schakelen"
|
||||
use-emptytrash: "&a Gebruik &l [label] lege prullenbak [player] &r &a om
|
||||
prullenbakitems permanent te verwijderen"
|
||||
use-switch: "&a Gebruik &l [label] switcht naar <player> <nummer> &r &a om speler
|
||||
naar eiland in prullenbak te schakelen"
|
||||
use-emptytrash: "&a Gebruik &l [label] lege prullenbak [player] &r &a om prullenbakitems
|
||||
permanent te verwijderen"
|
||||
emptytrash:
|
||||
parameters: "[speler]"
|
||||
description: Wis de prullenbak voor de speler of verwijder alle eilanden die
|
||||
|
@ -273,14 +270,26 @@ commands:
|
|||
eiland van de eigenaar
|
||||
unknown-rank: "&c Onbekende rang!"
|
||||
not-possible: "&c Rang moet hoger zijn dan bezoeker."
|
||||
rank-set: "&a Rang ingesteld van &b [from] &a naar &b [to] &a op &b
|
||||
[name] &a 's eiland."
|
||||
rank-set: "&a Rang ingesteld van &b [from] &a naar &b [to] &a op &b [name] &a
|
||||
's eiland."
|
||||
setprotectionlocation:
|
||||
parameters: "[x y z coördinaten]"
|
||||
description: stel de huidige locatie in of [x y z] als centrum van het beschermde
|
||||
gebied van het eiland
|
||||
island: "&c Dit heeft gevolgen voor het eiland op [xyz] dat eigendom is van
|
||||
'[name]'."
|
||||
confirmation: "&c Weet u zeker dat u [xyz] wilt instellen als het beschermingscentrum?"
|
||||
success: "&a [xyz] met succes ingesteld als het beschermingscentrum."
|
||||
fail: "&a Kan [xyz] niet instellen als het beschermingscentrum."
|
||||
island-location-changed: "&a [user] heeft het beschermingscentrum van het eiland
|
||||
gewijzigd in [xyz]."
|
||||
xyz-error: "&c Specificeer drie integer-coördinaten: bijvoorbeeld 100120100"
|
||||
setspawn:
|
||||
description: stel een eiland in als spawn voor deze spelmodus
|
||||
already-spawn: "&c Dit eiland is al een spawn!"
|
||||
no-island-here: "&c Er is hier geen eiland."
|
||||
confirmation: "&c Weet je zeker dat je dit eiland wilt instellen als spawn
|
||||
voor deze wereld?"
|
||||
confirmation: "&c Weet je zeker dat je dit eiland wilt instellen als spawn voor
|
||||
deze wereld?"
|
||||
success: "&a Stel dit eiland met succes in als de spawn voor deze wereld."
|
||||
setspawnpoint:
|
||||
description: stel de huidige locatie in als spawn-punt voor dit eiland
|
||||
|
@ -288,8 +297,7 @@ commands:
|
|||
confirmation: "&c Weet u zeker dat u deze locatie wilt instellen als het spawn-punt
|
||||
voor dit eiland?"
|
||||
success: "&a Stel deze locatie met succes in als het spawn-punt voor dit eiland."
|
||||
island-spawnpoint-changed: "&a [user] heeft dit spawnpunt op het eiland
|
||||
gewijzigd."
|
||||
island-spawnpoint-changed: "&a [user] heeft dit spawnpunt op het eiland gewijzigd."
|
||||
settings:
|
||||
parameters: "[speler] / [wereldvlag] / spawn-island [vlag / active / disable]
|
||||
[rang / active / disable]"
|
||||
|
@ -348,8 +356,7 @@ commands:
|
|||
rename:
|
||||
parameters: "<blauwdruknaam> <nieuwe naam>"
|
||||
description: hernoem een blauwdruk
|
||||
success: "&a Blauwdruk &b [old] &a is met succes hernoemd naar &b [name]
|
||||
&a."
|
||||
success: "&a Blauwdruk &b [old] &a is met succes hernoemd naar &b [name] &a."
|
||||
pick-different-name: "&c Geef een naam op die verschilt van de huidige naam
|
||||
van de blueprint."
|
||||
management:
|
||||
|
@ -364,9 +371,13 @@ commands:
|
|||
Plaats blauwdruk
|
||||
naar rechts om in te stellen
|
||||
trash: Prullenbak
|
||||
no-trash: Kan niet weggooien
|
||||
trash-instructions: Klik hier met de rechtermuisknop om te verwijderen
|
||||
no-trash-instructions: Kan standaardbundel niet weggooien
|
||||
permission: Toestemming
|
||||
no-permission: Geen toestemming
|
||||
perm-required: Verplicht
|
||||
no-perm-required: Kan geen permissie instellen voor standaardbundel
|
||||
perm-not-required: Niet verplicht
|
||||
perm-format: "&e"
|
||||
remove: Klik met de rechtermuisknop om te verwijderen
|
||||
|
@ -395,10 +406,6 @@ commands:
|
|||
slot-instructions: |
|
||||
&a linkermuisknop om te verhogen
|
||||
&a Klik met de rechtermuisknop om te verlagen
|
||||
no-trash: Kan niet weggooien
|
||||
no-trash-instructions: Kan standaardbundel niet weggooien
|
||||
no-permission: Geen toestemming
|
||||
no-perm-required: Kan geen permissie instellen voor standaardbundel
|
||||
resetflags:
|
||||
parameters: "[vlag]"
|
||||
description: Reset alle eilanden naar de standaard vlaginstellingen in config.yml
|
||||
|
@ -413,6 +420,7 @@ commands:
|
|||
cannot-delete-owner: "&c Alle eilandleden moeten van het eiland worden verwijderd
|
||||
voordat ze het kunnen verwijderen."
|
||||
deleted-island: "&a Island at &e [xyz] &a is succesvol verwijderd."
|
||||
deletehomes: {}
|
||||
why:
|
||||
parameters: "<speler>"
|
||||
description: schakel foutopsporingsrapportage voor consolebeveiliging in
|
||||
|
@ -423,35 +431,22 @@ commands:
|
|||
reset:
|
||||
description: reset de dood van de speler
|
||||
parameters: "<speler>"
|
||||
success: "&a Met succes &b [name] &a 's sterfgevallen gereset naar &b
|
||||
0 &a."
|
||||
success: "&a Met succes &b [name] &a 's sterfgevallen gereset naar &b 0 &a."
|
||||
set:
|
||||
description: stelt de dood van de speler in
|
||||
parameters: "<speler> <doden>"
|
||||
success: "&a De sterfgevallen van &b [name] &a zijn succesvol ingesteld
|
||||
op &b [number] &a."
|
||||
success: "&a De sterfgevallen van &b [name] &a zijn succesvol ingesteld op
|
||||
&b [number] &a."
|
||||
add:
|
||||
description: voegt sterfgevallen toe aan de speler
|
||||
parameters: "<speler> <doden>"
|
||||
success: "&a Met succes &b [number]&a sterfgevallen toegevoegd aan &b
|
||||
[name], waardoor het totaal is verhoogd naar &b [total] &a sterfgevallen."
|
||||
success: "&a Met succes &b [number]&a sterfgevallen toegevoegd aan &b [name],
|
||||
waardoor het totaal is verhoogd naar &b [total] &a sterfgevallen."
|
||||
remove:
|
||||
description: verwijdert sterfgevallen voor de speler
|
||||
parameters: "<speler> <doden>"
|
||||
success: "&a Met succes verwijderd &b [number]&a sterfgevallen aan &b
|
||||
[name], waardoor het totaal afneemt tot &b [total] &a sterfgevallen."
|
||||
setprotectionlocation:
|
||||
parameters: "[x y z coördinaten]"
|
||||
description: stel de huidige locatie in of [x y z] als centrum van het beschermde
|
||||
gebied van het eiland
|
||||
island: "&c Dit heeft gevolgen voor het eiland op [xyz] dat eigendom is van
|
||||
'[name]'."
|
||||
confirmation: "&c Weet u zeker dat u [xyz] wilt instellen als het beschermingscentrum?"
|
||||
success: "&a [xyz] met succes ingesteld als het beschermingscentrum."
|
||||
fail: "&a Kan [xyz] niet instellen als het beschermingscentrum."
|
||||
island-location-changed: "&a [user] heeft het beschermingscentrum van
|
||||
het eiland gewijzigd in [xyz]."
|
||||
xyz-error: "&c Specificeer drie integer-coördinaten: bijvoorbeeld 100120100"
|
||||
success: "&a Met succes verwijderd &b [number]&a sterfgevallen aan &b [name],
|
||||
waardoor het totaal afneemt tot &b [total] &a sterfgevallen."
|
||||
bentobox:
|
||||
description: BentoBox admin-opdracht
|
||||
about:
|
||||
|
@ -529,8 +524,7 @@ commands:
|
|||
creating-island: "&a Een plek vinden voor uw eiland ..."
|
||||
pasting:
|
||||
estimated-time: "&a Geschatte tijd: &b [number]&a seconden."
|
||||
blocks: "&a Building it blok voor blok: &b [number] &a blokken in totaal
|
||||
..."
|
||||
blocks: "&a Building it blok voor blok: &b [number] &a blokken in totaal ..."
|
||||
entities: "&a Het vullen met entiteiten: &b [number]&a entiteiten in totaal
|
||||
..."
|
||||
done: "&a Klaar! Je eiland staat klaar en wacht op je!"
|
||||
|
@ -540,6 +534,11 @@ commands:
|
|||
het voorbereiden van uw eiland."
|
||||
you-can-teleport-to-your-island: "&a Je kunt naar je eiland teleporteren wanneer
|
||||
je maar wilt."
|
||||
deletehome:
|
||||
description: een thuislocatie verwijderen
|
||||
parameters: "[naam huis]"
|
||||
homes:
|
||||
description: lijst uw huizen
|
||||
info:
|
||||
description: informatie weergeven over uw eiland of het eiland van de speler
|
||||
parameters: "<speler>"
|
||||
|
@ -561,12 +560,15 @@ commands:
|
|||
&c Weet u zeker dat u dit wilt doen?
|
||||
&c Alle eilandleden worden van het eiland getrapt, je zult ze daarna opnieuw moeten uitnodigen.
|
||||
&c Er is geen weg meer terug: als je huidige eiland eenmaal is verwijderd, is er &l geen &r &c manier om het later terug te halen.
|
||||
kicked-from-island: "&c Je wordt van je eiland getrapt in [gamemode] omdat
|
||||
de eigenaar het aan het resetten is."
|
||||
kicked-from-island: "&c Je wordt van je eiland getrapt in [gamemode] omdat de
|
||||
eigenaar het aan het resetten is."
|
||||
sethome:
|
||||
description: stel uw thuisteleporteerpunt in
|
||||
must-be-on-your-island: "&c Je moet op je eiland zijn om naar huis te gaan!"
|
||||
too-many-homes: "&c Kan niet instellen - je eiland heeft maximaal [number] huizen."
|
||||
home-set: "&6 Uw eilandhuis is ingesteld op uw huidige locatie."
|
||||
homes-are: "&6 eilandwoningen zijn:"
|
||||
home-list-syntax: "&6 [name]"
|
||||
nether:
|
||||
not-allowed: "&c Het is niet toegestaan om uw huis in Nederland te plaatsen."
|
||||
confirmation: "&c Weet u zeker dat u uw huis in de Nether wilt plaatsen?"
|
||||
|
@ -574,10 +576,6 @@ commands:
|
|||
not-allowed: "&c Je mag je huis niet op het einde zetten."
|
||||
confirmation: "&c Weet u zeker dat u uw huis op het einde wilt zetten?"
|
||||
parameters: "[naam huis]"
|
||||
too-many-homes: "&c Kan niet instellen - je eiland heeft maximaal [number]
|
||||
huizen."
|
||||
homes-are: "&6 eilandwoningen zijn:"
|
||||
home-list-syntax: "&6 [name]"
|
||||
setname:
|
||||
description: stel een naam voor je eiland in
|
||||
name-too-short: "&c Te kort. Minimale grootte is [number]tekens."
|
||||
|
@ -585,6 +583,11 @@ commands:
|
|||
name-already-exists: "&c Er is al een eiland met die naam in deze spelmodus."
|
||||
parameters: "<naam>"
|
||||
success: "&a Stel de naam van je eiland succesvol in op &b [name] &a."
|
||||
renamehome:
|
||||
description: de naam van een thuislocatie wijzigen
|
||||
parameters: "[naam huis]"
|
||||
enter-new-name: "&6 Voer de nieuwe naam in"
|
||||
already-exists: "&c Die naam bestaat al, probeer een andere naam."
|
||||
resetname:
|
||||
description: reset je eilandnaam
|
||||
success: "&a Reset je eilandnaam succesvol."
|
||||
|
@ -654,8 +657,8 @@ commands:
|
|||
removing-invite: "&c Uitnodiging verwijderen."
|
||||
name-has-invited-you: "&a [name] heeft je uitgenodigd om lid te worden van
|
||||
hun eiland."
|
||||
to-accept-or-reject: "&a Do /[label] team accepteren om te accepteren,
|
||||
of /[label] team weigeren om te weigeren"
|
||||
to-accept-or-reject: "&a Do /[label] team accepteren om te accepteren, of
|
||||
/[label] team weigeren om te weigeren"
|
||||
you-will-lose-your-island: "&c WAARSCHUWING! Je verliest je eiland als je
|
||||
accepteert!"
|
||||
errors:
|
||||
|
@ -671,8 +674,8 @@ commands:
|
|||
you-can-invite: "&a Je kunt nog [number]spelers uitnodigen."
|
||||
accept:
|
||||
description: accepteer een uitnodiging
|
||||
you-joined-island: "&a Je bent lid geworden van een eiland! Gebruik &b
|
||||
/[label] team &a om de andere leden te zien."
|
||||
you-joined-island: "&a Je bent lid geworden van een eiland! Gebruik &b /[label]
|
||||
team &a om de andere leden te zien."
|
||||
name-joined-your-island: "&a [name] kwam bij je eiland!"
|
||||
confirmation: |-
|
||||
&c Weet u zeker dat u deze uitnodiging wilt accepteren?
|
||||
|
@ -759,16 +762,6 @@ commands:
|
|||
not-on-island: "&c Die speler is niet op jouw eiland!"
|
||||
player-expelled-you: "&b [name] &c hebben je van het eiland verdreven!"
|
||||
success: "&a Je hebt &b [name] &a van het eiland verdreven."
|
||||
deletehome:
|
||||
description: een thuislocatie verwijderen
|
||||
parameters: "[naam huis]"
|
||||
renamehome:
|
||||
description: de naam van een thuislocatie wijzigen
|
||||
parameters: "[naam huis]"
|
||||
enter-new-name: "&6 Voer de nieuwe naam in"
|
||||
already-exists: "&c Die naam bestaat al, probeer een andere naam."
|
||||
homes:
|
||||
description: lijst uw huizen
|
||||
ranks:
|
||||
owner: Eigenaar
|
||||
sub-owner: Ondereigenaar
|
||||
|
@ -856,6 +849,13 @@ protection:
|
|||
&7 Andere containers worden behandeld
|
||||
&7 door speciale vlaggen.
|
||||
hint: Containertoegang uitgeschakeld
|
||||
CHEST: {}
|
||||
BARREL: {}
|
||||
BLOCK_EXPLODE_DAMAGE: {}
|
||||
COMPOSTER: {}
|
||||
FLOWER_POT: {}
|
||||
SHULKER_BOX: {}
|
||||
TRAPPED_CHEST: {}
|
||||
DISPENSER:
|
||||
name: Dispensers
|
||||
description: Wissel de interactie tussen de dispenser
|
||||
|
@ -1026,6 +1026,10 @@ protection:
|
|||
&a buitenkant beschermd
|
||||
&a eilandruimte
|
||||
name: "&e Beperk mobs tot het eiland"
|
||||
HIVE:
|
||||
description: "&a Toggle bijenkorf oogsten."
|
||||
name: Bijenkorf oogsten
|
||||
hint: Oogsten uitgeschakeld
|
||||
HURT_ANIMALS:
|
||||
description: Schakel pijn uit
|
||||
name: Gekwetste dieren
|
||||
|
@ -1186,6 +1190,13 @@ protection:
|
|||
&a Kan vertraging helpen verminderen.
|
||||
&a Heeft geen invloed op het spawn-eiland.
|
||||
name: Offline Redstone
|
||||
PETS_STAY_AT_HOME:
|
||||
description: |-
|
||||
&a Bij actieve, getemde huisdieren
|
||||
&a kan alleen naar en gaan
|
||||
&a kan de eigenaar niet verlaten
|
||||
&a thuiseiland.
|
||||
name: Huisdieren blijven thuis
|
||||
PISTON_PUSH:
|
||||
description: |-
|
||||
&a Schakel dit in om te voorkomen
|
||||
|
@ -1322,28 +1333,19 @@ protection:
|
|||
&a terug naar hun eiland met behulp van commando's
|
||||
&a als ze vallen.
|
||||
hint: "&c Dat kun je niet doen terwijl je valt."
|
||||
VISITOR_KEEP_INVENTORY: {}
|
||||
WITHER_DAMAGE:
|
||||
name: Schakel schoftschade in
|
||||
description: |-
|
||||
&a Indien actief, kan de schoft
|
||||
&a schadeblokken en spelers
|
||||
WORLD_BLOCK_EXPLODE_DAMAGE: {}
|
||||
WORLD_TNT_DAMAGE:
|
||||
description: |-
|
||||
&a Allow TNT en TNT mijnkarren
|
||||
&a om blokken te breken en te beschadigen
|
||||
&a entiteit buiten de eilandgrenzen.
|
||||
name: Wereld TNT-schade
|
||||
PETS_STAY_AT_HOME:
|
||||
description: |-
|
||||
&a Bij actieve, getemde huisdieren
|
||||
&a kan alleen naar en gaan
|
||||
&a kan de eigenaar niet verlaten
|
||||
&a thuiseiland.
|
||||
name: Huisdieren blijven thuis
|
||||
HIVE:
|
||||
description: "&a Toggle bijenkorf oogsten."
|
||||
name: Bijenkorf oogsten
|
||||
hint: Oogsten uitgeschakeld
|
||||
locked: "&c Dit eiland is op slot!"
|
||||
protected: "&c Eiland beschermd: [omschrijving]."
|
||||
world-protected: "&c Wereld beschermd: [omschrijving]."
|
||||
|
@ -1361,8 +1363,8 @@ protection:
|
|||
expert:
|
||||
name: "&c Expertinstellingen"
|
||||
description: "&a Geeft alle beschikbare instellingen weer."
|
||||
click-to-switch: "&e Klik op &7 om over te schakelen naar de &r [volgende]
|
||||
&r &7."
|
||||
click-to-switch: "&e Klik op &7 om over te schakelen naar de &r [volgende] &r
|
||||
&7."
|
||||
reset-to-default:
|
||||
name: "&c Reset naar standaard"
|
||||
description: |
|
||||
|
@ -1530,29 +1532,6 @@ catalog:
|
|||
&a Sta BentoBox toe om verbinding te maken met GitHub in
|
||||
&a de configuratie of probeer het later opnieuw.
|
||||
|
||||
panel:
|
||||
credits:
|
||||
title: "&8 [name] &2 credits"
|
||||
contributor:
|
||||
name: "&a naam]"
|
||||
description: "&a Commits: &b [commits]\n"
|
||||
empty-here:
|
||||
name: "&c Dit ziet er hier leeg uit ..."
|
||||
description: |+
|
||||
&c BentoBox kon de bijdragers niet verzamelen
|
||||
&c voor deze add-on.
|
||||
|
||||
&a Sta BentoBox toe om verbinding te maken met GitHub in
|
||||
&a de configuratie of probeer het later opnieuw.
|
||||
|
||||
successfully-loaded: |2
|
||||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 door &a tastybento &7 en &a Poslovitch
|
||||
&6 | | _) | ___ _ __ | | _ ___ | | _) | _____ __ &7 2017-2021
|
||||
&6 | _ </ _ \ '_ \ | __ / _ \ | _ </ _ \ \ / /
|
||||
&6 | | _) | __ / | | | || (_) | | _) | (_)> <&b v &e [version]
|
||||
&6 | ____ / \ ___ | _ | | _ | \ __ \ ___ / | ____ / \ ___ / _ / \ _ \ &8 Geladen in &e [time] &8 ms.
|
||||
enums:
|
||||
DamageCause:
|
||||
CONTACT: Contact
|
||||
|
@ -1583,3 +1562,26 @@ enums:
|
|||
HOT_FLOOR: Hete vloer
|
||||
CRAMMING: Proppen
|
||||
DRYOUT: Uitdrogen
|
||||
panel:
|
||||
credits:
|
||||
title: "&8 [name] &2 credits"
|
||||
contributor:
|
||||
name: "&a naam]"
|
||||
description: "&a Commits: &b [commits]\n"
|
||||
empty-here:
|
||||
name: "&c Dit ziet er hier leeg uit ..."
|
||||
description: |+
|
||||
&c BentoBox kon de bijdragers niet verzamelen
|
||||
&c voor deze add-on.
|
||||
|
||||
&a Sta BentoBox toe om verbinding te maken met GitHub in
|
||||
&a de configuratie of probeer het later opnieuw.
|
||||
|
||||
successfully-loaded: |2
|
||||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 door &a tastybento &7 en &a Poslovitch
|
||||
&6 | | _) | ___ _ __ | | _ ___ | | _) | _____ __ &7 2017-2022
|
||||
&6 | _ </ _ \ '_ \ | __ / _ \ | _ </ _ \ \ / /
|
||||
&6 | | _) | __ / | | | || (_) | | _) | (_)> <&b v &e [version]
|
||||
&6 | ____ / \ ___ | _ | | _ | \ __ \ ___ / | ____ / \ ___ / _ / \ _ \ &8 Geladen in &e [time] &8 ms.
|
||||
|
|
|
@ -1435,7 +1435,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 by &a tastybento &7 i &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Wczytano w &e [time]&8 ms.
|
||||
|
|
|
@ -1463,7 +1463,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 por &a tastybento &7 e &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Carregado em &e [time]&8 ms.
|
||||
|
|
|
@ -1520,7 +1520,7 @@ successfully-loaded: |2
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7 by &a tastybento &7 and &a Poslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &7 2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Loaded in &e [time]&8 ms.
|
||||
|
|
|
@ -911,7 +911,7 @@ successfully-loaded: |
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7by &atastybento &7and &aPoslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8Loaded in &e[time]&8ms.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
meta:
|
||||
banner: RED_BANNER:1:RHOMBUS_MIDDLE:WHITE:CIRCLE_MIDDLE:RED:HALF_HORIZONTAL_MIRROR:RED:TRIANGLE_BOTTOM:WHITE:STRIPE_BOTTOM:RED
|
||||
authors:
|
||||
- Over_Brave
|
||||
- None
|
||||
banner: RED_BANNER:1:RHOMBUS_MIDDLE:WHITE:CIRCLE_MIDDLE:RED:HALF_HORIZONTAL_MIRROR:RED:TRIANGLE_BOTTOM:WHITE:STRIPE_BOTTOM:RED
|
||||
prefixes:
|
||||
bentobox: "&6 BentoBox &7 &l > &r "
|
||||
general:
|
||||
|
@ -74,6 +74,7 @@ commands:
|
|||
purge:
|
||||
parameters: "[gün]"
|
||||
description: Belirlediğiniz süreden uzun olan adaları siler.
|
||||
days-one-or-more: Gün sayısı 1 veya daha uzun olmalıdır.
|
||||
purgable-islands: "&e[number] &5silinebilecek ada bulundu!"
|
||||
purge-in-progress: "&cTemizleme devam ediyor. Durdurmak için durdurma komutunu
|
||||
kullanın."
|
||||
|
@ -100,7 +101,6 @@ commands:
|
|||
description: temizlemenin durumunu gösterir
|
||||
status: "&b [purgeable] &a adadan &b [purged]'si temizlendi &7(&b[percentage]
|
||||
%&7)&a."
|
||||
days-one-or-more: Gün sayısı 1 veya daha uzun olmalıdır.
|
||||
team:
|
||||
add:
|
||||
parameters: "<owner> <player>"
|
||||
|
@ -114,6 +114,16 @@ commands:
|
|||
use-disband-owner: "&4Sahibi degilsin. Sahibi &d[owner]"
|
||||
disbanded: "&4Admin takımınızı dağıttı!"
|
||||
success: "&d[name] &btakımı dağıtıldı!"
|
||||
fix:
|
||||
description: Veritabanındaki adalar arası üyeliği tarar ve düzeltir
|
||||
scanning: Veritabanı taranıyor ...
|
||||
duplicate-owner: "&c Oyuncunun veritabanında birden fazla adası var: [name]"
|
||||
player-has: "&c Oyuncu [name], [number] adaya sahip"
|
||||
duplicate-member: "&c [name], veri tabanında bulunan birden fazla adanın
|
||||
üyesi"
|
||||
rank-on-island: "&c [rank] adada [xyz]"
|
||||
fixed: "&a Sabit"
|
||||
done: "&a Tarama"
|
||||
kick:
|
||||
parameters: "<team player>"
|
||||
description: takımından oyuncu at
|
||||
|
@ -126,16 +136,6 @@ commands:
|
|||
description: Oyuncuya ada liderligini ver!
|
||||
already-owner: "&d[name] &4zaten ada sahibi!"
|
||||
success: "&d[name] &bartık adanın sahibi!"
|
||||
fix:
|
||||
description: Veritabanındaki adalar arası üyeliği tarar ve düzeltir
|
||||
scanning: Veritabanı taranıyor ...
|
||||
duplicate-owner: "&c Oyuncunun veritabanında birden fazla adası var: [name]"
|
||||
player-has: "&c Oyuncu [name], [number] adaya sahip"
|
||||
fixed: "&a Sabit"
|
||||
done: "&a Tarama"
|
||||
duplicate-member: "&c [name], veri tabanında bulunan birden fazla adanın
|
||||
üyesi"
|
||||
rank-on-island: "&c [rank] adada [xyz]"
|
||||
range:
|
||||
description: Admin ada menzili ayarlama
|
||||
invalid-value:
|
||||
|
@ -198,11 +198,14 @@ commands:
|
|||
island-uuid: "&5UUID: [uuid]"
|
||||
owner: "&bSahibi: &5[owner] ([uuid])"
|
||||
last-login: "&bSon giris: &5[date]"
|
||||
last-login-date-time-format: EEE MMM dd HH:mm:ss zzz yyyy
|
||||
deaths: "&bÖlme sayısı: &5[number]"
|
||||
resets-left: "&bSıfırlama hakkı: &5[number] (Max: [total])"
|
||||
team-members-title: "&bTakım üyeleri:"
|
||||
team-owner-format: "&d[name] [rank]"
|
||||
team-member-format: "&d[name] [rank]"
|
||||
island-protection-center: 'Korumalı alan merkezi: [xyz]'
|
||||
island-center: 'Ada merkezi: [xyz]'
|
||||
island-coords: "&bAda kordinatları: [xz1] ile [xz2] arasında"
|
||||
islands-in-trash: "&bOyuncun adası çöp kutusunda!"
|
||||
protection-range: "&bKoruma alanı: [range]"
|
||||
|
@ -213,8 +216,6 @@ commands:
|
|||
banned-players: "&b Banlanan oyuncular:"
|
||||
banned-format: "&4[name]"
|
||||
unowned: "&eBilinmiyor"
|
||||
island-protection-center: 'Korumalı alan merkezi: [xyz]'
|
||||
island-center: 'Ada merkezi: [xyz]'
|
||||
island-location: "&bAda lokasyonu: [xyz]"
|
||||
switch:
|
||||
description: Koruma izinlerine açma/kapama
|
||||
|
@ -266,6 +267,18 @@ commands:
|
|||
unknown-rank: "&4Bilinmeyen rütbe!"
|
||||
not-possible: "&cRütbe türü ziyaretçiden yüksek olmalıdır."
|
||||
rank-set: "&aRütbe &c[from]&a'dan &e[to] &ayükseltildi."
|
||||
setprotectionlocation:
|
||||
parameters: "[x y z coords]"
|
||||
description: Şu anki konumu veya [x y z] konumunu adanın koruma bölgesinin merkezi
|
||||
olarak ayarla
|
||||
island: "&c Bu [xyz] konumundaki '[name]' adlı kullanıcının adasını etkileyecek."
|
||||
confirmation: "&c Koruma bölgesinin merkezi olarak [xyz] konumunu ayarlamak
|
||||
istediğine emin misin?"
|
||||
success: "&a [xyz] konumu başarıyla koruma bölgesinin merkezi olarak ayarlandı."
|
||||
fail: "&a [xyz] noktası koruma bölgesinin merkezi olarak ayarlanamadı."
|
||||
island-location-changed: "&a [user] adlı kullanıcı adanın koruma alanı merkezini
|
||||
[xyz] konumuna değiştirdi."
|
||||
xyz-error: "&c Üç adet tam sayı koordinat girin: örn, 100 120 100"
|
||||
setspawn:
|
||||
description: Dünyanın adanın spawlanacağı bölgeyi seçer.
|
||||
already-spawn: "&cBu ada zaten spawnalacak bölgede."
|
||||
|
@ -349,9 +362,13 @@ commands:
|
|||
Place blueprint
|
||||
to right to set
|
||||
trash: Çöp
|
||||
no-trash: Çöp Kutusu olamaz
|
||||
trash-instructions: Silmek için sağ tıkla
|
||||
no-trash-instructions: Varsayılan grup çöp kutusuna atılamaz
|
||||
permission: Yetki
|
||||
no-permission: İzin yok
|
||||
perm-required: Yetki ihtyacı gerekli.
|
||||
no-perm-required: Varsayılan paket için izin ayarlanamaz
|
||||
perm-not-required: Yetki ihtiyacı yok.
|
||||
perm-format: "&e"
|
||||
remove: Silmek için sağ tıkla
|
||||
|
@ -380,13 +397,9 @@ commands:
|
|||
slot-instructions: |
|
||||
&aArtırmak için sol
|
||||
&aAzaltmak için sağ tıklayın.
|
||||
no-trash: Çöp Kutusu olamaz
|
||||
no-trash-instructions: Varsayılan grup çöp kutusuna atılamaz
|
||||
no-permission: İzin yok
|
||||
no-perm-required: Varsayılan paket için izin ayarlanamaz
|
||||
end: The End
|
||||
nether: Nether
|
||||
normal: Normal
|
||||
nether: Nether
|
||||
end: The End
|
||||
resetflags:
|
||||
parameters: "[flag]"
|
||||
description: Config.yml'deki tüm adaları varsayılan etiket ayarlarına sıfırla
|
||||
|
@ -400,6 +413,10 @@ commands:
|
|||
description: Oyuncunun adasını siler.
|
||||
cannot-delete-owner: "&4Silmeden önce adadaki herkesi at."
|
||||
deleted-island: "&e[xyz] &bkordinatlarındaki ada başarıyla silindi"
|
||||
deletehomes:
|
||||
parameters: "<oyuncu>"
|
||||
description: bir adadan tüm adlandırılmış evleri siler
|
||||
warning: "&c Adlandırılmış tüm evler adadan silinecek!"
|
||||
why:
|
||||
parameters: "<player>"
|
||||
description: Konsolu koruma hata ayıklama raporlaması
|
||||
|
@ -425,18 +442,6 @@ commands:
|
|||
parameters: "<oyuncu> <ölme sayısı>"
|
||||
success: "&d[name] &5oyuncusunun ölme sayısından &a[number] &5silindi. Toplam
|
||||
ölme sayısı: &5[total]'"
|
||||
setprotectionlocation:
|
||||
parameters: "[x y z coords]"
|
||||
description: Şu anki konumu veya [x y z] konumunu adanın koruma bölgesinin merkezi
|
||||
olarak ayarla
|
||||
island: "&c Bu [xyz] konumundaki '[name]' adlı kullanıcının adasını etkileyecek."
|
||||
confirmation: "&c Koruma bölgesinin merkezi olarak [xyz] konumunu ayarlamak
|
||||
istediğine emin misin?"
|
||||
success: "&a [xyz] konumu başarıyla koruma bölgesinin merkezi olarak ayarlandı."
|
||||
fail: "&a [xyz] noktası koruma bölgesinin merkezi olarak ayarlanamadı."
|
||||
island-location-changed: "&a [user] adlı kullanıcı adanın koruma alanı merkezini
|
||||
[xyz] konumuna değiştirdi."
|
||||
xyz-error: "&c Üç adet tam sayı koordinat girin: örn, 100 120 100"
|
||||
bentobox:
|
||||
description: BentoBox admin komudu
|
||||
about:
|
||||
|
@ -522,6 +527,11 @@ commands:
|
|||
on-first-login: "&9Hoşgeldin, adan bir kaç saniye içerisinde hazır olacaktır!"
|
||||
you-can-teleport-to-your-island: "&6İstediğiniz zaman adanıza ışınlanabilirsiniz."
|
||||
unknown-schem: "&4Taslak yüklenemedi!"
|
||||
deletehome:
|
||||
description: bir ev noktasını sil
|
||||
parameters: "[home name]"
|
||||
homes:
|
||||
description: evlerini listele
|
||||
info:
|
||||
description: Ada hakkında bilgi verir.
|
||||
parameters: "<player>"
|
||||
|
@ -549,7 +559,10 @@ commands:
|
|||
sethome:
|
||||
description: Oldugun noktaya ev olarak kaydeder
|
||||
must-be-on-your-island: "&4Önce adanda olmalısın!"
|
||||
too-many-homes: "&c Ayarlanamadı - adanızda maksimum sayıda [number] ev var."
|
||||
home-set: "&9Oldugun lokasyon ev olarak kaydedildi!"
|
||||
homes-are: "&6 Adadaki evler:"
|
||||
home-list-syntax: "&6 [name]"
|
||||
nether:
|
||||
not-allowed: "&4Netherde ev kaydetmek icin yetkin yok!."
|
||||
confirmation: "&4Nethera ev kaydetmek istedigine emin misin?"
|
||||
|
@ -557,9 +570,6 @@ commands:
|
|||
not-allowed: "&4Ende ev kaydetmek icin yetin yok!"
|
||||
confirmation: "&4Ende ev kaydetmek istedigine emin misin?"
|
||||
parameters: "[home number]"
|
||||
too-many-homes: "&c Ayarlanamadı - adanızda maksimum sayıda [number] ev var."
|
||||
homes-are: "&6 Adadaki evler:"
|
||||
home-list-syntax: "&6 [name]"
|
||||
setname:
|
||||
description: Ada ismini degistir.
|
||||
name-too-short: "&4Cok kısa. En az &e[number] &4karakter olabilir!."
|
||||
|
@ -567,6 +577,11 @@ commands:
|
|||
name-already-exists: "&cBöyle bir isim zaten bulunmakta."
|
||||
parameters: "<name>"
|
||||
success: "&9Yeni ada ismin &8- &a[name]"
|
||||
renamehome:
|
||||
description: bir evi yeniden adlandır
|
||||
parameters: "[home name]"
|
||||
enter-new-name: "&6 Yeni bir isim gir"
|
||||
already-exists: "&c Bu isim mevcut, lütfen farklı bir isim dene."
|
||||
resetname:
|
||||
description: Ada ismini resetle.
|
||||
success: "&9Ada ismini başarıyla sıfırladın."
|
||||
|
@ -733,16 +748,6 @@ commands:
|
|||
player-expelled-you: "&d[name] &4seni adadan attı!"
|
||||
success: "&d[name] &9oyuncusunu adadan attın!"
|
||||
cannot-ban-member: "&9Takımdan birisini adadan atamazsın!"
|
||||
deletehome:
|
||||
description: bir ev noktasını sil
|
||||
parameters: "[home name]"
|
||||
renamehome:
|
||||
description: bir evi yeniden adlandır
|
||||
parameters: "[home name]"
|
||||
enter-new-name: "&6 Yeni bir isim gir"
|
||||
already-exists: "&c Bu isim mevcut, lütfen farklı bir isim dene."
|
||||
homes:
|
||||
description: evlerini listele
|
||||
ranks:
|
||||
owner: Ada-Sahibi
|
||||
sub-owner: Yardımcı
|
||||
|
@ -826,6 +831,39 @@ protection:
|
|||
|
||||
&7Diğer kutular diğer etiketleri ilgilendirmekte.
|
||||
hint: Kutu kullanımı kapalı.
|
||||
CHEST:
|
||||
name: Sandıklar ve minecart sandıkları
|
||||
description: |-
|
||||
&a Toggle interaction with chests
|
||||
&a and chest minecarts.
|
||||
&a (does not include trapped chests)
|
||||
hint: Sandık erişimi devre dışı
|
||||
BARREL:
|
||||
name: Variller
|
||||
description: Varil etkileşimini aç/kapat
|
||||
hint: Varil erişimi devre dışı bırakıldı
|
||||
BLOCK_EXPLODE_DAMAGE:
|
||||
description: |-
|
||||
&a Allow Bed & Respawn Anchors
|
||||
&a to break blocks and damage
|
||||
&a entities.
|
||||
name: Patlama hasarını engelle
|
||||
COMPOSTER:
|
||||
name: Kompostolar
|
||||
description: Komposter etkileşimini aç/kapat
|
||||
hint: Komposto etkileşimi devre dışı bırakıldı
|
||||
FLOWER_POT:
|
||||
name: Çiçek saksıları
|
||||
description: Saksı etkileşimini aç/kapat
|
||||
hint: Saksı etkileşimi devre dışı bırakıldı
|
||||
SHULKER_BOX:
|
||||
name: Shulker kutuları
|
||||
description: Shulker kutusu etkileşimini aç/kapat
|
||||
hint: Shulker kutusu erişimi devre dışı bırakıldı
|
||||
TRAPPED_CHEST:
|
||||
name: Kapana kısılmış sandıklar
|
||||
description: Sıkışmış göğüs etkileşimini aç/kapat
|
||||
hint: Kapana kısılmış sandık erişimi devre dışı
|
||||
DISPENSER:
|
||||
name: Fırlatıcı
|
||||
description: Fırlatıcı kullanımı değiş.
|
||||
|
@ -981,6 +1019,10 @@ protection:
|
|||
GEO_LIMIT_MOBS:
|
||||
description: "&aAdanın koruma alanının dışındaki \n&amobları siler."
|
||||
name: "&eVarlıkları adayla sınırla."
|
||||
HIVE:
|
||||
description: "&a Kovan hasatını değiştir."
|
||||
name: Kovan hasatı
|
||||
hint: Hasat kapalı
|
||||
HURT_ANIMALS:
|
||||
description: Hasar alımını değiş
|
||||
name: Hayvan Hasarı
|
||||
|
@ -1117,6 +1159,13 @@ protection:
|
|||
&adeğilse redstonelar çalışmaz.
|
||||
&aLagı azaltmanızda yardımcı olabilir.
|
||||
name: Kapalı Redstone
|
||||
PETS_STAY_AT_HOME:
|
||||
description: |-
|
||||
&a Aktif iken, eğitilmiş
|
||||
&a hayvanlar sadece sahibin
|
||||
&a adasına gidebilir ve
|
||||
&a ana adadan ayrılamaz.
|
||||
name: Evcil hayvanlar evde kalır.
|
||||
PISTON_PUSH:
|
||||
description: |-
|
||||
&a Pistonların blokları adanın
|
||||
|
@ -1229,28 +1278,32 @@ protection:
|
|||
&aOyuncular adadan aşağa düşerken
|
||||
&aadaya geri dönme komudunu engeller.
|
||||
hint: "&cAdandan aşağaya düşerken adana geri ışınlanamazsın!"
|
||||
VISITOR_KEEP_INVENTORY:
|
||||
name: Ziyaretçiler ölümle ilgili envanter tutuyor
|
||||
description: |-
|
||||
&a Prevent players from losing their
|
||||
&a items and experience if they die on
|
||||
&a an island in which they are a visitor.
|
||||
&a
|
||||
&a Island members still lose their items
|
||||
&a if they die on their own island!
|
||||
WITHER_DAMAGE:
|
||||
name: Wither hasarını ayarlar.
|
||||
description: |-
|
||||
&aEğer etkin olursa oyunculara
|
||||
&ave adalara hasar verebilir.
|
||||
WORLD_BLOCK_EXPLODE_DAMAGE:
|
||||
description: |-
|
||||
&a Allow Bed & Respawn Anchors
|
||||
&a to break blocks and damage
|
||||
&a entities outside of island limits.
|
||||
name: Dünya bloğu patlama hasarı
|
||||
WORLD_TNT_DAMAGE:
|
||||
description: |-
|
||||
&a TNT ve TNT minecarts'ın blokları
|
||||
&a kırmasına ve ada sınırları dışındaki
|
||||
&a varlıklara zarar vermesine izin verin.
|
||||
name: Dünya TNT hasarı
|
||||
PETS_STAY_AT_HOME:
|
||||
description: |-
|
||||
&a Aktif iken, eğitilmiş
|
||||
&a hayvanlar sadece sahibin
|
||||
&a adasına gidebilir ve
|
||||
&a ana adadan ayrılamaz.
|
||||
name: Evcil hayvanlar evde kalır.
|
||||
HIVE:
|
||||
description: "&a Kovan hasatını değiştir."
|
||||
name: Kovan hasatı
|
||||
hint: Hasat kapalı
|
||||
ANIMAL_SPAWN:
|
||||
description: Doğmayı değiş
|
||||
name: Hayvan doğuşu
|
||||
|
@ -1399,26 +1452,6 @@ catalog:
|
|||
&aBentoBox'un konfigürasyondaki GitHub'a
|
||||
&abağlanmasına izin verin veya daha sonra tekrar deneyin.
|
||||
|
||||
panel:
|
||||
credits:
|
||||
title: "&8[name] &2Emeği geçenler"
|
||||
contributor:
|
||||
name: "&a[name]"
|
||||
description: "&a Commits: &b [commits]"
|
||||
empty-here:
|
||||
name: "&cBurası boş gibi gözüküyor..."
|
||||
description: |-
|
||||
&e● &cBentoBox bu Eklenti için Katkıda\n&cBulunanları &ctoplayamadı\
|
||||
.\n&f\n&e● &aBentoBox'ın yapılandırmada GitHub'a\n&abağlanmasına izin verin\
|
||||
\ veya daha \n&asonra tekrar deneyin.\n
|
||||
successfully-loaded: |2
|
||||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &bYazım yanlışları varsa iletişim:
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &cOver_Brave#9324 &b2017 - 2020
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ / &bYapımcısı : &atastybento &band &ePoslovitch
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bVersiyon &e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &e[time] &bsaniyede yüklendi!
|
||||
enums:
|
||||
DamageCause:
|
||||
CONTACT: Temas
|
||||
|
@ -1449,3 +1482,23 @@ enums:
|
|||
HOT_FLOOR: Sıcak Zemin
|
||||
CRAMMING: Sıkışma
|
||||
DRYOUT: Kuruma
|
||||
panel:
|
||||
credits:
|
||||
title: "&8[name] &2Emeği geçenler"
|
||||
contributor:
|
||||
name: "&a[name]"
|
||||
description: "&a Commits: &b [commits]"
|
||||
empty-here:
|
||||
name: "&cBurası boş gibi gözüküyor..."
|
||||
description: |-
|
||||
&e● &cBentoBox bu Eklenti için Katkıda\n&cBulunanları &ctoplayamadı\
|
||||
.\n&f\n&e● &aBentoBox'ın yapılandırmada GitHub'a\n&abağlanmasına izin verin\
|
||||
\ veya daha \n&asonra tekrar deneyin.\n
|
||||
successfully-loaded: |2
|
||||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &bYazım yanlışları varsa iletişim:
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &cOver_Brave#9324 &b2017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ / &bYapımcısı : &atastybento &band &ePoslovitch
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bVersiyon &e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &e[time] &bsaniyede yüklendi!
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -862,7 +862,7 @@ successfully-loaded: |
|
|||
|
||||
&6 ____ _ ____
|
||||
&6 | _ \ | | | _ \ &7by &atastybento &7and &aPoslovitch
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2020
|
||||
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
|
||||
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
|
||||
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
|
||||
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8使用了 &e[time]&8ms 來完成載入。
|
||||
|
|
|
@ -26,6 +26,7 @@ softdepend:
|
|||
- WildStacker
|
||||
- LuckPerms
|
||||
- HolographicDisplays
|
||||
- EconomyPlus
|
||||
|
||||
permissions:
|
||||
bentobox.admin:
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package world.bentobox.bentobox.database.objects;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -11,7 +9,6 @@ import static org.mockito.Mockito.when;
|
|||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
|
@ -101,17 +98,6 @@ public class PlayersTest {
|
|||
assertNotNull(new Players(plugin, UUID.randomUUID()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHomeLocationLocation() {
|
||||
Location l = mock(Location.class);
|
||||
when(l.getWorld()).thenReturn(world);
|
||||
p.setHomeLocation(l, 5);
|
||||
assertEquals(l, p.getHomeLocation(world, 5));
|
||||
assertNotEquals(l, p.getHomeLocation(world, 0));
|
||||
p.clearHomeLocations(world);
|
||||
assertTrue(p.getHomeLocations(world).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeaths() {
|
||||
assertEquals(0, p.getDeaths(world));
|
||||
|
|
|
@ -96,6 +96,7 @@ public class BlockEndDragonTest {
|
|||
when(block.getZ()).thenReturn(0);
|
||||
when(block.getWorld()).thenReturn(world);
|
||||
when(world.getBlockAt(anyInt(), anyInt(), anyInt())).thenReturn(block);
|
||||
when(world.getMaxHeight()).thenReturn(256);
|
||||
when(world.getEnvironment()).thenReturn(Environment.THE_END);
|
||||
// Player
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest;
|
|||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.listeners.flags.AbstractCommonSetup;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
@ -271,8 +272,8 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
|
|||
*/
|
||||
@Test
|
||||
public void testOnPlayerInteractEntityNamingWanderingTraderAllowedNoTrading() {
|
||||
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(WanderingTrader.class);
|
||||
when(clickedEntity.getType()).thenReturn(EntityType.WANDERING_TRADER);
|
||||
when(clickedEntity.getLocation()).thenReturn(location);
|
||||
|
@ -287,8 +288,8 @@ public class EntityInteractListenerTest extends AbstractCommonSetup {
|
|||
*/
|
||||
@Test
|
||||
public void testOnPlayerInteractEntityNamingWanderingTraderAllowedTradingNoNaming() {
|
||||
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(WanderingTrader.class);
|
||||
when(clickedEntity.getType()).thenReturn(EntityType.WANDERING_TRADER);
|
||||
when(clickedEntity.getLocation()).thenReturn(location);
|
||||
|
|
|
@ -107,7 +107,7 @@ public class TNTListenerTest extends AbstractCommonSetup {
|
|||
list.add(block);
|
||||
EntityExplodeEvent e = new EntityExplodeEvent(entity, location, list, 0);
|
||||
listener.onExplosion(e);
|
||||
assertTrue(list.isEmpty());
|
||||
assertTrue(e.isCancelled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -119,7 +119,7 @@ public class TNTListenerTest extends AbstractCommonSetup {
|
|||
list.add(block);
|
||||
EntityExplodeEvent e = new EntityExplodeEvent(entity, location, list, 0);
|
||||
listener.onExplosion(e);
|
||||
assertTrue(list.isEmpty());
|
||||
assertTrue(e.isCancelled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -131,6 +131,7 @@ public class TNTListenerTest extends AbstractCommonSetup {
|
|||
list.add(block);
|
||||
EntityExplodeEvent e = new EntityExplodeEvent(entity, location, list, 0);
|
||||
listener.onExplosion(e);
|
||||
assertFalse(e.isCancelled());
|
||||
assertFalse(list.isEmpty());
|
||||
}
|
||||
|
||||
|
@ -141,6 +142,7 @@ public class TNTListenerTest extends AbstractCommonSetup {
|
|||
list.add(block);
|
||||
EntityExplodeEvent e = new EntityExplodeEvent(entity, location, list, 0);
|
||||
listener.onExplosion(e);
|
||||
assertFalse(e.isCancelled());
|
||||
assertFalse(list.isEmpty());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
package world.bentobox.bentobox.listeners.flags.worldsettings;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
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.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
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.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||
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.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({BentoBox.class, Util.class})
|
||||
public class VisitorKeepInventoryListenerTest {
|
||||
|
||||
// Class under test
|
||||
private VisitorKeepInventoryListener l;
|
||||
@Mock
|
||||
private Player player;
|
||||
/* IslandWorldManager */
|
||||
@Mock
|
||||
private IslandWorldManager iwm;
|
||||
/* World */
|
||||
@Mock
|
||||
private World world;
|
||||
|
||||
/* Islands */
|
||||
@Mock
|
||||
private IslandsManager islandsManager;
|
||||
|
||||
@Mock
|
||||
private Island island;
|
||||
private PlayerDeathEvent e;
|
||||
@Mock
|
||||
private Location location;
|
||||
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// Set up plugin
|
||||
BentoBox plugin = mock(BentoBox.class);
|
||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||
/* Island World Manager */
|
||||
when(plugin.getIWM()).thenReturn(iwm);
|
||||
|
||||
// User
|
||||
User.setPlugin(plugin);
|
||||
UUID uuid = UUID.randomUUID();
|
||||
when(player.getUniqueId()).thenReturn(uuid);
|
||||
when(player.getName()).thenReturn("tastybento");
|
||||
when(player.getLocation()).thenReturn(location);
|
||||
when(location.getWorld()).thenReturn(world);
|
||||
when(location.toVector()).thenReturn(new Vector(1,2,3));
|
||||
// Turn on why for player
|
||||
when(player.getMetadata(eq("bskyblock_world_why_debug"))).thenReturn(Collections.singletonList(new FixedMetadataValue(plugin, true)));
|
||||
when(player.getMetadata(eq("bskyblock_world_why_debug_issuer"))).thenReturn(Collections.singletonList(new FixedMetadataValue(plugin, uuid.toString())));
|
||||
User.getInstance(player);
|
||||
|
||||
// WorldSettings and World Flags
|
||||
WorldSettings ws = mock(WorldSettings.class);
|
||||
when(iwm.getWorldSettings(any())).thenReturn(ws);
|
||||
Map<String, Boolean> worldFlags = new HashMap<>();
|
||||
when(ws.getWorldFlags()).thenReturn(worldFlags);
|
||||
|
||||
// World
|
||||
when(world.getName()).thenReturn("bskyblock_world");
|
||||
|
||||
// By default everything is in world
|
||||
when(iwm.inWorld(any(World.class))).thenReturn(true);
|
||||
when(iwm.inWorld(any(Location.class))).thenReturn(true);
|
||||
when(iwm.getAddon(any())).thenReturn(Optional.empty());
|
||||
|
||||
// Default not set
|
||||
Flags.VISITOR_KEEP_INVENTORY.setSetting(world, false);
|
||||
|
||||
/* Islands */
|
||||
when(plugin.getIslands()).thenReturn(islandsManager);
|
||||
// Visitor
|
||||
when(island.getMemberSet()).thenReturn(ImmutableSet.of());
|
||||
// By default, there should be an island.
|
||||
when(islandsManager.getProtectedIslandAt(any())).thenReturn(Optional.of(island));
|
||||
|
||||
// Util
|
||||
PowerMockito.mockStatic(Util.class, Mockito.CALLS_REAL_METHODS);
|
||||
when(Util.getWorld(any())).thenReturn(world);
|
||||
|
||||
// Default death event
|
||||
List<ItemStack> drops = new ArrayList<>();
|
||||
drops.add(new ItemStack(Material.ACACIA_BOAT));
|
||||
e = new PlayerDeathEvent(player, drops, 100, 0, 0, 0, "Death message");
|
||||
// Make new
|
||||
l = new VisitorKeepInventoryListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
User.clearUsers();
|
||||
Mockito.framework().clearInlineMocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.listeners.flags.worldsettings.VisitorKeepInventoryListener#onVisitorDeath(org.bukkit.event.entity.PlayerDeathEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnVisitorDeath() {
|
||||
l.onVisitorDeath(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.listeners.flags.worldsettings.VisitorKeepInventoryListener#onVisitorDeath(org.bukkit.event.entity.PlayerDeathEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnVisitorDeathFalseFlag() {
|
||||
l.onVisitorDeath(e);
|
||||
assertFalse(e.getKeepInventory());
|
||||
assertFalse(e.getKeepLevel());
|
||||
assertFalse(e.getDrops().isEmpty());
|
||||
assertEquals(100, e.getDroppedExp());
|
||||
// Why
|
||||
verify(player).sendMessage("Why: PlayerDeathEvent in world bskyblock_world at 1,2,3");
|
||||
verify(player).sendMessage("Why: tastybento VISITOR_KEEP_INVENTORY - SETTING_NOT_ALLOWED_IN_WORLD");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.listeners.flags.worldsettings.VisitorKeepInventoryListener#onVisitorDeath(org.bukkit.event.entity.PlayerDeathEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnVisitorDeathTrueFlag() {
|
||||
Flags.VISITOR_KEEP_INVENTORY.setSetting(world, true);
|
||||
l.onVisitorDeath(e);
|
||||
assertTrue(e.getKeepInventory());
|
||||
assertTrue(e.getKeepLevel());
|
||||
assertTrue(e.getDrops().isEmpty());
|
||||
assertEquals(0, e.getDroppedExp());
|
||||
// Why
|
||||
verify(player).sendMessage("Why: PlayerDeathEvent in world bskyblock_world at 1,2,3");
|
||||
verify(player).sendMessage("Why: tastybento VISITOR_KEEP_INVENTORY - SETTING_ALLOWED_IN_WORLD");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.listeners.flags.worldsettings.VisitorKeepInventoryListener#onVisitorDeath(org.bukkit.event.entity.PlayerDeathEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnVisitorDeathNotInWorld() {
|
||||
when(iwm.inWorld(eq(world))).thenReturn(false);
|
||||
Flags.VISITOR_KEEP_INVENTORY.setSetting(world, true);
|
||||
l.onVisitorDeath(e);
|
||||
assertFalse(e.getKeepInventory());
|
||||
assertFalse(e.getKeepLevel());
|
||||
assertFalse(e.getDrops().isEmpty());
|
||||
assertEquals(100, e.getDroppedExp());
|
||||
// Why
|
||||
verify(player).sendMessage("Why: PlayerDeathEvent in world bskyblock_world at 1,2,3");
|
||||
verify(player).sendMessage("Why: tastybento VISITOR_KEEP_INVENTORY - SETTING_NOT_ALLOWED_IN_WORLD");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.listeners.flags.worldsettings.VisitorKeepInventoryListener#onVisitorDeath(org.bukkit.event.entity.PlayerDeathEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnVisitorDeathTrueFlagNoIsland() {
|
||||
when(islandsManager.getProtectedIslandAt(any())).thenReturn(Optional.empty());
|
||||
Flags.VISITOR_KEEP_INVENTORY.setSetting(world, true);
|
||||
l.onVisitorDeath(e);
|
||||
assertFalse(e.getKeepInventory());
|
||||
assertFalse(e.getKeepLevel());
|
||||
assertFalse(e.getDrops().isEmpty());
|
||||
assertEquals(100, e.getDroppedExp());
|
||||
// Why
|
||||
verify(player, never()).sendMessage(anyString());
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import java.util.zip.ZipOutputStream;
|
|||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.After;
|
||||
|
@ -98,6 +99,8 @@ public class BlueprintClipboardManagerTest {
|
|||
" \"ySize\": 10,\n" +
|
||||
" \"zSize\": 10\n" +
|
||||
"}";
|
||||
@Mock
|
||||
private Server server;
|
||||
|
||||
private void zip(File targetFile) throws IOException {
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile.getAbsolutePath() + BlueprintsManager.BLUEPRINT_SUFFIX))) {
|
||||
|
@ -129,6 +132,9 @@ public class BlueprintClipboardManagerTest {
|
|||
BlockData blockData = mock(BlockData.class);
|
||||
when(Bukkit.createBlockData(any(Material.class))).thenReturn(blockData);
|
||||
when(blockData.getAsString()).thenReturn("test123");
|
||||
when(server.getBukkitVersion()).thenReturn("version");
|
||||
when(Bukkit.getServer()).thenReturn(server);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.jar.Manifest;
|
|||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
@ -93,6 +94,8 @@ public class BlueprintsManagerTest {
|
|||
private BukkitTask task;
|
||||
|
||||
private int times;
|
||||
@Mock
|
||||
private Server server;
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
|
@ -116,6 +119,8 @@ public class BlueprintsManagerTest {
|
|||
// Scheduler
|
||||
PowerMockito.mockStatic(Bukkit.class);
|
||||
when(Bukkit.getScheduler()).thenReturn(scheduler);
|
||||
when(server.getBukkitVersion()).thenReturn("version");
|
||||
when(Bukkit.getServer()).thenReturn(server);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ public class IslandDeletionManagerTest {
|
|||
private BukkitScheduler scheduler;
|
||||
@Mock
|
||||
private IslandWorldManager iwm;
|
||||
@Mock
|
||||
private IslandChunkDeletionManager chunkDeletionManager;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -101,6 +103,8 @@ public class IslandDeletionManagerTest {
|
|||
// IWM
|
||||
when(plugin.getIWM()).thenReturn(iwm);
|
||||
when(iwm.getIslandDistance(any())).thenReturn(64);
|
||||
// Chunk deletion manager
|
||||
when(plugin.getIslandChunkDeletionManager()).thenReturn(chunkDeletionManager);
|
||||
|
||||
// Island Deletion Manager
|
||||
idm = new IslandDeletionManager(plugin);
|
||||
|
|
|
@ -108,6 +108,8 @@ public class IslandsManagerTest {
|
|||
@Mock
|
||||
private IslandWorldManager iwm;
|
||||
@Mock
|
||||
private IslandChunkDeletionManager chunkDeletionManager;
|
||||
@Mock
|
||||
private IslandCache islandCache;
|
||||
private Optional<Island> optionalIsland;
|
||||
@Mock
|
||||
|
@ -158,6 +160,9 @@ public class IslandsManagerTest {
|
|||
when(iwm.inWorld(any(Location.class))).thenReturn(true);
|
||||
when(plugin.getIWM()).thenReturn(iwm);
|
||||
|
||||
// Chunk deletion manager
|
||||
when(plugin.getIslandChunkDeletionManager()).thenReturn(chunkDeletionManager);
|
||||
|
||||
// Settings
|
||||
Settings s = mock(Settings.class);
|
||||
when(plugin.getSettings()).thenReturn(s);
|
||||
|
|
|
@ -147,9 +147,17 @@ public class PlayersManagerTest {
|
|||
when(nether.getSpawnLocation()).thenReturn(netherSpawn);
|
||||
when(iwm.getNetherSpawnRadius(Mockito.any())).thenReturn(100);
|
||||
|
||||
// UUID
|
||||
uuid = UUID.randomUUID();
|
||||
notUUID = UUID.randomUUID();
|
||||
while(notUUID.equals(uuid)) {
|
||||
notUUID = UUID.randomUUID();
|
||||
}
|
||||
|
||||
// Player
|
||||
when(p.getEnderChest()).thenReturn(inv);
|
||||
when(p.getInventory()).thenReturn(playerInv);
|
||||
when(p.getUniqueId()).thenReturn(uuid);
|
||||
AttributeInstance at = mock(AttributeInstance.class);
|
||||
when(at.getValue()).thenReturn(20D);
|
||||
when(p.getAttribute(Attribute.GENERIC_MAX_HEALTH)).thenReturn(at);
|
||||
|
@ -157,11 +165,6 @@ public class PlayersManagerTest {
|
|||
// Sometimes use Mockito.withSettings().verboseLogging()
|
||||
user = mock(User.class);
|
||||
when(user.isOp()).thenReturn(false);
|
||||
uuid = UUID.randomUUID();
|
||||
notUUID = UUID.randomUUID();
|
||||
while(notUUID.equals(uuid)) {
|
||||
notUUID = UUID.randomUUID();
|
||||
}
|
||||
when(user.getUniqueId()).thenReturn(uuid);
|
||||
when(user.getPlayer()).thenReturn(p);
|
||||
when(user.getName()).thenReturn("tastybento");
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
package world.bentobox.bentobox.util.teleport;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.LocalesManager;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest(SafeSpotTeleport.Builder.class)
|
||||
public class SafeSpotTeleportBuilderTest {
|
||||
|
||||
@Mock
|
||||
private SafeSpotTeleport sst;
|
||||
@Mock
|
||||
private BentoBox plugin;
|
||||
@Mock
|
||||
private Player player;
|
||||
@Mock
|
||||
private Location loc;
|
||||
|
||||
@InjectMocks
|
||||
private SafeSpotTeleport.Builder sstb;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
PowerMockito.whenNew(SafeSpotTeleport.class).withAnyArguments().thenReturn(sst);
|
||||
// Users
|
||||
User.setPlugin(plugin);
|
||||
// Locales - final
|
||||
LocalesManager lm = mock(LocalesManager.class);
|
||||
when(plugin.getLocalesManager()).thenReturn(lm);
|
||||
when(lm.get(any(), any())).thenReturn("mock translation");
|
||||
// Addon
|
||||
IslandWorldManager iwm = mock(IslandWorldManager.class);
|
||||
when(iwm.getAddon(Mockito.any())).thenReturn(Optional.empty());
|
||||
when(plugin.getIWM()).thenReturn(iwm);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Mockito.framework().clearInlineMocks();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
sstb = new SafeSpotTeleport.Builder(plugin);
|
||||
// Should fail because no data
|
||||
assertNull(sstb.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntity() throws Exception {
|
||||
// Start builder
|
||||
sstb = new SafeSpotTeleport.Builder(plugin);
|
||||
// Add entity
|
||||
sstb.entity(player);
|
||||
// Test for error
|
||||
assertNull(sstb.build());
|
||||
// Add location
|
||||
sstb.location(loc);
|
||||
// Build - expect success
|
||||
SafeSpotTeleport result = sstb.build();
|
||||
assertEquals(sst, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsland() {
|
||||
// Start builder
|
||||
SafeSpotTeleport.Builder sstb = new SafeSpotTeleport.Builder(plugin);
|
||||
// Add entity
|
||||
sstb.entity(player);
|
||||
// Add island
|
||||
Island island = mock(Island.class);
|
||||
when(island.getProtectionCenter()).thenReturn(loc);
|
||||
sstb.island(island);
|
||||
// Build - expect success
|
||||
SafeSpotTeleport result = sstb.build();
|
||||
assertEquals(sst, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHomeNumber() {
|
||||
// Start builder
|
||||
SafeSpotTeleport.Builder sstb = new SafeSpotTeleport.Builder(plugin);
|
||||
// Add entity
|
||||
sstb.entity(player);
|
||||
// Add location
|
||||
sstb.location(loc);
|
||||
// Add home
|
||||
sstb.homeName("my name");
|
||||
// Build - expect success
|
||||
SafeSpotTeleport result = sstb.build();
|
||||
assertEquals(sst, result);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPortal() {
|
||||
// Start builder
|
||||
SafeSpotTeleport.Builder sstb = new SafeSpotTeleport.Builder(plugin);
|
||||
// Add entity
|
||||
sstb.entity(player);
|
||||
// Add location
|
||||
sstb.location(loc);
|
||||
// Portal
|
||||
sstb.portal();
|
||||
// Build - expect success
|
||||
SafeSpotTeleport result = sstb.build();
|
||||
assertEquals(sst, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailureMessage() {
|
||||
// Start builder
|
||||
SafeSpotTeleport.Builder sstb = new SafeSpotTeleport.Builder(plugin);
|
||||
// Add entity
|
||||
sstb.entity(player);
|
||||
// Add location
|
||||
sstb.location(loc);
|
||||
// Add failure
|
||||
sstb.failureMessage("testing 123");
|
||||
// Build - expect success
|
||||
SafeSpotTeleport result = sstb.build();
|
||||
assertEquals(sst, result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
package world.bentobox.bentobox.util.teleport;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||
import world.bentobox.bentobox.managers.IslandsManager;
|
||||
import world.bentobox.bentobox.util.Pair;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* Test class for safe teleporting
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({Util.class, Bukkit.class})
|
||||
public class SafeSpotTeleportTest {
|
||||
|
||||
// Class under test
|
||||
private SafeSpotTeleport sst;
|
||||
|
||||
@Mock
|
||||
private SafeSpotTeleport.Builder builder;
|
||||
@Mock
|
||||
private BentoBox plugin;
|
||||
@Mock
|
||||
private Location location;
|
||||
@Mock
|
||||
private World world;
|
||||
@Mock
|
||||
private Entity entity;
|
||||
|
||||
private boolean portal;
|
||||
|
||||
private int num;
|
||||
|
||||
private String name;
|
||||
@Mock
|
||||
private Runnable runnable;
|
||||
@Mock
|
||||
private Runnable failRunnable;
|
||||
@Mock
|
||||
private CompletableFuture<Boolean> result;
|
||||
@Mock
|
||||
private @NonNull CompletableFuture<Chunk> cfChunk;
|
||||
@Mock
|
||||
private IslandsManager im;
|
||||
@Mock
|
||||
private BukkitScheduler scheduler;
|
||||
|
||||
private Island island;
|
||||
@Mock
|
||||
private IslandWorldManager iwm;
|
||||
|
||||
@Mock
|
||||
private BukkitTask task;
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// Setup instance
|
||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||
// IWM
|
||||
when(iwm.getIslandProtectionRange(any())).thenReturn(100);
|
||||
when(iwm.getIslandDistance(any())).thenReturn(400);
|
||||
when(plugin.getIWM()).thenReturn(iwm);
|
||||
|
||||
// Mock static Util
|
||||
PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS);
|
||||
when(Util.getChunkAtAsync(any(Location.class))).thenReturn(cfChunk);
|
||||
// Same world
|
||||
when(Util.sameWorld(any(), any())).thenReturn(true);
|
||||
// Set up a mock builder
|
||||
when(builder.getPlugin()).thenReturn(plugin);
|
||||
when(builder.getEntity()).thenReturn(entity);
|
||||
when(builder.getLocation()).thenReturn(location);
|
||||
when(builder.isPortal()).thenReturn(portal);
|
||||
when(builder.getHomeNumber()).thenReturn(num);
|
||||
when(builder.getHomeName()).thenReturn(name);
|
||||
when(builder.getRunnable()).thenReturn(runnable);
|
||||
when(builder.getFailRunnable()).thenReturn(failRunnable);
|
||||
when(builder.getResult()).thenReturn(result);
|
||||
// Set the default world
|
||||
when(location.getWorld()).thenReturn(world);
|
||||
|
||||
// Island
|
||||
island = new Island(location, UUID.randomUUID(), 50);
|
||||
|
||||
// Plugin Island Manager
|
||||
// Default that locations are safe
|
||||
when(im.isSafeLocation(any(Location.class))).thenReturn(true);
|
||||
// Provide an island
|
||||
when(im.getIslandAt(any(Location.class))).thenReturn(Optional.of(island));
|
||||
|
||||
|
||||
when(plugin.getIslands()).thenReturn(im);
|
||||
|
||||
// Bukkit scheduler
|
||||
when(scheduler.runTaskTimer(eq(plugin), any(Runnable.class), anyLong(), anyLong())).thenReturn(task);
|
||||
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
|
||||
when(Bukkit.getScheduler()).thenReturn(scheduler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#SafeSpotTeleport(world.bentobox.bentobox.util.teleport.SafeSpotTeleport.Builder)}.
|
||||
*/
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testSafeSpotTeleportNullWorld() {
|
||||
when(location.getWorld()).thenReturn(null);
|
||||
sst = new SafeSpotTeleport(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#SafeSpotTeleport(world.bentobox.bentobox.util.teleport.SafeSpotTeleport.Builder)}.
|
||||
*/
|
||||
@Test
|
||||
public void testSafeSpotTeleport() {
|
||||
sst = new SafeSpotTeleport(builder);
|
||||
verify(cfChunk).thenRun(any(Runnable.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#tryToGo(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testTryToGoSafeNotPortal() {
|
||||
portal = false;
|
||||
testSafeSpotTeleport();
|
||||
sst.tryToGo("failure message");
|
||||
PowerMockito.verifyStatic(Util.class);
|
||||
// Verify that the teleport is done immediately
|
||||
Util.teleportAsync(entity, location);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#tryToGo(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testTryToGoUnsafe() {
|
||||
when(im.isSafeLocation(any(Location.class))).thenReturn(false);
|
||||
// Set up fields
|
||||
testSafeSpotTeleport();
|
||||
sst.tryToGo("failure message");
|
||||
verify(scheduler).runTaskTimer(eq(plugin), any(Runnable.class), eq(0L), eq(1L));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#gatherChunks(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testGatherChunks() {
|
||||
// Setup fields
|
||||
testTryToGoUnsafe();
|
||||
// run test
|
||||
assertTrue(sst.gatherChunks("failure message"));
|
||||
PowerMockito.verifyStatic(Util.class);
|
||||
Util.getChunkAtAsync(eq(world), anyInt(), anyInt());
|
||||
// run test again - should be blocked because of atomic boolean
|
||||
assertFalse(sst.gatherChunks("failure message"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#tidyUp(org.bukkit.entity.Entity, java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testTidyUpNoPlayerFailRunnable() {
|
||||
when(im.isSafeLocation(any(Location.class))).thenReturn(false);
|
||||
sst = new SafeSpotTeleport(builder);
|
||||
sst.tryToGo("failure message");
|
||||
sst.tidyUp(entity, "failure note");
|
||||
verify(task).cancel();
|
||||
verify(scheduler).runTask(plugin, failRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#tidyUp(org.bukkit.entity.Entity, java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testTidyUpPlayer() {
|
||||
when(im.isSafeLocation(any(Location.class))).thenReturn(false);
|
||||
sst = new SafeSpotTeleport(builder);
|
||||
sst.tryToGo("failure message");
|
||||
sst.tidyUp(entity, "failure note");
|
||||
verify(task).cancel();
|
||||
verify(scheduler).runTask(plugin, failRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#makeAndTeleport(org.bukkit.Material)}.
|
||||
*/
|
||||
@Test
|
||||
public void testMakeAndTeleport() {
|
||||
//fail("Not yet implemented"); // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#getChunksToScan()}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetChunksToScan() {
|
||||
testSafeSpotTeleport();
|
||||
List<Pair<Integer, Integer>> pairs = sst.getChunksToScan();
|
||||
assertEquals(62, pairs.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#scanChunk(org.bukkit.ChunkSnapshot)}.
|
||||
*/
|
||||
@Test
|
||||
public void testScanChunk() {
|
||||
//fail("Not yet implemented"); // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#teleportEntity(org.bukkit.Location)}.
|
||||
*/
|
||||
@Test
|
||||
public void testTeleportEntity() {
|
||||
//fail("Not yet implemented"); // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#checkBlock(org.bukkit.ChunkSnapshot, int, int, int)}.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckBlock() {
|
||||
//fail("Not yet implemented"); // TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.util.teleport.SafeSpotTeleport#safe(org.bukkit.ChunkSnapshot, int, int, int, org.bukkit.World)}.
|
||||
*/
|
||||
@Test
|
||||
public void testSafe() {
|
||||
//fail("Not yet implemented"); // TODO
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue