Skip to content

Commit

Permalink
Merge pull request #2536 from BentoBoxWorld/2534_new_island_scaling
Browse files Browse the repository at this point in the history
2534 new island scaling
  • Loading branch information
tastybento authored Oct 21, 2024
2 parents ca9c81e + 3d696e1 commit 84b0fa3
Show file tree
Hide file tree
Showing 21 changed files with 848 additions and 344 deletions.
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.6.0</build.version>
<build.version>2.7.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
12 changes: 0 additions & 12 deletions src/main/java/world/bentobox/bentobox/BentoBox.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package world.bentobox.bentobox;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;

Expand Down Expand Up @@ -466,16 +464,6 @@ public boolean loadSettings() {
return false;
}

log("Saving default panels...");
if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "island_creation_panel.yml"))) {
log("Saving default island_creation_panel...");
this.saveResource("panels/island_creation_panel.yml", false);
}

if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "language_panel.yml"))) {
log("Saving default language_panel...");
this.saveResource("panels/language_panel.yml", false);
}
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ private CompositeCommand getCommandFromArgs(String[] args) {
*
* @return IslandsManager
*/
protected IslandsManager getIslands() {
public IslandsManager getIslands() {
return plugin.getIslands();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ public boolean canExecute(User user, String label, List<String> args) {

@Override
public boolean execute(User user, String label, List<String> args) {
Map<String, IslandInfo> names = getNameIslandMap(user);
// Check if the home is known
if (!args.isEmpty()) {
Map<String, IslandInfo> names = getNameIslandMap(user);
final String name = String.join(" ", args);
if (!names.containsKey(name)) {
// Failed home name check
Expand Down Expand Up @@ -113,7 +113,11 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String>

}

private record IslandInfo(Island island, boolean islandName) {}
/**
* Record of islands and the name to type
*/
private record IslandInfo(Island island, boolean islandName) {
}

private Map<String, IslandInfo> getNameIslandMap(User user) {
Map<String, IslandInfo> islandMap = new HashMap<>();
Expand All @@ -129,7 +133,8 @@ private Map<String, IslandInfo> getNameIslandMap(User user) {
islandMap.put(text, new IslandInfo(island, true));
}
// Add homes. Homes do not need an island specified
island.getHomes().keySet().forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
island.getHomes().keySet().stream().filter(n -> !n.isBlank())
.forEach(n -> islandMap.put(n, new IslandInfo(island, false)));
}

return islandMap;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
package world.bentobox.bentobox.api.commands.island;

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

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;
import world.bentobox.bentobox.panels.customizable.IslandHomesPanel;

public class IslandHomesCommand extends ConfirmableCommand {

private List<Island> islands;
public class IslandHomesCommand extends CompositeCommand {

public IslandHomesCommand(CompositeCommand islandCommand) {
super(islandCommand, "homes");
Expand All @@ -28,9 +21,8 @@ public void setup() {

@Override
public boolean canExecute(User user, String label, List<String> args) {
islands = getIslands().getIslands(getWorld(), user);
// Check island
if (islands.isEmpty()) {
if (getIslands().getIslands(getWorld(), user).isEmpty()) {
user.sendMessage("general.errors.no-island");
return false;
}
Expand All @@ -39,22 +31,8 @@ public boolean canExecute(User user, String label, List<String> args) {

@Override
public boolean execute(User user, String label, List<String> args) {
user.sendMessage("commands.island.sethome.homes-are");
islands.forEach(island ->
island.getHomes().keySet().stream().filter(s -> !s.isEmpty())
.forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)));
IslandHomesPanel.openPanel(this, user);
return true;
}

@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
List<String> result = new ArrayList<>();
for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) {
result.addAll(island.getHomes().keySet());
}
return Optional.of(Util.tabLimit(result, lastArg));

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,8 @@ ItemSlot nextItemSlot() {
* this button is present.
*
* @return Map that links button type to amount in the gui.
* @deprecated Use {@link #amount(String)} instead.
* Use {@link #amount(String)} instead.
*/
@Deprecated
public Map<String, Integer> amountMap() {
return this.parentPanel.typeSlotMap;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,29 @@ public static PanelTemplateRecord readTemplatePanel(@NonNull String panelName, @
}

File file = new File(panelLocation, templateName.endsWith(YML) ? templateName : templateName + YML);

String absolutePath = file.getAbsolutePath();
if (!file.exists())
{
BentoBox.getInstance().logError(file.getAbsolutePath() + " does not exist for panel template");
// Return as file does not exist.
return null;
// Try to get it from the JAR

String keyword = "panels/";

// Find the index of the keyword "panels/"
int index = absolutePath.indexOf(keyword);

// If the keyword is found, extract the substring starting from that index
if (index != -1) {
BentoBox.getInstance().saveResource(absolutePath.substring(index), false);
file = new File(panelLocation, templateName.endsWith(YML) ? templateName : templateName + YML);
} else {
BentoBox.getInstance().logError(file.getAbsolutePath() + " does not exist for panel template");
// Return as file does not exist.
return null;
}

}

final String panelKey = file.getAbsolutePath() + ":" + panelName;
final String panelKey = absolutePath + ":" + panelName;

// Check if panel is already crafted.
if (TemplateReader.loadedPanels.containsKey(panelKey))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ public Optional<Island> getIslandAt(@NonNull Location location) {
: Optional.empty();
}

public boolean isIslandAt(@NonNull Location location) {
return plugin.getIWM().inWorld(location) ? islandCache.isIslandAt(location) : false;
}

/**
* Returns an <strong>unmodifiable collection</strong> of all existing islands
* (even those who may be unowned).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ public Location getNextLocation(World world) {
*/
protected Result isIsland(Location location) {
// Quick check
if (plugin.getIslands().getIslandAt(location).isPresent()) return Result.ISLAND_FOUND;
if (plugin.getIslands().isIslandAt(location)) {
return Result.ISLAND_FOUND;
}

World world = location.getWorld();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,23 @@ public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) {
}
}

/**
* Returns if there is island at the location. This includes
* the full island space, not just the protected area.
* Does not cause a database load of the island.
*
* @param location the location
* @return true if there is an island there
*/
@Nullable
public boolean isIslandAt(@NonNull Location location) {
World w = Util.getWorld(location.getWorld());
if (w == null || !grids.containsKey(w)) {
return false;
}
return grids.get(w).isIslandAt(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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.Map.Entry;
import java.util.TreeMap;

import org.eclipse.jdt.annotation.Nullable;

import world.bentobox.bentobox.database.objects.Island;

/**
Expand All @@ -11,7 +13,11 @@
*
*/
class IslandGrid {
private final TreeMap<Integer, TreeMap<Integer, String>> grid = new TreeMap<>();

private record IslandData(String id, int minX, int minZ, int range) {
}

private final TreeMap<Integer, TreeMap<Integer, IslandData>> grid = new TreeMap<>();
private final IslandCache im;

/**
Expand All @@ -29,25 +35,28 @@ public IslandGrid(IslandCache im) {
*/
public boolean addToGrid(Island island) {
// Check if we know about this island already
if (grid.containsKey(island.getMinX())) {
TreeMap<Integer, String> zEntry = grid.get(island.getMinX());
if (zEntry.containsKey(island.getMinZ())) {
if (island.getUniqueId().equals(zEntry.get(island.getMinZ()))) {
int minX = island.getMinX();
int minZ = island.getMinZ();
IslandData islandData = new IslandData(island.getUniqueId(), minX, minZ, island.getRange());
if (grid.containsKey(minX)) {
TreeMap<Integer, IslandData> zEntry = grid.get(minX);
if (zEntry.containsKey(minZ)) {
if (island.getUniqueId().equals(zEntry.get(minZ).id())) {
// If it is the same island then it's okay
return true;
}
// Island overlap, report error
return false;
} else {
// Add island
zEntry.put(island.getMinZ(), island.getUniqueId());
grid.put(island.getMinX(), zEntry);
zEntry.put(minZ, islandData);
grid.put(minX, zEntry);
}
} else {
// Add island
TreeMap<Integer, String> zEntry = new TreeMap<>();
zEntry.put(island.getMinZ(), island.getUniqueId());
grid.put(island.getMinX(), zEntry);
TreeMap<Integer, IslandData> zEntry = new TreeMap<>();
zEntry.put(minZ, islandData);
grid.put(minX, zEntry);
}
return true;
}
Expand All @@ -60,7 +69,7 @@ public boolean addToGrid(Island island) {
public boolean removeFromGrid(Island island) {
String id = island.getUniqueId();
boolean removed = grid.values().stream()
.anyMatch(innerMap -> innerMap.values().removeIf(innerValue -> innerValue.equals(id)));
.anyMatch(innerMap -> innerMap.values().removeIf(innerValue -> innerValue.id().equals(id)));

grid.values().removeIf(TreeMap::isEmpty);

Expand All @@ -70,35 +79,55 @@ public boolean removeFromGrid(Island island) {
/**
* Retrieves the island located at the specified x and z coordinates, covering both the protected area
* and the full island space. Returns null if no island exists at the given location.
* This will load the island from the database if it is not in the cache.
*
* @param x the x coordinate of the location
* @param z the z coordinate of the location
* @return the Island at the specified location, or null if no island is found
*/
public Island getIslandAt(int x, int z) {
String id = getIslandStringAt(x, z);
if (id == null) {
return null;
}

// Retrieve the island using the id found - loading from database if required
return im.getIslandById(id);
}

/**
* Checks if an island is at this coordinate or not
* @param x coord
* @param z coord
* @return true if there is an island registered here in the grid
*/
public boolean isIslandAt(int x, int z) {
return getIslandStringAt(x, z) != null;
}

/**
* Get the island ID string for an island at this coordinates, or null if none.
* @param x coord
* @param z coord
* @return Unique Island ID string, or null if there is no island here.
*/
public @Nullable String getIslandStringAt(int x, int z) {
// Attempt to find the closest x-coordinate entry that does not exceed 'x'
Entry<Integer, TreeMap<Integer, String>> xEntry = grid.floorEntry(x);
Entry<Integer, TreeMap<Integer, IslandData>> xEntry = grid.floorEntry(x);
if (xEntry == null) {
return null; // No x-coordinate entry found, return null
}

// Attempt to find the closest z-coordinate entry that does not exceed 'z' within the found x-coordinate
Entry<Integer, String> zEntry = xEntry.getValue().floorEntry(z);
Entry<Integer, IslandData> zEntry = xEntry.getValue().floorEntry(z);
if (zEntry == null) {
return null; // No z-coordinate entry found, return null
}

// Retrieve the island using the id found in the z-coordinate entry
Island island = im.getIslandById(zEntry.getValue());
if (island == null) {
return null; // No island found by the id, return null
}
// Check if the specified coordinates are within the island space
if (island.inIslandSpace(x, z)) {
return island; // Coordinates are within island space, return the island
if (x >= zEntry.getValue().minX() && x < (zEntry.getValue().minX() + zEntry.getValue().range() * 2)
&& z >= zEntry.getValue().minZ() && z < (zEntry.getValue().minZ() + zEntry.getValue().range() * 2)) {
return zEntry.getValue().id();
}

// Coordinates are outside the island space, return null
return null;
}

Expand All @@ -107,7 +136,7 @@ public Island getIslandAt(int x, int z) {
*/
public long getSize() {
long count = 0;
for (TreeMap<Integer, String> innerMap : grid.values()) {
for (TreeMap<Integer, IslandData> innerMap : grid.values()) {
count += innerMap.size();
}
return count;
Expand Down
Loading

0 comments on commit 84b0fa3

Please sign in to comment.