Adds multiple home support.
Some checks failed
Java CI with Gradle / build (push) Has been cancelled
Some checks failed
Java CI with Gradle / build (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
This file is part of Metropolis.
|
||||
|
||||
Metropolis is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Metropolis is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||
*/
|
||||
|
||||
package com.majinnaibu.bukkitplugins.metropolis;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class HomeNumberAllocator {
|
||||
private HomeNumberAllocator() {}
|
||||
|
||||
public static int nextHomeNumber(List<Plot> plots) {
|
||||
Set<Integer> allocatedNumbers = new HashSet<>();
|
||||
for (Plot plot : plots) {
|
||||
if (plot instanceof PlayerHome home) {
|
||||
allocatedNumbers.add(home.getNumber());
|
||||
}
|
||||
}
|
||||
|
||||
int nextHomeNumber = 1;
|
||||
while (allocatedNumbers.contains(nextHomeNumber)) {
|
||||
nextHomeNumber++;
|
||||
}
|
||||
return nextHomeNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
This file is part of Metropolis.
|
||||
|
||||
Metropolis is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Metropolis is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Metropolis. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
|
||||
*/
|
||||
|
||||
package com.majinnaibu.bukkitplugins.metropolis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
public final class HomePermissionOverride {
|
||||
private final String _permission;
|
||||
private final int _priority;
|
||||
private final int _plotMultiplier;
|
||||
private final int _maxPlots;
|
||||
|
||||
private HomePermissionOverride(
|
||||
String permission, int priority, int plotMultiplier, int maxPlots) {
|
||||
_permission = permission;
|
||||
_priority = priority;
|
||||
_plotMultiplier = plotMultiplier;
|
||||
_maxPlots = maxPlots;
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
return _permission;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return _priority;
|
||||
}
|
||||
|
||||
public int getPlotMultiplier() {
|
||||
return _plotMultiplier;
|
||||
}
|
||||
|
||||
public int getMaxPlots() {
|
||||
return _maxPlots;
|
||||
}
|
||||
|
||||
public static List<HomePermissionOverride> load(
|
||||
ConfigurationSection section, Consumer<String> warningLogger) {
|
||||
if (section == null) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<HomePermissionOverride> overrides = new ArrayList<>();
|
||||
collect(section, "", overrides, warningLogger);
|
||||
return List.copyOf(overrides);
|
||||
}
|
||||
|
||||
private static void collect(
|
||||
ConfigurationSection section,
|
||||
String permissionPrefix,
|
||||
List<HomePermissionOverride> overrides,
|
||||
Consumer<String> warningLogger) {
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
String permission =
|
||||
permissionPrefix.isEmpty() ? entry.getKey() : permissionPrefix + "." + entry.getKey();
|
||||
Map<?, ?> values = getValues(entry.getValue());
|
||||
if (values != null && !hasRuleValues(values)) {
|
||||
collect((ConfigurationSection) entry.getValue(), permission, overrides, warningLogger);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (permission.isBlank()
|
||||
|| values == null
|
||||
|| !(values.get("priority") instanceof Number priority)
|
||||
|| !(values.get("plotMultiplier") instanceof Number plotMultiplier)
|
||||
|| !(values.get("maxPlots") instanceof Number maxPlots)
|
||||
|| priority.intValue() != priority.doubleValue()
|
||||
|| plotMultiplier.intValue() != plotMultiplier.doubleValue()
|
||||
|| maxPlots.intValue() != maxPlots.doubleValue()
|
||||
|| plotMultiplier.intValue() < 1
|
||||
|| maxPlots.intValue() < 0) {
|
||||
warningLogger.accept("Ignoring invalid permissionOverrides entry '" + permission + "'.");
|
||||
continue;
|
||||
}
|
||||
|
||||
overrides.add(
|
||||
new HomePermissionOverride(
|
||||
permission, priority.intValue(), plotMultiplier.intValue(), maxPlots.intValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasRuleValues(Map<?, ?> values) {
|
||||
return values.containsKey("priority")
|
||||
|| values.containsKey("plotMultiplier")
|
||||
|| values.containsKey("maxPlots");
|
||||
}
|
||||
|
||||
public static HomePermissionOverride findMatch(
|
||||
List<HomePermissionOverride> overrides, Predicate<String> hasPermission) {
|
||||
HomePermissionOverride match = null;
|
||||
for (HomePermissionOverride override : overrides) {
|
||||
if (hasPermission.test(override.getPermission())
|
||||
&& (match == null || override.getPriority() >= match.getPriority())) {
|
||||
match = override;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
public static int resolveMaxPlots(
|
||||
UserOverride userOverride,
|
||||
List<HomePermissionOverride> overrides,
|
||||
Predicate<String> hasPermission,
|
||||
int fallback) {
|
||||
if (userOverride != null) {
|
||||
return userOverride.getMaxPlots();
|
||||
}
|
||||
HomePermissionOverride match = findMatch(overrides, hasPermission);
|
||||
return match == null ? fallback : match.getMaxPlots();
|
||||
}
|
||||
|
||||
public static int resolvePlotMultiplier(
|
||||
UserOverride userOverride,
|
||||
List<HomePermissionOverride> overrides,
|
||||
Predicate<String> hasPermission,
|
||||
int fallback) {
|
||||
if (userOverride != null) {
|
||||
return userOverride.getPlotMultiplier();
|
||||
}
|
||||
HomePermissionOverride match = findMatch(overrides, hasPermission);
|
||||
return match == null ? fallback : match.getPlotMultiplier();
|
||||
}
|
||||
|
||||
private static Map<?, ?> getValues(Object value) {
|
||||
if (value instanceof ConfigurationSection section) {
|
||||
return section.getValues(false);
|
||||
}
|
||||
if (value instanceof Map<?, ?> map) {
|
||||
return map;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,7 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
private List<Plot> _occupiedPlots;
|
||||
private HashMap<UUID, List<Plot>> _ownedPlots;
|
||||
private HashMap<UUID, UserOverride> _userOverrides;
|
||||
private List<HomePermissionOverride> _permissionOverrides;
|
||||
private HashMap<UUID, Integer> _currentHomes;
|
||||
|
||||
private PlayerJoinListener _playerJoinListener = null;
|
||||
@@ -196,10 +197,14 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
wallMaterial = safeGetMaterialFromConfig(config, "wall.material");
|
||||
wallHeight = safeGetIntFromConfig(config, "wall.height");
|
||||
worldName = safeGetStringFromConfig(config, "worldname");
|
||||
_maxPlots = safeGetIntFromConfig(config, "plot.multiplier");
|
||||
_plotMultiplier = safeGetIntFromConfig(config, "plot.maxPerPlayer");
|
||||
_plotMultiplier = safeGetIntFromConfig(config, "plot.multiplier");
|
||||
_maxPlots = safeGetIntFromConfig(config, "plot.maxPerPlayer");
|
||||
|
||||
buildUserOverrides();
|
||||
_permissionOverrides =
|
||||
HomePermissionOverride.load(
|
||||
config.getConfigurationSection("permissionOverrides"),
|
||||
warning -> getLogger().warning(warning));
|
||||
|
||||
saveConfig();
|
||||
if (DEBUG) {
|
||||
@@ -494,9 +499,6 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
ProtectedCuboidRegion cuboidRegion = (ProtectedCuboidRegion) region;
|
||||
if (cuboidRegion.getId().startsWith("h_")) {
|
||||
PlayerHome home = PlayerHome.get(region);
|
||||
if (!_currentHomes.containsKey(home.getPlayerId())) {
|
||||
_currentHomes.put(home.getPlayerId(), home.getNumber());
|
||||
}
|
||||
_occupiedPlots.add(home);
|
||||
addOwnedPlot(home.getPlayerId(), home);
|
||||
} else if (cuboidRegion.getId().startsWith("r_")) {
|
||||
@@ -505,7 +507,17 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
for (UUID playerId : _ownedPlots.keySet()) {
|
||||
if (!_currentHomes.containsKey(playerId)) {
|
||||
PlayerHome firstHome = getFirstOwnedHome(playerId);
|
||||
if (firstHome != null) {
|
||||
_currentHomes.put(playerId, firstHome.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size = calculateCitySize();
|
||||
saveCurrentHomes();
|
||||
}
|
||||
|
||||
private void addOwnedPlot(UUID playerId, Plot plot) {
|
||||
@@ -527,20 +539,27 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
public PlayerHome getPlayerHome(Player player) {
|
||||
PlayerHome home = null;
|
||||
|
||||
int homeNumber = _currentHomes.getOrDefault(player.getUniqueId(), 1);
|
||||
UUID playerId = player.getUniqueId();
|
||||
int homeNumber = _currentHomes.getOrDefault(playerId, 1);
|
||||
String regionName = String.format("h_%d_%s", homeNumber, player.getUniqueId());
|
||||
ProtectedRegion homeRegion = regionManager.getRegion(regionName);
|
||||
|
||||
if (homeRegion == null) {
|
||||
PlayerHome existingHome = getOwnedHome(player.getUniqueId(), homeNumber);
|
||||
PlayerHome existingHome = getOwnedHome(playerId, homeNumber);
|
||||
if (existingHome != null) {
|
||||
existingHome.setPlayerName(player.getName());
|
||||
return existingHome;
|
||||
}
|
||||
existingHome = getFirstOwnedHome(playerId);
|
||||
if (existingHome != null) {
|
||||
existingHome.setPlayerName(player.getName());
|
||||
setHome(playerId, existingHome.getNumber());
|
||||
return existingHome;
|
||||
}
|
||||
if (DEBUG) {
|
||||
getLogger().info(String.format("Creating home for player %s", player.getName()));
|
||||
}
|
||||
home = generateHome(player);
|
||||
home = generateHome(player, 1);
|
||||
} else {
|
||||
home = new PlayerHome(homeRegion);
|
||||
home.setPlayerName(player.getName());
|
||||
@@ -891,7 +910,7 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
|
||||
BlockVector3 bv =
|
||||
BlockVector3.at(
|
||||
(col + plotMultiplier) * gridSizeX * plotMultiplier - 1,
|
||||
(col + plotMultiplier) * gridSizeX - 1,
|
||||
(level + 1 /*plotMultiplier*/) * gridSizeY - 1,
|
||||
(row + plotMultiplier) * gridSizeZ - 1);
|
||||
getLogger().info(String.format("getGridMax (%d, %d, %d)", bv.x(), bv.y(), bv.z()));
|
||||
@@ -924,10 +943,14 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
public PlayerHome generateHome(OfflinePlayer player) {
|
||||
int homeNumber = _currentHomes.getOrDefault(player.getUniqueId(), 1);
|
||||
return generateHome(player, homeNumber);
|
||||
}
|
||||
|
||||
public PlayerHome generateHome(OfflinePlayer player, int homeNumber) {
|
||||
UUID playerId = player.getUniqueId();
|
||||
String playerName = player.getName() == null ? playerId.toString() : player.getName();
|
||||
int homeNumber = _currentHomes.getOrDefault(playerId, 1);
|
||||
int multiplier = getPlotMultiplier(playerId);
|
||||
int multiplier = getPlotMultiplier(player);
|
||||
|
||||
if (DEBUG) {
|
||||
getLogger().info(String.format("Generating home for %s", playerName));
|
||||
@@ -993,7 +1016,7 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
homeNumber,
|
||||
newHomeRegion.getMinimumPoint(),
|
||||
newHomeRegion.getMaximumPoint());
|
||||
_currentHomes.putIfAbsent(playerId, homeNumber);
|
||||
_currentHomes.put(playerId, homeNumber);
|
||||
saveCurrentHomes();
|
||||
|
||||
createRoads(homeCuboid);
|
||||
@@ -1130,10 +1153,28 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxPlots(Player player) {
|
||||
return HomePermissionOverride.resolveMaxPlots(
|
||||
_userOverrides.get(player.getUniqueId()),
|
||||
_permissionOverrides,
|
||||
player::hasPermission,
|
||||
_maxPlots);
|
||||
}
|
||||
|
||||
public void assignPlot(OfflinePlayer player) {
|
||||
generateHome(player);
|
||||
}
|
||||
|
||||
public PlayerHome acquireHome(OfflinePlayer player) {
|
||||
List<Plot> ownedPlots = _ownedPlots.getOrDefault(player.getUniqueId(), List.of());
|
||||
int nextHomeNumber = HomeNumberAllocator.nextHomeNumber(ownedPlots);
|
||||
PlayerHome home = generateHome(player, nextHomeNumber);
|
||||
if (home != null) {
|
||||
setHome(player.getUniqueId(), home.getNumber());
|
||||
}
|
||||
return home;
|
||||
}
|
||||
|
||||
private int getPlotMultiplier(UUID playerId) {
|
||||
if (_userOverrides.containsKey(playerId)) {
|
||||
return _userOverrides.get(playerId).getPlotMultiplier();
|
||||
@@ -1142,6 +1183,21 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private int getPlotMultiplier(OfflinePlayer player) {
|
||||
if (player instanceof Player onlinePlayer) {
|
||||
return HomePermissionOverride.resolvePlotMultiplier(
|
||||
_userOverrides.get(player.getUniqueId()),
|
||||
_permissionOverrides,
|
||||
onlinePlayer::hasPermission,
|
||||
_plotMultiplier);
|
||||
}
|
||||
return HomePermissionOverride.resolvePlotMultiplier(
|
||||
_userOverrides.get(player.getUniqueId()),
|
||||
_permissionOverrides,
|
||||
ignored -> false,
|
||||
_plotMultiplier);
|
||||
}
|
||||
|
||||
public Plot getPlot(String string) {
|
||||
/**
|
||||
* string is the name of the region to get a plot for
|
||||
@@ -1229,6 +1285,18 @@ public class MetropolisPlugin extends JavaPlugin {
|
||||
return null;
|
||||
}
|
||||
|
||||
private PlayerHome getFirstOwnedHome(UUID playerId) {
|
||||
List<Plot> plots = _ownedPlots.get(playerId);
|
||||
if (plots == null) {
|
||||
return null;
|
||||
}
|
||||
return plots.stream()
|
||||
.filter(PlayerHome.class::isInstance)
|
||||
.map(PlayerHome.class::cast)
|
||||
.min(java.util.Comparator.comparingInt(PlayerHome::getNumber))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private void saveCurrentHomes() {
|
||||
File homesFile = new File(getDataFolder(), "currentHomes.yml");
|
||||
try {
|
||||
|
||||
@@ -40,12 +40,11 @@ public class MetropolisHomeAcquire implements CommandExecutor {
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (_plugin.getNumPlots(player.getUniqueId()) >= _plugin.getMaxPlots(player.getUniqueId())) {
|
||||
if (_plugin.getNumPlots(player.getUniqueId()) >= _plugin.getMaxPlots(player)) {
|
||||
sender.sendMessage("You cannot have any more plots");
|
||||
return false;
|
||||
}
|
||||
|
||||
_plugin.assignPlot(player);
|
||||
return true;
|
||||
return _plugin.acquireHome(player) != null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user