mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-01-25 01:21:21 +01:00
Fix island resetting. #2223
Islands were being deleted in all worlds, and all islands were being deleted from the player instead of just the one island.
This commit is contained in:
parent
c63de278fe
commit
19d7e2fe0a
@ -19,181 +19,176 @@ import world.bentobox.bentobox.managers.island.NewIsland.Builder;
|
||||
import world.bentobox.bentobox.panels.IslandCreationPanel;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
* @author tastybento
|
||||
*/
|
||||
public class IslandResetCommand extends ConfirmableCommand {
|
||||
|
||||
private boolean noPaste;
|
||||
private boolean noPaste;
|
||||
|
||||
public IslandResetCommand(CompositeCommand islandCommand) {
|
||||
super(islandCommand, "reset", "restart");
|
||||
}
|
||||
public IslandResetCommand(CompositeCommand islandCommand) {
|
||||
super(islandCommand, "reset", "restart");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the island reset command
|
||||
* @param islandCommand - parent command
|
||||
* @param noPaste - true if resetting should not paste a new island
|
||||
*/
|
||||
public IslandResetCommand(CompositeCommand islandCommand, boolean noPaste) {
|
||||
super(islandCommand, "reset", "restart");
|
||||
this.noPaste = noPaste;
|
||||
}
|
||||
/**
|
||||
* Creates the island reset command
|
||||
*
|
||||
* @param islandCommand - parent command
|
||||
* @param noPaste - true if resetting should not paste a new island
|
||||
*/
|
||||
public IslandResetCommand(CompositeCommand islandCommand, boolean noPaste) {
|
||||
super(islandCommand, "reset", "restart");
|
||||
this.noPaste = noPaste;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("island.reset");
|
||||
setOnlyPlayer(true);
|
||||
setParametersHelp("commands.island.reset.parameters");
|
||||
setDescription("commands.island.reset.description");
|
||||
}
|
||||
@Override
|
||||
public void setup() {
|
||||
setPermission("island.reset");
|
||||
setOnlyPlayer(true);
|
||||
setParametersHelp("commands.island.reset.parameters");
|
||||
setDescription("commands.island.reset.description");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// Check cooldown
|
||||
if (getSettings().getResetCooldown() > 0 && checkCooldown(user)) {
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
int resetsLeft = getPlayers().getResetsLeft(getWorld(), user.getUniqueId());
|
||||
if (resetsLeft != -1) {
|
||||
// Resets are not unlimited here
|
||||
if (resetsLeft == 0) {
|
||||
// No resets allowed
|
||||
user.sendMessage("commands.island.reset.none-left");
|
||||
return false;
|
||||
} else {
|
||||
// Still some resets left
|
||||
// Notify how many resets are left
|
||||
user.sendMessage("commands.island.reset.resets-left", TextVariables.NUMBER, String.valueOf(resetsLeft));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean canExecute(User user, String label, List<String> args) {
|
||||
// Check cooldown
|
||||
if (getSettings().getResetCooldown() > 0 && checkCooldown(user)) {
|
||||
return false;
|
||||
}
|
||||
if (!getIslands().hasIsland(getWorld(), user.getUniqueId())) {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
int resetsLeft = getPlayers().getResetsLeft(getWorld(), user.getUniqueId());
|
||||
if (resetsLeft != -1) {
|
||||
// Resets are not unlimited here
|
||||
if (resetsLeft == 0) {
|
||||
// No resets allowed
|
||||
user.sendMessage("commands.island.reset.none-left");
|
||||
return false;
|
||||
} else {
|
||||
// Still some resets left
|
||||
// Notify how many resets are left
|
||||
user.sendMessage("commands.island.reset.resets-left", TextVariables.NUMBER, String.valueOf(resetsLeft));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Permission check if the name is not the default one
|
||||
if (!args.isEmpty()) {
|
||||
String name = getPlugin().getBlueprintsManager().validate(getAddon(), Util.sanitizeInput(args.get(0)));
|
||||
if (name == null || name.isEmpty()) {
|
||||
// The blueprint name is not valid.
|
||||
user.sendMessage("commands.island.create.unknown-blueprint");
|
||||
return false;
|
||||
}
|
||||
if (!getPlugin().getBlueprintsManager().checkPerm(getAddon(), user, Util.sanitizeInput(args.get(0)))) {
|
||||
return false;
|
||||
}
|
||||
return resetIsland(user, name);
|
||||
} else {
|
||||
// Show panel after confirmation
|
||||
if (getPlugin().getSettings().isResetConfirmation()) {
|
||||
this.askConfirmation(user, user.getTranslation("commands.island.reset.confirmation"), () -> selectBundle(user, label));
|
||||
} else {
|
||||
selectBundle(user, label);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Permission check if the name is not the default one
|
||||
if (!args.isEmpty()) {
|
||||
String name = getPlugin().getBlueprintsManager().validate(getAddon(), Util.sanitizeInput(args.get(0)));
|
||||
if (name == null || name.isEmpty()) {
|
||||
// The blueprint name is not valid.
|
||||
user.sendMessage("commands.island.create.unknown-blueprint");
|
||||
return false;
|
||||
}
|
||||
if (!getPlugin().getBlueprintsManager().checkPerm(getAddon(), user, Util.sanitizeInput(args.get(0)))) {
|
||||
return false;
|
||||
}
|
||||
return resetIsland(user, name);
|
||||
} else {
|
||||
// Show panel after confirmation
|
||||
if (getPlugin().getSettings().isResetConfirmation()) {
|
||||
this.askConfirmation(user, user.getTranslation("commands.island.reset.confirmation"),
|
||||
() -> selectBundle(user, label));
|
||||
} else {
|
||||
selectBundle(user, label);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Either selects the bundle to use or asks the user to choose.
|
||||
* @since 1.5.1
|
||||
*/
|
||||
private void selectBundle(@NonNull User user, @NonNull String label) {
|
||||
// Show panel only if there are multiple bundles available
|
||||
if (getPlugin().getBlueprintsManager().getBlueprintBundles(getAddon()).size() > 1) {
|
||||
// Show panel - once the player selected a bundle, this will re-run this command
|
||||
IslandCreationPanel.openPanel(this, user, label);
|
||||
} else {
|
||||
resetIsland(user, BlueprintsManager.DEFAULT_BUNDLE_NAME);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Either selects the bundle to use or asks the user to choose.
|
||||
*
|
||||
* @since 1.5.1
|
||||
*/
|
||||
private void selectBundle(@NonNull User user, @NonNull String label) {
|
||||
// Show panel only if there are multiple bundles available
|
||||
if (getPlugin().getBlueprintsManager().getBlueprintBundles(getAddon()).size() > 1) {
|
||||
// Show panel - once the player selected a bundle, this will re-run this command
|
||||
IslandCreationPanel.openPanel(this, user, label);
|
||||
} else {
|
||||
resetIsland(user, BlueprintsManager.DEFAULT_BUNDLE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset island
|
||||
* @param user user
|
||||
* @param name name of Blueprint Bundle
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean resetIsland(User user, String name) {
|
||||
// Get the player's old island
|
||||
Island oldIsland = getIslands().getIsland(getWorld(), user);
|
||||
deleteOldIsland(user, oldIsland);
|
||||
/**
|
||||
* Reset island
|
||||
*
|
||||
* @param user user
|
||||
* @param name name of Blueprint Bundle
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean resetIsland(User user, String name) {
|
||||
// Get the player's old island
|
||||
Island oldIsland = getIslands().getIsland(getWorld(), user);
|
||||
deleteOldIsland(user, oldIsland);
|
||||
|
||||
user.sendMessage("commands.island.create.creating-island");
|
||||
// Create new island and then delete the old one
|
||||
try {
|
||||
Builder builder = NewIsland.builder()
|
||||
.player(user)
|
||||
.reason(Reason.RESET)
|
||||
.addon(getAddon())
|
||||
.oldIsland(oldIsland)
|
||||
.name(name);
|
||||
if (noPaste) builder.noPaste();
|
||||
builder.build();
|
||||
} catch (IOException e) {
|
||||
getPlugin().logError("Could not create island for player. " + e.getMessage());
|
||||
user.sendMessage(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
setCooldown(user.getUniqueId(), getSettings().getResetCooldown());
|
||||
return true;
|
||||
}
|
||||
user.sendMessage("commands.island.create.creating-island");
|
||||
// Create new island and then delete the old one
|
||||
try {
|
||||
Builder builder = NewIsland.builder().player(user).reason(Reason.RESET).addon(getAddon())
|
||||
.oldIsland(oldIsland).name(name);
|
||||
if (noPaste)
|
||||
builder.noPaste();
|
||||
builder.build();
|
||||
} catch (IOException e) {
|
||||
getPlugin().logError("Could not create island for player. " + e.getMessage());
|
||||
user.sendMessage(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
setCooldown(user.getUniqueId(), getSettings().getResetCooldown());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void deleteOldIsland(User user, Island oldIsland) {
|
||||
// Fire island preclear event
|
||||
IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(Reason.PRECLEAR)
|
||||
.island(oldIsland)
|
||||
.oldIsland(oldIsland)
|
||||
.location(oldIsland.getCenter())
|
||||
.build();
|
||||
private void deleteOldIsland(User user, Island oldIsland) {
|
||||
// Fire island preclear event
|
||||
IslandEvent.builder().involvedPlayer(user.getUniqueId()).reason(Reason.PRECLEAR).island(oldIsland)
|
||||
.oldIsland(oldIsland).location(oldIsland.getCenter()).build();
|
||||
|
||||
// Reset the island
|
||||
// Reset the island
|
||||
|
||||
// Kick all island members (including the owner)
|
||||
kickMembers(oldIsland);
|
||||
// Kick all island members (including the owner)
|
||||
kickMembers(oldIsland);
|
||||
|
||||
// Add a reset
|
||||
getPlayers().addReset(getWorld(), user.getUniqueId());
|
||||
}
|
||||
// Add a reset
|
||||
getPlayers().addReset(getWorld(), user.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks the members (incl. owner) of the island.
|
||||
* @since 1.7.0
|
||||
*/
|
||||
private void kickMembers(Island island) {
|
||||
/*
|
||||
* We cannot assume the island owner can run /[cmd] team kick (it might be disabled, or there could be permission restrictions...)
|
||||
* Therefore, we need to do it manually.
|
||||
* Plus, a more specific team event (TeamDeleteEvent) is called by this method.
|
||||
*/
|
||||
island.getMemberSet().forEach(memberUUID -> {
|
||||
/**
|
||||
* Kicks the members (incl. owner) of the island.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
private void kickMembers(Island island) {
|
||||
/*
|
||||
* We cannot assume the island owner can run /[cmd] team kick (it might be
|
||||
* disabled, or there could be permission restrictions...) Therefore, we need to
|
||||
* do it manually. Plus, a more specific team event (TeamDeleteEvent) is called
|
||||
* by this method.
|
||||
*/
|
||||
island.getMemberSet().forEach(memberUUID -> {
|
||||
|
||||
User member = User.getInstance(memberUUID);
|
||||
// Send a "you're kicked" message if the member is not the island owner (send before removing!)
|
||||
if (!memberUUID.equals(island.getOwner())) {
|
||||
member.sendMessage("commands.island.reset.kicked-from-island", TextVariables.GAMEMODE, getAddon().getDescription().getName());
|
||||
}
|
||||
// Remove player
|
||||
getIslands().removePlayer(getWorld(), memberUUID);
|
||||
User member = User.getInstance(memberUUID);
|
||||
// Send a "you're kicked" message if the member is not the island owner (send
|
||||
// before removing!)
|
||||
if (!memberUUID.equals(island.getOwner())) {
|
||||
member.sendMessage("commands.island.reset.kicked-from-island", TextVariables.GAMEMODE,
|
||||
getAddon().getDescription().getName());
|
||||
}
|
||||
// Remove player
|
||||
getIslands().removePlayer(island, memberUUID);
|
||||
|
||||
// Clean player
|
||||
getPlayers().cleanLeavingPlayer(getWorld(), member, false, island);
|
||||
// Clean player
|
||||
getPlayers().cleanLeavingPlayer(getWorld(), member, false, island);
|
||||
|
||||
// Fire event
|
||||
TeamEvent.builder()
|
||||
.island(island)
|
||||
.reason(TeamEvent.Reason.DELETE)
|
||||
.involvedPlayer(memberUUID)
|
||||
.build();
|
||||
});
|
||||
}
|
||||
// Fire event
|
||||
TeamEvent.builder().island(island).reason(TeamEvent.Reason.DELETE).involvedPlayer(memberUUID).build();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@ -21,399 +22,439 @@ import world.bentobox.bentobox.util.Util;
|
||||
|
||||
/**
|
||||
* This class stores the islands in memory
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
public class IslandCache {
|
||||
@NonNull
|
||||
private final Map<@NonNull Location, @NonNull Island> islandsByLocation;
|
||||
/**
|
||||
* Map of all islands with island uniqueId as key
|
||||
*/
|
||||
@NonNull
|
||||
private final Map<@NonNull String, @NonNull Island> islandsById;
|
||||
/**
|
||||
* Every player who is associated with an island is in this map.
|
||||
*/
|
||||
@NonNull
|
||||
private final Map<@NonNull UUID, Set<Island>> islandsByUUID;
|
||||
@NonNull
|
||||
private final Map<@NonNull Location, @NonNull Island> islandsByLocation;
|
||||
/**
|
||||
* Map of all islands with island uniqueId as key
|
||||
*/
|
||||
@NonNull
|
||||
private final Map<@NonNull String, @NonNull Island> islandsById;
|
||||
/**
|
||||
* Every player who is associated with an island is in this map. Key is player
|
||||
* UUID, value is a set of islands
|
||||
*/
|
||||
@NonNull
|
||||
private final Map<@NonNull UUID, Set<Island>> islandsByUUID;
|
||||
|
||||
@NonNull
|
||||
private final Map<@NonNull World, @NonNull IslandGrid> grids;
|
||||
@NonNull
|
||||
private final Map<@NonNull World, @NonNull IslandGrid> grids;
|
||||
|
||||
public IslandCache() {
|
||||
islandsByLocation = new HashMap<>();
|
||||
islandsById = new HashMap<>();
|
||||
islandsByUUID = new HashMap<>();
|
||||
grids = new HashMap<>();
|
||||
}
|
||||
public IslandCache() {
|
||||
islandsByLocation = new HashMap<>();
|
||||
islandsById = new HashMap<>();
|
||||
islandsByUUID = new HashMap<>();
|
||||
grids = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an island to the grid
|
||||
* @param island island to add, not null
|
||||
* @return true if successfully added, false if not
|
||||
*/
|
||||
public boolean addIsland(@NonNull Island island) {
|
||||
if (island.getCenter() == null || island.getWorld() == null) {
|
||||
/* Special handling - return true.
|
||||
The island will not be quarantined, but just not loaded
|
||||
This can occur when a gamemode is removed temporarily from the server
|
||||
TODO: have an option to remove these when the purge command is added
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
if (addToGrid(island)) {
|
||||
islandsByLocation.put(island.getCenter(), island);
|
||||
islandsById.put(island.getUniqueId(), island);
|
||||
// Only add islands to this map if they are owned
|
||||
if (island.isOwned()) {
|
||||
islandsByUUID.computeIfAbsent(island.getOwner(), k -> new HashSet<>()).add(island);
|
||||
island.getMemberSet().forEach(member -> addPlayer(member, island));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Adds an island to the grid
|
||||
*
|
||||
* @param island island to add, not null
|
||||
* @return true if successfully added, false if not
|
||||
*/
|
||||
public boolean addIsland(@NonNull Island island) {
|
||||
if (island.getCenter() == null || island.getWorld() == null) {
|
||||
/*
|
||||
* Special handling - return true. The island will not be quarantined, but just
|
||||
* not loaded This can occur when a gamemode is removed temporarily from the
|
||||
* server TODO: have an option to remove these when the purge command is added
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
if (addToGrid(island)) {
|
||||
islandsByLocation.put(island.getCenter(), island);
|
||||
islandsById.put(island.getUniqueId(), island);
|
||||
// Only add islands to this map if they are owned
|
||||
if (island.isOwned()) {
|
||||
islandsByUUID.computeIfAbsent(island.getOwner(), k -> new HashSet<>()).add(island);
|
||||
island.getMemberSet().forEach(member -> addPlayer(member, island));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a player's UUID to the look up for islands. Does no checking
|
||||
* @param uuid player's uuid
|
||||
* @param island island to associate with this uuid. Only one island can be associated per world.
|
||||
*/
|
||||
public void addPlayer(@NonNull UUID uuid, @NonNull Island island) {
|
||||
islandsByUUID.computeIfAbsent(uuid, k -> new HashSet<>()).add(island);
|
||||
}
|
||||
/**
|
||||
* Adds a player's UUID to the look up for islands. Does no checking
|
||||
*
|
||||
* @param uuid player's uuid
|
||||
* @param island island to associate with this uuid. Only one island can be
|
||||
* associated per world.
|
||||
*/
|
||||
public void addPlayer(@NonNull UUID uuid, @NonNull Island island) {
|
||||
islandsByUUID.computeIfAbsent(uuid, k -> new HashSet<>()).add(island);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an island to the grid register
|
||||
* @param newIsland new island
|
||||
* @return true if successfully added, false if not
|
||||
*/
|
||||
private boolean addToGrid(@NonNull Island newIsland) {
|
||||
return grids.computeIfAbsent(newIsland.getWorld(), k -> new IslandGrid()).addToGrid(newIsland);
|
||||
}
|
||||
/**
|
||||
* Adds an island to the grid register
|
||||
*
|
||||
* @param newIsland new island
|
||||
* @return true if successfully added, false if not
|
||||
*/
|
||||
private boolean addToGrid(@NonNull Island newIsland) {
|
||||
return grids.computeIfAbsent(newIsland.getWorld(), k -> new IslandGrid()).addToGrid(newIsland);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
islandsByLocation.clear();
|
||||
islandsById.clear();
|
||||
islandsByUUID.clear();
|
||||
}
|
||||
public void clear() {
|
||||
islandsByLocation.clear();
|
||||
islandsById.clear();
|
||||
islandsByUUID.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an island from the cache. Does not remove blocks.
|
||||
* @param island island to delete
|
||||
* @return true if successful, false if not
|
||||
*/
|
||||
public boolean deleteIslandFromCache(@NonNull Island island) {
|
||||
if (!islandsByLocation.remove(island.getCenter(), island)) {
|
||||
return false;
|
||||
}
|
||||
islandsById.remove(island.getUniqueId());
|
||||
removeFromIslandsByUUID(island);
|
||||
// Remove from grid
|
||||
grids.putIfAbsent(island.getWorld(), new IslandGrid());
|
||||
return grids.get(island.getWorld()).removeFromGrid(island);
|
||||
}
|
||||
/**
|
||||
* Deletes an island from the cache. Does not remove blocks.
|
||||
*
|
||||
* @param island island to delete
|
||||
* @return true if successful, false if not
|
||||
*/
|
||||
public boolean deleteIslandFromCache(@NonNull Island island) {
|
||||
if (!islandsByLocation.remove(island.getCenter(), island)) {
|
||||
return false;
|
||||
}
|
||||
islandsById.remove(island.getUniqueId());
|
||||
removeFromIslandsByUUID(island);
|
||||
// Remove from grid
|
||||
grids.putIfAbsent(island.getWorld(), new IslandGrid());
|
||||
return grids.get(island.getWorld()).removeFromGrid(island);
|
||||
}
|
||||
|
||||
private void removeFromIslandsByUUID(Island island) {
|
||||
for (Set<Island> set : islandsByUUID.values()) {
|
||||
set.removeIf(island::equals);
|
||||
}
|
||||
}
|
||||
private void removeFromIslandsByUUID(Island island) {
|
||||
for (Set<Island> set : islandsByUUID.values()) {
|
||||
Iterator<Island> is = set.iterator();
|
||||
while (is.hasNext()) {
|
||||
Island i = is.next();
|
||||
if (i.equals(island)) {
|
||||
is.remove();
|
||||
}
|
||||
}
|
||||
// set.removeIf(island::equals);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete island from the cache by ID. Does not remove blocks.
|
||||
* @param uniqueId - island unique ID
|
||||
*/
|
||||
public void deleteIslandFromCache(@NonNull String uniqueId) {
|
||||
islandsById.remove(uniqueId);
|
||||
islandsByLocation.values().removeIf(i -> i.getUniqueId().equals(uniqueId));
|
||||
for (Set<Island> set : islandsByUUID.values()) {
|
||||
set.removeIf(i -> i.getUniqueId().equals(uniqueId));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Delete island from the cache by ID. Does not remove blocks.
|
||||
*
|
||||
* @param uniqueId - island unique ID
|
||||
*/
|
||||
public void deleteIslandFromCache(@NonNull String uniqueId) {
|
||||
islandsById.remove(uniqueId);
|
||||
islandsByLocation.values().removeIf(i -> i.getUniqueId().equals(uniqueId));
|
||||
for (Set<Island> set : islandsByUUID.values()) {
|
||||
set.removeIf(i -> i.getUniqueId().equals(uniqueId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get island based on the exact center location of the island
|
||||
* @param location location to search for
|
||||
* @return island or null if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
public Island get(@NonNull Location location) {
|
||||
return islandsByLocation.get(location);
|
||||
}
|
||||
/**
|
||||
* Get island based on the exact center location of the island
|
||||
*
|
||||
* @param location location to search for
|
||||
* @return island or null if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
public Island get(@NonNull Location location) {
|
||||
return islandsByLocation.get(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns island referenced by player's UUID.
|
||||
* Returns the island the player is on now, or their last known island
|
||||
* @param world world to check. Includes nether and end worlds.
|
||||
* @param uuid player's UUID
|
||||
* @return island or null if none
|
||||
*/
|
||||
@Nullable
|
||||
public Island get(@NonNull World world, @NonNull UUID uuid) {
|
||||
Set<Island> islands = getIslands(world, uuid);
|
||||
if (islands.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (Island island : islands) {
|
||||
if (island.isPrimary()) {
|
||||
return island;
|
||||
}
|
||||
}
|
||||
// If there is no primary set, then set one - it doesn't matter which.
|
||||
Island result = islands.iterator().next();
|
||||
result.setPrimary(true);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Returns island referenced by player's UUID. Returns the island the player is
|
||||
* on now, or their last known island
|
||||
*
|
||||
* @param world world to check. Includes nether and end worlds.
|
||||
* @param uuid player's UUID
|
||||
* @return island or null if none
|
||||
*/
|
||||
@Nullable
|
||||
public Island get(@NonNull World world, @NonNull UUID uuid) {
|
||||
Set<Island> islands = getIslands(world, uuid);
|
||||
if (islands.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (Island island : islands) {
|
||||
if (island.isPrimary()) {
|
||||
return island;
|
||||
}
|
||||
}
|
||||
// If there is no primary set, then set one - it doesn't matter which.
|
||||
Island result = islands.iterator().next();
|
||||
result.setPrimary(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the islands referenced by player's UUID.
|
||||
* @param world world to check. Includes nether and end worlds.
|
||||
* @param uuid player's UUID
|
||||
* @return list of island or empty list if none
|
||||
*/
|
||||
public Set<Island> getIslands(@NonNull World world, @NonNull UUID uuid) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
return islandsByUUID.computeIfAbsent(uuid, k -> new HashSet<>()).stream().filter(i -> w.equals(i.getWorld())).collect(Collectors.toSet());
|
||||
}
|
||||
/**
|
||||
* Returns all the islands referenced by player's UUID.
|
||||
*
|
||||
* @param world world to check. Includes nether and end worlds.
|
||||
* @param uuid player's UUID
|
||||
* @return list of island or empty list if none
|
||||
*/
|
||||
public Set<Island> getIslands(@NonNull World world, @NonNull UUID uuid) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
return islandsByUUID.computeIfAbsent(uuid, k -> new HashSet<>()).stream().filter(i -> w.equals(i.getWorld()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current island for the user as their primary island
|
||||
* @param uuid UUID of user
|
||||
* @param island island to make primary
|
||||
*/
|
||||
public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) {
|
||||
for (Island is : getIslands(island.getWorld(), uuid)) {
|
||||
is.setPrimary(island.equals(is));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the current island for the user as their primary island
|
||||
*
|
||||
* @param uuid UUID of user
|
||||
* @param island island to make primary
|
||||
*/
|
||||
public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) {
|
||||
for (Island is : getIslands(island.getWorld(), uuid)) {
|
||||
is.setPrimary(island.equals(is));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the island at the location or null if there is none.
|
||||
* This includes the full island space, not just the protected area
|
||||
*
|
||||
* @param location the location
|
||||
* @return Island object
|
||||
*/
|
||||
@Nullable
|
||||
public Island getIslandAt(@NonNull Location location) {
|
||||
World w = Util.getWorld(location.getWorld());
|
||||
if (w == null || !grids.containsKey(w)) {
|
||||
return null;
|
||||
}
|
||||
return grids.get(w).getIslandAt(location.getBlockX(), location.getBlockZ());
|
||||
}
|
||||
/**
|
||||
* Returns the island at the location or null if there is none. This includes
|
||||
* the full island space, not just the protected area
|
||||
*
|
||||
* @param location the location
|
||||
* @return Island object
|
||||
*/
|
||||
@Nullable
|
||||
public Island getIslandAt(@NonNull Location location) {
|
||||
World w = Util.getWorld(location.getWorld());
|
||||
if (w == null || !grids.containsKey(w)) {
|
||||
return null;
|
||||
}
|
||||
return grids.get(w).getIslandAt(location.getBlockX(), location.getBlockZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <strong>unmodifiable collection</strong> of all the islands (even those who may be unowned).
|
||||
* @return unmodifiable collection containing every island.
|
||||
*/
|
||||
@NonNull
|
||||
public Collection<Island> getIslands() {
|
||||
return Collections.unmodifiableCollection(islandsByLocation.values());
|
||||
}
|
||||
/**
|
||||
* Returns an <strong>unmodifiable collection</strong> of all the islands (even
|
||||
* those who may be unowned).
|
||||
*
|
||||
* @return unmodifiable collection containing every island.
|
||||
*/
|
||||
@NonNull
|
||||
public Collection<Island> getIslands() {
|
||||
return Collections.unmodifiableCollection(islandsByLocation.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <strong>unmodifiable collection</strong> of all the islands (even those who may be unowned) in the specified world.
|
||||
* @param world World of the gamemode.
|
||||
* @return unmodifiable collection containing all the islands in the specified world.
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@NonNull
|
||||
public Collection<Island> getIslands(@NonNull World world) {
|
||||
World overworld = Util.getWorld(world);
|
||||
if (overworld == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return islandsByLocation.entrySet().stream()
|
||||
.filter(entry -> overworld.equals(Util.getWorld(entry.getKey().getWorld()))) // shouldn't make NPEs
|
||||
.map(Map.Entry::getValue).toList();
|
||||
}
|
||||
/**
|
||||
* Returns an <strong>unmodifiable collection</strong> of all the islands (even
|
||||
* those who may be unowned) in the specified world.
|
||||
*
|
||||
* @param world World of the gamemode.
|
||||
* @return unmodifiable collection containing all the islands in the specified
|
||||
* world.
|
||||
* @since 1.7.0
|
||||
*/
|
||||
@NonNull
|
||||
public Collection<Island> getIslands(@NonNull World world) {
|
||||
World overworld = Util.getWorld(world);
|
||||
if (overworld == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return islandsByLocation.entrySet().stream()
|
||||
.filter(entry -> overworld.equals(Util.getWorld(entry.getKey().getWorld()))) // shouldn't make NPEs
|
||||
.map(Map.Entry::getValue).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the members of the user's team
|
||||
* @param world world to check
|
||||
* @param uuid uuid of player to check
|
||||
* @param minimumRank minimum rank requested
|
||||
* @return set of UUID's of island members. If there are no islands, this set will be empty
|
||||
*/
|
||||
@NonNull
|
||||
public Set<UUID> getMembers(@NonNull World world, @NonNull UUID uuid, int minimumRank) {
|
||||
return getIslands(world, uuid)
|
||||
.stream()
|
||||
.flatMap(island -> island.getMemberSet(minimumRank).stream())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
/**
|
||||
* Get the members of the user's team
|
||||
*
|
||||
* @param world world to check
|
||||
* @param uuid uuid of player to check
|
||||
* @param minimumRank minimum rank requested
|
||||
* @return set of UUID's of island members. If there are no islands, this set
|
||||
* will be empty
|
||||
*/
|
||||
@NonNull
|
||||
public Set<UUID> getMembers(@NonNull World world, @NonNull UUID uuid, int minimumRank) {
|
||||
return getIslands(world, uuid).stream().flatMap(island -> island.getMemberSet(minimumRank).stream())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UUID of the owner of the island of the player, which may be their UUID
|
||||
* @param world the world to check
|
||||
* @param uuid the player's UUID
|
||||
* @return island owner's UUID or null if there is no island owned by the player in this world
|
||||
*/
|
||||
@Nullable
|
||||
public UUID getOwner(@NonNull World world, @NonNull UUID uuid) {
|
||||
World w = Util.getWorld(world);
|
||||
Set<Island> islands = islandsByUUID.get(uuid);
|
||||
if (w == null || islands == null || islands.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// Find the island for this world
|
||||
return islands.stream().filter(i -> w.equals(i.getWorld())).findFirst().map(Island::getOwner).orElse(null);
|
||||
}
|
||||
/**
|
||||
* Get the UUID of the owner of the island of the player, which may be their
|
||||
* UUID
|
||||
*
|
||||
* @param world the world to check
|
||||
* @param uuid the player's UUID
|
||||
* @return island owner's UUID or null if there is no island owned by the player
|
||||
* in this world
|
||||
*/
|
||||
@Nullable
|
||||
public UUID getOwner(@NonNull World world, @NonNull UUID uuid) {
|
||||
World w = Util.getWorld(world);
|
||||
Set<Island> islands = islandsByUUID.get(uuid);
|
||||
if (w == null || islands == null || islands.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// Find the island for this world
|
||||
return islands.stream().filter(i -> w.equals(i.getWorld())).findFirst().map(Island::getOwner).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks is a player has an island and owns it
|
||||
* @param world the world to check
|
||||
* @param uuid the player
|
||||
* @return true if player has island and owns it
|
||||
*/
|
||||
public boolean hasIsland(@NonNull World world, @NonNull UUID uuid) {
|
||||
return uuid.equals(getOwner(world, uuid));
|
||||
}
|
||||
/**
|
||||
* Checks is a player has an island and owns it
|
||||
*
|
||||
* @param world the world to check
|
||||
* @param uuid the player
|
||||
* @return true if player has island and owns it
|
||||
*/
|
||||
public boolean hasIsland(@NonNull World world, @NonNull UUID uuid) {
|
||||
return uuid.equals(getOwner(world, uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a player from the cache. If the player has an island, the island owner is removed and membership cleared.
|
||||
* The island is removed from the islandsByUUID map, but kept in the location map.
|
||||
* @param world world
|
||||
* @param uuid player's UUID
|
||||
* @return list of islands player had or empty if none
|
||||
*/
|
||||
public Set<Island> removePlayer(@NonNull World world, @NonNull UUID uuid) {
|
||||
World w = Util.getWorld(world);
|
||||
Set<Island> islandSet = islandsByUUID.get(uuid);
|
||||
if (w == null || islandSet == null) {
|
||||
return Collections.emptySet(); // Return empty list if no islands map exists for the world
|
||||
}
|
||||
/**
|
||||
* Removes a player from the cache. If the player has an island, the island
|
||||
* owner is removed and membership cleared. The island is removed from the
|
||||
* islandsByUUID map, but kept in the location map.
|
||||
*
|
||||
* @param world world
|
||||
* @param uuid player's UUID
|
||||
* @return list of islands player had or empty if none
|
||||
*/
|
||||
public Set<Island> removePlayer(@NonNull World world, @NonNull UUID uuid) {
|
||||
World w = Util.getWorld(world);
|
||||
Set<Island> islandSet = islandsByUUID.get(uuid);
|
||||
if (w == null || islandSet == null) {
|
||||
return Collections.emptySet(); // Return empty list if no islands map exists for the world
|
||||
}
|
||||
|
||||
islandSet.forEach(island -> {
|
||||
if (uuid.equals(island.getOwner())) {
|
||||
island.getMembers().clear();
|
||||
island.setOwner(null);
|
||||
} else {
|
||||
island.removeMember(uuid);
|
||||
}
|
||||
});
|
||||
islandSet.stream().filter(i -> w.equals(i.getWorld())).forEach(island -> {
|
||||
if (uuid.equals(island.getOwner())) {
|
||||
island.getMembers().clear();
|
||||
island.setOwner(null);
|
||||
} else {
|
||||
island.removeMember(uuid);
|
||||
}
|
||||
});
|
||||
|
||||
islandsByUUID.remove(uuid);
|
||||
islandsByUUID.remove(uuid);
|
||||
|
||||
return islandSet;
|
||||
}
|
||||
return islandSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes player from island and removes the cache reference
|
||||
* @param island member's island
|
||||
* @param uuid uuid of member to remove
|
||||
*/
|
||||
public void removePlayer(@NonNull Island island, @NonNull UUID uuid) {
|
||||
Set<Island> islandSet = islandsByUUID.get(uuid);
|
||||
if (islandSet != null) {
|
||||
islandSet.remove(island);
|
||||
}
|
||||
island.removeMember(uuid);
|
||||
}
|
||||
/**
|
||||
* Removes player from island and removes the cache reference
|
||||
*
|
||||
* @param island member's island
|
||||
* @param uuid uuid of member to remove
|
||||
*/
|
||||
public void removePlayer(@NonNull Island island, @NonNull UUID uuid) {
|
||||
Set<Island> islandSet = islandsByUUID.get(uuid);
|
||||
if (islandSet != null) {
|
||||
islandSet.remove(island);
|
||||
}
|
||||
island.removeMember(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of islands in the cache
|
||||
* @return the number of islands
|
||||
*/
|
||||
public int size() {
|
||||
return islandsByLocation.size();
|
||||
}
|
||||
/**
|
||||
* Get the number of islands in the cache
|
||||
*
|
||||
* @return the number of islands
|
||||
*/
|
||||
public int size() {
|
||||
return islandsByLocation.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of islands in the cache for this world
|
||||
* @param world world to get the number of islands in
|
||||
* @return the number of islands
|
||||
*/
|
||||
public long size(World world) {
|
||||
return this.islandsByLocation.keySet().stream().map(Location::getWorld).filter(world::equals).count();
|
||||
}
|
||||
/**
|
||||
* Gets the number of islands in the cache for this world
|
||||
*
|
||||
* @param world world to get the number of islands in
|
||||
* @return the number of islands
|
||||
*/
|
||||
public long size(World world) {
|
||||
return this.islandsByLocation.keySet().stream().map(Location::getWorld).filter(world::equals).count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an island owner.
|
||||
* Clears out any other owner.
|
||||
* @param island island
|
||||
* @param newOwnerUUID new owner
|
||||
*/
|
||||
public void setOwner(@NonNull Island island, @Nullable UUID newOwnerUUID) {
|
||||
island.setOwner(newOwnerUUID);
|
||||
if (newOwnerUUID != null) {
|
||||
islandsByUUID.computeIfAbsent(newOwnerUUID, k -> new HashSet<>()).add(island);
|
||||
}
|
||||
islandsByLocation.put(island.getCenter(), island);
|
||||
islandsById.put(island.getUniqueId(), island);
|
||||
}
|
||||
/**
|
||||
* Sets an island owner. Clears out any other owner.
|
||||
*
|
||||
* @param island island
|
||||
* @param newOwnerUUID new owner
|
||||
*/
|
||||
public void setOwner(@NonNull Island island, @Nullable UUID newOwnerUUID) {
|
||||
island.setOwner(newOwnerUUID);
|
||||
if (newOwnerUUID != null) {
|
||||
islandsByUUID.computeIfAbsent(newOwnerUUID, k -> new HashSet<>()).add(island);
|
||||
}
|
||||
islandsByLocation.put(island.getCenter(), island);
|
||||
islandsById.put(island.getUniqueId(), island);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the island by unique id
|
||||
* @param uniqueId unique id of the Island.
|
||||
* @return island or null if none found
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Nullable
|
||||
public Island getIslandById(@NonNull String uniqueId) {
|
||||
return islandsById.get(uniqueId);
|
||||
}
|
||||
/**
|
||||
* Get the island by unique id
|
||||
*
|
||||
* @param uniqueId unique id of the Island.
|
||||
* @return island or null if none found
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Nullable
|
||||
public Island getIslandById(@NonNull String uniqueId) {
|
||||
return islandsById.get(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an island from the cache completely without altering the island object
|
||||
* @param island - island to remove
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public void removeIsland(@NonNull Island island) {
|
||||
islandsByLocation.values().removeIf(island::equals);
|
||||
islandsById.values().removeIf(island::equals);
|
||||
islandsByUUID.values().removeIf(island::equals);
|
||||
World w = Util.getWorld(island.getWorld());
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Removes an island from the cache completely without altering the island
|
||||
* object
|
||||
*
|
||||
* @param island - island to remove
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public void removeIsland(@NonNull Island island) {
|
||||
islandsByLocation.values().removeIf(island::equals);
|
||||
islandsById.values().removeIf(island::equals);
|
||||
islandsByUUID.values().removeIf(island::equals);
|
||||
World w = Util.getWorld(island.getWorld());
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (grids.containsKey(w)) {
|
||||
grids.get(w).removeFromGrid(island);
|
||||
}
|
||||
}
|
||||
if (grids.containsKey(w)) {
|
||||
grids.get(w).removeFromGrid(island);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all islands in this game mode to default flag settings
|
||||
* @param world - world
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public void resetAllFlags(World world) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
islandsById.values().stream().filter(i -> i.getWorld().equals(w)).forEach(Island::setFlagsDefaults);
|
||||
}
|
||||
/**
|
||||
* Resets all islands in this game mode to default flag settings
|
||||
*
|
||||
* @param world - world
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public void resetAllFlags(World world) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
islandsById.values().stream().filter(i -> i.getWorld().equals(w)).forEach(Island::setFlagsDefaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a specific flag on all game mode islands in world to default setting
|
||||
* @param world - world
|
||||
* @param flag - flag to reset
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public void resetFlag(World world, Flag flag) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
int setting = BentoBox.getInstance().getIWM().getDefaultIslandFlags(w).getOrDefault(flag, flag.getDefaultRank());
|
||||
islandsById.values().stream().filter(i -> i.getWorld().equals(w)).forEach(i -> i.setFlag(flag, setting));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the island ids
|
||||
* @return set of ids
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public Set<String> getAllIslandIds() {
|
||||
return islandsById.keySet();
|
||||
}
|
||||
/**
|
||||
* Resets a specific flag on all game mode islands in world to default setting
|
||||
*
|
||||
* @param world - world
|
||||
* @param flag - flag to reset
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public void resetFlag(World world, Flag flag) {
|
||||
World w = Util.getWorld(world);
|
||||
if (w == null) {
|
||||
return;
|
||||
}
|
||||
int setting = BentoBox.getInstance().getIWM().getDefaultIslandFlags(w).getOrDefault(flag,
|
||||
flag.getDefaultRank());
|
||||
islandsById.values().stream().filter(i -> i.getWorld().equals(w)).forEach(i -> i.setFlag(flag, setting));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the island ids
|
||||
*
|
||||
* @return set of ids
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public Set<String> getAllIslandIds() {
|
||||
return islandsById.keySet();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,303 +22,309 @@ import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||
|
||||
/**
|
||||
* Create and paste a new island
|
||||
*
|
||||
* @author tastybento
|
||||
*
|
||||
*/
|
||||
public class NewIsland {
|
||||
private final BentoBox plugin;
|
||||
private Island island;
|
||||
private final User user;
|
||||
private final Reason reason;
|
||||
private final World world;
|
||||
private String name;
|
||||
private final boolean noPaste;
|
||||
private final GameModeAddon addon;
|
||||
private final BentoBox plugin;
|
||||
private Island island;
|
||||
private final User user;
|
||||
private final Reason reason;
|
||||
private final World world;
|
||||
private String name;
|
||||
private final boolean noPaste;
|
||||
private final GameModeAddon addon;
|
||||
|
||||
private NewIslandLocationStrategy locationStrategy;
|
||||
private NewIslandLocationStrategy locationStrategy;
|
||||
|
||||
public NewIsland(Builder builder) throws IOException {
|
||||
plugin = BentoBox.getInstance();
|
||||
this.user = builder.user2;
|
||||
this.reason = builder.reason2;
|
||||
this.world = builder.world2;
|
||||
this.name = builder.name2;
|
||||
this.noPaste = builder.noPaste2;
|
||||
this.addon = builder.addon2;
|
||||
this.locationStrategy = builder.locationStrategy2;
|
||||
public NewIsland(Builder builder) throws IOException {
|
||||
plugin = BentoBox.getInstance();
|
||||
this.user = builder.user2;
|
||||
this.reason = builder.reason2;
|
||||
this.world = builder.world2;
|
||||
this.name = builder.name2;
|
||||
this.noPaste = builder.noPaste2;
|
||||
this.addon = builder.addon2;
|
||||
this.locationStrategy = builder.locationStrategy2;
|
||||
|
||||
if (this.locationStrategy == null) {
|
||||
this.locationStrategy = new DefaultNewIslandLocationStrategy();
|
||||
}
|
||||
// Fire pre-create event
|
||||
IslandBaseEvent event = IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(Reason.PRECREATE)
|
||||
.build();
|
||||
if (event.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(event.isCancelled())) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
newIsland(builder.oldIsland2);
|
||||
}
|
||||
if (this.locationStrategy == null) {
|
||||
this.locationStrategy = new DefaultNewIslandLocationStrategy();
|
||||
}
|
||||
// Fire pre-create event
|
||||
IslandBaseEvent event = IslandEvent.builder().involvedPlayer(user.getUniqueId()).reason(Reason.PRECREATE)
|
||||
.build();
|
||||
if (event.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(event.isCancelled())) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
newIsland(builder.oldIsland2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the island that was created
|
||||
*/
|
||||
public Island getIsland() {
|
||||
return island;
|
||||
}
|
||||
/**
|
||||
* @return the island that was created
|
||||
*/
|
||||
public Island getIsland() {
|
||||
return island;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start building a new island
|
||||
* @return New island builder object
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
/**
|
||||
* Start building a new island
|
||||
*
|
||||
* @return New island builder object
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new island for a player
|
||||
* @author tastybento
|
||||
*/
|
||||
public static class Builder {
|
||||
private Island oldIsland2;
|
||||
private User user2;
|
||||
private Reason reason2;
|
||||
private World world2;
|
||||
private String name2 = BlueprintsManager.DEFAULT_BUNDLE_NAME;
|
||||
private boolean noPaste2;
|
||||
private GameModeAddon addon2;
|
||||
private NewIslandLocationStrategy locationStrategy2;
|
||||
/**
|
||||
* Build a new island for a player
|
||||
*
|
||||
* @author tastybento
|
||||
*/
|
||||
public static class Builder {
|
||||
private Island oldIsland2;
|
||||
private User user2;
|
||||
private Reason reason2;
|
||||
private World world2;
|
||||
private String name2 = BlueprintsManager.DEFAULT_BUNDLE_NAME;
|
||||
private boolean noPaste2;
|
||||
private GameModeAddon addon2;
|
||||
private NewIslandLocationStrategy locationStrategy2;
|
||||
|
||||
public Builder oldIsland(Island oldIsland) {
|
||||
this.oldIsland2 = oldIsland;
|
||||
this.world2 = oldIsland.getWorld();
|
||||
return this;
|
||||
}
|
||||
public Builder oldIsland(Island oldIsland) {
|
||||
this.oldIsland2 = oldIsland;
|
||||
this.world2 = oldIsland.getWorld();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder player(User player) {
|
||||
this.user2 = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder player(User player) {
|
||||
this.user2 = player;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Sets the reason
|
||||
*
|
||||
* @param reason reason, can only be {@link Reason#CREATE} or
|
||||
* {@link Reason#RESET}.
|
||||
*/
|
||||
public Builder reason(Reason reason) {
|
||||
if (!reason.equals(Reason.CREATE) && !reason.equals(Reason.RESET)) {
|
||||
throw new IllegalArgumentException("Reason must be CREATE or RESET.");
|
||||
}
|
||||
this.reason2 = reason;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reason
|
||||
* @param reason reason, can only be {@link Reason#CREATE} or {@link Reason#RESET}.
|
||||
*/
|
||||
public Builder reason(Reason reason) {
|
||||
if (!reason.equals(Reason.CREATE) && !reason.equals(Reason.RESET)) {
|
||||
throw new IllegalArgumentException("Reason must be CREATE or RESET.");
|
||||
}
|
||||
this.reason2 = reason;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Set the addon
|
||||
*
|
||||
* @param addon a game mode addon
|
||||
*/
|
||||
public Builder addon(GameModeAddon addon) {
|
||||
this.addon2 = addon;
|
||||
this.world2 = addon.getOverWorld();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the addon
|
||||
* @param addon a game mode addon
|
||||
*/
|
||||
public Builder addon(GameModeAddon addon) {
|
||||
this.addon2 = addon;
|
||||
this.world2 = addon.getOverWorld();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* No blocks will be pasted
|
||||
*/
|
||||
public Builder noPaste() {
|
||||
this.noPaste2 = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* No blocks will be pasted
|
||||
*/
|
||||
public Builder noPaste() {
|
||||
this.noPaste2 = true;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @param name - name of Blueprint bundle
|
||||
*/
|
||||
public Builder name(String name) {
|
||||
this.name2 = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - name of Blueprint bundle
|
||||
*/
|
||||
public Builder name(String name) {
|
||||
this.name2 = name;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @param strategy - the location strategy to use
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public Builder locationStrategy(NewIslandLocationStrategy strategy) {
|
||||
this.locationStrategy2 = strategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param strategy - the location strategy to use
|
||||
* @since 1.8.0
|
||||
*/
|
||||
public Builder locationStrategy(NewIslandLocationStrategy strategy) {
|
||||
this.locationStrategy2 = strategy;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @return Island
|
||||
* @throws IOException - if there are insufficient parameters, i.e., no user
|
||||
*/
|
||||
public Island build() throws IOException {
|
||||
if (user2 != null) {
|
||||
NewIsland newIsland = new NewIsland(this);
|
||||
return newIsland.getIsland();
|
||||
}
|
||||
throw new IOException("Insufficient parameters. Must have a user!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Island
|
||||
* @throws IOException - if there are insufficient parameters, i.e., no user
|
||||
*/
|
||||
public Island build() throws IOException {
|
||||
if (user2 != null) {
|
||||
NewIsland newIsland = new NewIsland(this);
|
||||
return newIsland.getIsland();
|
||||
}
|
||||
throw new IOException("Insufficient parameters. Must have a user!");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Makes an island.
|
||||
*
|
||||
* @param oldIsland old island that is being replaced, if any
|
||||
* @throws IOException - if an island cannot be made. Message is the tag to show
|
||||
* the user.
|
||||
*/
|
||||
public void newIsland(Island oldIsland) throws IOException {
|
||||
// Find the new island location
|
||||
Location next = checkReservedIsland();
|
||||
if (next == null) {
|
||||
next = this.makeNextIsland();
|
||||
}
|
||||
// Clean up the user
|
||||
cleanUpUser(next);
|
||||
// Fire event
|
||||
IslandBaseEvent event = IslandEvent.builder().involvedPlayer(user.getUniqueId()).reason(reason).island(island)
|
||||
.location(island.getCenter())
|
||||
.blueprintBundle(plugin.getBlueprintsManager().getBlueprintBundles(addon).get(name))
|
||||
.oldIsland(oldIsland).build();
|
||||
if (event.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(event.isCancelled())) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
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 -> {
|
||||
// Do nothing of other cases
|
||||
}
|
||||
}
|
||||
// Set the player's primary island
|
||||
plugin.getIslands().setPrimaryIsland(user.getUniqueId(), island);
|
||||
// Run task to run after creating the island in one tick if island is not being
|
||||
// pasted
|
||||
if (noPaste) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> postCreationTask(oldIsland));
|
||||
} else {
|
||||
// Create islands, then run task
|
||||
plugin.getBlueprintsManager().paste(addon, island, name, () -> postCreationTask(oldIsland));
|
||||
}
|
||||
// Set default settings
|
||||
island.setFlagsDefaults();
|
||||
// Register metrics
|
||||
plugin.getMetrics().ifPresent(BStats::increaseIslandsCreatedCount);
|
||||
// Save island
|
||||
plugin.getIslands().save(island);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an island.
|
||||
* @param oldIsland old island that is being replaced, if any
|
||||
* @throws IOException - if an island cannot be made. Message is the tag to show the user.
|
||||
*/
|
||||
public void newIsland(Island oldIsland) throws IOException {
|
||||
// Find the new island location
|
||||
Location next = checkReservedIsland();
|
||||
if (next == null) {
|
||||
next = this.makeNextIsland();
|
||||
}
|
||||
// Clean up the user
|
||||
cleanUpUser(next);
|
||||
// Fire event
|
||||
IslandBaseEvent event = IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(reason)
|
||||
.island(island)
|
||||
.location(island.getCenter())
|
||||
.blueprintBundle(plugin.getBlueprintsManager().getBlueprintBundles(addon).get(name))
|
||||
.oldIsland(oldIsland)
|
||||
.build();
|
||||
if (event.getNewEvent().map(IslandBaseEvent::isCancelled).orElse(event.isCancelled())) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
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 -> {
|
||||
// Do nothing of other cases
|
||||
}
|
||||
}
|
||||
// Set the player's primary island
|
||||
plugin.getIslands().setPrimaryIsland(user.getUniqueId(), island);
|
||||
// Run task to run after creating the island in one tick if island is not being pasted
|
||||
if (noPaste) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> postCreationTask(oldIsland));
|
||||
} else {
|
||||
// Create islands, then run task
|
||||
plugin.getBlueprintsManager().paste(addon, island, name, () -> postCreationTask(oldIsland));
|
||||
}
|
||||
// Set default settings
|
||||
island.setFlagsDefaults();
|
||||
// Register metrics
|
||||
plugin.getMetrics().ifPresent(BStats::increaseIslandsCreatedCount);
|
||||
// Save island
|
||||
plugin.getIslands().save(island);
|
||||
}
|
||||
/**
|
||||
* Tasks to run after the new island has been created
|
||||
*
|
||||
* @param oldIsland - old island that will be deleted
|
||||
*/
|
||||
private void postCreationTask(Island oldIsland) {
|
||||
// Set initial spawn point if one exists
|
||||
if (island.getSpawnPoint(Environment.NORMAL) != null) {
|
||||
plugin.getIslands().setHomeLocation(user, island.getSpawnPoint(Environment.NORMAL));
|
||||
}
|
||||
// Stop the player from falling or moving if they are
|
||||
if (user.isOnline()) {
|
||||
if (reason.equals(Reason.RESET) || (reason.equals(Reason.CREATE)
|
||||
&& plugin.getIWM().isTeleportPlayerToIslandUponIslandCreation(world))) {
|
||||
user.getPlayer().setVelocity(new Vector(0, 0, 0));
|
||||
user.getPlayer().setFallDistance(0F);
|
||||
// Teleport player after this island is built
|
||||
plugin.getIslands().homeTeleportAsync(world, user.getPlayer(), true).thenRun(() -> tidyUp(oldIsland));
|
||||
return;
|
||||
} else {
|
||||
// let's send him a message so that he knows he can teleport to his island!
|
||||
user.sendMessage("commands.island.create.you-can-teleport-to-your-island");
|
||||
}
|
||||
} else {
|
||||
// Remove the player again to completely clear the data
|
||||
User.removePlayer(user.getPlayer());
|
||||
}
|
||||
tidyUp(oldIsland);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tasks to run after the new island has been created
|
||||
* @param oldIsland - old island that will be deleted
|
||||
*/
|
||||
private void postCreationTask(Island oldIsland) {
|
||||
// Set initial spawn point if one exists
|
||||
if (island.getSpawnPoint(Environment.NORMAL) != null) {
|
||||
plugin.getIslands().setHomeLocation(user, island.getSpawnPoint(Environment.NORMAL));
|
||||
}
|
||||
// Stop the player from falling or moving if they are
|
||||
if (user.isOnline()) {
|
||||
if (reason.equals(Reason.RESET) || (reason.equals(Reason.CREATE) && plugin.getIWM().isTeleportPlayerToIslandUponIslandCreation(world))) {
|
||||
user.getPlayer().setVelocity(new Vector(0, 0, 0));
|
||||
user.getPlayer().setFallDistance(0F);
|
||||
// Teleport player after this island is built
|
||||
plugin.getIslands().homeTeleportAsync(world, user.getPlayer(), true).thenRun(() -> tidyUp(oldIsland));
|
||||
return;
|
||||
} else {
|
||||
// let's send him a message so that he knows he can teleport to his island!
|
||||
user.sendMessage("commands.island.create.you-can-teleport-to-your-island");
|
||||
}
|
||||
} else {
|
||||
// Remove the player again to completely clear the data
|
||||
User.removePlayer(user.getPlayer());
|
||||
}
|
||||
tidyUp(oldIsland);
|
||||
}
|
||||
/**
|
||||
* Cleans up a user before moving them to a new island. Resets deaths. Checks
|
||||
* range permissions and saves the player to the database.
|
||||
*
|
||||
* @param loc - the new island location
|
||||
*/
|
||||
private void cleanUpUser(Location loc) {
|
||||
// Reset deaths
|
||||
if (plugin.getIWM().isDeathsResetOnNewIsland(world)) {
|
||||
plugin.getPlayers().setDeaths(world, user.getUniqueId(), 0);
|
||||
}
|
||||
// Check if owner has a different range permission than the island size
|
||||
island.setProtectionRange(user.getPermissionValue(
|
||||
plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("")
|
||||
+ "island.range",
|
||||
island.getProtectionRange()));
|
||||
// Save the player so that if the server crashes weird things won't happen
|
||||
plugin.getPlayers().save(user.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up a user before moving them to a new island.
|
||||
* Resets deaths.
|
||||
* Checks range permissions and saves the player to the database.
|
||||
* @param loc - the new island location
|
||||
*/
|
||||
private void cleanUpUser(Location loc) {
|
||||
// Reset deaths
|
||||
if (plugin.getIWM().isDeathsResetOnNewIsland(world)) {
|
||||
plugin.getPlayers().setDeaths(world, user.getUniqueId(), 0);
|
||||
}
|
||||
// Check if owner has a different range permission than the island size
|
||||
island.setProtectionRange(user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld())
|
||||
.map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getProtectionRange()));
|
||||
// Save the player so that if the server crashes weird things won't happen
|
||||
plugin.getPlayers().save(user.getUniqueId());
|
||||
}
|
||||
/**
|
||||
* Get the next island location and add it to the island grid
|
||||
*
|
||||
* @return location of new island
|
||||
* @throws IOException - if there are no unoccupied spots or the island could
|
||||
* not be added to the grid
|
||||
*/
|
||||
private Location makeNextIsland() throws IOException {
|
||||
// If the reservation fails, then we need to make a new island anyway
|
||||
Location next = this.locationStrategy.getNextLocation(world);
|
||||
if (next == null) {
|
||||
plugin.logError("Failed to make island - no unoccupied spot found.");
|
||||
plugin.logError("If the world was imported, try multiple times until all unowned islands are known.");
|
||||
throw new IOException("commands.island.create.cannot-create-island");
|
||||
}
|
||||
// Add to the grid
|
||||
island = plugin.getIslands().createIsland(next, user.getUniqueId());
|
||||
if (island == null) {
|
||||
plugin.logError("Failed to make island! Island could not be added to the grid.");
|
||||
throw new IOException("commands.island.create.unable-create-island");
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next island location and add it to the island grid
|
||||
* @return location of new island
|
||||
* @throws IOException - if there are no unoccupied spots or the island could not be added to the grid
|
||||
*/
|
||||
private Location makeNextIsland() throws IOException {
|
||||
// If the reservation fails, then we need to make a new island anyway
|
||||
Location next = this.locationStrategy.getNextLocation(world);
|
||||
if (next == null) {
|
||||
plugin.logError("Failed to make island - no unoccupied spot found.");
|
||||
plugin.logError("If the world was imported, try multiple times until all unowned islands are known.");
|
||||
throw new IOException("commands.island.create.cannot-create-island");
|
||||
}
|
||||
// Add to the grid
|
||||
island = plugin.getIslands().createIsland(next, user.getUniqueId());
|
||||
if (island == null) {
|
||||
plugin.logError("Failed to make island! Island could not be added to the grid.");
|
||||
throw new IOException("commands.island.create.unable-create-island");
|
||||
}
|
||||
return next;
|
||||
}
|
||||
/**
|
||||
* Get the reserved island location
|
||||
*
|
||||
* @return reserved island location, or null if none found
|
||||
*/
|
||||
private Location checkReservedIsland() {
|
||||
if (plugin.getIslands().hasIsland(world, user)) {
|
||||
// Island exists, it just needs pasting
|
||||
island = plugin.getIslands().getIsland(world, user);
|
||||
if (island != null && island.isReserved()) {
|
||||
Location l = island.getCenter();
|
||||
// Clear the reservation
|
||||
island.setReserved(false);
|
||||
return l;
|
||||
} else {
|
||||
// This should never happen unless we allow another way to paste over islands
|
||||
// without reserving
|
||||
plugin.logError("New island for user " + user.getName() + " was not reserved!");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reserved island location
|
||||
* @return reserved island location, or null if none found
|
||||
*/
|
||||
private Location checkReservedIsland() {
|
||||
if (plugin.getIslands().hasIsland(world, user)) {
|
||||
// Island exists, it just needs pasting
|
||||
island = plugin.getIslands().getIsland(world, user);
|
||||
if (island != null && island.isReserved()) {
|
||||
Location l = island.getCenter();
|
||||
// Clear the reservation
|
||||
island.setReserved(false);
|
||||
return l;
|
||||
} else {
|
||||
// This should never happen unless we allow another way to paste over islands without reserving
|
||||
plugin.logError("New island for user " + user.getName() + " was not reserved!");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void tidyUp(Island oldIsland) {
|
||||
// Delete old island
|
||||
if (oldIsland != null && !plugin.getSettings().isKeepPreviousIslandOnReset()) {
|
||||
// Delete the old island
|
||||
plugin.getIslands().deleteIsland(oldIsland, true, user.getUniqueId());
|
||||
}
|
||||
|
||||
private void tidyUp(Island oldIsland) {
|
||||
// Delete old island
|
||||
if (oldIsland != null && !plugin.getSettings().isKeepPreviousIslandOnReset()) {
|
||||
// Delete the old island
|
||||
plugin.getIslands().deleteIsland(oldIsland, true, user.getUniqueId());
|
||||
}
|
||||
// Fire exit event
|
||||
IslandEvent.builder().involvedPlayer(user.getUniqueId())
|
||||
.reason(reason == Reason.RESET ? Reason.RESETTED : Reason.CREATED).island(island)
|
||||
.location(island.getCenter()).oldIsland(oldIsland).build();
|
||||
|
||||
// Fire exit event
|
||||
IslandEvent.builder()
|
||||
.involvedPlayer(user.getUniqueId())
|
||||
.reason(reason == Reason.RESET ? Reason.RESETTED : Reason.CREATED)
|
||||
.island(island)
|
||||
.location(island.getCenter())
|
||||
.oldIsland(oldIsland)
|
||||
.build();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user