240 lines
8.5 KiB
Java

package net.knarcraft.permissionsigns.container;
import net.knarcraft.permissionsigns.formatting.StringFormatter;
import net.knarcraft.permissionsigns.formatting.TranslatableMessage;
import net.knarcraft.permissionsigns.formatting.Translator;
import net.knarcraft.permissionsigns.manager.EconomyManager;
import org.bukkit.Location;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static net.knarcraft.permissionsigns.formatting.StringFormatter.replacePlaceholder;
/**
* This class represents a placed and active permission sign
*/
public class PermissionSign {
private Location signLocation;
private final String name;
private final List<String> permissionNodes;
private final int duration;
private final double cost;
private static Map<Double, TranslatableMessage[]> timeUnits;
private static List<Double> sortedUnits;
/**
* Instantiates a new permission sign
*
* @param signLocation <p>The location of the permission sing in the world</p>
* @param name <p>The name to display on the permission sign</p>
* @param permissionNodes <p>The permissions granted when this permission sign is used</p>
* @param duration <p>The duration, in seconds, until the permission should be revoked. 0 for non-temporary</p>
* @param cost <p>The cost of using this permission sign</p>
*/
public PermissionSign(Location signLocation, String name, List<String> permissionNodes, int duration, double cost) {
this.signLocation = signLocation;
this.name = name;
this.permissionNodes = new ArrayList<>(permissionNodes);
//Automatically fix negative values
this.duration = Math.max(0, duration);
this.cost = Math.max(0, cost);
}
/**
* Instantiates a new permission sign
*
* @param name <p>The name to display on the permission sign</p>
* @param permissionNodes <p>The permissions granted when this permission sign is used</p>
* @param duration <p>The duration, in seconds, until the permission should be revoked. 0 for non-temporary</p>
* @param cost <p>The cost of using this permission sign</p>
*/
public PermissionSign(String name, List<String> permissionNodes, int duration, double cost) {
this.name = name;
this.permissionNodes = new ArrayList<>(permissionNodes);
this.duration = Math.max(0, duration);
this.cost = Math.max(0, cost);
}
/**
* Sets the sign location of this permission sign
*
* @param signLocation <p>>The location of this permission sign's actual sign</p>
*/
public void setSignLocation(Location signLocation) {
if (this.signLocation == null) {
this.signLocation = signLocation;
} else {
throw new IllegalArgumentException("A sign location cannot be overwritten");
}
}
/**
* Gets the location of this permission sign
*
* <p>The location might be null until a sign has been right-clicked</p>
*
* @return <p>The location of this permission sign</p>
*/
public Location getSignLocation() {
return signLocation;
}
/**
* Gets the name of this permission sign
*
* @return <p>The name of this permission sign</p>
*/
public String getName() {
return name;
}
/**
* Gets the permissions nodes granted by this permission sign
*
* @return <p>The permission nodes granted by this permission sign</p>
*/
public List<String> getPermissionNodes() {
return new ArrayList<>(this.permissionNodes);
}
/**
* Gets the duration the permissions should last before expiring
*
* <p>A duration of 0 will give a permanent permission.</p>
*
* @return <p>The duration of the permissions</p>
*/
public int getDuration() {
return this.duration;
}
/**
* Gets the cost of using this permissions sign
*
* @return <p>The cost of using this permission sign</p>
*/
public double getCost() {
return this.cost;
}
/**
* Gets the lines used to represent this permission sign on a sign
*
* @return <p>The lines used to draw this permission sign</p>
*/
public String[] getSignLines() {
String[] lines = new String[4];
lines[0] = Translator.getTranslatedMessage(TranslatableMessage.SIGN_PREFIX);
lines[1] = replacePlaceholder(Translator.getTranslatedMessage(
TranslatableMessage.SIGN_NAME_FORMAT), "{name}", getName());
lines[2] = getDurationString();
lines[3] = getCostString();
return lines;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof PermissionSign)) {
return false;
}
if (this == other) {
return true;
}
return this.signLocation.equals(((PermissionSign) other).signLocation);
}
/**
* Gets the string used for displaying this sign's duration
*
* @return <p>The string used for displaying this sign's duration</p>
*/
public String getDurationString() {
if (duration == 0) {
return Translator.getTranslatedMessage(TranslatableMessage.SIGN_PERMANENT);
} else {
if (sortedUnits == null) {
initializeUnits();
}
for (Double unit : sortedUnits) {
if (duration / unit >= 1) {
double units = round(duration / unit);
return formatDurationString(units, timeUnits.get(unit)[units == 1 ? 0 : 1],
(units * 10) % 10 == 0);
}
}
return formatDurationString(duration, TranslatableMessage.UNIT_SECONDS, false);
}
}
/**
* Gets the string used for displaying this sign's cost
*
* @return <p>The string used for displaying this sign's cost</p>
*/
public String getCostString() {
if (cost == 0) {
return Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FREE);
} else {
String currency = EconomyManager.getCurrency(cost != 1);
String format = Translator.getTranslatedMessage(TranslatableMessage.SIGN_COST_FORMAT);
String formatted = StringFormatter.replacePlaceholders(format, new String[]{"{cost}", "{currency}"},
new String[]{"%.2f", currency});
return String.format(formatted, cost);
}
}
/**
* Rounds a number to its last two digits
*
* @param number <p>The number to round</p>
* @return <p>The rounded number</p>
*/
private double round(double number) {
return Math.round(number * 100.0) / 100.0;
}
/**
* Formats a duration string
*
* @param duration <p>The duration to display</p>
* @param translatableMessage <p>The time unit to display</p>
* @param castToInt <p>Whether to cast the duration to an int</p>
* @return <p>The formatted duration string</p>
*/
private String formatDurationString(double duration, TranslatableMessage translatableMessage, boolean castToInt) {
String durationFormat = Translator.getTranslatedMessage(TranslatableMessage.SIGN_DURATION_FORMAT);
durationFormat = replacePlaceholder(durationFormat, "{unit}",
Translator.getTranslatedMessage(translatableMessage));
return replacePlaceholder(durationFormat, "{duration}", castToInt ? String.valueOf((int) duration) :
String.valueOf(duration));
}
/**
* Initializes the mapping of available time units for formatting permission sign duration
*/
private static void initializeUnits() {
double minute = 60;
double hour = minute * 60;
double day = hour * 24;
timeUnits = new HashMap<>();
timeUnits.put(day, new TranslatableMessage[]{TranslatableMessage.UNIT_DAY, TranslatableMessage.UNIT_DAYS});
timeUnits.put(hour, new TranslatableMessage[]{TranslatableMessage.UNIT_HOUR, TranslatableMessage.UNIT_HOURS});
timeUnits.put(minute, new TranslatableMessage[]{TranslatableMessage.UNIT_MINUTE, TranslatableMessage.UNIT_MINUTES});
timeUnits.put(1D, new TranslatableMessage[]{TranslatableMessage.UNIT_SECOND, TranslatableMessage.UNIT_SECONDS});
sortedUnits = new ArrayList<>(timeUnits.keySet());
Collections.sort(sortedUnits);
Collections.reverse(sortedUnits);
}
}