package us.icebrg.hungry;
import java.io.File;
import java.io.IOException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.bukkit.ChatColor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
public class HungryConfiguration {
/**
* Whether or not the Hungry hunger increment loop is enabled
*/
public Boolean isEnabled = true;
/**
* The interval after which to check for and increment hunger, in seconds
*/
public Long checkInterval = 60L;
/**
* The amount by which to increment hunger after every check
*/
public Integer incrementAmount = 1;
/**
* The default amount of hunger (what a new player starts out with)
*/
public Integer defaultHunger = 0;
/**
* The maximum amount of hunger a player can have before starving
*/
public Integer maxHunger = 100;
/**
* The minimum amount of hunger a player can have - ignored if canStockUp is
* set to true
*/
public Integer minHunger = 0;
/**
* Whether the player can stock up infinitely on food, overrides minHunger
*/
public Boolean canStockUpInfinitely = false;
/**
* The amount of damage that should be done to the player every time a check
* finds them as starving - a value of 2 equals one heart
*/
public Integer starvationDamage = 2;
/**
* Whether or not starvation should do actual damage (affects armor first)
* or simply subtract health (will not affect armor)
*/
public Boolean starvationDoesActualDamage = false;
/**
* Whether or not to reset the hunger level when the player respawns
*/
public Boolean resetHungerAtRespawn = true;
/**
* The hunger levels of all players
*/
public volatile HashMap<String, Integer> playerHungers;
/**
* The different foods and the amount of hunger each restores, specify item
* names using the org.bukkit.Material enum
*/
public HashMap<String, Integer> foods;
/**
* Blocks which right-clicking on should restore hunger, specify block names
* using the org.bukkit.Material enum NOTE: the only supported block food is
* cake. No others will work.
*/
public HashMap<String, Integer> foodBlocks;
public String[] ignoreClickBlocks = { "DISPENSER", "NOTE_BLOCK",
"BED_BLOCK", "CHEST", "WORKBENCH", "FURNACE", "BURNING_FURNACE",
"WOODEN_DOOR", "LEVER", "IRON_DOOR_BLOCK", "STONE_BUTTON",
"JUKEBOX", "LOCKED_CHEST", "TRAP_DOOR" };
/**
* The prefix to display in front of messages sent by Hungry.
*/
public String messagePrefix = ChatColor.YELLOW + "[Hungry] ";
/**
* Custom language support, through fully configurable messages!
* Uses printf-style formatting.
*/
public HashMap<HungryMessages, String> messages;
/**
* Hunger level notifications.
*/
public HashMap<Integer, String> hungerLevelNotifications;
/**
* Only show hunger level notifications when the hunger is exactly at the
* specified level.
*/
public Boolean hungerLevelNotificationsOnlyOnExact = false;
public HungryConfiguration() {
}
/**
* Sets default sub-values for complex values.
* We can't have this in the constructor, because then we'd mess up the Gson
* object deserialization process. Instead, we specifically call this when
* we are setting up an initial configuration file.
*/
public void setDefaults() {
this.foods = new HashMap<String, Integer>();
this.foodBlocks = new HashMap<String, Integer>();
this.playerHungers = new HashMap<String, Integer>();
this.messages = new HashMap<HungryMessages, String>();
this.hungerLevelNotifications = new HashMap<Integer, String>();
this.foods.put("APPLE", 100);
this.foods.put("MUSHROOM_SOUP", 25);
this.foods.put("PORK", 20);
this.foods.put("GRILLED_PORK", 35);
this.foods.put("GOLDEN_APPLE", 100);
this.foods.put("RAW_FISH", 25);
this.foods.put("COOKED_FISH", 35);
this.foods.put("COOKIE", 35);
this.foodBlocks.put("CAKE_BLOCK", 15);
/**
* Non-Variable Messages
*/
/**
* Food list messages
*/
this.messages.put(HungryMessages.MSG_FOOD_LIST_START,
ChatColor.GREEN + "=== EDIBLE FOODS ===");
this.messages.put(HungryMessages.MSG_FOOD_LIST_END,
ChatColor.GREEN + "=== END EDIBLE FOODS ===");
this.messages.put(HungryMessages.MSG_TOGGLED_ENABLED,
ChatColor.GREEN + "Hungry is now enabled!");
this.messages.put(HungryMessages.MSG_TOGGLED_DISABLED,
ChatColor.RED + "Hungry is now disabled!");
this.messages.put(HungryMessages.MSG_SAVECONFIG_SUCCESS,
ChatColor.GREEN + "Configuration succesfully saved!");
this.messages.put(HungryMessages.ERR_SAVECONFIG_FAILURE,
ChatColor.RED + "Configuration failed to save!");
this.messages.put(HungryMessages.MSG_RELOAD_SUCCESS,
ChatColor.GREEN + "Hungry succesfully reloaded!");
this.messages.put(HungryMessages.ERR_RELOAD_FAILURE,
ChatColor.RED + "Hungry failed to reloaded!");
/**
* Error Messages
*/
this.messages.put(HungryMessages.ERR_ONLY_USABLE_INGAME,
ChatColor.RED + "This command can only be used by in-game players.");
this.messages.put(HungryMessages.ERR_NO_SUCH_FOOD,
ChatColor.RED + "No food with that name/id was found.");
this.messages.put(HungryMessages.ERR_INVALID_HUNGER_FORMAT,
ChatColor.RED + "Invalid format for player hunger!");
/**
* Variable Messages
*/
this.messages.put(HungryMessages.VAR_CURRENT_HUNGER_IS,
ChatColor.GREEN + "Your current hunger level is " + ChatColor.WHITE + "%s");
this.messages.put(HungryMessages.VAR_FOOD_INFO,
ChatColor.WHITE + "%s " + ChatColor.GREEN
+ " restores " + ChatColor.WHITE + " %s " + ChatColor.GREEN + " hunger.");
this.messages.put(HungryMessages.VAR_SETHUNGER,
ChatColor.GREEN + "Succesfully set"
+ ChatColor.WHITE + " %s's " + ChatColor.GREEN + "hunger to"
+ ChatColor.WHITE + " %s.");
this.messages.put(HungryMessages.VAR_FOOD_LIST_ITEM,
ChatColor.GREEN + "%s" + ChatColor.YELLOW + " : " + ChatColor.GREEN + "%s");
this.hungerLevelNotifications.put(20, "You feel a bit peckish.");
this.hungerLevelNotifications.put(40, "Your stomach rumbles.");
this.hungerLevelNotifications.put(60, "You start to feel hungry.");
this.hungerLevelNotifications.put(80, "Your stomach aches from hunger.");
this.hungerLevelNotifications.put(100, ChatColor.RED + "You are starving!");
}
/**
* Convenience function for getting a formattable message and replacing variables...
*/
public String getMessage(HungryMessages name, String ... variables) {
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.getDefault()); // The Locale doesn't really
// matter, because we aren't using any localizable fields (date, etc.)
formatter.format(this.messages.get(name), (Object[])variables);
// Do tricky stuff with casting the variables array to an Object for a varargs
// invocation
// Example: (red) [Hungry] (reset to white) SomeMessageHere
return this.messagePrefix + ChatColor.WHITE + sb.toString();
}
/**
* Convenience function for getting the suitable hungerLevelNotification for the
* specified hungerLevel.
* @param hungerLevel the hungerLevel to get a notification for
* @return a String with the proper message if possible, null otherwise
*/
public String getHungerLevelNotification(Integer hungerLevel) {
Iterator<Map.Entry<Integer, String>> hungerLevelIt =
this.hungerLevelNotifications.entrySet().iterator();
Map.Entry<Integer, String> bestNotification;
// If we're only supposed to show hungerLevelNotifactions at the exact amount
if (this.hungerLevelNotificationsOnlyOnExact) {
if (this.hungerLevelNotifications.containsKey(hungerLevel)) {
return this.hungerLevelNotifications.get(hungerLevel);
}
// If no hungerLevelNotification was found with exactly that value,
// just return null;
return null;
}
bestNotification = null;
// Now, get the highest possible hunger
while (hungerLevelIt.hasNext()) {
Map.Entry<Integer, String> notification = hungerLevelIt.next();
// If the playerHunger satisfies this key and if this key is a better match
// (higher up) than the existing bestNotification...
if (hungerLevel >= notification.getKey())
{
if (bestNotification == null
|| notification.getKey() > bestNotification.getKey()) {
bestNotification = notification;
}
}
}
// Double-check in case we couldn't get a suitable notification at all, then
// display it
if (bestNotification != null && hungerLevel >= bestNotification.getKey()) {
return this.messagePrefix + ChatColor.WHITE + bestNotification.getValue();
}
return null;
}
public static HungryConfiguration load(File location) throws IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonConfig = FileUtils.readFileToString(location, "utf-8");
if (jsonConfig.length() == 0) {
throw new JsonSyntaxException("File is empty!");
}
return gson.fromJson(jsonConfig, HungryConfiguration.class);
}
/**
* Saves the configuration object to disk
* @param location the location to save the configuration
*/
public void save(File location) throws IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
FileUtils.writeStringToFile(location, gson.toJson(this), "utf-8");
}
}