Code clean up from Sonar Cloud analysis (#2068)

* Code clean up from Sonar Cloud analysis

* Fix tests

* Remove code smell

* Rename "island" which hides the field declared at line 25.

* Removed code smells.

* Rename variable record to rec

Renamed "record" variable to not match a restricted identifier.
Restricted Identifiers should not be used as identifiers. "record" is
using in Java 16.

* Added private constructor to prevent instantiation of static class

Changed variable name to rec instead of restricted "record".

* Remove Blueprint code smells.

* Use a record for database settings constructor

Code smell: Methods should not have too many parameters. I'm not sure
what methods are using this class though.

* Update MyWorlds version

The POM for MyWorlds is invalid and causes a warning, but this still
persists with this version.

* Extracted nested try block into a separate method.

Makes it clear when reading the code what might be caught

* Extracted nested try block into a separate method.

* Fixed JavaDoc /** instead of just /*

* Extracted nested try block into a separate method.

* Refactored to not assign loop counter from within the loop body.

* Better delete option. With results.

That said, this is legacy code to handle an issue that occurred a long
time ago and this whole set of code can probably be removed.

* Catch Exceptions not Throwable

* Log error with BentoBox logError

* Use computeIfAbsent

Using these instead leads to cleaner and more readable code.

* User can no longer be null

* Added the missing @Deprecated annotation and @since ref

* Added @since reference

* Merge if statements

* Use BentoBox error logging.

* Added JavaDoc @since

* Remove deprecated class and move used class

* Remove deprecated WoodType and use Type.

* Remove unused import

* Extracted nested try block into a separate method.

* Comment empty default statement

* Clean up logic; avoid switch

* Use Java instead of Guava

* private constructor to hide the implicit public one.

* Private constructor to hide the implicit public one.

Merged if statement.

* Add comment

* if merge

* Make variable constant

* Remove unused imports

* Remove deprecated and unused method

* Remove unused import

* Typo

* Remove instanceof and cast

* Remove superfluous null check

* Put constant at bottom of file because @BONNe likes it there.

* Simplify particle validation code
This commit is contained in:
tastybento 2022-12-31 16:41:17 -08:00 committed by GitHub
parent 0183380b82
commit 056cff4b6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 594 additions and 652 deletions

View File

@ -82,7 +82,7 @@
<placeholderapi.version>2.10.9</placeholderapi.version>
<githubapi.version>d5f5e0bbd8</githubapi.version>
<dynmap.version>3.0-SNAPSHOT</dynmap.version>
<myworlds.version>1.19-v2</myworlds.version>
<myworlds.version>1.19.3-v1</myworlds.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- Do not change unless you want different name for local builds. -->

View File

@ -87,11 +87,9 @@ public class AdminSettingsCommand extends CompositeCommand {
}
private boolean getIsland(User user, List<String> args) {
if (args.get(0).equalsIgnoreCase(SPAWN_ISLAND)) {
if (getIslands().getSpawn(getWorld()).isPresent()) {
island = getIslands().getSpawn(getWorld()).get();
return true;
}
if (args.get(0).equalsIgnoreCase(SPAWN_ISLAND) && getIslands().getSpawn(getWorld()).isPresent()) {
island = getIslands().getSpawn(getWorld()).get();
return true;
}
// Get target player
@Nullable UUID targetUUID = Util.getUUID(args.get(0));
@ -191,17 +189,18 @@ public class AdminSettingsCommand extends CompositeCommand {
// Command line setting
flag.ifPresent(f -> {
switch (f.getType()) {
case PROTECTION -> {
island.setFlag(f, rank);
getIslands().save(island);
}
case SETTING -> {
island.setSettingsFlag(f, activeState);
getIslands().save(island);
}
case WORLD_SETTING -> f.setSetting(getWorld(), activeState);
default -> {
}
case PROTECTION -> {
island.setFlag(f, rank);
getIslands().save(island);
}
case SETTING -> {
island.setSettingsFlag(f, activeState);
getIslands().save(island);
}
case WORLD_SETTING -> f.setSetting(getWorld(), activeState);
default -> {
// Do nothing
}
}
});
user.sendMessage("general.success");

View File

@ -51,7 +51,7 @@ public class AdminBlueprintSaveCommand extends ConfirmableCommand
return false;
}
if (clipboard.getBlueprint().getBedrock() == null)
if (clipboard.getBlueprint() != null && clipboard.getBlueprint().getBedrock() == null)
{
// Bedrock is required for all blueprints.
user.sendMessage("commands.admin.blueprint.bedrock-required");

View File

@ -84,9 +84,9 @@ public class IslandDeletehomeCommand extends ConfirmableCommand {
@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
if (island != null) {
return Optional.of(Util.tabLimit(new ArrayList<>(island.getHomes().keySet()), lastArg));
Island is = getIslands().getIsland(getWorld(), user.getUniqueId());
if (is != null) {
return Optional.of(Util.tabLimit(new ArrayList<>(is.getHomes().keySet()), lastArg));
} else {
return Optional.empty();
}

View File

@ -55,13 +55,11 @@ public class IslandGoCommand extends DelayedTeleportCommand {
user.sendMessage(Flags.PREVENT_TELEPORT_WHEN_FALLING.getHintReference());
return false;
}
if (!args.isEmpty()) {
if (!getIslands().isHomeLocation(island, String.join(" ", args))) {
user.sendMessage("commands.island.go.unknown-home");
user.sendMessage("commands.island.sethome.homes-are");
island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s));
return false;
}
if (!args.isEmpty() && !getIslands().isHomeLocation(island, String.join(" ", args))) {
user.sendMessage("commands.island.go.unknown-home");
user.sendMessage("commands.island.sethome.homes-are");
island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s));
return false;
}
return true;
}

View File

@ -87,9 +87,9 @@ public class IslandRenamehomeCommand extends ConfirmableCommand {
@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
Island island = getIslands().getIsland(getWorld(), user.getUniqueId());
if (island != null) {
return Optional.of(Util.tabLimit(new ArrayList<>(island.getHomes().keySet()), lastArg));
Island is = getIslands().getIsland(getWorld(), user.getUniqueId());
if (is != null) {
return Optional.of(Util.tabLimit(new ArrayList<>(is.getHomes().keySet()), lastArg));
} else {
return Optional.empty();
}

View File

@ -96,22 +96,24 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
// Remove the invite
itc.removeInvite(playerUUID);
User inviter = User.getInstance(invite.getInviter());
if (inviter != null) {
Island island = getIslands().getIsland(getWorld(), inviter);
if (island != null) {
if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.TRUSTED_RANK)) {
user.sendMessage("commands.island.team.trust.is-full");
return;
}
island.setRank(user, RanksManager.TRUSTED_RANK);
IslandEvent.builder()
.island(island)
.involvedPlayer(user.getUniqueId())
.admin(false)
.reason(IslandEvent.Reason.RANK_CHANGE)
.rankChange(island.getRank(user), RanksManager.TRUSTED_RANK)
.build();
Island island = getIslands().getIsland(getWorld(), inviter);
if (island != null) {
if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.TRUSTED_RANK)) {
user.sendMessage("commands.island.team.trust.is-full");
return;
}
island.setRank(user, RanksManager.TRUSTED_RANK);
IslandEvent.builder()
.island(island)
.involvedPlayer(user.getUniqueId())
.admin(false)
.reason(IslandEvent.Reason.RANK_CHANGE)
.rankChange(island.getRank(user), RanksManager.TRUSTED_RANK)
.build();
if (inviter.isOnline()) {
inviter.sendMessage("commands.island.team.trust.success", TextVariables.NAME, user.getName());
}
if (inviter.isPlayer()) {
user.sendMessage("commands.island.team.trust.you-are-trusted", TextVariables.NAME, inviter.getName());
}
}
@ -121,22 +123,24 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
// Remove the invite
itc.removeInvite(playerUUID);
User inviter = User.getInstance(invite.getInviter());
if (inviter != null) {
Island island = getIslands().getIsland(getWorld(), inviter);
if (island != null) {
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.COOP_RANK)) {
user.sendMessage("commands.island.team.coop.is-full");
return;
}
island.setRank(user, RanksManager.COOP_RANK);
IslandEvent.builder()
.island(island)
.involvedPlayer(user.getUniqueId())
.admin(false)
.reason(IslandEvent.Reason.RANK_CHANGE)
.rankChange(island.getRank(user), RanksManager.COOP_RANK)
.build();
Island island = getIslands().getIsland(getWorld(), inviter);
if (island != null) {
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.COOP_RANK)) {
user.sendMessage("commands.island.team.coop.is-full");
return;
}
island.setRank(user, RanksManager.COOP_RANK);
IslandEvent.builder()
.island(island)
.involvedPlayer(user.getUniqueId())
.admin(false)
.reason(IslandEvent.Reason.RANK_CHANGE)
.rankChange(island.getRank(user), RanksManager.COOP_RANK)
.build();
if (inviter.isOnline()) {
inviter.sendMessage("commands.island.team.coop.success", TextVariables.NAME, user.getName());
}
if (inviter.isPlayer()) {
user.sendMessage("commands.island.team.coop.you-are-a-coop-member", TextVariables.NAME, inviter.getName());
}
}
@ -179,7 +183,7 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
}
user.sendMessage("commands.island.team.invite.accept.you-joined-island", TextVariables.LABEL, getTopLabel());
User inviter = User.getInstance(invite.getInviter());
if (inviter != null) {
if (inviter.isOnline()) {
inviter.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME, user.getName());
}
getIslands().save(teamIsland);

View File

@ -96,11 +96,11 @@ public class TemplatedPanel extends Panel
{
for (int k = 0; k < this.panelTemplate.content()[i].length; k++)
{
ItemTemplateRecord record = this.panelTemplate.content()[i][k];
ItemTemplateRecord rec = this.panelTemplate.content()[i][k];
if (record != null && record.dataMap().containsKey("type"))
if (rec != null && rec.dataMap().containsKey("type"))
{
String type = String.valueOf(record.dataMap().get("type"));
String type = String.valueOf(rec.dataMap().get("type"));
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
this.typeSlotMap.put(type, counter + 1);
@ -226,11 +226,11 @@ public class TemplatedPanel extends Panel
// Analyze the template
for (int i = 0; i < 5; i++)
{
ItemTemplateRecord record = this.panelTemplate.content()[0][i];
ItemTemplateRecord rec = this.panelTemplate.content()[0][i];
if (record != null && record.dataMap().containsKey("type"))
if (rec != null && rec.dataMap().containsKey("type"))
{
String type = String.valueOf(record.dataMap().get("type"));
String type = String.valueOf(rec.dataMap().get("type"));
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
this.typeSlotMap.put(type, counter + 1);
@ -289,11 +289,11 @@ public class TemplatedPanel extends Panel
{
for (int k = 0; k < 3; k++)
{
ItemTemplateRecord record = this.panelTemplate.content()[i][k];
ItemTemplateRecord rec = this.panelTemplate.content()[i][k];
if (record != null && record.dataMap().containsKey("type"))
if (rec != null && rec.dataMap().containsKey("type"))
{
String type = String.valueOf(record.dataMap().get("type"));
String type = String.valueOf(rec.dataMap().get("type"));
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
this.typeSlotMap.put(type, counter + 1);
@ -354,41 +354,41 @@ public class TemplatedPanel extends Panel
/**
* This method passes button creation from given record template.
* @param record Template of the button that must be created.
* @param rec Template of the button that must be created.
* @return PanelItem of the template, otherwise null.
*/
@Nullable
private PanelItem makeButton(@Nullable ItemTemplateRecord record)
private PanelItem makeButton(@Nullable ItemTemplateRecord rec)
{
if (record == null)
if (rec == null)
{
// Immediate exit if record is null.
return null;
}
if (record.dataMap().containsKey("type"))
if (rec.dataMap().containsKey("type"))
{
// If dataMap is not null, and it is not empty, then pass button to the object creator function.
return this.makeAddonButton(record);
return this.makeAddonButton(rec);
}
else
{
PanelItemBuilder itemBuilder = new PanelItemBuilder();
if (record.icon() != null)
if (rec.icon() != null)
{
itemBuilder.icon(record.icon().clone());
itemBuilder.icon(rec.icon().clone());
}
if (record.title() != null)
if (rec.title() != null)
{
itemBuilder.name(this.user.getTranslation(record.title()));
itemBuilder.name(this.user.getTranslation(rec.title()));
}
if (record.description() != null)
if (rec.description() != null)
{
itemBuilder.description(this.user.getTranslation(record.description()));
itemBuilder.description(this.user.getTranslation(rec.description()));
}
// If there are generic click handlers that could be added, then this is a place
@ -402,19 +402,19 @@ public class TemplatedPanel extends Panel
/**
* This method passes button to the type creator, if that exists.
* @param record Template of the button that must be created.
* @param rec Template of the button that must be created.
* @return PanelItem of the button created by typeCreator, otherwise null.
*/
@Nullable
private PanelItem makeAddonButton(@NonNull ItemTemplateRecord record)
private PanelItem makeAddonButton(@NonNull ItemTemplateRecord rec)
{
// Get object type.
String type = String.valueOf(record.dataMap().getOrDefault("type", ""));
String type = String.valueOf(rec.dataMap().getOrDefault("type", ""));
if (!this.typeCreators.containsKey(type))
{
// There are no object with a given type.
return this.makeFallBack(record.fallback());
return this.makeFallBack(rec.fallback());
}
BiFunction<ItemTemplateRecord, ItemSlot, PanelItem> buttonBuilder = this.typeCreators.get(type);
@ -426,48 +426,48 @@ public class TemplatedPanel extends Panel
this.typeIndex.put(type, itemSlot.nextItemSlot());
// Try to get next object.
PanelItem item = buttonBuilder.apply(record, itemSlot);
return item == null ? this.makeFallBack(record.fallback()) : item;
PanelItem item = buttonBuilder.apply(rec, itemSlot);
return item == null ? this.makeFallBack(rec.fallback()) : item;
}
/**
* This method creates a fall back button for given record.
* @param record Record which fallback must be created.
* @param rec Record which fallback must be created.
* @return PanelItem if fallback was creates successfully, otherwise null.
*/
@Nullable
private PanelItem makeFallBack(@Nullable ItemTemplateRecord record)
private PanelItem makeFallBack(@Nullable ItemTemplateRecord rec)
{
return record == null ? null : this.makeButton(record.fallback());
return rec == null ? null : this.makeButton(rec.fallback());
}
/**
* This method translates template record into a panel item.
* @param record Record that must be translated.
* @param rec Record that must be translated.
* @return PanelItem that contains all information from the record.
*/
private PanelItem makeTemplate(PanelTemplateRecord.TemplateItem record)
private PanelItem makeTemplate(PanelTemplateRecord.TemplateItem rec)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder();
// Read icon only if it is not null.
if (record.icon() != null)
if (rec.icon() != null)
{
itemBuilder.icon(record.icon().clone());
itemBuilder.icon(rec.icon().clone());
}
// Read title only if it is not null.
if (record.title() != null)
if (rec.title() != null)
{
itemBuilder.name(this.user.getTranslation(record.title()));
itemBuilder.name(this.user.getTranslation(rec.title()));
}
// Read description only if it is not null.
if (record.description() != null)
if (rec.description() != null)
{
itemBuilder.description(this.user.getTranslation(record.description()));
itemBuilder.description(this.user.getTranslation(rec.description()));
}
// Click Handlers are managed by custom addon buttons.

View File

@ -17,7 +17,6 @@ import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
/**
* This Record contains all necessary information about Item Template that can be used to craft panel item.
*

View File

@ -16,7 +16,6 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.panels.Panel;
/**
* This is template object for the panel reader. It contains data that can exist in the panel.
* PanelBuilder will use this to build panel.

View File

@ -49,6 +49,14 @@ public class TemplateReader
private static final String TYPE = "type";
/**
* Utility classes, which are collections of static members, are not meant to be instantiated.
* Even abstract utility classes, which can be extended, should not have public constructors.
* Java adds an implicit public constructor to every class which does not define at least one explicitly.
* Hence, at least one non-public constructor should be defined.
*/
private TemplateReader() {}
/**
* Read template panel panel template record.
*
@ -95,7 +103,7 @@ public class TemplateReader
return TemplateReader.loadedPanels.get(panelKey);
}
PanelTemplateRecord record;
PanelTemplateRecord rec;
try
{
@ -103,16 +111,16 @@ public class TemplateReader
YamlConfiguration config = new YamlConfiguration();
config.load(file);
// Read panel
record = readPanelTemplate(config.getConfigurationSection(panelName));
rec = readPanelTemplate(config.getConfigurationSection(panelName));
// Put panel into memory
TemplateReader.loadedPanels.put(panelKey, record);
TemplateReader.loadedPanels.put(panelKey, rec);
}
catch (IOException | InvalidConfigurationException e)
{
record = null;
rec = null;
}
return record;
return rec;
}

View File

@ -1,5 +1,7 @@
package world.bentobox.bentobox.api.user;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@ -16,6 +18,7 @@ import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.Particle;
import org.bukkit.Particle.DustTransition;
import org.bukkit.Vibration;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
@ -53,6 +56,26 @@ public class User implements MetaDataAble {
private static final Map<UUID, User> users = new HashMap<>();
// Used for particle validation
private static final Map<Particle, Class<?>> VALIDATION_CHECK;
static {
Map<Particle, Class<?>> v = new EnumMap<>(Particle.class);
v.put(Particle.REDSTONE, Particle.DustOptions.class);
v.put(Particle.ITEM_CRACK, ItemStack.class);
v.put(Particle.BLOCK_CRACK, BlockData.class);
v.put(Particle.BLOCK_DUST, BlockData.class);
v.put(Particle.FALLING_DUST, BlockData.class);
v.put(Particle.BLOCK_MARKER, BlockData.class);
v.put(Particle.DUST_COLOR_TRANSITION, DustTransition.class);
v.put(Particle.VIBRATION, Vibration.class);
v.put(Particle.SCULK_CHARGE, Float.class);
v.put(Particle.SHRIEK, Integer.class);
v.put(Particle.LEGACY_BLOCK_CRACK, BlockData.class);
v.put(Particle.LEGACY_BLOCK_DUST, BlockData.class);
v.put(Particle.LEGACY_FALLING_DUST, BlockData.class);
VALIDATION_CHECK = Collections.unmodifiableMap(v);
}
/**
* Clears all users from the user list
*/
@ -88,7 +111,8 @@ public class User implements MetaDataAble {
}
/**
* Gets an instance of User from a UUID.
* Gets an instance of User from a UUID. This will always return a user object.
* If the player is offline then the getPlayer value will be null.
* @param uuid - UUID
* @return user - user
*/
@ -97,7 +121,7 @@ public class User implements MetaDataAble {
if (users.containsKey(uuid)) {
return users.get(uuid);
}
// Return player, or null if they are not online
// Return a user instance
return new User(uuid);
}
@ -597,73 +621,18 @@ public class User implements MetaDataAble {
* @param y Y coordinate of the particle to display.
* @param z Z coordinate of the particle to display.
*/
public void spawnParticle(Particle particle, Object dustOptions, double x, double y, double z)
public void spawnParticle(Particle particle, @Nullable Object dustOptions, double x, double y, double z)
{
// Improve particle validation.
switch (particle)
{
case REDSTONE ->
{
if (!(dustOptions instanceof Particle.DustOptions))
{
throw new IllegalArgumentException("A non-null Particle.DustOptions must be provided when using Particle.REDSTONE as particle.");
}
}
case ITEM_CRACK ->
{
if (!(dustOptions instanceof ItemStack))
{
throw new IllegalArgumentException("A non-null ItemStack must be provided when using Particle.ITEM_CRACK as particle.");
}
}
case BLOCK_CRACK, BLOCK_DUST, FALLING_DUST, BLOCK_MARKER ->
{
if (!(dustOptions instanceof BlockData))
{
throw new IllegalArgumentException("A non-null BlockData must be provided when using Particle." + particle + " as particle.");
}
}
case DUST_COLOR_TRANSITION ->
{
if (!(dustOptions instanceof Particle.DustTransition))
{
throw new IllegalArgumentException("A non-null Particle.DustTransition must be provided when using Particle.DUST_COLOR_TRANSITION as particle.");
}
}
case VIBRATION ->
{
if (!(dustOptions instanceof Vibration))
{
throw new IllegalArgumentException("A non-null Vibration must be provided when using Particle.VIBRATION as particle.");
}
}
case SCULK_CHARGE ->
{
if (!(dustOptions instanceof Float))
{
throw new IllegalArgumentException("A non-null Float must be provided when using Particle.SCULK_CHARGE as particle.");
}
}
case SHRIEK ->
{
if (!(dustOptions instanceof Integer))
{
throw new IllegalArgumentException("A non-null Integer must be provided when using Particle.SHRIEK as particle.");
}
}
case LEGACY_BLOCK_CRACK, LEGACY_BLOCK_DUST, LEGACY_FALLING_DUST ->
{
if (!(dustOptions instanceof BlockData))
{
throw new IllegalArgumentException("A non-null MaterialData must be provided when using Particle." + particle + " as particle.");
}
}
default -> throw new IllegalArgumentException("Unexpected value: " + particle);
Class<?> expectedClass = VALIDATION_CHECK.get(dustOptions);
if (expectedClass == null) throw new IllegalArgumentException("Unexpected value: " + particle);
if (!(expectedClass.isInstance(dustOptions))) {
throw new IllegalArgumentException("A non-null " + expectedClass.getName() + " must be provided when using Particle." + particle + " as particle.");
}
// Check if this particle is beyond the viewing distance of the server
if (this.player != null &&
this.player.getLocation().toVector().distanceSquared(new Vector(x, y, z)) <
if (this.player != null
&& this.player.getLocation().toVector().distanceSquared(new Vector(x, y, z)) <
(Bukkit.getServer().getViewDistance() * 256 * Bukkit.getServer().getViewDistance()))
{
if (particle.equals(Particle.REDSTONE))

View File

@ -287,10 +287,8 @@ public class BlueprintClipboard {
if (entity instanceof Villager villager) {
setVillager(villager, bpe);
}
if (entity instanceof Colorable c) {
if (c.getColor() != null) {
bpe.setColor(c.getColor());
}
if (entity instanceof Colorable c && c.getColor() != null) {
bpe.setColor(c.getColor());
}
if (entity instanceof Tameable) {
bpe.setTamed(((Tameable)entity).isTamed());
@ -374,7 +372,7 @@ public class BlueprintClipboard {
if (pos1 != null) {
final int minHeight = pos1.getWorld() == null ? 0 : pos1.getWorld().getMinHeight();
final int maxHeight = pos1.getWorld() == null ? 255 : pos1.getWorld().getMaxHeight();
if (pos1.getBlockY() < minHeight)
{
pos1.setY(minHeight);

View File

@ -229,13 +229,13 @@ public class BlueprintPaster {
} else {
pasteState = PasteState.DONE;
String world = switch (location.getWorld().getEnvironment()) {
String dimensionType = switch (location.getWorld().getEnvironment()) {
case NETHER -> owner.map(user -> user.getTranslation("general.worlds.nether")).orElse("");
case THE_END -> owner.map(user -> user.getTranslation("general.worlds.the-end")).orElse("");
default -> owner.map(user -> user.getTranslation("general.worlds.overworld")).orElse("");
};
owner.ifPresent(user -> user.sendMessage("commands.island.create.pasting.dimension-done", "[world]", world));
owner.ifPresent(user -> user.sendMessage("commands.island.create.pasting.dimension-done", "[world]", dimensionType));
}
}
else if (pasteState.equals(PasteState.DONE)) {

View File

@ -102,7 +102,8 @@ public class Database<T> {
* Save object. Saving may be done async or sync, depending on the underlying database.
* @param instance to save
* @return true - always.
* @deprecated As of 1.13.0. Use {@link #saveObjectAsync(Object)}.
* @deprecated Use {@link #saveObjectAsync(Object)}.
* @since 1.13.0
*/
@Deprecated
public boolean saveObject(T instance) {

View File

@ -39,27 +39,35 @@ public class DatabaseConnectionSettingsImpl {
* @param host - database host
* @param port - port
* @param databaseName - database name
* @param username - username
* @param username - username
* @param password - password
* @param useSSL - whether to use SSL or not
* @param maxConnections - max number of connections
* @param extraProperties Map with extra properties.
*/
public DatabaseConnectionSettingsImpl(String host,
int port,
String databaseName,
String username,
String password,
boolean useSSL,
int maxConnections,
Map<String, String> extraProperties)
public record DatabaseSettings(String host,
int port,
String databaseName,
String username,
String password,
boolean useSSL,
int maxConnections,
Map<String, String> extraProperties) {}
/**
* Hosts database settings
* @param settings - database settings see {@link DatabaseSettings}
*/
public DatabaseConnectionSettingsImpl(DatabaseSettings settings)
{
this.host = host;
this.port = port;
this.databaseName = databaseName;
this.username = username;
this.password = password;
this.useSSL = useSSL;
this.maxConnections = maxConnections;
this.extraProperties = extraProperties;
this.host = settings.host;
this.port = settings.port;
this.databaseName = settings.databaseName;
this.username = settings.username;
this.password = settings.password;
this.useSSL = settings.useSSL;
this.maxConnections = settings.maxConnections;
this.extraProperties = settings.extraProperties;
}
@ -74,14 +82,14 @@ public class DatabaseConnectionSettingsImpl {
* @param maxConnections - number of maximal connections in pool.
*/
public DatabaseConnectionSettingsImpl(String host,
int port,
String databaseName,
String username,
String password,
boolean useSSL,
int maxConnections)
int port,
String databaseName,
String username,
String password,
boolean useSSL,
int maxConnections)
{
this(host, port, databaseName, username, password, useSSL, maxConnections, Collections.emptyMap());
this(new DatabaseSettings(host, port, databaseName, username, password, useSSL, maxConnections, Collections.emptyMap()));
}
@ -95,13 +103,13 @@ public class DatabaseConnectionSettingsImpl {
* @param useSSL - ssl usage.
*/
public DatabaseConnectionSettingsImpl(String host,
int port,
String databaseName,
String username,
String password,
boolean useSSL)
int port,
String databaseName,
String username,
String password,
boolean useSSL)
{
this(host, port, databaseName, username, password, useSSL, 0, Collections.emptyMap());
this(new DatabaseSettings(host, port, databaseName, username, password, useSSL, 0, Collections.emptyMap()));
}

View File

@ -97,31 +97,31 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
{
// Transition from the old table name
String sql = this.sqlConfig.getRenameTableSQL().
replace("[oldTableName]", this.sqlConfig.getOldTableName()).
replace("[tableName]", this.sqlConfig.getTableName());
replace("[oldTableName]", this.sqlConfig.getOldTableName()).
replace("[tableName]", this.sqlConfig.getTableName());
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql))
PreparedStatement preparedStatement = connection.prepareStatement(sql))
{
preparedStatement.execute();
}
catch (SQLException e)
{
this.plugin.logError("Could not rename " + this.sqlConfig.getOldTableName() + " for data object " +
this.dataObject.getCanonicalName() + " " + e.getMessage());
this.dataObject.getCanonicalName() + " " + e.getMessage());
}
}
// Prepare and execute the database statements
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getSchemaSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getSchemaSQL()))
{
preparedStatement.execute();
}
catch (SQLException e)
{
this.plugin.logError("Problem trying to create schema for data object " +
this.dataObject.getCanonicalName() + " " + e.getMessage());
this.dataObject.getCanonicalName() + " " + e.getMessage());
}
}
@ -133,7 +133,7 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
public List<T> loadObjects()
{
try (Connection connection = this.dataSource.getConnection();
Statement preparedStatement = connection.createStatement())
Statement preparedStatement = connection.createStatement())
{
return this.loadIt(preparedStatement);
}
@ -166,20 +166,7 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
if (json != null)
{
try
{
T gsonResult = gson.fromJson(json, this.dataObject);
if (gsonResult != null)
{
list.add(gsonResult);
}
}
catch (JsonSyntaxException ex)
{
this.plugin.logError(COULD_NOT_LOAD_OBJECT + ex.getMessage());
this.plugin.logError(json);
}
getGsonResultSet(gson, json, list);
}
}
}
@ -192,37 +179,68 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
}
private void getGsonResultSet(Gson gson, String json, List<T> list) {
try
{
T gsonResult = gson.fromJson(json, this.dataObject);
if (gsonResult != null)
{
list.add(gsonResult);
}
}
catch (JsonSyntaxException ex)
{
this.plugin.logError(COULD_NOT_LOAD_OBJECT + ex.getMessage());
this.plugin.logError(json);
}
}
/**
* {@inheritDoc}
*/
@Override
public T loadObject(@NonNull String uniqueId)
{
T result = null;
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getLoadObjectSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getLoadObjectSQL()))
{
// UniqueId needs to be placed in quotes?
preparedStatement.setString(1, this.sqlConfig.isUseQuotes() ? "\"" + uniqueId + "\"" : uniqueId);
try (ResultSet resultSet = preparedStatement.executeQuery())
{
if (resultSet.next())
{
// If there is a result, we only want/need the first one
Gson gson = this.getGson();
return gson.fromJson(resultSet.getString("json"), this.dataObject);
}
}
catch (Exception e)
{
this.plugin.logError(COULD_NOT_LOAD_OBJECT + uniqueId + " " + e.getMessage());
}
result = getObject(uniqueId, preparedStatement);
}
catch (SQLException e)
{
this.plugin.logError(COULD_NOT_LOAD_OBJECT + uniqueId + " " + e.getMessage());
}
return result;
}
/**
* Return the object decoded from JSON or null if there is an error
* @param uniqueId - unique Id of object used in error reporting
* @param preparedStatement - database statement to execute
* @return
*/
private T getObject(@NonNull String uniqueId, PreparedStatement preparedStatement) {
try (ResultSet resultSet = preparedStatement.executeQuery())
{
if (resultSet.next())
{
// If there is a result, we only want/need the first one
Gson gson = this.getGson();
return gson.fromJson(resultSet.getString("json"), this.dataObject);
}
}
catch (Exception e)
{
this.plugin.logError(COULD_NOT_LOAD_OBJECT + uniqueId + " " + e.getMessage());
}
return null;
}
@ -257,10 +275,10 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
{
// Async
this.processQueue.add(() -> store(completableFuture,
instance.getClass().getName(),
toStore,
this.sqlConfig.getSaveObjectSQL(),
true));
instance.getClass().getName(),
toStore,
this.sqlConfig.getSaveObjectSQL(),
true));
}
else
{
@ -289,7 +307,7 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
}
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(storeSQL))
PreparedStatement preparedStatement = connection.prepareStatement(storeSQL))
{
preparedStatement.setString(1, toStore);
preparedStatement.setString(2, toStore);
@ -321,7 +339,7 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
private void delete(String uniqueId)
{
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getDeleteObjectSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getDeleteObjectSQL()))
{
// UniqueId needs to be placed in quotes?
preparedStatement.setString(1, this.sqlConfig.isUseQuotes() ? "\"" + uniqueId + "\"" : uniqueId);
@ -330,7 +348,7 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
catch (Exception e)
{
this.plugin.logError("Could not delete object " + this.plugin.getSettings().getDatabasePrefix() +
this.dataObject.getCanonicalName() + " " + uniqueId + " " + e.getMessage());
this.dataObject.getCanonicalName() + " " + uniqueId + " " + e.getMessage());
}
}
@ -374,7 +392,7 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T>
{
// Query to see if this key exists
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getObjectExistsSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.sqlConfig.getObjectExistsSQL()))
{
// UniqueId needs to be placed in quotes?
preparedStatement.setString(1, this.sqlConfig.isUseQuotes() ? "\"" + uniqueId + "\"" : uniqueId);

View File

@ -17,7 +17,7 @@ public class MariaDBDatabase implements DatabaseSetup
private MariaDBDatabaseConnector connector;
/*
/**
* {@inheritDoc}
*/
@Override
@ -28,13 +28,13 @@ public class MariaDBDatabase implements DatabaseSetup
if (this.connector == null)
{
this.connector = new MariaDBDatabaseConnector(new DatabaseConnectionSettingsImpl(
plugin.getSettings().getDatabaseHost(),
plugin.getSettings().getDatabasePort(),
plugin.getSettings().getDatabaseName(),
plugin.getSettings().getDatabaseUsername(),
plugin.getSettings().getDatabasePassword(),
plugin.getSettings().isUseSSL(),
plugin.getSettings().getMaximumPoolSize()));
plugin.getSettings().getDatabaseHost(),
plugin.getSettings().getDatabasePort(),
plugin.getSettings().getDatabaseName(),
plugin.getSettings().getDatabaseUsername(),
plugin.getSettings().getDatabasePassword(),
plugin.getSettings().isUseSSL(),
plugin.getSettings().getMaximumPoolSize()));
}
return new MariaDBDatabaseHandler<>(plugin, type, this.connector);

