Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple island location from island center. #1659

Merged
merged 15 commits into from
Feb 13, 2021
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private void deletePlayer(User user, UUID targetUUID) {
if (vector == null) {
user.sendMessage("general.success");
} else {
user.sendMessage("commands.admin.delete.deleted-island", "[xyz]", Util.xyz(vector));
user.sendMessage("commands.admin.delete.deleted-island", TextVariables.XYZ, Util.xyz(vector));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private boolean register(User user, String targetName, UUID targetUUID, Optional
if (i.isSpawn()) {
getIslands().clearSpawn(i.getWorld());
}
user.sendMessage("commands.admin.register.registered-island", "[xyz]", Util.xyz(i.getCenter().toVector()),
user.sendMessage("commands.admin.register.registered-island", TextVariables.XYZ, Util.xyz(i.getCenter().toVector()),
TextVariables.NAME, targetName);
user.sendMessage("general.success");
// Build and call event
Expand Down Expand Up @@ -114,7 +114,7 @@ private boolean register(User user, String targetName, UUID targetUUID, Optional
getIslands().setOwner(user, targetUUID, i);
i.setReserved(true);
i.getCenter().getBlock().setType(Material.BEDROCK);
user.sendMessage("commands.admin.register.reserved-island", "[xyz]", Util.xyz(i.getCenter().toVector()),
user.sendMessage("commands.admin.register.reserved-island", TextVariables.XYZ, Util.xyz(i.getCenter().toVector()),
TextVariables.NAME, targetName);
// Build and fire event
IslandEvent.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package world.bentobox.bentobox.api.commands.admin;


import java.util.List;
import java.util.Optional;

import org.bukkit.Location;

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;


/**
* This command sets the island location. This defines the center of the protected area.
* The island location can be anywhere inside the island range area. Therefore the protected
* range can be up to 2x the island range.
* The island location will change for all environments.
* @author tastybento
* @since 1.16.0
*/
public class AdminSetLocationCommand extends ConfirmableCommand
{
private Location targetLoc;
private Island island;


/**
* Sub-command constructor
*
* @param parent - the parent composite command
*/
public AdminSetLocationCommand(CompositeCommand parent) {
super(parent, "setlocation");
}


@Override
public void setup()
{
this.setPermission("admin.setlocation");
this.setParametersHelp("commands.admin.setlocation.parameters");
this.setDescription("commands.admin.setlocation.description");
}

@Override
public boolean canExecute(User user, String label, List<String> args) {
if (args.size() == 3) {
// Get location
targetLoc = getLocation(user, args);
} else {
targetLoc = new Location(getWorld(), user.getLocation().getBlockX(), user.getLocation().getBlockY(), user.getLocation().getBlockZ());
}
if (targetLoc == null) {
user.sendMessage("commands.admin.setlocation.xyz-error");
return false;
}
Optional<Island> optionalIsland = getIslands().getIslandAt(targetLoc);
if (!optionalIsland.isPresent()) {
user.sendMessage("commands.admin.setspawnpoint.no-island-here");
return false;
}
island = optionalIsland.get();
return true;
}

private Location getLocation(User user, List<String> args) {
try {
int x = Integer.parseInt(args.get(0));
int y = Integer.parseInt(args.get(1));
int z = Integer.parseInt(args.get(2));
return new Location(getWorld(), x, y, z);
} catch (Exception e) {
return null;
}
}

@Override
public boolean execute(User user, String label, List<String> args) {
String name = getPlayers().getName(island.getOwner());
user.sendMessage("commands.admin.setlocation.island", TextVariables.XYZ, Util.xyz(island.getCenter().toVector()), TextVariables.NAME, name);
// Confirm
this.askConfirmation(user, user.getTranslation("commands.admin.setlocation.confirmation", TextVariables.XYZ, Util.xyz(targetLoc.toVector())),
() -> this.setLocation(user));
return true;
}


/**
* Set the island location to the user's location.
* @param user User who initiate change.
*/
private void setLocation(User user) {
try {
// Set
island.setLocation(targetLoc);
user.sendMessage("commands.admin.setlocation.success", TextVariables.XYZ, Util.xyz(targetLoc.toVector()));
} catch (Exception e) {
user.sendMessage("commands.admin.setlocation.failure", TextVariables.XYZ, Util.xyz(targetLoc.toVector()));
getAddon().logError("Island location could not be changed because the island does not exist");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private void setSpawn(User user, Island i) {
getIslands().setSpawn(i);
i.setSpawnPoint(World.Environment.NORMAL, user.getLocation());
// Set the island's range to the full island space because it is spawn
i.setProtectionRange(i.getRange());
i.setProtectionRange(i.getRange() * 2);
user.sendMessage("commands.admin.setspawn.success");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void unregisterPlayer(User user, String targetName, UUID targetUUID) {
// Remove all island players that reference this island
oldIsland.getMembers().clear();
getIslands().save(oldIsland);
user.sendMessage("commands.admin.unregister.unregistered-island", "[xyz]", Util.xyz(oldIsland.getCenter().toVector()),
user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(oldIsland.getCenter().toVector()),
TextVariables.NAME, targetName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ public void setup() {
new AdminPurgeCommand(this);
// Settings
new AdminSettingsCommand(this);
// Location
new AdminSetLocationCommand(this);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public boolean execute(User user, String label, @NonNull List<String> args) {
Island island = getIslands().getIsland(getWorld(), targetUUID);
int newRange = island.getProtectionRange() + Integer.parseInt(args.get(1));

if (newRange > island.getRange()) {
if (newRange > island.getRange() * 2) {
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER, String.valueOf(island.getRange()));
return false;
} else if (newRange == island.getProtectionRange()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;

/**
* @author Poslovitch
Expand Down Expand Up @@ -84,15 +85,15 @@ private void showZones(User user) {

getIslands().getIslandAt(user.getLocation()).ifPresent(island -> {
// Draw the island protected area
drawZone(user, Particle.BARRIER, null, island.getCenter(), island.getProtectionRange());
drawZone(user, Particle.BARRIER, null, island, island.getProtectionRange());

// Draw the default protected area if island protected zone is different
if (island.getProtectionRange() != getPlugin().getIWM().getIslandProtectionRange(getWorld())) {
drawZone(user, Particle.VILLAGER_HAPPY, null, island.getCenter(), getPlugin().getIWM().getIslandProtectionRange(getWorld()));
drawZone(user, Particle.VILLAGER_HAPPY, null, island, getPlugin().getIWM().getIslandProtectionRange(getWorld()));
}

// Draw the island area
drawZone(user, Particle.REDSTONE, new Particle.DustOptions(Color.GRAY, 1.0F), island.getCenter(), island.getRange());
drawZone(user, Particle.REDSTONE, new Particle.DustOptions(Color.GRAY, 1.0F), island, island.getRange());
});
}, 20, 30));
}
Expand All @@ -103,7 +104,8 @@ private void hideZones(User user) {
displayRanges.remove(user);
}

private void drawZone(User user, Particle particle, Particle.DustOptions dustOptions, Location center, int range) {
private void drawZone(User user, Particle particle, Particle.DustOptions dustOptions, Island island, int range) {
Location center = island.getLocation();
// Get player Y coordinate
int playerY = user.getPlayer().getLocation().getBlockY() + 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public boolean execute(User user, String label, List<String> args) {
user.sendMessage("commands.admin.range.invalid-value.too-low", TextVariables.NUMBER, args.get(1));
return false;
}
if (range > island.getRange()) {
if (range > island.getRange() * 2) {
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER, String.valueOf(island.getRange()));
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,9 @@ private TextVariables() {}
* @since 1.15.0
*/
public static final String GAMEMODE = "[gamemode]";
/**
* Used for coordinates
* @since 1.16.0
*/
public static final String XYZ = "[xyz]";
}
72 changes: 56 additions & 16 deletions src/main/java/world/bentobox/bentobox/database/objects/Island.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package world.bentobox.bentobox.database.objects;

import java.io.IOException;
import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
Expand Down Expand Up @@ -73,11 +74,16 @@ public class Island implements DataObject, MetaDataAble {
private String uniqueId = UUID.randomUUID().toString();

//// Island ////
// The center of the island itself
// The center of the island space
@Expose
@Nullable
private Location center;

@Expose
@Nullable
private Location location;


// Island range
@Expose
private int range;
Expand Down Expand Up @@ -227,6 +233,7 @@ public Island(Island island) {
this.gameMode = island.getGameMode();
this.history.addAll(island.getHistory());
this.levelHandicap = island.getLevelHandicap();
this.location = island.getLocation();
this.maxEverProtectionRange = island.getMaxEverProtectionRange();
this.members.putAll(island.getMembers());
island.getMetaData().ifPresent(m -> {
Expand Down Expand Up @@ -404,33 +411,41 @@ public ImmutableSet<UUID> getMemberSet(){
}

/**
* Get the minimum protected X block coord based on the island location.
* It will never be less than {@link #getMinX()}
* @return the minProtectedX
*/
public int getMinProtectedX() {
return center.getBlockX() - protectionRange;
return getLocation() == null ? 0 : Math.max(getMinX(), getLocation().getBlockX() - protectionRange);
}

/**
* Get the maximum protected X block coord based on the island location.
* It will never be more than {@link #getMaxX()}
* @return the maxProtectedX
* @since 1.5.2
*/
public int getMaxProtectedX() {
return center.getBlockX() + protectionRange;
return getLocation() == null ? 0 : Math.min(getMaxX(), getLocation().getBlockX() + protectionRange);
}

/**
* Get the minimum protected Z block coord based on the island location.
* It will never be less than {@link #getMinZ()}
* @return the minProtectedZ
*/
public int getMinProtectedZ() {
return center.getBlockZ() - protectionRange;
return getLocation() == null ? 0 : Math.max(getMinZ(), getLocation().getBlockZ() - protectionRange);
}

/**
* Get the maximum protected Z block coord based on the island location.
* It will never be more than {@link #getMinZ()}
* @return the maxProtectedZ
* @since 1.5.2
*/
public int getMaxProtectedZ() {
return center.getBlockZ() + protectionRange;
return getLocation() == null ? 0 : Math.min(getMaxZ(), getLocation().getBlockZ() + protectionRange);
}

/**
Expand Down Expand Up @@ -760,7 +775,7 @@ public void removeMember(UUID playerUUID) {
/**
* @param center the center to set
*/
public void setCenter(Location center) {
public void setCenter(@Nullable Location center) {
if (center != null) {
this.world = center.getWorld();
}
Expand Down Expand Up @@ -1017,16 +1032,13 @@ public boolean showInfo(User user) {
// Show team members
showMembers(user);
}
Vector location = getCenter().toVector();
user.sendMessage("commands.admin.info.island-location", "[xyz]", Util.xyz(location));
Vector from = getCenter().toVector().subtract(new Vector(getRange(), 0, getRange())).setY(0);
Vector to = getCenter().toVector().add(new Vector(getRange()-1, 0, getRange()-1)).setY(getCenter().getWorld().getMaxHeight());
user.sendMessage("commands.admin.info.island-coords", "[xz1]", Util.xyz(from), "[xz2]", Util.xyz(to));
Vector location = getLocation().toVector();
user.sendMessage("commands.admin.info.island-location", TextVariables.XYZ, Util.xyz(location));
user.sendMessage("commands.admin.info.island-center", TextVariables.XYZ, Util.xyz(getCenter().toVector()));
user.sendMessage("commands.admin.info.island-coords", "[xz1]", Util.xyz(new Vector(this.getMinX(), 0, getMinZ())), "[xz2]", Util.xyz(new Vector(this.getMaxX(), 0, getMaxZ())));
user.sendMessage("commands.admin.info.protection-range", "[range]", String.valueOf(getProtectionRange()));
user.sendMessage("commands.admin.info.max-protection-range", "[range]", String.valueOf(getMaxEverProtectionRange()));
Vector pfrom = getCenter().toVector().subtract(new Vector(getProtectionRange(), 0, getProtectionRange())).setY(0);
Vector pto = getCenter().toVector().add(new Vector(getProtectionRange()-1, 0, getProtectionRange()-1)).setY(getCenter().getWorld().getMaxHeight());
user.sendMessage("commands.admin.info.protection-coords", "[xz1]", Util.xyz(pfrom), "[xz2]", Util.xyz(pto));
user.sendMessage("commands.admin.info.protection-coords", "[xz1]", Util.xyz(new Vector(this.getMinProtectedX(), 0, getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(this.getMaxProtectedX(), 0, getMaxProtectedZ())));
if (spawn) {
user.sendMessage("commands.admin.info.is-spawn");
}
Expand Down Expand Up @@ -1347,10 +1359,38 @@ public void setChanged(boolean changed) {
this.changed = changed;
}

/**
* Get the location of the island. This can be anywhere within the island
* space and can move. It is used to calculate the protected area. Unless
* explicitly set, it will return the same as {@link #getCenter()}.
* @return a clone of the location
* @since 1.16.0
*/
@Nullable
public Location getLocation() {
return location == null ? getCenter() : location.clone();
}

/**
* Sets the location of the island within the island space.
* @param location the location to set
* @throws IOException if the location is not in island space
* @since 1.16.0
*/
public void setLocation(Location location) throws IOException {
if (!this.inIslandSpace(location)) {
throw new IOException("Location must be in island space");
}
this.location = location;
setChanged();
}

@Override
public String toString() {
return "Island [deleted=" + deleted + ", " + (uniqueId != null ? "uniqueId=" + uniqueId + ", " : "")
+ (center != null ? "center=" + center + ", " : "") + "range=" + range + ", protectionRange="
return "Island [changed=" + changed + ", deleted=" + deleted + ", "
+ (uniqueId != null ? "uniqueId=" + uniqueId + ", " : "")
+ (center != null ? "center=" + center + ", " : "")
+ (location != null ? "location=" + location + ", " : "") + "range=" + range + ", protectionRange="
+ protectionRange + ", maxEverProtectionRange=" + maxEverProtectionRange + ", "
+ (world != null ? "world=" + world + ", " : "")
+ (gameMode != null ? "gameMode=" + gameMode + ", " : "") + (name != null ? "name=" + name + ", " : "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public IslandDeletion() {}

public IslandDeletion(Island island) {
// Get the world's island distance
int islandDistance = BentoBox.getInstance().getIWM().getIslandDistance(island.getWorld());
int range = Math.min(island.getMaxEverProtectionRange(), islandDistance);
int range = BentoBox.getInstance().getIWM().getIslandDistance(island.getWorld());
uniqueId = UUID.randomUUID().toString();
location = island.getCenter();
minX = location.getBlockX() - range;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ private void updateIslandRange(User user) {
if (island != null) {
// Check if new owner has a different range permission than the island size
int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getProtectionRange());
// Range cannot be greater than the island distance
range = Math.min(range, plugin.getIWM().getIslandDistance(island.getWorld()));
// Range cannot be greater than the island distance * 2
range = Math.min(range, 2 * plugin.getIWM().getIslandDistance(island.getWorld()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is a correct way how to do it.

I would prefer to calculate by offset from the actual island center.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protection range is now relative to the protection center location, so if the player is to be given the ability to use all of their island area, then their protection range must be able to go up to 2x island distance away from that point.

For example:

Island range = 400
Island center = 0,0
Island location = 399, 0
Island protection range = 800

This last value will enable them to operate anywhere with all of the island space.

// Range can go up or down
if (range != island.getProtectionRange()) {
user.sendMessage("commands.admin.setrange.range-updated", TextVariables.NUMBER, String.valueOf(range));
Expand Down
Loading