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

Release 2.6.0 #2527

Merged
merged 22 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
541d966
Fix for 2515
tastybento Sep 27, 2024
69de5ea
Merge pull request #2516 from BentoBoxWorld/2515_Island_Settings_Icon…
tastybento Sep 27, 2024
fd1ab22
Implements admin command to set an island's max homes #2517
tastybento Sep 28, 2024
2784f19
Added test class and made some methods easier to test
tastybento Sep 28, 2024
4a972a8
Add placeholders. Put in defensive code against nulls.
tastybento Sep 28, 2024
f1219ec
Remove test class
tastybento Sep 28, 2024
83b7c66
Merge pull request #2518 from BentoBoxWorld/2517_Admin_command_for_ma…
tastybento Sep 29, 2024
80e1063
Add AdminResetHome command #2522
tastybento Oct 1, 2024
6d8ac15
Merge pull request #2523 from BentoBoxWorld/2522_admin_command_to_res…
tastybento Oct 1, 2024
aa19319
Improve teleporting #2524 - this commit has debug.
tastybento Oct 1, 2024
a7f9f21
Make all islands Op's
tastybento Oct 2, 2024
1782dd6
Remove unused imports
tastybento Oct 2, 2024
81fb17d
Merge pull request #2526 from BentoBoxWorld/oraxen
tastybento Oct 2, 2024
3992102
Merge branch 'develop' into 2524_is_teleport_command_delay
tastybento Oct 2, 2024
b949727
Update IslandGoCommand.java
tastybento Oct 2, 2024
1085332
Merge pull request #2525 from BentoBoxWorld/2524_is_teleport_command_…
tastybento Oct 2, 2024
9cb8d1c
Test fix for teleporting using new in-progress message
tastybento Oct 2, 2024
0da7130
Add clickable text and hover text
tastybento Oct 5, 2024
97aff7a
Merge pull request #2529 from BentoBoxWorld/clickable_text
tastybento Oct 5, 2024
29c5057
Fix tests, optimize tests, reord imports.
tastybento Oct 5, 2024
bac59d7
Merge pull request #2530 from BentoBoxWorld/test_fixing
tastybento Oct 5, 2024
32a9f71
Merge branch 'master' into develop
tastybento Oct 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>2.5.4</build.version>
<build.version>2.6.0</build.version>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<server.jars>${project.basedir}/lib</server.jars>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ private List<String> getSubCommandLabels(@NonNull CommandSender sender, @NonNull
* @param user - the User
* @return result of help command or false if no help defined
*/
protected boolean showHelp(CompositeCommand command, User user) {
public boolean showHelp(CompositeCommand command, User user) {
return command.getSubCommand("help")
.map(helpCommand -> helpCommand.execute(user, helpCommand.getLabel(), new ArrayList<>())).orElse(false);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package world.bentobox.bentobox.api.commands.admin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import com.google.common.primitives.Ints;

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;

/**
* Sets the maximum number of homes allowed on this island.
*
* Commands:
* <ul>
* <li><b>/bsb maxhomes &lt;player&gt; &lt;number&gt;</b> - Sets the maximum number of homes for each island where the player is the owner. This could apply to multiple islands.</li>
* <li><b>/bsb maxhomes &lt;player&gt; &lt;number&gt; [island name]</b> - Sets the maximum number of homes for a specific named island where the player is the owner.</li>
* <li><b>/bsb maxhomes &lt;number&gt;</b> - Sets the maximum number of homes for the island you are standing on (in-game only).</li>
* </ul>
*
* @author tastybento
* @since 2.6.0
*/

public class AdminMaxHomesCommand extends ConfirmableCommand {

Integer maxHomes;
Map<String, Island> islands = new HashMap<>();

public AdminMaxHomesCommand(CompositeCommand parent) {
super(parent, "setmaxhomes");
}

@Override
public void setup() {
setPermission("mod.maxhomes");
setOnlyPlayer(false);
setParametersHelp("commands.admin.maxhomes.parameters");
setDescription("commands.admin.maxhomes.description");
}

@Override
public boolean canExecute(User user, String label, List<String> args) {
islands.clear();
if (args.isEmpty()) {
showHelp(this, user);
return false;
}
// Check arguments
if (args.size() == 1) {
// Player must be in game
if (!user.isPlayer()) {
user.sendMessage("general.errors.use-in-game");
return false;
}
// Check world
if (user.getWorld() != getWorld()) {
user.sendMessage("general.errors.wrong-world");
return false;
}
// Arg must be an integer to return true, otherwise false
maxHomes = Ints.tryParse(args.get(0));
if (maxHomes == null || maxHomes < 1) {
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(0));
return false;
}
// Get the island the user is standing on
boolean onIsland = getIslands().getIslandAt(user.getLocation()).map(is -> {
islands.put("", is);
return true;
}).orElse(false);
if (!onIsland) {
user.sendMessage("general.errors.not-on-island");
return false;
}
return true;
}
// More than one argument
// First arg must be a valid player name
UUID targetUUID = getPlayers().getUUID(args.get(0));
if (targetUUID == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false;
}
// Second arg must be the max homes number
maxHomes = Ints.tryParse(args.get(1));
if (maxHomes == null) {
user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1));
return false;
}
// Get islands
islands = this.getNameIslandMap(User.getInstance(targetUUID));
if (islands.isEmpty()) {
user.sendMessage("general.errors.player-has-no-island");
return false;
}
if (args.size() > 2) {
// A specific island is mentioned. Parse which one it is and remove the others
final String name = String.join(" ", args.subList(2, args.size())); // Join all the args from here with spaces

islands.keySet().removeIf(n -> !name.equalsIgnoreCase(n));

if (islands.isEmpty()) {
// Failed name check - there are either
user.sendMessage("commands.admin.maxhomes.errors.unknown-island", TextVariables.NAME, name);
return false;
}
}

return true;
}

@Override
public boolean execute(User user, String label, List<String> args) {
if (islands.isEmpty() || maxHomes < 1) {
// Sanity check
return false;
}
islands.forEach((name, island) -> {
island.setMaxHomes(maxHomes);
user.sendMessage("commands.admin.maxhomes.max-homes-set", TextVariables.NAME, name, TextVariables.NUMBER,
String.valueOf(maxHomes));
});
return true;
}

@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
if (args.size() == 2) {
// Suggest player names
return Optional.of(Util.getOnlinePlayerList(user));
}
if (args.size() > 3) {
// Work out who is in arg 2
UUID targetUUID = getPlayers().getUUID(args.get(1));
if (targetUUID != null) {
User target = User.getInstance(targetUUID);
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(target).keySet()), lastArg));
}
}
return Optional.of(List.of("1"));

}