View File

@ -13,7 +13,7 @@ public class MySQLDatabase implements DatabaseSetup
private MySQLDatabaseConnector connector;
/*
/**
* {@inheritDoc}
*/
@Override
@ -24,13 +24,13 @@ public class MySQLDatabase implements DatabaseSetup
if (this.connector == null)
{
this.connector = new MySQLDatabaseConnector(new DatabaseConnectionSettingsImpl(
plugin.getSettings().getDatabaseHost(),
plugin.getSettings().getDatabasePort(),
plugin.getSettings().getDatabaseName(),
plugin.getSettings().getDatabaseUsername(),
plugin.getSettings().getDatabasePassword(),
plugin.getSettings().isUseSSL(),
plugin.getSettings().getMaximumPoolSize()));
plugin.getSettings().getDatabaseHost(),
plugin.getSettings().getDatabasePort(),
plugin.getSettings().getDatabaseName(),
plugin.getSettings().getDatabaseUsername(),
plugin.getSettings().getDatabasePassword(),
plugin.getSettings().isUseSSL(),
plugin.getSettings().getMaximumPoolSize()));
}
return new MySQLDatabaseHandler<>(plugin, type, this.connector);

View File

@ -17,7 +17,7 @@ public class PostgreSQLDatabase implements DatabaseSetup
PostgreSQLDatabaseConnector connector;
/*
/**
* {@inheritDoc}
*/
@Override
@ -28,13 +28,13 @@ public class PostgreSQLDatabase implements DatabaseSetup
if (this.connector == null)
{
this.connector = new PostgreSQLDatabaseConnector(new DatabaseConnectionSettingsImpl(
plugin.getSettings().getDatabaseHost(),
plugin.getSettings().getDatabasePort(),
plugin.getSettings().getDatabaseName(),
plugin.getSettings().getDatabaseUsername(),
plugin.getSettings().getDatabasePassword(),
plugin.getSettings().isUseSSL(),
plugin.getSettings().getMaximumPoolSize()));
plugin.getSettings().getDatabaseHost(),
plugin.getSettings().getDatabasePort(),
plugin.getSettings().getDatabaseName(),
plugin.getSettings().getDatabaseUsername(),
plugin.getSettings().getDatabasePassword(),
plugin.getSettings().isUseSSL(),
plugin.getSettings().getMaximumPoolSize()));
}
return new PostgreSQLDatabaseHandler<>(plugin, dataObjectClass, this.connector);

