Adds bonus range elements to Island object. (#1921)

* Adds bonus range elements to Island object.

Admin commands still need to be adjusted or added to support management
of the bonus ranges.

* Changed to mutable class

Fixed bugs.
This commit is contained in:
tastybento 2022-01-28 18:35:55 -08:00 committed by GitHub
parent 54869a400a
commit 7b94aa0ea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 185 additions and 12 deletions

View File

@ -270,6 +270,11 @@
<artifactId>GitHubWebAPI4Java</artifactId>
<version>${githubapi.version}</version>
</dependency>
<dependency>
<groupId>com.github.Marcono1234</groupId>
<artifactId>gson-record-type-adapter-factory</artifactId>
<version>0.1.0</version>
</dependency>
<!-- Static analysis -->
<!-- We are using Eclipse's annotations. If you're using IDEA, update
your project settings to take these into account for in real time static

View File

@ -56,7 +56,7 @@ public class AdminRangeAddCommand extends CompositeCommand {
Island island = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID));
int newRange = island.getProtectionRange() + Integer.parseInt(args.get(1));
if (newRange > island.getRange() * 2) {
if (newRange > island.getRange()) {
user.sendMessage("commands.admin.range.invalid-value.too-high", TextVariables.NUMBER, String.valueOf(island.getRange()));
return false;
} else if (newRange == island.getProtectionRange()) {

View File

@ -0,0 +1,67 @@
package world.bentobox.bentobox.database.objects;
import com.google.gson.annotations.Expose;
/**
* Record for bonus ranges
* @author tastybento
* @param id an id to identify this bonus
* @param range the additional bonus range
* @param message the reference key to a locale message related to this bonus. May be blank.
*/
public class BonusRangeRecord {
@Expose
private String uniqueId;
@Expose
private int range;
@Expose
private String message;
/**
* @param uniqueId
* @param range
* @param message
*/
public BonusRangeRecord(String uniqueId, int range, String message) {
this.uniqueId = uniqueId;
this.range = range;
this.message = message;
}
/**
* @return the uniqueId
*/
public String getUniqueId() {
return uniqueId;
}
/**
* @param uniqueId the uniqueId to set
*/
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
/**
* @return the range
*/
public int getRange() {
return range;
}
/**
* @param range the range to set
*/
public void setRange(int range) {
this.range = range;
}
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -1,6 +1,7 @@
package world.bentobox.bentobox.database.objects;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
@ -91,6 +92,13 @@ public class Island implements DataObject, MetaDataAble {
@Expose
private int protectionRange;
/**
* Bonuses to protection range
* @since 1.20.0
*/
@Expose
private List<BonusRangeRecord> bonusRanges = new ArrayList<>();
// Maximum ever protection range - used in island deletion
@Expose
private int maxEverProtectionRange;
@ -272,6 +280,7 @@ public class Island implements DataObject, MetaDataAble {
this.uniqueId = island.getUniqueId();
this.updatedDate = island.getUpdatedDate();
this.world = island.getWorld();
this.bonusRanges.addAll(island.getBonusRanges());
this.setChanged();
}
@ -534,12 +543,22 @@ public class Island implements DataObject, MetaDataAble {
}
/**
* Returns the protection range of this Island.
* Returns the protection range of this Island plus any bonuses. Will not be greater than getRange().
* This represents half of the length of the side of a theoretical square around the island center inside which flags are enforced.
* @return the protection range of this island, strictly positive integer.
* @see #getRange()
*/
public int getProtectionRange() {
return Math.min(this.getRange(), getRawProtectionRange() + this.getBonusRanges().stream().mapToInt(BonusRangeRecord::getRange).sum());
}
/**
* Returns the protection range of this Island without any bonuses
* This represents half of the length of the side of a theoretical square around the island center inside which flags are enforced.
* @return the protection range of this island, strictly positive integer.
* @since 1.20.0
*/
public int getRawProtectionRange() {
return protectionRange;
}
@ -549,15 +568,21 @@ public class Island implements DataObject, MetaDataAble {
public int getMaxEverProtectionRange() {
if (maxEverProtectionRange > this.range) {
maxEverProtectionRange = this.range;
setChanged();
}
return Math.max(protectionRange, maxEverProtectionRange);
}
/**
* Sets the maximum protection range. This can be used to optimize
* island deletion. Setting this values to a lower value than the current value
* will have no effect.
* @param maxEverProtectionRange the maxEverProtectionRange to set
*/
public void setMaxEverProtectionRange(int maxEverProtectionRange) {
this.maxEverProtectionRange = maxEverProtectionRange;
if (maxEverProtectionRange > this.maxEverProtectionRange) {
this.maxEverProtectionRange = maxEverProtectionRange;
}
if (maxEverProtectionRange > this.range) {
this.maxEverProtectionRange = this.range;
}
@ -1354,7 +1379,7 @@ public class Island implements DataObject, MetaDataAble {
}
/**
* Indicates the class has been changed
* Indicates the fields have been changed. Used to optimize saving on shutdown.
*/
public void setChanged() {
this.changed = true;
@ -1534,6 +1559,73 @@ public class Island implements DataObject, MetaDataAble {
getMaxMembers().put(rank, maxMembers);
}
/**
* @return the bonusRanges
*/
public List<BonusRangeRecord> getBonusRanges() {
if (bonusRanges == null) {
this.setBonusRanges(new ArrayList<>());
}
return bonusRanges;
}
/**
* @param bonusRanges the bonusRanges to set
*/
public void setBonusRanges(List<BonusRangeRecord> bonusRanges) {
this.bonusRanges = bonusRanges;
setChanged();
}
/**
* Get the bonus range provided by all settings of the range giver
* @param id an id to identify this bonus
* @return bonus range, or 0 if unknown
*/
public int getBonusRange(String id) {
return this.getBonusRanges().stream().filter(r -> r.getUniqueId().equals(id)).mapToInt(BonusRangeRecord::getRange).sum();
}
/**
* Get the BonusRangeRecord for uniqueId
* @param uniqueId a unique id to identify this bonus
* @return optional BonusRangeRecord
*/
public Optional<BonusRangeRecord> getBonusRangeRecord(String uniqueId) {
return this.getBonusRanges().stream().filter(r -> r.getUniqueId().equals(uniqueId)).findFirst();
}
/**
* Add a bonus range amount to the island for this addon or plugin.
* Note, this will not replace any range set already with the same id
* @param id an id to identify this bonus
* @param range range to add to the island protected range
* @param message the reference key to a locale message related to this bonus. May be blank.
*/
public void addBonusRange(String id, int range, String message) {
this.getBonusRanges().add(new BonusRangeRecord(id, range, message));
setMaxEverProtectionRange(this.getProtectionRange());
setChanged();
}
/**
* Clear the bonus ranges for a unique ID
* @param id id to identify this bonus
*/
public void clearBonusRange(String id) {
this.getBonusRanges().removeIf(r -> r.getUniqueId().equals(id));
setChanged();
}
/**
* Clear all bonus ranges for this island
*/
public void clearAllBonusRanges() {
this.getBonusRanges().clear();
setChanged();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/

View File

@ -219,20 +219,17 @@ public class JoinLeaveListener implements Listener {
Island island = plugin.getIslands().getIsland(world, user);
if (island != null) {
// Check if new owner has a different range permission than the island size
int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getProtectionRange());
int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getRawProtectionRange());
// Range cannot be greater than the island distance
range = Math.min(range, plugin.getIWM().getIslandDistance(island.getWorld()));
// Range can go up or down
if (range != island.getProtectionRange()) {
if (range != island.getRawProtectionRange()) {
user.sendMessage("commands.admin.setrange.range-updated", TextVariables.NUMBER, String.valueOf(range));
plugin.log("Island protection range changed from " + island.getProtectionRange() + " to "
+ range + " for " + user.getName() + " due to permission.");
// Get old range for event
int oldRange = island.getProtectionRange();
island.setProtectionRange(range);
plugin.log("Island protection range changed from " + oldRange + " to "
+ island.getProtectionRange() + " for " + user.getName() + " due to permission.");
// Call Protection Range Change event. Does not support canceling.
IslandEvent.builder()
.island(island)
@ -240,7 +237,7 @@ public class JoinLeaveListener implements Listener {
.reason(IslandEvent.Reason.RANGE_CHANGE)
.involvedPlayer(user.getUniqueId())
.admin(true)
.protectionRange(range, oldRange)
.protectionRange(island.getProtectionRange(), oldRange)
.build();
}
}

View File

@ -74,6 +74,16 @@ public class IslandInfo {
user.sendMessage("commands.admin.info.island-center", TextVariables.XYZ, Util.xyz(island.getCenter().toVector()));
user.sendMessage("commands.admin.info.island-coords", "[xz1]", Util.xyz(new Vector(island.getMinX(), 0, island.getMinZ())), "[xz2]", Util.xyz(new Vector(island.getMaxX(), 0, island.getMaxZ())));
user.sendMessage("commands.admin.info.protection-range", "[range]", String.valueOf(island.getProtectionRange()));
if (!island.getBonusRanges().isEmpty()) {
user.sendMessage("commands.admin.info.protection-range-bonus-title");
}
island.getBonusRanges().forEach(brb -> {
if (brb.getMessage().isBlank()) {
user.sendMessage("commands.admin.info.protection-range-bonus", TextVariables.NUMBER, String.valueOf(brb.getRange()));
} else {
user.sendMessage(brb.getMessage(), TextVariables.NUMBER, String.valueOf(brb.getRange()));
}
});
user.sendMessage("commands.admin.info.max-protection-range", "[range]", String.valueOf(island.getMaxEverProtectionRange()));
user.sendMessage("commands.admin.info.protection-coords", "[xz1]", Util.xyz(new Vector(island.getMinProtectedX(), 0, island.getMinProtectedZ())), "[xz2]", Util.xyz(new Vector(island.getMaxProtectedX() - 1, 0, island.getMaxProtectedZ() - 1)));
if (island.isSpawn()) {

View File

@ -199,6 +199,8 @@ commands:
island-coords: "Island coordinates: [xz1] to [xz2]"
islands-in-trash: "&d Player has islands in trash."
protection-range: "Protection range: [range]"
protection-range-bonus-title: "&b Includes these bonues:"
protection-range-bonus: "Bonus: [number]"
purge-protected: "Island is purge protected"
max-protection-range: "Largest historical protection range: [range]"
protection-coords: "Protection coordinates: [xz1] to [xz2]"