Map<String, Island> getNameIslandMap(User user) {
Map<String, Island> islandMap = new HashMap<>();
int index = 0;
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
index++;
if (island.getName() != null && !island.getName().isBlank()) {
// Name has been set
islandMap.put(island.getName(), island);
} else {
// Name has not been set
String text = user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()) + " " + index;
islandMap.put(text, island);
}
}

return islandMap;

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package world.bentobox.bentobox.api.commands.admin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import world.bentobox.bentobox.api.commands.CompositeCommand;
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 resets players island name.
* @author BONNe
*/
public class AdminResetHomeCommand extends CompositeCommand
{
Map<String, Island> islands = new HashMap<>();

/**
* Default constructor.
* @param command Parent command.
*/
public AdminResetHomeCommand(CompositeCommand command)
{
super(command, "resethome");
}


/**
* {@inheritDoc}
*/
@Override
public void setup()
{
this.setPermission("mod.resethome");
this.setDescription("commands.admin.resethome.description");
this.setParametersHelp("commands.admin.resethome.parameters");
}


/**
* @param user the {@link User} who is executing this command.
* @param label the label which has been used to execute this command.
* It can be {@link CompositeCommand#getLabel()} or an alias.
* @param args the command arguments.
* @return {@code true} if name can be reset, {@code false} otherwise.
*/
@Override
public boolean canExecute(User user, String label, List<String> args)
{
islands.clear();
if (args.isEmpty()) {
this.showHelp(this, user);
return false;
}
// First arg must be a valid player name
UUID targetUUID = getPlayers().getUUID(args.get(0));
if (targetUUID == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false;
}
// Get islands
islands = this.getNameIslandMap(User.getInstance(targetUUID));
if (islands.isEmpty()) {
user.sendMessage("general.errors.player-has-no-island");
return false;
}

// Second optional arg must be the name of the island
if (args.size() == 1) {
return true;
}

// A specific island is mentioned. Parse which one it is and remove the others
final String name = String.join(" ", args.subList(1, args.size())); // Join all the args from here with spaces

islands.keySet().removeIf(n -> !name.equalsIgnoreCase(n));

if (islands.isEmpty()) {
// Failed name check - there are either
user.sendMessage("commands.admin.maxhomes.errors.unknown-island", TextVariables.NAME, name);
return false;
}

return true;
}


/**
* @param user the {@link User} who is executing this command.
* @param label the label which has been used to execute this command.
* It can be {@link CompositeCommand#getLabel()} or an alias.
* @param args the command arguments.
* @return {@code true}
*/
@Override
public boolean execute(User user, String label, List<String> args)
{
if (islands.isEmpty()) {
// Sanity check
return false;
}
islands.forEach((name, island) -> {
island.getHomes().keySet().removeIf(String::isEmpty); // Remove the default home
user.sendMessage("commands.admin.resethome.cleared", TextVariables.NAME, name);
});

user.sendMessage("general.success");
return true;
}


@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() == 2) {
// Suggest player names
return Optional.of(Util.getOnlinePlayerList(user));
}
if (args.size() > 2) {
// Work out who is in arg 2
UUID targetUUID = getPlayers().getUUID(args.get(0));
if (targetUUID != null) {
User target = User.getInstance(targetUUID);
return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(target).keySet()), lastArg));
}
}
return Optional.empty();

}