View File

@ -33,9 +33,9 @@ public class PostgreSQLDatabaseHandler<T> extends SQLDatabaseHandler<T>
PostgreSQLDatabaseHandler(BentoBox plugin, Class<T> type, DatabaseConnector databaseConnector)
{
super(plugin,
type,
databaseConnector,
new SQLConfiguration(plugin, type).
type,
databaseConnector,
new SQLConfiguration(plugin, type).
// Set uniqueid as the primary key (index). Postgresql convention is to use lower case field names
// Postgresql also uses double quotes (") instead of (`) around tables names with dots.
schema("CREATE TABLE IF NOT EXISTS \"[tableName]\" (uniqueid VARCHAR PRIMARY KEY, json jsonb NOT NULL)").
@ -44,18 +44,18 @@ public class PostgreSQLDatabaseHandler<T> extends SQLDatabaseHandler<T>
// uniqueId has to be added into the row explicitly so we need to override the saveObject method
// The json value is a string but has to be cast to json when done in Java
saveObject("INSERT INTO \"[tableName]\" (uniqueid, json) VALUES (?, cast(? as json)) "
// This is the Postgresql version of UPSERT.
+ "ON CONFLICT (uniqueid) DO UPDATE SET json = cast(? as json)").
// This is the Postgresql version of UPSERT.
+ "ON CONFLICT (uniqueid) DO UPDATE SET json = cast(? as json)").
loadObjects("SELECT json FROM \"[tableName]\"").
// Postgres exists function returns true or false natively
objectExists("SELECT EXISTS(SELECT * FROM \"[tableName]\" WHERE uniqueid = ?)").
renameTable("ALTER TABLE IF EXISTS \"[oldTableName]\" RENAME TO \"[tableName]\"").
setUseQuotes(false)
);
);
}
/*
/**
* {@inheritDoc}
*/
@Override
@ -85,7 +85,7 @@ public class PostgreSQLDatabaseHandler<T> extends SQLDatabaseHandler<T>
this.processQueue.add(() ->
{
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.getSqlConfig().getSaveObjectSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.getSqlConfig().getSaveObjectSQL()))
{
preparedStatement.setString(1, uniqueId); // INSERT
preparedStatement.setString(2, toStore); // INSERT

View File

@ -24,7 +24,7 @@ public class SQLiteDatabase implements DatabaseSetup
private SQLiteDatabaseConnector connector;
/*
/**
* {@inheritDoc}
*/
@Override

View File

@ -31,12 +31,12 @@ public class SQLiteDatabaseHandler<T> extends SQLDatabaseHandler<T>
protected SQLiteDatabaseHandler(BentoBox plugin, Class<T> type, DatabaseConnector databaseConnector)
{
super(plugin, type, databaseConnector, new SQLConfiguration(plugin, type).
schema("CREATE TABLE IF NOT EXISTS `[tableName]` (json JSON, uniqueId VARCHAR(255) NOT NULL PRIMARY KEY)").
saveObject("INSERT INTO `[tableName]` (json, uniqueId) VALUES (?, ?) ON CONFLICT(uniqueId) DO UPDATE SET json = ?").
objectExists("SELECT EXISTS (SELECT 1 FROM `[tableName]` WHERE `uniqueId` = ?)").
renameTable("ALTER TABLE `[oldTableName]` RENAME TO `[tableName]`").
setUseQuotes(false)
);
schema("CREATE TABLE IF NOT EXISTS `[tableName]` (json JSON, uniqueId VARCHAR(255) NOT NULL PRIMARY KEY)").
saveObject("INSERT INTO `[tableName]` (json, uniqueId) VALUES (?, ?) ON CONFLICT(uniqueId) DO UPDATE SET json = ?").
objectExists("SELECT EXISTS (SELECT 1 FROM `[tableName]` WHERE `uniqueId` = ?)").
renameTable("ALTER TABLE `[oldTableName]` RENAME TO `[tableName]`").
setUseQuotes(false)
);
}
@ -50,29 +50,29 @@ public class SQLiteDatabaseHandler<T> extends SQLDatabaseHandler<T>
{
// SQLite does not have a rename if exists command so we have to manually check if the old table exists
String sql = "SELECT EXISTS (SELECT 1 FROM sqlite_master WHERE type='table' AND name='" +
this.getSqlConfig().getOldTableName() + "' COLLATE NOCASE)";
this.getSqlConfig().getOldTableName() + "' COLLATE NOCASE)";
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql))
PreparedStatement preparedStatement = connection.prepareStatement(sql))
{
this.rename(preparedStatement);
}
catch (SQLException e)
{
this.plugin.logError("Could not check if " + this.getSqlConfig().getOldTableName() + " exists for data object " +
this.dataObject.getCanonicalName() + " " + e.getMessage());
this.dataObject.getCanonicalName() + " " + e.getMessage());
}
}
// Prepare and execute the database statements
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.getSqlConfig().getSchemaSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.getSqlConfig().getSchemaSQL()))
{
preparedStatement.execute();
}
catch (SQLException e)
{
this.plugin.logError("Problem trying to create schema for data object " + dataObject.getCanonicalName() + " " +
e.getMessage());
e.getMessage());
}
}
@ -85,24 +85,29 @@ public class SQLiteDatabaseHandler<T> extends SQLDatabaseHandler<T>
{
// Transition from the old table name
String sql = this.getSqlConfig().getRenameTableSQL().replace("[oldTableName]",
this.getSqlConfig().getOldTableName().replace("[tableName]", this.getSqlConfig().getTableName()));
this.getSqlConfig().getOldTableName().replace("[tableName]", this.getSqlConfig().getTableName()));
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql))
{
preparedStatement.execute();
}
catch (SQLException e)
{
this.plugin.logError("Could not rename " + getSqlConfig().getOldTableName() + " for data object " +
this.dataObject.getCanonicalName() + " " + e.getMessage());
}
executeStatement(sql);
}
}
catch (Exception ex)
{
this.plugin.logError("Could not check if " + getSqlConfig().getOldTableName() + " exists for data object " +
this.dataObject.getCanonicalName() + " " + ex.getMessage());
this.dataObject.getCanonicalName() + " " + ex.getMessage());
}
}
private void executeStatement(String sql) {
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql))
{
preparedStatement.execute();
}
catch (SQLException e)
{
this.plugin.logError("Could not rename " + getSqlConfig().getOldTableName() + " for data object " +
this.dataObject.getCanonicalName() + " " + e.getMessage());
}
}
@ -133,7 +138,7 @@ public class SQLiteDatabaseHandler<T> extends SQLDatabaseHandler<T>
this.processQueue.add(() ->
{
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(this.getSqlConfig().getSaveObjectSQL()))
PreparedStatement preparedStatement = connection.prepareStatement(this.getSqlConfig().getSaveObjectSQL()))
{
preparedStatement.setString(1, toStore);
preparedStatement.setString(2, ((DataObject) instance).getUniqueId());

View File

@ -100,11 +100,14 @@ public class YamlDatabaseConnector implements DatabaseConnector {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(yamlFile), StandardCharsets.UTF_8))){
File temp = File.createTempFile("file", ".tmp", yamlFile.getParentFile());
writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(temp), StandardCharsets.UTF_8));
for (String line; (line = reader.readLine()) != null;) {
String line = reader.readLine();
while (line != null) {
line = line.replace("!!java.util.UUID", "");
writer.println(line);
line = reader.readLine();
}
if (yamlFile.delete() && !temp.renameTo(yamlFile)) {
Files.delete(yamlFile.toPath());
if (!temp.renameTo(yamlFile)) {
plugin.logError("Could not rename fixed Island object. Are the writing permissions correctly setup?");
}
} catch (Exception e) {

View File

@ -1,7 +1,5 @@
package world.bentobox.bentobox.hooks;
import java.util.logging.Level;
import org.bukkit.Material;
import org.bukkit.World;
@ -58,9 +56,8 @@ public class MyWorldsHook extends Hook implements WorldManagementHook {
.getMethod("setChunkGeneratorName", String.class)
.invoke(worldConfig, name);
*/
} catch (Throwable t) {
BentoBox.getInstance().getLogger().log(Level.SEVERE,
"Failed to register world " + world.getName() + " with MyWorlds", t);
} catch (Exception t) {
BentoBox.getInstance().logError("Failed to register world " + world.getName() + " with MyWorlds " + t.getMessage());
}
}

View File

@ -70,12 +70,12 @@ public class PlaceholderAPIHook extends PlaceholderHook {
@Override
public void registerPlaceholder(@NonNull Addon addon, @NonNull String placeholder, @NonNull PlaceholderReplacer replacer) {
// Check if the addon expansion does not exist
if (!addonsExpansions.containsKey(addon)) {
addonsExpansions.computeIfAbsent(addon, k -> {
AddonPlaceholderExpansion addonPlaceholderExpansion = new AddonPlaceholderExpansion(addon);
addonPlaceholderExpansion.register();
addonsExpansions.put(addon, addonPlaceholderExpansion);
this.addonPlaceholders.computeIfAbsent(addon, k -> new HashSet<>()).add(placeholder);
}
this.addonPlaceholders.computeIfAbsent(addon, kk -> new HashSet<>()).add(placeholder);
return addonPlaceholderExpansion;
});
addonsExpansions.get(addon).registerPlaceholder(placeholder, replacer);
}

View File

@ -50,7 +50,8 @@ public class JoinLeaveListener implements Listener {
User.removePlayer(event.getPlayer());
User user = User.getInstance(event.getPlayer());
if (user == null || user.getUniqueId() == null) {
if (!user.isPlayer() || user.getUniqueId() == null) {
// This should never be the case, but it might be caused by some fake player plugins
return;
}
UUID playerUUID = event.getPlayer().getUniqueId();

View File

@ -18,7 +18,9 @@ import world.bentobox.bentobox.database.objects.Island;
* Abstracts PlayerPortalEvent and EntityPortalEvent
* @author tastybento
* @deprecated replaced not used in new listeners.
* @since 1.12.1
*/
@Deprecated
public class PlayerEntityPortalEvent {
private final EntityPortalEvent epe;

View File

@ -43,6 +43,7 @@ import world.bentobox.bentobox.util.teleport.SafeSpotTeleport;
* @deprecated replaced by better listeners.
* @see world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener
* @see world.bentobox.bentobox.listeners.teleports.EntityTeleportListener
* @since 1.12.1
*/
@Deprecated
public class PortalTeleportationListener implements Listener {
@ -268,9 +269,8 @@ public class PortalTeleportationListener implements Listener {
return null;
}
Location toLocation = e.getIsland().map(island -> island.getSpawnPoint(env)).
orElse(e.getFrom().toVector().toLocation(toWorld));
Location toLocation = Objects.requireNonNullElse(e.getIsland().map(island -> island.getSpawnPoint(env)).
orElse(e.getFrom().toVector().toLocation(toWorld)), e.getFrom().toVector().toLocation(toWorld));
// Limit Y to the min/max world height.
toLocation.setY(Math.max(Math.min(toLocation.getY(), toWorld.getMaxHeight()), toWorld.getMinHeight()));
@ -298,7 +298,7 @@ public class PortalTeleportationListener implements Listener {
{
// Find the portal - due to speed, it is possible that the player will be below or above the portal
for (k = toWorld.getMinHeight(); (k < e.getWorld().getMaxHeight()) &&
!e.getWorld().getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++);
!e.getWorld().getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++);
}
// Find the maximum x and z corner
for (; (i < x + 5) && e.getWorld().getBlockAt(i, k, z).getType().equals(Material.END_PORTAL); i++) ;
@ -322,8 +322,8 @@ public class PortalTeleportationListener implements Listener {
*/
private boolean isMakePortals(GameModeAddon gm, Environment env) {
return env.equals(Environment.NETHER) ?
gm.getWorldSettings().isMakeNetherPortals() && Bukkit.getAllowNether() :
gm.getWorldSettings().isMakeEndPortals() && Bukkit.getAllowEnd();
gm.getWorldSettings().isMakeNetherPortals() && Bukkit.getAllowNether() :
gm.getWorldSettings().isMakeEndPortals() && Bukkit.getAllowEnd();
}
/**

View File

@ -67,13 +67,13 @@ public class BreakBlocksListener extends FlagListener {
Player p = e.getPlayer();
Location l = e.getClickedBlock().getLocation();
switch (e.getClickedBlock().getType())
{
case CAKE -> this.checkIsland(e, p, l, Flags.BREAK_BLOCKS);
case SPAWNER -> this.checkIsland(e, p, l, Flags.BREAK_SPAWNERS);
case DRAGON_EGG -> this.checkIsland(e, p, l, Flags.DRAGON_EGG);
case HOPPER -> this.checkIsland(e, p, l, Flags.BREAK_HOPPERS);
case CAKE -> this.checkIsland(e, p, l, Flags.BREAK_BLOCKS);
case SPAWNER -> this.checkIsland(e, p, l, Flags.BREAK_SPAWNERS);
case DRAGON_EGG -> this.checkIsland(e, p, l, Flags.DRAGON_EGG);
case HOPPER -> this.checkIsland(e, p, l, Flags.BREAK_HOPPERS);
}
}
@ -122,12 +122,10 @@ public class BreakBlocksListener extends FlagListener {
if (e.getDamager() instanceof Player p) {
// Check the break blocks flag
notAllowed(e, p, e.getEntity().getLocation());
} else if (e.getDamager() instanceof Projectile p) {
// Find out who fired the arrow
if (p.getShooter() instanceof Player && notAllowed(e, (Player)p.getShooter(), e.getEntity().getLocation())) {
e.getEntity().setFireTicks(0);
p.setFireTicks(0);
}
} else if (e.getDamager() instanceof Projectile p && // Find out who fired the arrow
p.getShooter() instanceof Player player && notAllowed(e, player, e.getEntity().getLocation())) {
e.getEntity().setFireTicks(0);
p.setFireTicks(0);
}
}

View File

@ -18,10 +18,9 @@ public class ElytraListener extends FlagListener {
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onGlide(EntityToggleGlideEvent e) {
if (e.getEntity() instanceof Player player) {
if (!checkIsland(e, player, player.getLocation(), Flags.ELYTRA)) {
player.setGliding(false);
}
if (e.getEntity() instanceof Player player
&& !checkIsland(e, player, player.getLocation(), Flags.ELYTRA)) {
player.setGliding(false);
}
}

View File

@ -76,11 +76,9 @@ public class HurtingListener extends FlagListener {
// Get the attacker
if (damager instanceof Player) {
checkIsland(e, (Player)damager, damager.getLocation(), flag);
} else if (damager instanceof Projectile p) {
// Find out who fired the projectile
if (p.getShooter() instanceof Player && !checkIsland(e, (Player)p.getShooter(), damager.getLocation(), flag)) {
e.getEntity().setFireTicks(0);
}
} else if (damager instanceof Projectile p && // Find out who fired the projectile
p.getShooter() instanceof Player player && !checkIsland(e, player, damager.getLocation(), flag)) {
e.getEntity().setFireTicks(0);
}
}

View File

@ -49,14 +49,12 @@ public class TNTListener extends FlagListener {
return;
}
// 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 shooter && projectile.getFireTicks() > 0
&& !checkIsland(e, shooter, e.getBlock().getLocation(), Flags.TNT_PRIMING)) {
// Remove the arrow
projectile.remove();
e.setCancelled(true);
}
if (e.getEntity() instanceof Projectile projectile && // Find out who fired it
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);
}
}

View File

@ -41,16 +41,17 @@ public class CreeperListener extends FlagListener {
}
// Check for griefing
Creeper creeper = (Creeper)e.getEntity();
if (!Flags.CREEPER_GRIEFING.isSetForWorld(e.getLocation().getWorld()) && creeper.getTarget() instanceof Player target && target != null) {
if (!getIslands().locationIsOnIsland(target, e.getLocation())) {
User user = User.getInstance(target);
user.notify("protection.protected", TextVariables.DESCRIPTION, user.getTranslation(Flags.CREEPER_GRIEFING.getHintReference()));
e.setCancelled(true);
e.blockList().clear();
}
if (!Flags.CREEPER_GRIEFING.isSetForWorld(e.getLocation().getWorld())
&& creeper.getTarget() instanceof Player target // if getTarget is null this won'e be true
&& !getIslands().locationIsOnIsland(target, e.getLocation())) {
User user = User.getInstance(target);
user.notify("protection.protected", TextVariables.DESCRIPTION, user.getTranslation(Flags.CREEPER_GRIEFING.getHintReference()));
e.setCancelled(true);
e.blockList().clear();
}
}
/**
* Prevent entities being damaged by explosion
* @param e - event

View File

@ -69,13 +69,13 @@ public class GeoLimitMobsListener extends FlagListener {
public void onProjectileExplode(final ExplosionPrimeEvent e) {
if (e.getEntity() instanceof Projectile && getIWM().inWorld(e.getEntity().getLocation())) {
ProjectileSource source = ((Projectile)e.getEntity()).getShooter();
if (source instanceof Entity shooter) {
if (mobSpawnTracker.containsKey(shooter)
&& !mobSpawnTracker.get(shooter).onIsland(e.getEntity().getLocation())) {
e.getEntity().remove();
e.setCancelled(true);
}
if (source instanceof Entity shooter
&& mobSpawnTracker.containsKey(shooter)
&& !mobSpawnTracker.get(shooter).onIsland(e.getEntity().getLocation())) {
e.getEntity().remove();
e.setCancelled(true);
}
}
}
}

View File

@ -10,6 +10,7 @@ package world.bentobox.bentobox.listeners.teleports;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -46,9 +47,9 @@ public abstract class AbstractTeleportListener
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
@ -81,8 +82,8 @@ public abstract class AbstractTeleportListener
protected boolean isMakePortals(World world, World.Environment environment)
{
return this.plugin.getIWM().getAddon(world).
map(gameMode -> this.isMakePortals(gameMode, environment)).
orElse(false);
map(gameMode -> this.isMakePortals(gameMode, environment)).
orElse(false);
}
@ -96,9 +97,9 @@ public abstract class AbstractTeleportListener
protected boolean isMakePortals(GameModeAddon gameMode, World.Environment environment)
{
return switch (environment) {
case NETHER -> gameMode.getWorldSettings().isMakeNetherPortals();
case THE_END -> gameMode.getWorldSettings().isMakeEndPortals();
default -> false;
case NETHER -> gameMode.getWorldSettings().isMakeNetherPortals();
case THE_END -> gameMode.getWorldSettings().isMakeEndPortals();
default -> false;
};
}
@ -113,9 +114,9 @@ public abstract class AbstractTeleportListener
protected boolean isAllowedInConfig(World overWorld, World.Environment environment)
{
return switch (environment) {
case NETHER -> this.plugin.getIWM().isNetherGenerate(overWorld);
case THE_END -> this.plugin.getIWM().isEndGenerate(overWorld);
default -> true;
case NETHER -> this.plugin.getIWM().isNetherGenerate(overWorld);
case THE_END -> this.plugin.getIWM().isEndGenerate(overWorld);
default -> true;
};
}
@ -129,9 +130,9 @@ public abstract class AbstractTeleportListener
protected boolean isAllowedOnServer(World.Environment environment)
{
return switch (environment) {
case NETHER -> Bukkit.getAllowNether();
case THE_END -> Bukkit.getAllowEnd();
default -> true;
case NETHER -> Bukkit.getAllowNether();
case THE_END -> Bukkit.getAllowEnd();
default -> true;
};
}
@ -146,9 +147,9 @@ public abstract class AbstractTeleportListener
protected boolean isIslandWorld(World overWorld, World.Environment environment)
{
return switch (environment) {
case NETHER -> this.plugin.getIWM().isNetherIslands(overWorld);
case THE_END -> this.plugin.getIWM().isEndIslands(overWorld);
default -> true;
case NETHER -> this.plugin.getIWM().isNetherIslands(overWorld);
case THE_END -> this.plugin.getIWM().isEndIslands(overWorld);
default -> true;
};
}
@ -163,9 +164,9 @@ public abstract class AbstractTeleportListener
protected World getNetherEndWorld(World overWorld, World.Environment environment)
{
return switch (environment) {
case NETHER -> this.plugin.getIWM().getNetherWorld(overWorld);
case THE_END -> this.plugin.getIWM().getEndWorld(overWorld);
default -> Util.getWorld(overWorld);
case NETHER -> this.plugin.getIWM().getNetherWorld(overWorld);
case THE_END -> this.plugin.getIWM().getEndWorld(overWorld);
default -> Util.getWorld(overWorld);
};
}
@ -180,9 +181,9 @@ public abstract class AbstractTeleportListener
protected boolean hasPartnerIsland(Island island, World.Environment environment)
{
return switch (environment) {
case NETHER -> island.hasNetherIsland();
case THE_END -> island.hasEndIsland();
default -> true;
case NETHER -> island.hasNetherIsland();
case THE_END -> island.hasEndIsland();
default -> true;
};
}
@ -204,7 +205,7 @@ public abstract class AbstractTeleportListener
int z = Math.abs(island.getProtectionCenter().getBlockZ() - location.getBlockZ());
diff = Math.min(this.plugin.getSettings().getSafeSpotSearchRange(),
island.getProtectionRange() - Math.max(x, z));
island.getProtectionRange() - Math.max(x, z));
}
else
{
@ -225,10 +226,10 @@ public abstract class AbstractTeleportListener
* @return Location for new portal.
*/
protected Location calculateLocation(Location fromLocation,
World fromWorld,
World toWorld,
World.Environment environment,
boolean canCreatePortal)
World fromWorld,
World toWorld,
World.Environment environment,
boolean canCreatePortal)
{
// Null check - not that useful
if (fromWorld == null || toWorld == null)
@ -240,9 +241,9 @@ public abstract class AbstractTeleportListener
if (!this.isMakePortals(fromWorld, environment))
{
toLocation = this.getIsland(fromLocation).
map(island -> island.getSpawnPoint(toWorld.getEnvironment())).
orElse(toLocation);
toLocation = Objects.requireNonNullElse(this.getIsland(fromLocation).
map(island -> island.getSpawnPoint(toWorld.getEnvironment())).
orElse(toLocation), toLocation);
}
// Limit Y to the min/max world height.
@ -275,7 +276,7 @@ public abstract class AbstractTeleportListener
{
// Find the portal - due to speed, it is possible that the player will be below or above the portal
for (k = toWorld.getMinHeight(); (k < fromWorld.getMaxHeight()) &&
!fromWorld.getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++);
!fromWorld.getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++);
}
// Find the maximum x and z corner
@ -301,11 +302,11 @@ public abstract class AbstractTeleportListener
protected Location getSpawnLocation(World world)
{
return this.plugin.getIslandsManager().getSpawn(world).map(island ->
island.getSpawnPoint(World.Environment.NORMAL) == null ?
island.getSpawnPoint(World.Environment.NORMAL) == null ?
island.getCenter() :
island.getSpawnPoint(World.Environment.NORMAL)).
orElse(this.plugin.getIslands().isSafeLocation(world.getSpawnLocation()) ?
world.getSpawnLocation() : null);
island.getSpawnPoint(World.Environment.NORMAL)).
orElse(this.plugin.getIslands().isSafeLocation(world.getSpawnLocation()) ?
world.getSpawnLocation() : null);
}
@ -318,13 +319,13 @@ public abstract class AbstractTeleportListener
protected boolean isPastingMissingIslands(World overWorld)
{
return this.plugin.getIWM().isPasteMissingIslands(overWorld) &&
!this.plugin.getIWM().isUseOwnGenerator(overWorld);
!this.plugin.getIWM().isUseOwnGenerator(overWorld);
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**

View File

@ -325,9 +325,9 @@ public final class Flags {
* @since 1.20.0
*/
public static final Flag CHANGE_SETTINGS = new Flag.Builder("CHANGE_SETTINGS", Material.CRAFTING_TABLE).defaultSetting(true)
.defaultRank(RanksManager.OWNER_RANK)
.clickHandler(new CycleClick("CHANGE_SETTINGS", RanksManager.MEMBER_RANK, RanksManager.OWNER_RANK))
.mode(Flag.Mode.TOP_ROW).build();
.defaultRank(RanksManager.OWNER_RANK)
.clickHandler(new CycleClick("CHANGE_SETTINGS", RanksManager.MEMBER_RANK, RanksManager.OWNER_RANK))
.mode(Flag.Mode.TOP_ROW).build();
/**
* This flag allows choosing which island member group can activate sculk sensors.
@ -335,12 +335,12 @@ public final class Flags {
* @since 1.21.0
*/
public static final Flag SCULK_SENSOR = new Flag.Builder("SCULK_SENSOR", Enums.getIfPresent(Material.class, "SCULK_SENSOR").or(Material.BARRIER)).
listener(new SculkSensorListener()).
type(Type.PROTECTION).
defaultSetting(true).
defaultRank(RanksManager.MEMBER_RANK).
clickHandler(new CycleClick("SCULK_SENSOR", RanksManager.VISITOR_RANK, RanksManager.MEMBER_RANK)).
build();
listener(new SculkSensorListener()).
type(Type.PROTECTION).
defaultSetting(true).
defaultRank(RanksManager.MEMBER_RANK).
clickHandler(new CycleClick("SCULK_SENSOR", RanksManager.VISITOR_RANK, RanksManager.MEMBER_RANK)).
build();
/**
* This flag allows choosing which island member group can activate sculk shrieker.
@ -348,12 +348,12 @@ public final class Flags {
* @since 1.21.0
*/
public static final Flag SCULK_SHRIEKER = new Flag.Builder("SCULK_SHRIEKER", Enums.getIfPresent(Material.class, "SCULK_SHRIEKER").or(Material.BARRIER)).
listener(new SculkShriekerListener()).
type(Type.PROTECTION).
defaultSetting(true).
defaultRank(RanksManager.MEMBER_RANK).
clickHandler(new CycleClick("SCULK_SHRIEKER", RanksManager.VISITOR_RANK, RanksManager.MEMBER_RANK)).
build();
listener(new SculkShriekerListener()).
type(Type.PROTECTION).
defaultSetting(true).
defaultRank(RanksManager.MEMBER_RANK).
clickHandler(new CycleClick("SCULK_SHRIEKER", RanksManager.VISITOR_RANK, RanksManager.MEMBER_RANK)).
build();
/*
* Settings flags (not protection flags)
@ -390,12 +390,14 @@ public final class Flags {
// Mob spawning
/**
* @deprecated as of 1.14.0, see {@link #ANIMAL_NATURAL_SPAWN} and {@link #ANIMAL_SPAWNERS_SPAWN}.
* @deprecated see {@link #ANIMAL_NATURAL_SPAWN} and {@link #ANIMAL_SPAWNERS_SPAWN}.
* @since 1.14.0
*/
@Deprecated
public static final Flag ANIMAL_SPAWN = new Flag.Builder("ANIMAL_SPAWN", Material.APPLE).defaultSetting(true).type(Type.SETTING).build();
/**
* @deprecated as of 1.14.0, see {@link #MONSTER_NATURAL_SPAWN} and {@link #MONSTER_SPAWNERS_SPAWN}.
* @deprecated see {@link #MONSTER_NATURAL_SPAWN} and {@link #MONSTER_SPAWNERS_SPAWN}.
* @since 1.14.0
*/
@Deprecated
public static final Flag MONSTER_SPAWN = new Flag.Builder("MONSTER_SPAWN", Material.SPAWNER).defaultSetting(true).type(Type.SETTING).build();

View File

@ -21,7 +21,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
@ -341,8 +340,8 @@ public class AddonsManager {
plugin.logWarning("NOTE: DO NOT report this as a bug from BentoBox.");
StringBuilder a = new StringBuilder();
addon.getDescription().getAuthors().forEach(author -> a.append(author).append(" "));
plugin.getLogger().log(Level.SEVERE, "Please report this stack trace to the addon's author(s): " + a, e);
plugin.logError("Please report this stack trace to the addon's author(s): " + a);
plugin.logStacktrace(e);
}
private boolean isAddonCompatibleWithBentoBox(@NonNull Addon addon) {

View File

@ -1,65 +0,0 @@
package world.bentobox.bentobox.managers;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.placeholders.PlaceholderReplacer;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.GameModePlaceholder;
/**
* Registers default placeholders for all GameModes. Will not overwrite any that the gamemode addon itself implements.
* @author tastybento
* @since 1.4.0
* @deprecated As of 1.5.0, for removal.
*/
@Deprecated
public class GameModePlaceholderManager {
private final BentoBox plugin;
public GameModePlaceholderManager(BentoBox plugin) {
this.plugin = plugin;
}
/**
* @since 1.4.0
* @deprecated As of 1.5.0, for removal. Use {@link PlaceholdersManager#registerDefaultPlaceholders(GameModeAddon)} instead.
*/
@Deprecated
public void registerGameModePlaceholders(@NonNull GameModeAddon addon) {
plugin.getPlaceholdersManager().registerDefaultPlaceholders(addon);
}
}
/**
* @author tastybento
* @since 1.4.0
*/
class DefaultPlaceholder implements PlaceholderReplacer {
private final GameModeAddon addon;
private final GameModePlaceholder type;
public DefaultPlaceholder(GameModeAddon addon, GameModePlaceholder type) {
this.addon = addon;
this.type = type;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.placeholders.PlaceholderReplacer#onReplace(world.bentobox.bentobox.api.user.User)
*/
@NonNull
@Override
public String onReplace(@Nullable User user) {
if (user == null) {
return "";
}
Island island = addon.getIslands().getIsland(addon.getOverWorld(), user);
return type.getReplacer().onReplace(addon, user, island);
}
}

View File

@ -22,11 +22,11 @@ import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Boat.Type;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@ -68,13 +68,13 @@ public class IslandsManager {
private final BentoBox plugin;
// Tree species to boat material map
private static final Map<TreeSpecies, Material> TREE_TO_BOAT = ImmutableMap.<TreeSpecies, Material>builder().
put(TreeSpecies.ACACIA, Material.ACACIA_BOAT).
put(TreeSpecies.BIRCH, Material.BIRCH_BOAT).
put(TreeSpecies.DARK_OAK, Material.DARK_OAK_BOAT).
put(TreeSpecies.JUNGLE, Material.JUNGLE_BOAT).
put(TreeSpecies.GENERIC, Material.OAK_BOAT).
put(TreeSpecies.REDWOOD, Material.SPRUCE_BOAT).build();
private static final Map<Type, Material> TREE_TO_BOAT = ImmutableMap.<Type, Material>builder().
put(Type.ACACIA, Material.ACACIA_BOAT).
put(Type.BIRCH, Material.BIRCH_BOAT).
put(Type.DARK_OAK, Material.DARK_OAK_BOAT).
put(Type.JUNGLE, Material.JUNGLE_BOAT).
put(Type.OAK, Material.OAK_BOAT).
put(Type.SPRUCE, Material.SPRUCE_BOAT).build();
/**
* One island can be spawn, this is the one - otherwise, this value is null
@ -1036,22 +1036,6 @@ public class IslandsManager {
return homeTeleportAsync(world, player, "", false);
}
/**
* Teleport player to a home location. If one cannot be found a search is done to
* find a safe place.
*
* @param world - world to check
* @param player - the player
* @param number - a number - home location to do to
* @return CompletableFuture true if successful, false if not
* @since 1.14.0
* @deprecated Use {@link #homeTeleportAsync(World, Player, String)}
*/
@Deprecated
public CompletableFuture<Boolean> homeTeleportAsync(@NonNull World world, @NonNull Player player, int number) {
return homeTeleportAsync(world, player, String.valueOf(number), false);
}
/**
* Teleport player to a home location. If one cannot be found a search is done to
* find a safe place.
@ -1095,7 +1079,7 @@ public class IslandsManager {
player.leaveVehicle();
// Remove the boat so they don't lie around everywhere
boat.remove();
player.getInventory().addItem(new ItemStack(TREE_TO_BOAT.getOrDefault(((Boat) boat).getWoodType(), Material.OAK_BOAT)));
player.getInventory().addItem(new ItemStack(TREE_TO_BOAT.getOrDefault(((Boat) boat).getBoatType(), Material.OAK_BOAT)));
player.updateInventory();
}
}
@ -1219,7 +1203,7 @@ public class IslandsManager {
player.leaveVehicle();
// Remove the boat so they don't lie around everywhere
boat.remove();
Material boatMat = Material.getMaterial(((Boat) boat).getWoodType() + "_BOAT");
Material boatMat = Material.getMaterial(((Boat) boat).getType() + "_BOAT");
if (boatMat == null) {
boatMat = Material.OAK_BOAT;
}

View File

@ -205,29 +205,32 @@ public class LocalesManager {
File targetFile = new File(localeDir, name.substring(Math.max(lastIndex, 0)));
copyFile(name, targetFile);
// Update the locale file if it exists already
try (InputStreamReader in = new InputStreamReader(plugin.getResource(name))) {
YamlConfiguration jarLocale = new YamlConfiguration();
jarLocale.load(in);
YamlConfiguration fileLocale = new YamlConfiguration();
fileLocale.load(targetFile);
for (String k : jarLocale.getKeys(true)) {
if (!fileLocale.contains(k, false)) {
fileLocale.set(k, jarLocale.get(k));
}
}
// Save it
fileLocale.save(targetFile);
} catch (InvalidConfigurationException e) {
plugin.logError("Could not update locale files from jar " + e.getMessage());
}
updateFile(name, targetFile);
}
} catch (IOException e) {
plugin.logError("Could not copy locale files from jar " + e.getMessage());
}
}
private void updateFile(String name, File targetFile) throws IOException {
try (InputStreamReader in = new InputStreamReader(plugin.getResource(name))) {
YamlConfiguration jarLocale = new YamlConfiguration();
jarLocale.load(in);
YamlConfiguration fileLocale = new YamlConfiguration();
fileLocale.load(targetFile);
for (String k : jarLocale.getKeys(true)) {
if (!fileLocale.contains(k, false)) {
fileLocale.set(k, jarLocale.get(k));
}
}
// Save it
fileLocale.save(targetFile);
} catch (InvalidConfigurationException e) {
plugin.logError("Could not update locale files from jar " + e.getMessage());
}
}
/**
* Loads all the locales available in the locale folder given. Used for loading all locales from plugin and addons
*

View File

@ -11,6 +11,8 @@ import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.placeholders.PlaceholderReplacer;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook;
import world.bentobox.bentobox.lists.GameModePlaceholder;
@ -133,4 +135,30 @@ public class PlaceholdersManager {
getPlaceholderAPIHook().ifPresent(PlaceholderAPIHook::unregisterAll);
}
/**
* Default placeholder
*
*/
class DefaultPlaceholder implements PlaceholderReplacer {
private final GameModeAddon addon;
private final GameModePlaceholder type;
public DefaultPlaceholder(GameModeAddon addon, GameModePlaceholder type) {
this.addon = addon;
this.type = type;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.placeholders.PlaceholderReplacer#onReplace(world.bentobox.bentobox.api.user.User)
*/
@NonNull
@Override
public String onReplace(@Nullable User user) {
if (user == null) {
return "";
}
Island island = addon.getIslands().getIsland(addon.getOverWorld(), user);
return type.getReplacer().onReplace(addon, user, island);
}
}
}

View File

@ -192,9 +192,11 @@ public class NewIsland {
event = event.getNewEvent().orElse(event);
// Get the new BlueprintBundle if it was changed
switch (reason) {
case CREATE -> name = ((IslandCreateEvent) event).getBlueprintBundle().getUniqueId();
case RESET -> name = ((IslandResetEvent) event).getBlueprintBundle().getUniqueId();
default -> {}
case CREATE -> name = ((IslandCreateEvent) event).getBlueprintBundle().getUniqueId();
case RESET -> name = ((IslandResetEvent) event).getBlueprintBundle().getUniqueId();
default -> {
// Do nothing of other cases
}
}
// Run task to run after creating the island in one tick if island is not being pasted
@ -311,16 +313,9 @@ public class NewIsland {
}
// Fire exit event
Reason reasonDone = Reason.CREATED;
switch (reason) {
case CREATE -> reasonDone = Reason.CREATED;
case RESET -> reasonDone = Reason.RESETTED;
default -> {
}
}
IslandEvent.builder()
.involvedPlayer(user.getUniqueId())
.reason(reasonDone)
.reason(reason == Reason.RESET ? Reason.RESETTED : Reason.CREATED)
.island(island)
.location(island.getCenter())
.oldIsland(oldIsland)

View File

@ -2,7 +2,6 @@ package world.bentobox.bentobox.panels;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@ -19,8 +18,6 @@ import org.bukkit.conversations.ConversationFactory;
import org.bukkit.event.inventory.ClickType;
import org.eclipse.jdt.annotation.NonNull;
import com.google.common.collect.ImmutableMap;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.localization.TextVariables;
@ -76,8 +73,8 @@ public class BlueprintManagementPanel {
endBlueprint = new Blueprint().setIcon(Material.YELLOW_STAINED_GLASS_PANE)
.setName(user.getTranslation("general.worlds.the-end"))
.setDescription(t(INSTRUCTION));
slotToEnvironment = ImmutableMap.of(3, World.Environment.NORMAL, 5, World.Environment.NETHER, 7, World.Environment.THE_END);
environmentToBlueprint = ImmutableMap.of(World.Environment.NORMAL, normalBlueprint, World.Environment.NETHER, netherBlueprint, World.Environment.THE_END, endBlueprint);
slotToEnvironment = Map.of(3, World.Environment.NORMAL, 5, World.Environment.NETHER, 7, World.Environment.THE_END);
environmentToBlueprint = Map.of(World.Environment.NORMAL, normalBlueprint, World.Environment.NETHER, netherBlueprint, World.Environment.THE_END, endBlueprint);
}
private String t(String t) {

View File

@ -47,6 +47,8 @@ public class DefaultPasteUtil {
plugin = BentoBox.getInstance();
}
private DefaultPasteUtil() {} // private constructor to hide the implicit public one.
/**
* Set the block to the location
*

View File

@ -35,6 +35,7 @@ import world.bentobox.bentobox.BentoBox;
*/
public class ItemParser {
private ItemParser() {} // private constructor to hide the implicit public one.
/**
* Parse given string to ItemStack.
* @param text String value of item stack.
@ -110,20 +111,20 @@ public class ItemParser {
returnValue = parseItemDurabilityAndQuantity(part);
}
if (returnValue != null) {
// If wrapper is just for code-style null-pointer checks.
if (customModelData != null) {
// We have custom data model. Now assign it to the item-stack.
ItemMeta itemMeta = returnValue.getItemMeta();
if (returnValue != null
// If wrapper is just for code-style null-pointer checks.
&& customModelData != null) {
// We have custom data model. Now assign it to the item-stack.
ItemMeta itemMeta = returnValue.getItemMeta();
// Another null-pointer check for materials that does not have item meta.
if (itemMeta != null) {
itemMeta.setCustomModelData(customModelData);
// Update meta to the return item.
returnValue.setItemMeta(itemMeta);
}
// Another null-pointer check for materials that does not have item meta.
if (itemMeta != null) {
itemMeta.setCustomModelData(customModelData);
// Update meta to the return item.
returnValue.setItemMeta(itemMeta);
}
}
} catch (Exception exception) {
BentoBox.getInstance().logError("Could not parse item " + text + " " + exception.getLocalizedMessage());
returnValue = defaultItemStack;
@ -309,7 +310,9 @@ public class ItemParser {
// Apply new meta to the item.
playerHead.setItemMeta(meta);
} catch (Exception ignored) {}
} catch (Exception ignored) {
// Ignored
}
return playerHead;
}

View File

@ -74,30 +74,28 @@ public class ClosestSafeSpotTeleport
*/
private void checkLocation()
{
if (this.plugin.getIslandsManager().isSafeLocation(this.location))
if (!this.portal && this.plugin.getIslandsManager().isSafeLocation(this.location))
{
if (!this.portal)
{
// If this is not a portal teleport, then go to the safe location immediately
this.teleportEntity(this.location);
// Position search is completed. Quit faster.
return;
}
// If this is not a portal teleport, then go to the safe location immediately
this.teleportEntity(this.location);
// Position search is completed. Quit faster.
return;
}
// Players should not be teleported outside protection range if they already are in it.
this.boundingBox = this.plugin.getIslandsManager().getIslandAt(this.location).
map(Island::getProtectionBoundingBox).
orElseGet(() -> {
int protectionRange = this.plugin.getIWM().getIslandProtectionRange(this.world);
map(Island::getProtectionBoundingBox).
orElseGet(() -> {
double protectionRange = this.plugin.getIWM().getIslandProtectionRange(this.world);
return new BoundingBox(this.location.getBlockX() - protectionRange,
Math.max(this.world.getMinHeight(), this.location.getBlockY() - protectionRange),
this.location.getBlockZ() - protectionRange,
this.location.getBlockX() + protectionRange,
Math.min(this.world.getMaxHeight(), this.location.getBlockY() + protectionRange),
this.location.getBlockZ() + protectionRange);
});
return new BoundingBox(this.location.getBlockX() - protectionRange,
Math.max(this.world.getMinHeight(), this.location.getBlockY() - protectionRange),
this.location.getBlockZ() - protectionRange,
this.location.getBlockX() + protectionRange,
Math.min(this.world.getMaxHeight(), this.location.getBlockY() + protectionRange),
this.location.getBlockZ() + protectionRange);
});
// The maximal range of search.
this.range = Math.min(this.plugin.getSettings().getSafeSpotSearchRange(), (int) this.boundingBox.getWidthX() / 2);
@ -148,17 +146,17 @@ public class ClosestSafeSpotTeleport
// Get the chunk snapshot and scan it
Util.getChunkAtAsync(this.world, chunkPair.x, chunkPair.z).
thenApply(Chunk::getChunkSnapshot).
whenCompleteAsync((snapshot, e) ->
thenApply(Chunk::getChunkSnapshot).
whenCompleteAsync((snapshot, e) ->
{
if (snapshot != null)
{
if (snapshot != null)
{
// Find best spot based on collected information chunks.
this.scanAndPopulateBlockQueue(snapshot);
}
// Find best spot based on collected information chunks.
this.scanAndPopulateBlockQueue(snapshot);
}
this.checking.set(false);
});
this.checking.set(false);
});
}
@ -174,11 +172,9 @@ public class ClosestSafeSpotTeleport
int x = this.location.getBlockX();
int z = this.location.getBlockZ();
int range = 20;
// Normalize block coordinates to chunk coordinates and add extra 1 for visiting.
int numberOfChunks = (((x + range) >> 4) - ((x - range) >> 4) + 1) *
(((z + range) >> 4) - ((z - range) >> 4) + 1);
int numberOfChunks = (((x + SCAN_RANGE) >> 4) - ((x - SCAN_RANGE) >> 4) + 1) *
(((z + SCAN_RANGE) >> 4) - ((z - SCAN_RANGE) >> 4) + 1);
// Ideally it would be if visitor switch from clockwise to counter-clockwise if X % 16 < 8 and
// up to down if Z % 16 < 8.
@ -215,11 +211,11 @@ public class ClosestSafeSpotTeleport
* @param chunkCoord Chunk coordinate.
*/
private void addChunk(List<Pair<Integer, Integer>> chunksToScan,
Pair<Integer, Integer> blockCoord,
Pair<Integer, Integer> chunkCoord)
Pair<Integer, Integer> blockCoord,
Pair<Integer, Integer> chunkCoord)
{
if (!chunksToScan.contains(chunkCoord) &&
this.plugin.getIslandsManager().getIslandAt(this.location).
this.plugin.getIslandsManager().getIslandAt(this.location).
map(is -> is.inIslandSpace(blockCoord)).orElse(true))
{
chunksToScan.add(chunkCoord);
@ -256,16 +252,16 @@ public class ClosestSafeSpotTeleport
// Process positions that are inside bounding box of search area.
PositionData positionData = new PositionData(
positionVector,
chunkSnapshot.getBlockType(x, y - 1, z),
y < maxY ? chunkSnapshot.getBlockType(x, y, z) : null,
y + 1 < maxY ? chunkSnapshot.getBlockType(x, y + 1, z) : null,
blockVector.distanceSquared(positionVector));
positionVector,
chunkSnapshot.getBlockType(x, y - 1, z),
y < maxY ? chunkSnapshot.getBlockType(x, y, z) : null,
y + 1 < maxY ? chunkSnapshot.getBlockType(x, y + 1, z) : null,
blockVector.distanceSquared(positionVector));
if (this.plugin.getIslandsManager().checkIfSafe(this.world,
positionData.block,
positionData.spaceOne,
positionData.spaceTwo))
positionData.block,
positionData.spaceOne,
positionData.spaceTwo))
{
// Add only safe locations to the queue.
this.blockQueue.add(positionData);
@ -313,7 +309,7 @@ public class ClosestSafeSpotTeleport
Block highestBlock = this.world.getHighestBlockAt(this.location);
if (highestBlock.getType().isSolid() &&
this.plugin.getIslandsManager().isSafeLocation(highestBlock.getLocation()))
this.plugin.getIslandsManager().isSafeLocation(highestBlock.getLocation()))
{
// Try to teleport player to the highest block.
this.asyncTeleport(highestBlock.getLocation().add(new Vector(0.5D, 0D, 0.5D)));
@ -438,15 +434,15 @@ public class ClosestSafeSpotTeleport
if (this.portal)
{
if (Material.NETHER_PORTAL.equals(positionData.spaceOne()) ||
Material.NETHER_PORTAL.equals(positionData.spaceTwo()))
Material.NETHER_PORTAL.equals(positionData.spaceTwo()))
{
// Portal is found. Teleport entity to the portal location.
this.teleportEntity(new Location(this.world,
positionData.vector().getBlockX() + 0.5,
positionData.vector().getBlockY() + 0.1,
positionData.vector().getBlockZ() + 0.5,
this.location.getYaw(),
this.location.getPitch()));
positionData.vector().getBlockX() + 0.5,
positionData.vector().getBlockY() + 0.1,
positionData.vector().getBlockZ() + 0.5,
this.location.getYaw(),
this.location.getPitch()));
// Position found and player can is already teleported to it.
return true;
@ -455,22 +451,22 @@ public class ClosestSafeSpotTeleport
{
// Mark first incoming position as the best for teleportation.
this.noPortalPosition = new Location(this.world,
positionData.vector().getBlockX() + 0.5,
positionData.vector().getBlockY() + 0.1,
positionData.vector().getBlockZ() + 0.5,
this.location.getYaw(),
this.location.getPitch());
positionData.vector().getBlockX() + 0.5,
positionData.vector().getBlockY() + 0.1,
positionData.vector().getBlockZ() + 0.5,
this.location.getYaw(),
this.location.getPitch());
}
}
else
{
// First best position should be valid for teleportation.
this.teleportEntity(new Location(this.world,
positionData.vector().getBlockX() + 0.5,
positionData.vector().getBlockY() + 0.1,
positionData.vector().getBlockZ() + 0.5,
this.location.getYaw(),
this.location.getPitch()));
positionData.vector().getBlockX() + 0.5,
positionData.vector().getBlockY() + 0.1,
positionData.vector().getBlockZ() + 0.5,
this.location.getYaw(),
this.location.getPitch()));
return true;
}
@ -495,9 +491,9 @@ public class ClosestSafeSpotTeleport
}
// ---------------------------------------------------------------------
// Section: Builder
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Section: Builder
// ---------------------------------------------------------------------
public static class Builder
@ -775,9 +771,9 @@ public class ClosestSafeSpotTeleport
}
// ---------------------------------------------------------------------
// Section: Constants
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Section: Constants
// ---------------------------------------------------------------------
/**
* This comparator sorts position data based in order:
@ -787,18 +783,24 @@ public class ClosestSafeSpotTeleport
* - the smallest y value
*/
private final static Comparator<PositionData> POSITION_COMPARATOR = Comparator.comparingDouble(PositionData::distance).
thenComparingInt(position -> position.vector().getBlockX()).
thenComparingInt(position -> position.vector().getBlockZ()).
thenComparingInt(position -> position.vector().getBlockY());
thenComparingInt(position -> position.vector().getBlockX()).
thenComparingInt(position -> position.vector().getBlockZ()).
thenComparingInt(position -> position.vector().getBlockY());
/**
* Stores chunk load speed.
*/
private static final long CHUNK_LOAD_SPEED = 1;
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Range to scan
*/
private static final int SCAN_RANGE = 20;
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* BentoBox plugin instance.

View File

@ -366,19 +366,6 @@ public class SafeSpotTeleport {
return this;
}
/**
* Set the home number to this number
*
* @param homeNumber home number
* @return Builder
* @deprecated use {@link #homeName}
*/
@Deprecated
public Builder homeNumber(int homeNumber) {
this.homeNumber = homeNumber;
return this;
}
/**
* Set the home name
*

View File

@ -7,6 +7,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -380,7 +381,7 @@ public class PortalTeleportationListenerTest {
// Event is canceled
assertTrue(e.isCancelled());
// If nether islands, then to = from but in nether
verify(from).toVector();
verify(from, times(2)).toVector();
// Do not go to spawn
verify(nether, never()).getSpawnLocation();
}
@ -416,7 +417,7 @@ public class PortalTeleportationListenerTest {
// Verify
assertTrue(e.isCancelled());
// If nether islands, then to = from but in nether
verify(from).toVector();
verify(from, times(2)).toVector();
// Do not go to spawn
verify(nether, never()).getSpawnLocation();
}
@ -447,7 +448,7 @@ public class PortalTeleportationListenerTest {
// Verify
assertTrue(e.isCancelled());
// If nether islands, then to = from but in nether
verify(from).toVector();
verify(from, times(2)).toVector();
// Do not go to spawn
verify(nether, never()).getSpawnLocation();
}