Map<String, Island> getNameIslandMap(User user) {
Map<String, Island> islandMap = new HashMap<>();
int index = 0;
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
index++;
if (island.getName() != null && !island.getName().isBlank()) {
// Name has been set
islandMap.put(island.getName(), island);
} else {
// Name has not been set
String text = user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME,
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()) + " " + index;
islandMap.put(text, island);
}
}

return islandMap;

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ public void setup() {
new AdminDeleteHomesCommand(this);
// Reset name
new AdminResetNameCommand(this);
// Max homes
new AdminMaxHomesCommand(this);
// Reset Home
new AdminResetHomeCommand(this);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public boolean canExecute(User user, String label, List<String> args) {
// Check if mid-teleport
if (getIslands().isGoingHome(user)) {
// Tell them again that it's in progress
user.sendMessage("commands.island.go.teleport");
user.sendMessage("commands.island.go.in-progress");
return false;
}
List<Island> islands = getIslands().getIslands(getWorld(), user.getUniqueId());
Expand Down Expand Up @@ -76,7 +76,15 @@ public boolean execute(User user, String label, List<String> args) {
getIslands().setPrimaryIsland(user.getUniqueId(), info.island);
if (!info.islandName) {
this.delayCommand(user, () -> getIslands().homeTeleportAsync(getWorld(), user.getPlayer(), name)
.thenAccept((r) -> getIslands().setPrimaryIsland(user.getUniqueId(), info.island)));
.thenAccept((r) -> {
if (r.booleanValue()) {
// Success
getIslands().setPrimaryIsland(user.getUniqueId(), info.island);
} else {
user.sendMessage("commands.island.go.failure");
getPlugin().logError(user.getName() + " could not teleport to their island - async teleport issue");
}
}));
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public boolean execute(User user, String label, List<String> args) {
.tab(2, new SettingsTab(getWorld(), user, Flag.Type.SETTING))
.startingSlot(1)
.size(54)
.hideIfEmpty()
.build().openPanel();
return true;
}
Expand Down
Loading
Loading