Introduction of new Alchemy skill!

This commit is contained in:
Eric Hildebrand
2013-11-15 18:21:00 -05:00
committed by TfT_02
parent 9afa8efd7d
commit 8f83e328b0
32 changed files with 2194 additions and 21 deletions

View File

@ -0,0 +1,99 @@
package com.gmail.nossr50.commands.skills;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.Player;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.alchemy.Alchemy.Tier;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
public class AlchemyCommand extends SkillCommand {
private String brewSpeed;
private String brewSpeedLucky;
private int tier;
private int ingredientCount;
private String ingredientList;
private boolean canCatalysis;
private boolean canConcoctions;
public AlchemyCommand() {
super(SkillType.ALCHEMY);
}
protected String[] calculateAbilityDisplayValues(Player player, float skillValue, boolean isLucky) {
String[] displayValues = new String[2];
displayValues[0] = decimal.format(UserManager.getPlayer(player).getAlchemyManager().getBrewSpeed()) + "x";
displayValues[1] = isLucky ? decimal.format(UserManager.getPlayer(player).getAlchemyManager().getBrewSpeedLucky()) + "x" : null;
return displayValues;
}
@Override
protected void dataCalculations(Player player, float skillValue, boolean isLucky) {
// CATALYSIS
if (canCatalysis) {
String[] catalysisStrings = calculateAbilityDisplayValues(player, skillValue, isLucky);
brewSpeed = catalysisStrings[0];
brewSpeedLucky = catalysisStrings[1];
}
// CONCOCTIONS
if (canConcoctions) {
tier = UserManager.getPlayer(player).getAlchemyManager().getTier();
ingredientCount = UserManager.getPlayer(player).getAlchemyManager().getIngredients().size();
ingredientList = UserManager.getPlayer(player).getAlchemyManager().getIngredientList();
}
}
@Override
protected void permissionsCheck(Player player) {
canCatalysis = Permissions.catalysis(player);
canConcoctions = Permissions.concoctions(player);
}
@Override
protected List<String> effectsDisplay() {
List<String> messages = new ArrayList<String>();
if (canCatalysis) {
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Alchemy.Effect.0"), LocaleLoader.getString("Alchemy.Effect.1")));
}
if (canConcoctions) {
messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Alchemy.Effect.2"), LocaleLoader.getString("Alchemy.Effect.3")));
}
return messages;
}
@Override
protected List<String> statsDisplay(Player player, float skillValue, boolean hasEndurance, boolean isLucky) {
List<String> messages = new ArrayList<String>();
if (canCatalysis) {
int unlockLevel = AdvancedConfig.getInstance().getCatalysisUnlockLevel();
if (skillValue < unlockLevel) {
messages.add(LocaleLoader.getString("Ability.Generic.Template.Lock", LocaleLoader.getString("Alchemy.Ability.Locked.0", unlockLevel)));
}
else {
messages.add(LocaleLoader.getString("Alchemy.Catalysis.Speed", brewSpeed) + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", brewSpeedLucky) : ""));
}
}
if (canConcoctions) {
messages.add(LocaleLoader.getString("Alchemy.Concoctions.Rank", tier, Tier.values().length));
messages.add(LocaleLoader.getString("Alchemy.Concoctions.Ingredients", ingredientCount, ingredientList));
}
return messages;
}
}

View File

@ -6,6 +6,7 @@ import java.util.List;
import com.gmail.nossr50.datatypes.skills.SecondaryAbility;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.fishing.Fishing;
import com.gmail.nossr50.skills.mining.BlastMining;
import com.gmail.nossr50.skills.repair.ArcaneForging;
@ -79,6 +80,38 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
reason.add("Skills.Acrobatics.GracefulRoll.DamageThreshold should be at least 0!");
}
/* ALCHEMY */
if (getCatalysisUnlockLevel() < 0) {
reason.add("Skills.Alchemy.Catalysis.UnlockLevel should be at least 0!");
}
if (getCatalysisMaxBonusLevel() <= getCatalysisUnlockLevel()) {
reason.add("Skills.Alchemy.Catalysis.MaxBonusLevel should be greater than Skills.Alchemy.Catalysis.UnlockLevel!");
}
if (getCatalysisMinSpeed() <= 0) {
reason.add("Skills.Alchemy.Catalysis.MinSpeed must be greater than 0!");
}
if (getCatalysisMaxSpeed() < getCatalysisMinSpeed()) {
reason.add("Skills.Alchemy.Catalysis.MaxSpeed should be at least Skills.Alchemy.Catalysis.MinSpeed!");
}
List<Alchemy.Tier> alchemyTierList = Arrays.asList(Alchemy.Tier.values());
for (Alchemy.Tier tier : alchemyTierList) {
if (getConcoctionsTierLevel(tier) < 0) {
reason.add("Skills.Alchemy.Rank_Levels.Rank_" + tier.toNumerical() + " should be at least 0!");
}
if (tier != Alchemy.Tier.fromNumerical(Alchemy.Tier.values().length)) {
Alchemy.Tier nextTier = alchemyTierList.get(alchemyTierList.indexOf(tier) - 1);
if (getConcoctionsTierLevel(tier) >= getConcoctionsTierLevel(nextTier)) {
reason.add("Skills.Alchemy.Rank_Levels.Rank_" + tier.toNumerical() + " should be less than Skills.Alchemy.Rank_Levels.Rank_" + nextTier.toNumerical() + "!");
}
}
}
/* ARCHERY */
if (getSkillShotIncreaseLevel() < 1) {
reason.add("Skills.Archery.SkillShot.IncreaseLevel should be at least 1!");
@ -624,6 +657,14 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
public double getGracefulRollDamageThreshold() { return config.getDouble("Skills.Acrobatics.GracefulRoll.DamageThreshold", 14.0D); }
/* ALCHEMY */
public int getCatalysisUnlockLevel() { return config.getInt("Skills.Alchemy.Catalysis.UnlockLevel", 100); }
public int getCatalysisMaxBonusLevel() { return config.getInt("Skills.Alchemy.Catalysis.MaxBonusLevel", 1000); }
public double getCatalysisMinSpeed() { return config.getDouble("Skills.Alchemy.Catalysis.MinSpeed", 1.0D); }
public double getCatalysisMaxSpeed() { return config.getDouble("Skills.Alchemy.Catalysis.MaxSpeed", 4.0D); }
public int getConcoctionsTierLevel(Alchemy.Tier tier) { return config.getInt("Skills.Alchemy.Rank_Levels.Rank_" + tier.toNumerical()); }
/* ARCHERY */
public int getSkillShotIncreaseLevel() { return config.getInt("Skills.Archery.SkillShot.IncreaseLevel", 50); }
public double getSkillShotIncreasePercentage() { return config.getDouble("Skills.Archery.SkillShot.IncreasePercentage", 0.1D); }

View File

@ -403,6 +403,10 @@ public class Config extends AutoUpdateConfigLoader {
public boolean getDodgeLightningDisabled() { return config.getBoolean("Skills.Acrobatics.Prevent_Dodge_Lightning", false); }
public boolean getPreventXPAfterTeleport() { return config.getBoolean("Skills.Acrobatics.Prevent_XP_After_Teleport", true); }
/* Alchemy */
public boolean getEnabledForHoppers() { return config.getBoolean("Skills.Alchemy.Enabled_for_Hoppers", true); }
public boolean getPreventHopperTransfer() { return config.getBoolean("Skills.Alchemy.Prevent_Hopper_Transfer", false); }
/* Fishing */
public boolean getFishingDropsEnabled() { return config.getBoolean("Skills.Fishing.Drops_Enabled", true); }

View File

@ -76,6 +76,11 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
* XP SETTINGS
*/
/* Alchemy */
if (getPotionXP() <= 0) {
reason.add("Experience.Alchemy.Potion should be greater than 0!");
}
/* Combat XP Multipliers */
if (getAnimalsXP() < 0) {
reason.add("Experience.Combat.Multiplier.Animals should be at least 0!");
@ -199,6 +204,9 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
public double getFeatherFallXPModifier() { return config.getDouble("Experience.Acrobatics.FeatherFall_Multiplier", 2.0); }
/* Alchemy */
public double getPotionXP() { return config.getDouble("Experience.Alchemy.Potion", 150D); }
/* Fishing */
public int getFishingBaseXP() { return config.getInt("Experience.Fishing.Base", 800); }
public int getFishingShakeXP() { return config.getInt("Experience.Fishing.Shake", 50); }

View File

@ -0,0 +1,188 @@
package com.gmail.nossr50.config.potion;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.ConfigLoader;
import com.gmail.nossr50.datatypes.AlchemyPotion;
public class PotionConfig extends ConfigLoader {
private static PotionConfig instance;
public List<ItemStack> concoctionsIngredientsTierOne = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierTwo = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierThree = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierFour = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierFive = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierSix = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierSeven = new ArrayList<ItemStack>();
public List<ItemStack> concoctionsIngredientsTierEight = new ArrayList<ItemStack>();
public Map<Short, AlchemyPotion> potionMap = new HashMap<Short, AlchemyPotion>();
private PotionConfig() {
super("potions.yml");
loadKeys();
}
public static PotionConfig getInstance() {
if (instance == null) {
instance = new PotionConfig();
}
return instance;
}
@Override
protected void loadKeys() {
loadConcoctions();
loadPotionMap();
}
private void loadConcoctions() {
ConfigurationSection concoctionSection = config.getConfigurationSection("Concoctions");
loadConcoctionsTier(concoctionsIngredientsTierOne, concoctionSection.getStringList("Tier_One_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierTwo, concoctionSection.getStringList("Tier_Two_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierThree, concoctionSection.getStringList("Tier_Three_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierFour, concoctionSection.getStringList("Tier_Four_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierFive, concoctionSection.getStringList("Tier_Five_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierSix, concoctionSection.getStringList("Tier_Six_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierSeven, concoctionSection.getStringList("Tier_Seven_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierEight, concoctionSection.getStringList("Tier_Eight_Ingredients"));
concoctionsIngredientsTierTwo.addAll(concoctionsIngredientsTierOne);
concoctionsIngredientsTierThree.addAll(concoctionsIngredientsTierTwo);
concoctionsIngredientsTierFour.addAll(concoctionsIngredientsTierThree);
concoctionsIngredientsTierFive.addAll(concoctionsIngredientsTierFour);
concoctionsIngredientsTierSix.addAll(concoctionsIngredientsTierFive);
concoctionsIngredientsTierSeven.addAll(concoctionsIngredientsTierSix);
concoctionsIngredientsTierEight.addAll(concoctionsIngredientsTierSeven);
}
private void loadConcoctionsTier(List<ItemStack> ingredientList, List<String> ingredientStrings) {
if (ingredientStrings != null && ingredientStrings.size() > 0) {
for (String ingredientString : ingredientStrings) {
ItemStack ingredient = loadIngredient(ingredientString);
if (ingredient != null) {
ingredientList.add(ingredient);
}
}
}
}
/**
* Find the Potions configuration section and load all defined potions.
*/
private void loadPotionMap() {
ConfigurationSection potionSection = config.getConfigurationSection("Potions");
int pass = 0;
int fail = 0;
for (String dataValue : potionSection.getKeys(false)) {
AlchemyPotion potion = loadPotion(potionSection.getConfigurationSection(dataValue));
if (potion != null) {
potionMap.put(potion.getDataValue(), potion);
pass++;
}
else {
fail++;
}
}
mcMMO.p.getLogger().info("Loaded " + pass + " Alchemy potions, skipped " + fail + ".");
}
/**
* Parse a ConfigurationSection representing a AlchemyPotion.
* Returns null if input cannot be parsed.
*
* @param potion_section ConfigurationSection to be parsed.
* @return Parsed AlchemyPotion.
*/
private AlchemyPotion loadPotion(ConfigurationSection potion_section) {
try {
short dataValue = Short.parseShort(potion_section.getName());
String name = potion_section.getString("Name");
List<String> lore = new ArrayList<String>();
if (potion_section.contains("Lore")) {
for (String line : potion_section.getStringList("Lore")) {
lore.add(line);
}
}
List<PotionEffect> effects = new ArrayList<PotionEffect>();
if (potion_section.contains("Effects")) {
for (String effect : potion_section.getStringList("Effects")) {
String[] parts = effect.split(" ");
PotionEffectType type = parts.length > 0 ? PotionEffectType.getByName(parts[0]) : null;
int amplifier = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;
int duration = parts.length > 2 ? Integer.parseInt(parts[2]) : 0;
if (type != null) {
effects.add(new PotionEffect(type, duration, amplifier));
}
else {
mcMMO.p.getLogger().warning("Failed to parse effect for potion " + name + ": " + effect);
}
}
}
Map<ItemStack, Short> children = new HashMap<ItemStack, Short>();
if (potion_section.contains("Children")) {
for (String child : potion_section.getConfigurationSection("Children").getKeys(false)) {
ItemStack ingredient = loadIngredient(child);
if (ingredient != null) {
children.put(ingredient, Short.parseShort(potion_section.getConfigurationSection("Children").getString(child)));
}
else {
mcMMO.p.getLogger().warning("Failed to parse child for potion " + name + ": " + child);
}
}
}
return new AlchemyPotion(dataValue, name, lore, effects, children);
}
catch (Exception e) {
mcMMO.p.getLogger().warning("Failed to load Alchemy potion: " + potion_section.getName());
return null;
}
}
/**
* Parse a string representation of an ingredient.
* Format: '&lt;MATERIAL&gt;[:data]'
* Returns null if input cannot be parsed.
*
* @param ingredient String representing an ingredient.
* @return Parsed ingredient.
*/
private ItemStack loadIngredient(String ingredient) {
if (ingredient == null || ingredient.isEmpty()) {
return null;
}
String[] parts = ingredient.split(":");
Material material = parts.length > 0 ? Material.getMaterial(parts[0]) : null;
short data = parts.length > 1 ? Short.parseShort(parts[1]) : 0;
if (material != null) {
return new ItemStack(material, 1, data);
}
return null;
}
}

View File

@ -265,6 +265,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
writer.append(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR).append(":");
MobHealthbarType mobHealthbarType = profile.getMobHealthbarType();
writer.append(mobHealthbarType == null ? Config.getInstance().getMobHealthbarDefault().toString() : mobHealthbarType.toString()).append(":");
writer.append(profile.getSkillLevel(SkillType.ALCHEMY)).append(":");
writer.append(profile.getSkillXpLevel(SkillType.ALCHEMY)).append(":");
writer.append("\r\n");
}
}
@ -354,7 +356,9 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
out.append("0:"); // Blast Mining
out.append(String.valueOf(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR)).append(":"); // LastLogin
out.append(Config.getInstance().getMobHealthbarDefault().toString()).append(":"); // Mob Healthbar HUD
out.append("0:"); // Alchemy
out.append("0:"); // AlchemyXp
// Add more in the same format as the line above
out.newLine();
@ -503,6 +507,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
List<PlayerStat> unarmed = new ArrayList<PlayerStat>();
List<PlayerStat> taming = new ArrayList<PlayerStat>();
List<PlayerStat> fishing = new ArrayList<PlayerStat>();
List<PlayerStat> alchemy = new ArrayList<PlayerStat>();
BufferedReader in = null;
String playerName = null;
@ -520,6 +525,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
Map<SkillType, Integer> skills = getSkillMapFromLine(data);
powerLevel += putStat(acrobatics, playerName, skills.get(SkillType.ACROBATICS));
powerLevel += putStat(alchemy, playerName, skills.get(SkillType.ALCHEMY));
powerLevel += putStat(archery, playerName, skills.get(SkillType.ARCHERY));
powerLevel += putStat(axes, playerName, skills.get(SkillType.AXES));
powerLevel += putStat(excavation, playerName, skills.get(SkillType.EXCAVATION));
@ -557,6 +563,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
Collections.sort(acrobatics, c);
Collections.sort(taming, c);
Collections.sort(fishing, c);
Collections.sort(alchemy, c);
Collections.sort(powerLevels, c);
playerStatHash.put(SkillType.MINING, mining);
@ -571,6 +578,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
playerStatHash.put(SkillType.ACROBATICS, acrobatics);
playerStatHash.put(SkillType.TAMING, taming);
playerStatHash.put(SkillType.FISHING, fishing);
playerStatHash.put(SkillType.ALCHEMY, alchemy);
}
/**
@ -623,7 +631,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
}
// If they're valid, rewrite them to the file.
if (character.length > 38) {
if (character.length > 40) {
writer.append(line).append("\r\n");
continue;
}
@ -675,6 +683,15 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
oldVersion = "1.4.06";
}
}
if (character.length <= 40) {
// Addition of Alchemy
// Version 1.4.08
newLine.append("0").append(":");
newLine.append("0").append(":");
if (oldVersion == null) {
oldVersion = "1.4.08";
}
}
if (oldVersion != null) {
mcMMO.p.debug("Updating database line for player " + character[0] + " from before version " + oldVersion);
@ -771,6 +788,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
skillsXp.put(SkillType.AXES, (float) Integer.valueOf(character[21]));
skillsXp.put(SkillType.ACROBATICS, (float) Integer.valueOf(character[22]));
skillsXp.put(SkillType.FISHING, (float) Integer.valueOf(character[35]));
skillsXp.put(SkillType.ALCHEMY, (float) Integer.valueOf(character[40]));
// Taming - Unused
skillsDATS.put(AbilityType.SUPER_BREAKER, Integer.valueOf(character[32]));
@ -810,6 +828,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
skills.put(SkillType.AXES, Integer.valueOf(character[13]));
skills.put(SkillType.ACROBATICS, Integer.valueOf(character[14]));
skills.put(SkillType.FISHING, Integer.valueOf(character[34]));
skills.put(SkillType.ALCHEMY, Integer.valueOf(character[39]));
return skills;
}

View File

@ -152,7 +152,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
+ ", unarmed = ?, herbalism = ?, excavation = ?"
+ ", archery = ?, swords = ?, axes = ?, acrobatics = ?"
+ ", fishing = ? WHERE user_id = ?",
+ ", fishing = ?, alchemy = ? WHERE user_id = ?",
profile.getSkillLevel(SkillType.TAMING),
profile.getSkillLevel(SkillType.MINING),
profile.getSkillLevel(SkillType.REPAIR),
@ -165,13 +165,14 @@ public final class SQLDatabaseManager implements DatabaseManager {
profile.getSkillLevel(SkillType.AXES),
profile.getSkillLevel(SkillType.ACROBATICS),
profile.getSkillLevel(SkillType.FISHING),
profile.getSkillLevel(SkillType.ALCHEMY),
userId);
success &= saveIntegers(
"UPDATE " + tablePrefix + "experience SET "
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
+ ", unarmed = ?, herbalism = ?, excavation = ?"
+ ", archery = ?, swords = ?, axes = ?, acrobatics = ?"
+ ", fishing = ? WHERE user_id = ?",
+ ", fishing = ?, alchemy = ? WHERE user_id = ?",
profile.getSkillXpLevel(SkillType.TAMING),
profile.getSkillXpLevel(SkillType.MINING),
profile.getSkillXpLevel(SkillType.REPAIR),
@ -184,6 +185,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
profile.getSkillXpLevel(SkillType.AXES),
profile.getSkillXpLevel(SkillType.ACROBATICS),
profile.getSkillXpLevel(SkillType.FISHING),
profile.getSkillXpLevel(SkillType.ALCHEMY),
userId);
return success;
}
@ -192,7 +194,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
List<PlayerStat> stats = new ArrayList<PlayerStat>();
if (checkConnected()) {
String query = skill == null ? "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing" : skill.name().toLowerCase();
String query = skill == null ? "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy" : skill.name().toLowerCase();
ResultSet resultSet = null;
PreparedStatement statement = null;
@ -271,9 +273,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
"WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > 0 " +
"AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > " +
"(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " +
"WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy > 0 " +
"AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy > " +
"(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy " +
"FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?)";
PreparedStatement statement = connection.prepareStatement(sql);
@ -286,11 +288,11 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.close();
sql = "SELECT user, taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " +
sql = "SELECT user, taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy " +
"FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
"WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > 0 " +
"AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing = " +
"(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " +
"WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy > 0 " +
"AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy = " +
"(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy " +
"FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?) ORDER BY user";
statement = connection.prepareStatement(sql);
@ -359,8 +361,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
try {
statement = connection.prepareStatement(
"SELECT "
+ "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, "
+ "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, "
+ "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, "
+ "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, "
+ "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, "
+ "h.mobhealthbar "
+ "FROM " + tablePrefix + "users u "
@ -435,8 +437,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
try {
statement = connection.prepareStatement(
"SELECT "
+ "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, "
+ "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, "
+ "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, "
+ "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, "
+ "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, "
+ "h.mobhealthbar "
+ "FROM " + tablePrefix + "users u "
@ -687,6 +689,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`axes` int(10) unsigned NOT NULL DEFAULT '0',"
+ "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0',"
+ "`fishing` int(10) unsigned NOT NULL DEFAULT '0',"
+ "`alchemy` int(10) unsigned NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=latin1;");
write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "experience` ("
@ -703,6 +706,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`axes` int(10) unsigned NOT NULL DEFAULT '0',"
+ "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0',"
+ "`fishing` int(10) unsigned NOT NULL DEFAULT '0',"
+ "`alchemy` int(10) unsigned NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=latin1;");
@ -728,6 +732,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
sql = "SELECT * FROM `" + tablePrefix + "experience` ORDER BY `" + tablePrefix + "experience`.`fishing` ASC LIMIT 0 , 30";
break;
case ALCHEMY:
sql = "SELECT * FROM `" + tablePrefix + "experience` ORDER BY `" + tablePrefix + "experience`.`alchemy` ASC LIMIT 0 , 30";
break;
case INDEX:
if (read("SHOW INDEX FROM " + tablePrefix + "skills").size() != 13 && checkConnected()) {
mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases");
@ -830,6 +838,12 @@ public final class SQLDatabaseManager implements DatabaseManager {
write("ALTER TABLE `" + tablePrefix + "huds` ADD `mobhealthbar` varchar(50) NOT NULL DEFAULT '" + Config.getInstance().getMobHealthbarDefault() + "' ;");
break;
case ALCHEMY:
mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Alchemy...");
write("ALTER TABLE `"+tablePrefix + "skills` ADD `alchemy` int(10) NOT NULL DEFAULT '0' ;");
write("ALTER TABLE `"+tablePrefix + "experience` ADD `alchemy` int(10) NOT NULL DEFAULT '0' ;");
break;
default:
break;
}
@ -1199,6 +1213,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
skills.put(SkillType.AXES, result.getInt(OFFSET_SKILLS + 10));
skills.put(SkillType.ACROBATICS, result.getInt(OFFSET_SKILLS + 11));
skills.put(SkillType.FISHING, result.getInt(OFFSET_SKILLS + 12));
skills.put(SkillType.ALCHEMY, result.getInt(OFFSET_SKILLS + 13));
skillsXp.put(SkillType.TAMING, result.getFloat(OFFSET_XP + 1));
skillsXp.put(SkillType.MINING, result.getFloat(OFFSET_XP + 2));
@ -1212,6 +1227,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
skillsXp.put(SkillType.AXES, result.getFloat(OFFSET_XP + 10));
skillsXp.put(SkillType.ACROBATICS, result.getFloat(OFFSET_XP + 11));
skillsXp.put(SkillType.FISHING, result.getFloat(OFFSET_XP + 12));
skillsXp.put(SkillType.ALCHEMY, result.getFloat(OFFSET_XP + 13));
// Taming - Unused - result.getInt(OFFSET_DATS + 1)
skillsDATS.put(AbilityType.SUPER_BREAKER, result.getInt(OFFSET_DATS + 2));

View File

@ -0,0 +1,101 @@
package com.gmail.nossr50.datatypes;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
public class AlchemyPotion {
private short dataValue;
private String name;
private List<String> lore;
private List<PotionEffect> effects;
private Map<ItemStack, Short> children;
public AlchemyPotion(short dataValue, String name, List<String> lore, List<PotionEffect> effects, Map<ItemStack, Short> children) {
this.dataValue = dataValue;
this.lore = lore;
this.name = name;
this.effects = effects;
this.children = children;
}
public String toString() {
return "AlchemyPotion{" + dataValue + "," + name + ",Effects[" + effects.size() + "], Children[" + children.size() + "]}";
}
public ItemStack toItemStack() {
return toItemStack(1);
}
public ItemStack toItemStack(int amount) {
ItemStack potion = new ItemStack(Material.POTION, amount, this.getDataValue());
PotionMeta meta = (PotionMeta) potion.getItemMeta();
meta.setDisplayName(this.getName());
if (this.getLore() != null && !this.getLore().isEmpty()) {
meta.setLore(this.getLore());
}
if (!this.getEffects().isEmpty()) {
for (PotionEffect effect : this.getEffects()) {
meta.addCustomEffect(effect, true);
}
}
potion.setItemMeta(meta);
return potion;
}
public short getDataValue() {
return dataValue;
}
public void setDataValue(short data_value) {
this.dataValue = data_value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getLore() {
return lore;
}
public void setLore(List<String> lore) {
this.lore = lore;
}
public List<PotionEffect> getEffects() {
return effects;
}
public void setEffects(List<PotionEffect> effects) {
this.effects = effects;
}
public Map<ItemStack, Short> getChildren() {
return children;
}
public void setChildren(Map<ItemStack, Short> children) {
this.children = children;
}
public Short getChildDataValue(ItemStack ingredient) {
if (!children.isEmpty()) {
for (Entry<ItemStack, Short> child : children.entrySet()) {
if (ingredient.isSimilar(child.getKey())) {
return child.getValue();
}
}
}
return -1;
}
}

View File

@ -7,6 +7,7 @@ public enum DatabaseUpdateType {
MOB_HEALTHBARS,
PARTY_NAMES,
KILL_ORPHANS,
DROPPED_SPOUT
DROPPED_SPOUT,
ALCHEMY
;
}

View File

@ -31,6 +31,7 @@ import com.gmail.nossr50.runnables.skills.AbilityDisableTask;
import com.gmail.nossr50.runnables.skills.ToolLowerTask;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
import com.gmail.nossr50.skills.alchemy.AlchemyManager;
import com.gmail.nossr50.skills.archery.ArcheryManager;
import com.gmail.nossr50.skills.axes.AxesManager;
import com.gmail.nossr50.skills.child.FamilyTree;
@ -192,6 +193,10 @@ public class McMMOPlayer {
return (AcrobaticsManager) skillManagers.get(SkillType.ACROBATICS);
}
public AlchemyManager getAlchemyManager() {
return (AlchemyManager) skillManagers.get(SkillType.ALCHEMY);
}
public ArcheryManager getArcheryManager() {
return (ArcheryManager) skillManagers.get(SkillType.ARCHERY);
}

View File

@ -15,6 +15,7 @@ import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
import com.gmail.nossr50.skills.alchemy.AlchemyManager;
import com.gmail.nossr50.skills.archery.ArcheryManager;
import com.gmail.nossr50.skills.axes.AxesManager;
import com.gmail.nossr50.skills.excavation.ExcavationManager;
@ -35,6 +36,7 @@ import com.google.common.collect.ImmutableList;
public enum SkillType {
ACROBATICS(AcrobaticsManager.class, Color.WHITE, ImmutableList.of(SecondaryAbility.DODGE, SecondaryAbility.GRACEFUL_ROLL, SecondaryAbility.ROLL)),
ALCHEMY(AlchemyManager.class, Color.FUCHSIA, null),
ARCHERY(ArcheryManager.class, Color.MAROON, ImmutableList.of(SecondaryAbility.DAZE, SecondaryAbility.RETRIEVE, SecondaryAbility.SKILL_SHOT)),
AXES(AxesManager.class, Color.AQUA, AbilityType.SKULL_SPLITTER, ToolType.AXE, ImmutableList.of(SecondaryAbility.ARMOR_IMPACT, SecondaryAbility.AXE_MASTERY, SecondaryAbility.CRITICAL_HIT, SecondaryAbility.GREATER_IMPACT)),
EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), AbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL, ImmutableList.of(SecondaryAbility.EXCAVATION_TREASURE_HUNTER)),
@ -61,7 +63,7 @@ public enum SkillType {
public static final List<SkillType> COMBAT_SKILLS = ImmutableList.of(ARCHERY, AXES, SWORDS, TAMING, UNARMED);
public static final List<SkillType> GATHERING_SKILLS = ImmutableList.of(EXCAVATION, FISHING, HERBALISM, MINING, WOODCUTTING);
public static final List<SkillType> MISC_SKILLS = ImmutableList.of(ACROBATICS, REPAIR, SMELTING);
public static final List<SkillType> MISC_SKILLS = ImmutableList.of(ACROBATICS, ALCHEMY, REPAIR, SMELTING);
static {
List<SkillType> childSkills = new ArrayList<SkillType>();

View File

@ -0,0 +1,37 @@
package com.gmail.nossr50.events.skills.alchemy;
import org.bukkit.block.Block;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.events.skills.McMMOPlayerSkillEvent;
public class McMMOPlayerBrewEvent extends McMMOPlayerSkillEvent implements Cancellable {
private Block brewingStand;
private boolean cancelled;
public McMMOPlayerBrewEvent(Player player, Block brewingStand) {
super(player, SkillType.ALCHEMY);
this.brewingStand = brewingStand;
cancelled = false;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean newValue) {
this.cancelled = newValue;
}
public Block getBrewingStandBlock() {
return brewingStand;
}
public BrewingStand getBrewingStand() {
return brewingStand.getState() instanceof BrewingStand ? (BrewingStand) brewingStand.getState() : null;
}
}

View File

@ -0,0 +1,35 @@
package com.gmail.nossr50.events.skills.alchemy;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.events.skills.McMMOPlayerSkillEvent;
public class McMMOPlayerCatalysisEvent extends McMMOPlayerSkillEvent implements Cancellable {
private double speed;
private boolean cancelled;
public McMMOPlayerCatalysisEvent(Player player, double speed) {
super(player, SkillType.ALCHEMY);
this.speed = speed;
cancelled = false;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean newValue) {
this.cancelled = newValue;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
}

View File

@ -8,6 +8,7 @@ import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.BrewingStand;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -30,6 +31,7 @@ import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
import com.gmail.nossr50.runnables.StickyPistonTrackerTask;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.excavation.ExcavationManager;
import com.gmail.nossr50.skills.herbalism.HerbalismManager;
import com.gmail.nossr50.skills.mining.MiningManager;
@ -135,6 +137,11 @@ public class BlockListener implements Listener {
return;
}
/* ALCHEMY - Cancel any brew in progress for that BrewingStand */
if (blockState instanceof BrewingStand && Alchemy.brewingStandMap.containsKey(event.getBlock())) {
Alchemy.brewingStandMap.get(event.getBlock()).cancelBrew();
}
Player player = event.getPlayer();
if (Misc.isNPCEntity(player) || player.getGameMode() == GameMode.CREATIVE) {

View File

@ -28,9 +28,12 @@ import org.bukkit.event.entity.EntityTameEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.potion.PotionEffect;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.AdvancedConfig;
@ -592,4 +595,23 @@ public class EntityListener implements Listener {
event.setCancelled(true);
}
}
/**
* Handle PotionSplash events in order to fix broken Splash Potion of Saturation.
*
* @param event The event to process
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {
for (PotionEffect effect : ((PotionMeta) event.getEntity().getItem().getItemMeta()).getCustomEffects()) {
// (effect.getType() == PotionEffectType.SATURATION) is seemingly broken, so we use deprecated method for now.
if (effect.getType().getId() == 23) {
for (LivingEntity entity : event.getAffectedEntities()) {
int duration = (int) (effect.getDuration() * event.getIntensity(entity));
entity.addPotionEffect(new PotionEffect(effect.getType(), duration, effect.getAmplifier(), effect.isAmbient()));
}
}
return;
}
}
}

View File

@ -2,8 +2,10 @@ package com.gmail.nossr50.listeners;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.BrewingStand;
import org.bukkit.block.Furnace;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
@ -16,16 +18,21 @@ import org.bukkit.event.inventory.FurnaceExtractEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.skills.SecondaryAbility;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.runnables.PlayerUpdateInventoryTask;
import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
@ -129,6 +136,48 @@ public class InventoryListener implements Listener {
event.setExpToDrop(UserManager.getPlayer(player).getSmeltingManager().vanillaXPBoost(event.getExpToDrop()));
}
@EventHandler(ignoreCancelled = true)
public void onAlchemyClickEvent(InventoryClickEvent event) {
if (event.getInventory().getType() != InventoryType.BREWING || !(event.getInventory().getHolder() instanceof BrewingStand)) {
return;
}
if (!(event.getWhoClicked() instanceof Player) || Misc.isNPCEntity(event.getWhoClicked()) || !Permissions.concoctions(event.getWhoClicked())) {
return;
}
AlchemyPotionBrewer.handleInventoryClick(event);
}
@EventHandler(ignoreCancelled = true)
public void onAlchemyDragEvent(InventoryDragEvent event) {
if (event.getInventory().getType() != InventoryType.BREWING || !(event.getInventory().getHolder() instanceof BrewingStand)) {
return;
}
if (!(event.getWhoClicked() instanceof Player) || Misc.isNPCEntity(event.getWhoClicked()) || !Permissions.concoctions(event.getWhoClicked())) {
return;
}
AlchemyPotionBrewer.handleInventoryDrag(event);
}
@EventHandler(ignoreCancelled = true)
public void onAlchemyMoveItemEvent(InventoryMoveItemEvent event) {
if (event.getDestination().getType() != InventoryType.BREWING || !(event.getDestination().getHolder() instanceof BrewingStand)) {
return;
}
if (Config.getInstance().getPreventHopperTransfer() && event.getItem() != null && event.getItem().getType() != Material.POTION) {
event.setCancelled(true);
return;
}
if (Config.getInstance().getEnabledForHoppers()) {
AlchemyPotionBrewer.handleInventoryMoveItem(event);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryClickEvent(InventoryClickEvent event) {
SkillUtils.removeAbilityBuff(event.getCurrentItem());

View File

@ -19,6 +19,7 @@ import com.gmail.nossr50.config.mods.CustomBlockConfig;
import com.gmail.nossr50.config.mods.CustomEntityConfig;
import com.gmail.nossr50.config.mods.CustomToolConfig;
import com.gmail.nossr50.config.repair.RepairConfigManager;
import com.gmail.nossr50.config.potion.PotionConfig;
import com.gmail.nossr50.config.treasure.TreasureConfig;
import com.gmail.nossr50.database.DatabaseManager;
import com.gmail.nossr50.database.DatabaseManagerFactory;
@ -38,6 +39,7 @@ import com.gmail.nossr50.runnables.database.UserPurgeTask;
import com.gmail.nossr50.runnables.party.PartyAutoKickTask;
import com.gmail.nossr50.runnables.player.PowerLevelUpdatingTask;
import com.gmail.nossr50.runnables.skills.BleedTimerTask;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.child.ChildConfig;
import com.gmail.nossr50.skills.repair.repairables.Repairable;
import com.gmail.nossr50.skills.repair.repairables.RepairableManager;
@ -198,6 +200,7 @@ public class mcMMO extends JavaPlugin {
@Override
public void onDisable() {
try {
Alchemy.finishAllBrews(); // Finish all partially complete AlchemyBrewTasks to prevent vanilla brewing continuation on restart
UserManager.saveAll(); // Make sure to save player information if the server shuts down
PartyManager.saveParties(); // Save our parties
ScoreboardManager.teardownAll();
@ -358,6 +361,7 @@ public class mcMMO extends JavaPlugin {
TreasureConfig.getInstance();
HiddenConfig.getInstance();
AdvancedConfig.getInstance();
PotionConfig.getInstance();
new ChildConfig();
List<Repairable> repairables = new ArrayList<Repairable>();

View File

@ -0,0 +1,42 @@
package com.gmail.nossr50.runnables.skills;
import java.util.Arrays;
import org.bukkit.block.Block;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer;
public class AlchemyBrewCheckTask extends BukkitRunnable {
private final static int INGREDIENT_SLOT = 3;
private Player player;
private Block brewingStand;
private ItemStack[] oldInventory;
private ItemStack[] newInventory;
public AlchemyBrewCheckTask(Player player, BrewingStand brewingStand) {
this.player = player;
this.brewingStand = brewingStand.getBlock();
this.oldInventory = Arrays.copyOfRange(brewingStand.getInventory().getContents(), 0, 4);
}
@Override
public void run() {
this.newInventory = Arrays.copyOfRange(((BrewingStand) brewingStand.getState()).getInventory().getContents(), 0, 4);
if (Alchemy.brewingStandMap.containsKey(brewingStand)) {
if (oldInventory[INGREDIENT_SLOT] == null || newInventory[INGREDIENT_SLOT] == null || !oldInventory[INGREDIENT_SLOT].isSimilar(newInventory[INGREDIENT_SLOT]) || !AlchemyPotionBrewer.isValidBrew(player, newInventory)) {
Alchemy.brewingStandMap.get(brewingStand).cancelBrew();
}
}
if (!Alchemy.brewingStandMap.containsKey(brewingStand) && AlchemyPotionBrewer.isValidBrew(player, newInventory)) {
Alchemy.brewingStandMap.put(brewingStand, new AlchemyBrewTask(brewingStand, player));
}
}
}

View File

@ -0,0 +1,95 @@
package com.gmail.nossr50.runnables.skills;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.events.skills.alchemy.McMMOPlayerBrewEvent;
import com.gmail.nossr50.events.skills.alchemy.McMMOPlayerCatalysisEvent;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
public class AlchemyBrewTask extends BukkitRunnable {
private final double DEFAULT_BREW_SPEED = 1.0;
private final int DEFAULT_BREW_TICKS = 400;
private Block brewingStand;
private double brewSpeed;
private double brewTimer;
private Player player;
public AlchemyBrewTask(Block brewingStand, Player player) {
this.brewingStand = brewingStand;
this.player = player;
brewSpeed = DEFAULT_BREW_SPEED;
brewTimer = DEFAULT_BREW_TICKS;
if (player != null && !Misc.isNPCEntity(player) && Permissions.catalysis(player)) {
double catalysis = UserManager.getPlayer(player).getAlchemyManager().getBrewSpeed();
if (Permissions.lucky(player, SkillType.ALCHEMY)) {
catalysis = UserManager.getPlayer(player).getAlchemyManager().getBrewSpeedLucky();
}
McMMOPlayerCatalysisEvent event = new McMMOPlayerCatalysisEvent(player, catalysis);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
brewSpeed = catalysis;
}
}
if (Alchemy.brewingStandMap.containsKey(brewingStand)) {
Alchemy.brewingStandMap.get(brewingStand).cancel();
}
Alchemy.brewingStandMap.put(brewingStand, this);
this.runTaskTimer(mcMMO.p, 1, 1);
}
@Override
public void run() {
brewTimer -= brewSpeed;
// Vanilla potion brewing completes when BrewingTime == 1
if (brewTimer < Math.max(brewSpeed, 2)) {
this.cancel();
finish();
}
else {
((BrewingStand) brewingStand.getState()).setBrewingTime((int) brewTimer);
}
}
private void finish() {
McMMOPlayerBrewEvent event = new McMMOPlayerBrewEvent(player, brewingStand);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
AlchemyPotionBrewer.finishBrewing(brewingStand, player, false);
}
Alchemy.brewingStandMap.remove(brewingStand);
}
public void finishImmediately() {
this.cancel();
AlchemyPotionBrewer.finishBrewing(brewingStand, player, true);
Alchemy.brewingStandMap.remove(brewingStand);
}
public void cancelBrew() {
this.cancel();
((BrewingStand) brewingStand.getState()).setBrewingTime(-1);
Alchemy.brewingStandMap.remove(brewingStand);
}
}

View File

@ -0,0 +1,83 @@
package com.gmail.nossr50.skills.alchemy;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.block.Block;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.runnables.skills.AlchemyBrewTask;
public final class Alchemy {
public enum Tier {
EIGHT(8),
SEVEN(7),
SIX(6),
FIVE(5),
FOUR(4),
THREE(3),
TWO(2),
ONE(1);
int numerical;
private Tier(int numerical) {
this.numerical = numerical;
}
public int toNumerical() {
return numerical;
}
public static Tier fromNumerical(int numerical) {
for (Tier tier : Tier.values()) {
if (tier.toNumerical() == numerical) {
return tier;
}
}
return null;
}
protected int getLevel() {
return AdvancedConfig.getInstance().getConcoctionsTierLevel(this);
}
}
public static int catalysisUnlockLevel = AdvancedConfig.getInstance().getCatalysisUnlockLevel();
public static int catalysisMaxBonusLevel = AdvancedConfig.getInstance().getCatalysisMaxBonusLevel();
public static double catalysisMinSpeed = AdvancedConfig.getInstance().getCatalysisMinSpeed();
public static double catalysisMaxSpeed = AdvancedConfig.getInstance().getCatalysisMaxSpeed();
public static double potionXp = ExperienceConfig.getInstance().getPotionXP();
public static Map<Block, AlchemyBrewTask> brewingStandMap = new HashMap<Block, AlchemyBrewTask>();
private Alchemy() {};
/**
* Calculate base brewing speed, given a skill level and ignoring all perks.
*
* @param skillLevel Skill level used for calculation.
* @return Base brewing speed for the level.
*/
public static double calculateBrewSpeed(int skillLevel) {
if (skillLevel < catalysisUnlockLevel) {
return catalysisMinSpeed;
}
return Math.min(catalysisMaxSpeed, catalysisMinSpeed + (catalysisMaxSpeed - catalysisMinSpeed) * (skillLevel - catalysisUnlockLevel) / (catalysisMaxBonusLevel - catalysisUnlockLevel));
}
/**
* Finish all active brews. Used upon Disable to prevent vanilla potions from being brewed upon next Enable.
*/
public static void finishAllBrews() {
mcMMO.p.getLogger().info("Completing " + brewingStandMap.size() + " unfinished Alchemy brews.");
for (Entry<Block, AlchemyBrewTask> entry : brewingStandMap.entrySet()) {
entry.getValue().finishImmediately();
}
}
}

View File

@ -0,0 +1,86 @@
package com.gmail.nossr50.skills.alchemy;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.config.potion.PotionConfig;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils;
public class AlchemyManager extends SkillManager {
private final double LUCKY_MODIFIER = 4.0 / 3.0;
public AlchemyManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, SkillType.ALCHEMY);
}
public boolean canCatalysis() {
return Permissions.catalysis(getPlayer());
}
public boolean canUseIngredient(ItemStack item) {
for (ItemStack ingredient : getIngredients()) {
if (item.isSimilar(ingredient)) {
return true;
}
}
return false;
}
public int getTier() {
for (Alchemy.Tier tier : Alchemy.Tier.values()) {
if (getSkillLevel() >= tier.getLevel()) {
return tier.toNumerical();
}
}
return 0;
}
public List<ItemStack> getIngredients() {
switch (Alchemy.Tier.fromNumerical(getTier())) {
case EIGHT:
return PotionConfig.getInstance().concoctionsIngredientsTierEight;
case SEVEN:
return PotionConfig.getInstance().concoctionsIngredientsTierSeven;
case SIX:
return PotionConfig.getInstance().concoctionsIngredientsTierSix;
case FIVE:
return PotionConfig.getInstance().concoctionsIngredientsTierFive;
case FOUR:
return PotionConfig.getInstance().concoctionsIngredientsTierFour;
case THREE:
return PotionConfig.getInstance().concoctionsIngredientsTierThree;
case TWO:
return PotionConfig.getInstance().concoctionsIngredientsTierTwo;
default:
return PotionConfig.getInstance().concoctionsIngredientsTierOne;
}
}
public String getIngredientList() {
String list = "";
for (ItemStack ingredient : getIngredients()) {
list += ", " + StringUtils.getPrettyItemString(ingredient.getType()) + (ingredient.getDurability() != 0 ? ":" + ingredient.getDurability() : "");
}
return list.substring(2);
}
public double getBrewSpeed() {
return Alchemy.calculateBrewSpeed(getSkillLevel());
}
public double getBrewSpeedLucky() {
return LUCKY_MODIFIER * Alchemy.calculateBrewSpeed(getSkillLevel());
}
public void handlePotionBrewSuccesses(int amount) {
applyXpGain((float) (ExperienceConfig.getInstance().getPotionXP() * amount));
}
}

View File

@ -0,0 +1,349 @@
package com.gmail.nossr50.skills.alchemy;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BrewingStand;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.inventory.BrewerInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.potion.PotionConfig;
import com.gmail.nossr50.datatypes.AlchemyPotion;
import com.gmail.nossr50.runnables.PlayerUpdateInventoryTask;
import com.gmail.nossr50.runnables.skills.AlchemyBrewCheckTask;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
public final class AlchemyPotionBrewer {
private final static int[] BOTTLE_SLOTS = new int[] { 0, 1, 2 };
private final static int INGREDIENT_SLOT = 3;
public static boolean isValidBrew(Player player, ItemStack[] contents) {
if (isValidIngredient(player, contents[INGREDIENT_SLOT])) {
for (int bottle : BOTTLE_SLOTS) {
if (contents[bottle] != null && contents[bottle].getType() == Material.POTION) {
AlchemyPotion potion = PotionConfig.getInstance().potionMap.get(contents[bottle].getDurability());
if (getChildPotion(potion, contents[INGREDIENT_SLOT]) != null) {
return true;
}
}
}
}
return false;
}
private static AlchemyPotion getChildPotion(AlchemyPotion potion, ItemStack ingredient) {
if (potion != null && potion.getChildDataValue(ingredient) != -1) {
return PotionConfig.getInstance().potionMap.get(potion.getChildDataValue(ingredient));
}
return null;
}
private static boolean isEmpty(ItemStack item) {
return item == null || item.getType() == Material.AIR || item.getAmount() == 0;
}
private static boolean removeIngredient(BrewerInventory inventory, Player player) {
ItemStack ingredient = inventory.getIngredient();
if (isEmpty(ingredient) || !isValidIngredient(player, ingredient)) {
return false;
}
else if (ingredient.getAmount() <= 1) {
inventory.setItem(INGREDIENT_SLOT, null);
return true;
}
else {
ingredient.setAmount(ingredient.getAmount() - 1);
inventory.setItem(INGREDIENT_SLOT, ingredient);
return true;
}
}
private static boolean isValidIngredient(Player player, ItemStack item) {
if (isEmpty(item)) {
return false;
}
for (ItemStack ingredient : getValidIngredients(player)) {
if (item.isSimilar(ingredient)) {
return true;
}
}
return false;
}
private static List<ItemStack> getValidIngredients(Player player) {
if (player == null || !Permissions.concoctions(player)) {
return PotionConfig.getInstance().concoctionsIngredientsTierOne;
}
switch (UserManager.getPlayer(player).getAlchemyManager().getTier()) {
case 5:
return PotionConfig.getInstance().concoctionsIngredientsTierFive;
case 4:
return PotionConfig.getInstance().concoctionsIngredientsTierFour;
case 3:
return PotionConfig.getInstance().concoctionsIngredientsTierThree;
case 2:
return PotionConfig.getInstance().concoctionsIngredientsTierTwo;
default:
return PotionConfig.getInstance().concoctionsIngredientsTierOne;
}
}
public static void finishBrewing(Block brewingStand, Player player, boolean forced) {
if (!(brewingStand.getState() instanceof BrewingStand)) {
return;
}
BrewerInventory inventory = ((BrewingStand) brewingStand.getState()).getInventory();
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
if (removeIngredient(inventory, player)) {
for (int bottle : BOTTLE_SLOTS) {
if (!isEmpty(inventory.getItem(bottle)) && PotionConfig.getInstance().potionMap.containsKey(inventory.getItem(bottle).getDurability())) {
AlchemyPotion input = PotionConfig.getInstance().potionMap.get(inventory.getItem(bottle).getDurability());
AlchemyPotion output = PotionConfig.getInstance().potionMap.get(input.getChildDataValue(ingredient));
if (output != null) {
inventory.setItem(bottle, output.toItemStack(inventory.getItem(bottle).getAmount()).clone());
if (player != null) {
UserManager.getPlayer(player).getAlchemyManager().handlePotionBrewSuccesses(1);
}
}
}
}
if (!forced) {
scheduleUpdate(inventory);
}
return;
}
}
private static boolean transferOneItem(InventoryView view, int fromSlot, int toSlot) {
ItemStack from = view.getItem(fromSlot).clone();
ItemStack to = view.getItem(toSlot).clone();
if (isEmpty(from)) {
return false;
}
else if (!isEmpty(to) && from.getAmount() >= from.getType().getMaxStackSize()) {
return false;
}
else if (isEmpty(to) || from.isSimilar(to)) {
if (isEmpty(to)) {
to = from.clone();
to.setAmount(1);
}
else {
to.setAmount(to.getAmount() + 1);
}
from.setAmount(from.getAmount() - 1);
view.setItem(toSlot, isEmpty(to) ? null : to);
view.setItem(fromSlot, isEmpty(from) ? null : from);
return true;
}
return false;
}
/**
* Transfer items between two ItemStacks, returning the leftover status
*/
private static boolean transferItems(InventoryView view, int fromSlot, int toSlot) {
if (isEmpty(view.getItem(fromSlot))) {
return false;
}
else if (isEmpty(view.getItem(toSlot))) {
view.setItem(toSlot, view.getItem(fromSlot).clone());
view.setItem(fromSlot, null);
return true;
}
else if (view.getItem(fromSlot).isSimilar(view.getItem(toSlot))) {
if (view.getItem(fromSlot).getAmount() + view.getItem(toSlot).getAmount() > view.getItem(toSlot).getType().getMaxStackSize()) {
int left = view.getItem(fromSlot).getAmount() + view.getItem(toSlot).getAmount() - view.getItem(toSlot).getType().getMaxStackSize();
ItemStack to = new ItemStack(view.getItem(toSlot));
to.setAmount(to.getType().getMaxStackSize());
view.setItem(toSlot, to);
ItemStack from = new ItemStack(view.getItem(fromSlot));
from.setAmount(left);
view.setItem(fromSlot, from);
return true;
}
ItemStack to = new ItemStack(view.getItem(toSlot));
to.setAmount(view.getItem(fromSlot).getAmount() + view.getItem(toSlot).getAmount());
view.setItem(fromSlot, null);
view.setItem(toSlot, to);
return true;
}
return false;
}
private static void scheduleCheck(Player player, BrewingStand brewingStand) {
Bukkit.getScheduler().scheduleSyncDelayedTask(mcMMO.p, new AlchemyBrewCheckTask(player, brewingStand));
}
private static void scheduleUpdate(Inventory inventory) {
for (HumanEntity he : inventory.getViewers()) {
if (he instanceof Player) {
scheduleUpdate((Player) he);
}
}
}
private static void scheduleUpdate(Player player) {
Bukkit.getScheduler().scheduleSyncDelayedTask(mcMMO.p, new PlayerUpdateInventoryTask(player));
}
public static void handleInventoryClick(InventoryClickEvent event) {
Player player = event.getWhoClicked() instanceof Player ? (Player) event.getWhoClicked() : null;
BrewingStand brewingStand = (BrewingStand) event.getInventory().getHolder();
ItemStack cursor = event.getCursor();
ItemStack clicked = event.getCurrentItem();
if (clicked != null && clicked.getType() == Material.POTION) {
scheduleCheck(player, brewingStand);
return;
}
if (event.isShiftClick()) {
if (event.getSlotType() == SlotType.FUEL) {
scheduleCheck(player, brewingStand);
return;
}
else if (event.getSlotType() == SlotType.CONTAINER || event.getSlotType() == SlotType.QUICKBAR) {
if (isValidIngredient(player, clicked)) {
if (event.isLeftClick()) {
transferItems(event.getView(), event.getRawSlot(), INGREDIENT_SLOT);
}
else if (event.isRightClick()) {
transferOneItem(event.getView(), event.getRawSlot(), INGREDIENT_SLOT);
}
event.setCancelled(true);
scheduleUpdate(brewingStand.getInventory());
scheduleCheck(player, brewingStand);
return;
}
}
}
else if (event.getRawSlot() == INGREDIENT_SLOT) {
if (isEmpty(cursor) && isEmpty(clicked)) {
return;
}
else if (isEmpty(cursor)) {
scheduleCheck(player, brewingStand);
return;
}
else if (isEmpty(clicked)) {
if (isValidIngredient(player, event.getCursor())) {
if (event.getClick() == ClickType.LEFT || (event.getClick() == ClickType.RIGHT && event.getCursor().getAmount() == 1)) {
event.setCancelled(true);
event.setCurrentItem(event.getCursor().clone());
event.setCursor(null);
scheduleUpdate(brewingStand.getInventory());
scheduleCheck(player, brewingStand);
return;
}
else if (event.getClick() == ClickType.RIGHT) {
event.setCancelled(true);
ItemStack one = event.getCursor().clone();
one.setAmount(1);
ItemStack rest = event.getCursor().clone();
rest.setAmount(event.getCursor().getAmount() - 1);
event.setCurrentItem(one);
event.setCursor(rest);
scheduleUpdate(brewingStand.getInventory());
scheduleCheck(player, brewingStand);
return;
}
}
return;
}
}
}
public static void handleInventoryDrag(InventoryDragEvent event) {
Player player = event.getWhoClicked() instanceof Player ? (Player) event.getWhoClicked() : null;
BrewingStand brewingStand = (BrewingStand) event.getInventory().getHolder();
ItemStack cursor = event.getCursor();
ItemStack ingredient = brewingStand.getInventory().getIngredient();
if (event.getInventorySlots().contains(INGREDIENT_SLOT)) {
if (isEmpty(ingredient) || ingredient.isSimilar(cursor)) {
if (isValidIngredient(player, cursor)) {
// Not handled: dragging custom ingredients over ingredient slot (does not trigger any event)
scheduleCheck(player, brewingStand);
return;
}
else {
event.setCancelled(true);
scheduleUpdate(brewingStand.getInventory());
return;
}
}
}
}
public static void handleInventoryMoveItem(InventoryMoveItemEvent event) {
Player player = null;
BrewingStand brewingStand = (BrewingStand) event.getDestination().getHolder();
if (isValidIngredient(player, event.getItem())) {
scheduleCheck(player, brewingStand);
return;
}
else {
event.setCancelled(true);
return;
}
}
}

View File

@ -126,6 +126,20 @@ public final class Permissions {
public static boolean skillEnabled(Permissible permissible, SkillType skill) {return permissible.hasPermission("mcmmo.skills." + skill.toString().toLowerCase()); }
public static boolean vanillaXpBoost(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.ability." + skill.toString().toLowerCase() + ".vanillaxpboost"); }
public static boolean secondaryAbilityEnabled(Permissible permissible, SecondaryAbility skillAbility) { return permissible.hasPermission("mcmmo.ability." + SkillType.bySecondaryAbility(skillAbility).toString().toLowerCase() + "." + StringUtils.getPrettySecondaryAbilityString(skillAbility).replace(" ", "").toLowerCase()); }
public static boolean bonusDamage(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.ability." + skill.toString().toLowerCase() + ".bonusdamage"); }
/* ACROBATICS */
public static boolean dodge(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.acrobatics.dodge"); }
public static boolean gracefulRoll(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.acrobatics.gracefulroll"); }
public static boolean roll(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.acrobatics.roll"); }
/* ALCHEMY */
public static boolean catalysis(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.alchemy.catalysis"); }
public static boolean concoctions(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.alchemy.concoctions"); }
/* ARCHERY */
public static boolean arrowRetrieval(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.archery.trackarrows"); }
public static boolean daze(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.archery.daze"); }
/* AXES */
public static boolean skullSplitter(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.axes.skullsplitter"); }

View File

@ -35,6 +35,7 @@ import com.gmail.nossr50.commands.player.McrankCommand;
import com.gmail.nossr50.commands.player.McstatsCommand;
import com.gmail.nossr50.commands.player.MctopCommand;
import com.gmail.nossr50.commands.skills.AcrobaticsCommand;
import com.gmail.nossr50.commands.skills.AlchemyCommand;
import com.gmail.nossr50.commands.skills.ArcheryCommand;
import com.gmail.nossr50.commands.skills.AxesCommand;
import com.gmail.nossr50.commands.skills.ExcavationCommand;
@ -76,6 +77,10 @@ public final class CommandRegistrationManager {
command.setExecutor(new AcrobaticsCommand());
break;
case ALCHEMY:
command.setExecutor(new AlchemyCommand());
break;
case ARCHERY:
command.setExecutor(new ArcheryCommand());
break;

View File

@ -48,6 +48,30 @@ Skills:
MaxBonusLevel: 500
DamageThreshold: 14.0
#
# Settings for Alchemy
###
Alchemy:
Catalysis:
# UnlockLevel: Alchemy level when the Catalysis ability unlocks
# MaxBonusLevel: Maximum bonus level of Catalysis, when a player reaches this level his brewing speed will be <MaxSpeed>
# MinSpeed: Minimum brewing speed allowed when at <UnlockLevel> or lower
# MaxSpeed: Maximum brewing speed allowed when at <MaxBonusLevel> or higher
UnlockLevel: 100
MaxBonusLevel: 1000
MinSpeed: 1.0
MaxSpeed: 4.0
# Rank_Levels: Alchemy level where rank gets unlocked
Rank_Levels:
Rank_1: 0
Rank_2: 125
Rank_3: 250
Rank_4: 375
Rank_5: 500
Rank_6: 625
Rank_7: 750
Rank_8: 875
#
# Settings for Archery
###
Archery:

View File

@ -251,6 +251,12 @@ Skills:
Prevent_Dodge_Lightning: false
Prevent_XP_After_Teleport: true
Level_Cap: 0
Alchemy:
# Allow Hoppers to transfer ingredients and brew Rank 1 Alchemy potions
Enabled_for_Hoppers: true
# Prevent Hoppers from transferring ingredients into Brewing Stands
Prevent_Hopper_Transfer: false
Level_Cap: 0
Archery:
Enabled_For_PVP: true
Enabled_For_PVE: true

View File

@ -52,6 +52,7 @@ Experience_Formula:
Axes: 1.0
Repair: 1.0
Fishing: 1.0
Alchemy: 1.0
#
# Settings for XP conversion with '/mcconvert experience'
@ -73,6 +74,8 @@ Experience:
# FeatherFall_Multiplier: Multiply Acrobatics XP by this value when wearing boots with the Feather Fall enchant
FeatherFall_Multiplier: 2.0
Alchemy:
Potion: 120
Fishing:
Base: 800
Shake: 50

View File

@ -32,6 +32,19 @@ Acrobatics.Roll.Text=**Rolled**
Acrobatics.SkillName=ACROBATICS
Acrobatics.Skillup=[[YELLOW]]Acrobatics skill increased by {0}. Total ({1})
#ALCHEMY
Alchemy.Effect.0=Catalysis
Alchemy.Effect.1=Increases potion brewing speed
Alchemy.Effect.2=Concoctions
Alchemy.Effect.3=Brew potions with more ingredients
Alchemy.Listener=Alchemy:
Alchemy.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (CATALYSIS)
Alchemy.Catalysis.Speed=[[RED]]Brewing Speed: [[YELLOW]]{0}
Alchemy.Concoctions.Rank=[[RED]]Concoctions Rank: [[YELLOW]]{0}
Alchemy.Concoctions.Ingredients=[[RED]]Ingredients [[[YELLOW]]{0}[[RED]]]: [[YELLOW]]{1}
Alchemy.SkillName=ALCHEMY
Alchemy.Skillup=[[YELLOW]]Alchemy skill increased by {0}. Total ({1})
#ARCHERY
Archery.Combat.DazeChance=[[RED]]Chance to Daze: [[YELLOW]]{0}
Archery.Combat.RetrieveChance=[[RED]]Chance to Retrieve Arrows: [[YELLOW]]{0}
@ -408,7 +421,7 @@ Combat.TouchedFuzzy=[[DARK_RED]]Touched Fuzzy. Felt Dizzy.
#COMMANDS
##generic
mcMMO.Description=[[DARK_AQUA]]About the [[YELLOW]]mcMMO[[DARK_AQUA]] Project:,[[GOLD]]mcMMO is an [[RED]]open source[[GOLD]] RPG mod created in February 2011,[[GOLD]]by [[BLUE]]nossr50[[GOLD]]. The goal is to provide a quality RPG experience.,[[DARK_AQUA]]Tips:,[[GOLD]] - [[GREEN]]Use [[RED]]/mcmmo help[[GREEN]] to see commands,[[GOLD]] - [[GREEN]]Type [[RED]]/SKILLNAME[[GREEN]] to see detailed skill info,[[DARK_AQUA]]Developers:,[[GOLD]] - [[GREEN]]nossr50 [[BLUE]](Founder),[[GOLD]] - [[GREEN]]GJ [[BLUE]](Project Lead),[[GOLD]] - [[GREEN]]NuclearW [[BLUE]](Developer),[[GOLD]] - [[GREEN]]bm01 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]TfT_02 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]Glitchfinder [[BLUE]](Developer),[[GOLD]] - [[GREEN]]t00thpick1 [[BLUE]](Developer),[[DARK_AQUA]]Useful Links:,[[GOLD]] - [[GREEN]]https://github.com/mcMMO-Dev/mcMMO/issues[[GOLD]] Bug Reporting,[[GOLD]] - [[GREEN]]#mcmmo @ irc.esper.net[[GOLD]] IRC Chat,
mcMMO.Description=[[DARK_AQUA]]About the [[YELLOW]]mcMMO[[DARK_AQUA]] Project:,[[GOLD]]mcMMO is an [[RED]]open source[[GOLD]] RPG mod created in February 2011,[[GOLD]]by [[BLUE]]nossr50[[GOLD]]. The goal is to provide a quality RPG experience.,[[DARK_AQUA]]Tips:,[[GOLD]] - [[GREEN]]Use [[RED]]/mcmmo help[[GREEN]] to see commands,[[GOLD]] - [[GREEN]]Type [[RED]]/SKILLNAME[[GREEN]] to see detailed skill info,[[DARK_AQUA]]Developers:,[[GOLD]] - [[GREEN]]nossr50 [[BLUE]](Founder),[[GOLD]] - [[GREEN]]GJ [[BLUE]](Project Lead),[[GOLD]] - [[GREEN]]NuclearW [[BLUE]](Developer),[[GOLD]] - [[GREEN]]bm01 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]TfT_02 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]Glitchfinder [[BLUE]](Developer),[[GOLD]] - [[GREEN]]t00thpick1 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]EasyMFnE [[BLUE]](Developer),[[DARK_AQUA]]Useful Links:,[[GOLD]] - [[GREEN]]https://github.com/mcMMO-Dev/mcMMO/issues[[GOLD]] Bug Reporting,[[GOLD]] - [[GREEN]]#mcmmo @ irc.esper.net[[GOLD]] IRC Chat,
Commands.addlevels.AwardAll.1=[[GREEN]]You were awarded {0} levels in all skills!
Commands.addlevels.AwardAll.2=[[RED]]All skills have been modified for {0}.
Commands.addlevels.AwardSkill.1=[[GREEN]]You were awarded {0} levels in {1}!
@ -611,6 +624,7 @@ Party.ItemShare.Category.Misc=Misc
##xp
Commands.XPGain.Acrobatics=Falling
Commands.XPGain.Alchemy=Brewing Potions
Commands.XPGain.Archery=Attacking Monsters
Commands.XPGain.Axes=Attacking Monsters
Commands.XPGain.Child=Gains levels from Parent Skills

View File

@ -11,7 +11,7 @@ description: >
in order to evaluate and balance the mechanics of mcMMO in every update.
author: nossr50
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking]
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking, EasyMFnE]
website: http://dev.bukkit.org/server-mods/mcmmo/
main: com.gmail.nossr50.mcMMO
@ -89,6 +89,8 @@ commands:
description: Detailed mcMMO skill info
smelting:
description: Detailed mcMMO skill info
alchemy:
description: Detailed mcMMO skill info
adminchat:
aliases: [ac, a]
description: Toggle Admin chat or send admin chat messages
@ -139,6 +141,7 @@ permissions:
description: Implies all mcmmo.ability permissions.
children:
mcmmo.ability.acrobatics.all: true
mcmmo.ability.alchemy.all: true
mcmmo.ability.archery.all: true
mcmmo.ability.axes.all: true
mcmmo.ability.excavation.all: true
@ -168,6 +171,20 @@ permissions:
description: Allows access to the Graceful Roll ability
mcmmo.ability.acrobatics.roll:
description: Allows access to the Roll ability
mcmmo.ability.alchemy.*:
default: false
description: Allows access to all Alchemy abilities
children:
mcmmo.ability.alchemy.all: true
mcmmo.ability.alchemy.all:
description: Allows access to all Alchemy abilities
children:
mcmmo.ability.alchemy.catalysis: true
mcmmo.ability.alchemy.concoctions: true
mcmmo.ability.alchemy.catalysis:
description: Allows access to the Catalysis ability
mcmmo.ability.alchemy.concoctions:
description: Allows access to the Concoctions ability
mcmmo.ability.archery.*:
default: false
description: Allows access to all Archery abilities
@ -626,6 +643,7 @@ permissions:
description: Implies all default mcmmo.commands permissions.
children:
mcmmo.commands.acrobatics: true
mcmmo.commands.alchemy: true
mcmmo.commands.archery: true
mcmmo.commands.axes: true
mcmmo.commands.excavation: true
@ -695,6 +713,8 @@ permissions:
description: Allows access to the addxp command
mcmmo.commands.addxp.others:
description: Allows access to the addxp command for other players
mcmmo.commands.alchemy:
description: Allows access to the alchemy command
mcmmo.commands.archery:
description: Allows access to the archery command
mcmmo.commands.axes:
@ -833,6 +853,7 @@ permissions:
children:
mcmmo.commands.mctop: true
mcmmo.commands.mctop.acrobatics: true
mcmmo.commands.mctop.alchemy: true
mcmmo.commands.mctop.archery: true
mcmmo.commands.mctop.axes: true
mcmmo.commands.mctop.excavation: true
@ -849,6 +870,8 @@ permissions:
description: Allows access to the mctop command
mcmmo.commands.mctop.acrobatics:
description: Allows access to the mctop command for acrobatics
mcmmo.commands.mctop.alchemy:
description: Allows access to the mctop command for alchemy
mcmmo.commands.mctop.archery:
description: Allows access to the mctop command for archery
mcmmo.commands.mctop.axes:
@ -1001,6 +1024,7 @@ permissions:
children:
mcmmo.commands.skillreset: true
mcmmo.commands.skillreset.acrobatics: true
mcmmo.commands.skillreset.alchemy: true
mcmmo.commands.skillreset.archery: true
mcmmo.commands.skillreset.axes: true
mcmmo.commands.skillreset.excavation: true
@ -1018,6 +1042,8 @@ permissions:
description: Allows access to the skillreset command
mcmmo.commands.skillreset.acrobatics:
description: Allows access to the skillreset command for acrobatics
mcmmo.commands.skillreset.alchemy:
description: Allows access to the skillreset command for alchemy
mcmmo.commands.skillreset.archery:
description: Allows access to the skillreset command for archery
mcmmo.commands.skillreset.axes:
@ -1040,6 +1066,7 @@ permissions:
children:
mcmmo.commands.skillreset.others: true
mcmmo.commands.skillreset.others.acrobatics: true
mcmmo.commands.skillreset.others.alchemy: true
mcmmo.commands.skillreset.others.archery: true
mcmmo.commands.skillreset.others.axes: true
mcmmo.commands.skillreset.others.excavation: true
@ -1056,6 +1083,8 @@ permissions:
description: Allows access to the skillreset command for other players
mcmmo.commands.skillreset.others.acrobatics:
description: Allows access to the skillreset command for acrobatics for other players
mcmmo.commands.skillreset.others.alchemy:
description: Allows access to the skillreset command for alchemy for other players
mcmmo.commands.skillreset.others.archery:
description: Allows access to the skillreset command for archery for other players
mcmmo.commands.skillreset.others.axes:
@ -1246,6 +1275,7 @@ permissions:
description: Gives all abilities & skills a 33.3% better chance to activate.
children:
mcmmo.perks.lucky.acrobatics: true
mcmmo.perks.lucky.alchemy: true
mcmmo.perks.lucky.archery: true
mcmmo.perks.lucky.axes: true
mcmmo.perks.lucky.excavation: true
@ -1261,6 +1291,9 @@ permissions:
mcmmo.perks.lucky.acrobatics:
default: false
description: Gives Acrobatics abilities & skills a 33.3% better chance to activate.
mcmmo.perks.lucky.alchemy:
default: false
description: Gives Alchemy abilities & skills a 33.3% better chance to activate.
mcmmo.perks.lucky.archery:
default: false
description: Gives Archery abilities & skills a 33.3% better chance to activate.
@ -1326,6 +1359,7 @@ permissions:
description: Mulitplies incoming XP by 2.5
children:
mcmmo.perks.xp.150percentboost.acrobatics: true
mcmmo.perks.xp.150percentboost.alchemy: true
mcmmo.perks.xp.150percentboost.archery: true
mcmmo.perks.xp.150percentboost.axes: true
mcmmo.perks.xp.150percentboost.excavation: true
@ -1341,6 +1375,9 @@ permissions:
mcmmo.perks.xp.150percentboost.acrobatics:
default: false
description: Multiplies incoming Acrobatics XP by 2.5
mcmmo.perks.xp.150percentboost.alchemy:
default: false
description: Multiplies incoming Alchemy XP by 2.5
mcmmo.perks.xp.150percentboost.archery:
default: false
description: Multiplies incoming Archery XP by 2.5
@ -1392,6 +1429,7 @@ permissions:
description: Mulitplies incoming XP by 1.5
children:
mcmmo.perks.xp.50percentboost.acrobatics: true
mcmmo.perks.xp.50percentboost.alchemy: true
mcmmo.perks.xp.50percentboost.archery: true
mcmmo.perks.xp.50percentboost.axes: true
mcmmo.perks.xp.50percentboost.excavation: true
@ -1407,6 +1445,9 @@ permissions:
mcmmo.perks.xp.50percentboost.acrobatics:
default: false
description: Multiplies incoming Acrobatics XP by 1.5
mcmmo.perks.xp.50percentboost.alchemy:
default: false
description: Multiplies incoming Acrobatics XP by 1.5
mcmmo.perks.xp.50percentboost.archery:
default: false
description: Multiplies incoming Archery XP by 1.5
@ -1458,6 +1499,7 @@ permissions:
description: Doubles incoming XP
children:
mcmmo.perks.xp.double.acrobatics: true
mcmmo.perks.xp.double.alchemy: true
mcmmo.perks.xp.double.archery: true
mcmmo.perks.xp.double.axes: true
mcmmo.perks.xp.double.excavation: true
@ -1473,6 +1515,9 @@ permissions:
mcmmo.perks.xp.double.acrobatics:
default: false
description: Doubles incoming Acrobatics XP
mcmmo.perks.xp.double.alchemy:
default: false
description: Doubles incoming Alchemy XP
mcmmo.perks.xp.double.archery:
default: false
description: Doubles incoming Archery XP
@ -1524,6 +1569,7 @@ permissions:
description: Quadruples incoming XP
children:
mcmmo.perks.xp.quadruple.acrobatics: true
mcmmo.perks.xp.quadruple.alchemy: true
mcmmo.perks.xp.quadruple.archery: true
mcmmo.perks.xp.quadruple.axes: true
mcmmo.perks.xp.quadruple.excavation: true
@ -1539,6 +1585,9 @@ permissions:
mcmmo.perks.xp.quadruple.acrobatics:
default: false
description: Quadruples incoming Acrobatics XP
mcmmo.perks.xp.quadruple.alchemy:
default: false
description: Quadruples incoming Alchemy XP
mcmmo.perks.xp.quadruple.archery:
default: false
description: Quadruples incoming Archery XP
@ -1590,6 +1639,7 @@ permissions:
description: Triples incoming XP
children:
mcmmo.perks.xp.triple.acrobatics: true
mcmmo.perks.xp.triple.alchemy: true
mcmmo.perks.xp.triple.archery: true
mcmmo.perks.xp.triple.axes: true
mcmmo.perks.xp.triple.excavation: true
@ -1605,6 +1655,9 @@ permissions:
mcmmo.perks.xp.triple.acrobatics:
default: false
description: Triples incoming Acrobatics XP
mcmmo.perks.xp.triple.alchemy:
default: false
description: Triples incoming Acrobatics XP
mcmmo.perks.xp.triple.archery:
default: false
description: Triples incoming Archery XP
@ -1656,6 +1709,7 @@ permissions:
description: Implies all mcmmo.skills permissions.
children:
mcmmo.skills.acrobatics: true
mcmmo.skills.alchemy: true
mcmmo.skills.archery: true
mcmmo.skills.axes: true
mcmmo.skills.excavation: true
@ -1673,6 +1727,11 @@ permissions:
children:
mcmmo.ability.acrobatics.all: true
mcmmo.commands.acrobatics: true
mcmmo.skills.alchemy:
description: Allows access to the Alchemy skill
children:
mcmmo.ability.alchemy.all: true
mcmmo.commands.alchemy: true
mcmmo.skills.archery:
description: Allows access to the Archery skill
children:

View File

@ -0,0 +1,752 @@
#
# Settings for Concoctions
# Last updated on ${project.version}-b${BUILD_NUMBER}
###
Concoctions:
Tier_One_Ingredients:
- BLAZE_POWDER
- FERMENTED_SPIDER_EYE
- GHAST_TEAR
- GLOWSTONE_DUST
- GOLDEN_CARROT
- MAGMA_CREAM
- NETHER_STALK
- REDSTONE
- SPECKLED_MELON
- SPIDER_EYE
- SUGAR
- SULPHUR
- WATER_LILY # TODO: 'RAW_FISH:3' (Minecraft 1.7)
Tier_Two_Ingredients:
- CARROT_ITEM
- SLIME_BALL
Tier_Three_Ingredients:
- QUARTZ
- RED_MUSHROOM
Tier_Four_Ingredients:
- APPLE
- ROTTEN_FLESH
Tier_Five_Ingredients:
- BROWN_MUSHROOM
- 'INK_SACK:0'
Tier_Six_Ingredients:
- 'LONG_GRASS:2'
Tier_Seven_Ingredients:
- POISONOUS_POTATO
Tier_Eight_Ingredients:
- 'GOLDEN_APPLE:0'
#
# Settings for Potions
#
# <data_value>: Data value used for identifying this potion
# Name: <name> Custom display name for this potion (optional)
# Lore: ["lore1","lore2"...] Custom lore for this potion (section is optional)
# Children: The potential children of this potion (section is optional)
# <INGREDIENT>: <NEW_DV> The ingredient used, and resultant potion's new data value
# Effects: List of strings for the potion's effects (section is optional)
# - "<POTION_EFFECT> [EFFECT_TIER] [DURATION_TICKS]"
#
# DataValues - These potions follow the normal data value pattern except for bits 8-12:
# Bits 0-3: Liquid Color (http://minecraft.gamepedia.com/Data_values#Potions)
# Bit 4: (Unused)
# Bit 5: Power
# Bit 6: Extended
# Bit 7: (Unused)
# Bits 8-12: Custom Status Effect (http://minecraft.gamepedia.com/Data_values#Status_effects)
# Bit 13: Can become splash
# Bit 14: Splash
# Bit 15: (Unused)
###
Potions:
### NON-EFFECT POTIONS #####################################################
0: # Water Bottle
Children:
BLAZE_POWDER: 8192 # Mundane Potion
FERMENTED_SPIDER_EYE: 4616 # Potion of Weakness
GHAST_TEAR: 8192 # Mundane Potion
GLOWSTONE_DUST: 32 # Thick Potion
MAGMA_CREAM: 8192 # Mundane Potion
NETHER_STALK: 16 # Awkward Potion
REDSTONE: 64 # Mundane Potion Extended
SPECKLED_MELON: 8192 # Mundane Potion
SPIDER_EYE: 8192 # Mundane Potion
SUGAR: 8192 # Mundane Potion
16: # Awkward Potion
Children:
APPLE: 5376 # Potion of Health Boost
BLAZE_POWDER: 1289 # Potion of Strength
BROWN_MUSHROOM: 2304 # Potion of Nausea
CARROT_ITEM: 768 # Potion of Haste
FERMENTED_SPIDER_EYE: 4616 # Potion of Weakness
GHAST_TEAR: 2561 # Potion of Regeneration
'GOLDEN_APPLE:0': 2816 # Potion of Resistance
GOLDEN_CARROT: 4102 # Potion of Night Vision
'INK_SACK:0': 3840 # Potion of Blindness
'LONG_GRASS:2': 5888 # Potion of Saturation
MAGMA_CREAM: 3075 # Potion of Fire Resistance
POISONOUS_POTATO: 5120 # Potion of Decay
QUARTZ: 5632 # Potion of Absorption
RED_MUSHROOM: 2048 # Potion of Leaping
ROTTEN_FLESH: 4352 # Potion of Hunger
SLIME_BALL: 1024 # Potion of Dullness
SPECKLED_MELON: 1541 # Potion of Healing
SPIDER_EYE: 4868 # Potion of Poison
SUGAR: 258 # Potion of Swiftness
WATER_LILY: 3341 # Potion of Water Breathing (Minecraft 1.6)
# 'RAW_FISH:3': 3341 # TODO: Potion of Water Breathing (Minecraft 1.7)
32: # Thick Potion
Children:
FERMENTED_SPIDER_EYE: 4616
64: # Mundane Potion Extended
Children:
FERMENTED_SPIDER_EYE: 4680
8192: # Mundane Potion
Children:
FERMENTED_SPIDER_EYE: 4616
SULPHUR: 16384
### DRINKABLE POTIONS ######################################################
258: # Potion of Swiftness
Effects: ["SPEED 0 3600"]
Children:
FERMENTED_SPIDER_EYE: 522
GLOWSTONE_DUST: 290
REDSTONE: 322
SULPHUR: 16642
290: # Potion of Swiftness II
Effects: ["SPEED 1 1800"]
Children:
FERMENTED_SPIDER_EYE: 586
REDSTONE: 322
SULPHUR: 16642
322: # Potion of Swiftness Extended
Effects: ["SPEED 0 9600"]
Children:
FERMENTED_SPIDER_EYE: 522
GLOWSTONE_DUST: 290
SULPHUR: 16706
522: # Potion of Slowness
Effects: ["SLOW 0 1800"]
Children:
REDSTONE: 586
SULPHUR: 16906
586: # Potion of Slowness Extended
Effects: ["SLOW 0 4800"]
Children:
GLOWSTONE_DUST: 522
SULPHUR: 16970
768: # Potion of Haste
Effects: ["FAST_DIGGING 0 3600"]
Children:
GLOWSTONE_DUST: 800
REDSTONE: 832
SULPHUR: 17152
800: # Potion of Haste II
Effects: ["FAST_DIGGING 1 1800"]
Children:
REDSTONE: 832
SULPHUR: 17184
832: # Potion of Haste Extended
Effects: ["FAST_DIGGING 0 9600"]
Children:
GLOWSTONE_DUST: 800
SULPHUR: 17216
1024: # Potion of Dullness
Effects: ["SLOW_DIGGING 0 3600"]
Children:
GLOWSTONE_DUST: 1056
REDSTONE: 1088
SULPHUR: 17408
1056: # Potion of Dullness II
Effects: ["SLOW_DIGGING 1 1800"]
Children:
REDSTONE: 1088
SULPHUR: 17408
1088: # Potion of Dullness Extended
Effects: ["SLOW_DIGGING 0 9600"]
Children:
GLOWSTONE_DUST: 1056
SULPHUR: 17472
1289: # Potion of Strength
Effects: ["INCREASE_DAMAGE 0 3600"]
Children:
FERMENTED_SPIDER_EYE: 4616
GLOWSTONE_DUST: 1321
REDSTONE: 1353
SULPHUR: 17673
1321: # Potion of Strength II
Effects: ["INCREASE_DAMAGE 1 1800"]
Children:
FERMENTED_SPIDER_EYE: 4616
REDSTONE: 1353
SULPHUR: 17705
1353: # Potion of Strength Extended
Effects: ["INCREASE_DAMAGE 0 9600"]
Children:
FERMENTED_SPIDER_EYE: 4680
GLOWSTONE_DUST: 1321
SULPHUR: 17737
1541: # Potion of Healing
Effects: ["HEAL 0"]
Children:
FERMENTED_SPIDER_EYE: 1804
GLOWSTONE_DUST: 1573
SULPHUR: 17925
1573: # Potion of Healing II
Effects: ["HEAL 1"]
Children:
FERMENTED_SPIDER_EYE: 1836
REDSTONE: 1541
SULPHUR: 17957
1804: # Potion of Harming
Effects: ["HARM 0"]
Children:
GLOWSTONE_DUST: 1836
SULPHUR: 18188
1836: # Potion of Harming II
Effects: ["HARM 1"]
Children:
REDSTONE: 1804
SULPHUR: 18220
2048: # Potion of Leaping
Effects: ["JUMP 0 3600"]
Children:
GLOWSTONE_DUST: 2080
REDSTONE: 2112
SULPHUR: 18432
2080: # Potion of Leaping II
Effects: ["JUMP 1 1800"]
Children:
REDSTONE: 2112
SULPHUR: 18464
2112: # Potion of Leaping Extended
Effects: ["JUMP 0 9600"]
Children:
GLOWSTONE_DUST: 2080
SULPHUR: 18496
2304: # Potion of Nausea
Effects: ["CONFUSION 0 450"]
Children:
REDSTONE: 2368
SULPHUR: 18688
2368: # Potion of Nausea Extended
Effects: ["CONFUSION 0 1200"]
Children:
GLOWSTONE_DUST: 2304
SULPHUR: 18752
2561: # Potion of Regeneration
Effects: ["REGENERATION 0 900"]
Children:
FERMENTED_SPIDER_EYE: 4616
GLOWSTONE_DUST: 2593
REDSTONE: 2625
SULPHUR: 18945
2593: # Potion of Regeneration II
Effects: ["REGENERATION 1 450"]
Children:
FERMENTED_SPIDER_EYE: 4616
REDSTONE: 2625
SULPHUR: 18977
2625: # Potion of Regeneration Extended
Effects: ["REGENERATION 0 2400"]
Children:
FERMENTED_SPIDER_EYE: 4680
GLOWSTONE_DUST: 2593
SULPHUR: 19009
2816: # Potion of Resistance
Effects: ["DAMAGE_RESISTANCE 0 450"]
Children:
GLOWSTONE_DUST: 2848
REDSTONE: 2880
SULPHUR: 19200
2848: # Potion of Resistance II
Effects: ["DAMAGE_RESISTANCE 1 225"]
Children:
REDSTONE: 2880
SULPHUR: 19232
2880: # Potion of Resistance Extended
Effects: ["DAMAGE_RESISTANCE 0 1200"]
Children:
GLOWSTONE_DUST: 2848
SULPHUR: 19264
3075: # Potion of Fire Resistance
Effects: ["FIRE_RESISTANCE 0 3600"]
Children:
FERMENTED_SPIDER_EYE: 522
REDSTONE: 3139
SULPHUR: 19459
3139: # Potion of Fire Resistance Extended
Effects: ["FIRE_RESISTANCE 0 9600"]
Children:
FERMENTED_SPIDER_EYE: 586
GLOWSTONE_DUST: 3075
SULPHUR: 19523
3341: # Potion of Water Breathing
Effects: ["WATER_BREATHING 0 3600"]
Children:
REDSTONE: 3405
SULPHUR: 19725
3405: # Potion of Water Breathing Extended
Effects: ["WATER_BREATHING 0 9600"]
Children:
GLOWSTONE_DUST: 3341
SULPHUR: 19789
3598: # Potion of Invisibility
Effects: ["INVISIBILITY 0 3600"]
Children:
REDSTONE: 3662
SULPHUR: 19982
3662: # Potion of Invisibility Extended
Effects: ["INVISIBILITY 0 9600"]
Children:
GLOWSTONE_DUST: 3598
SULPHUR: 20046
3840: # Potion of Blindness
Effects: ["BLINDNESS 0 225"]
Children:
REDSTONE: 3904
SULPHUR: 20224
3904: # Potion of Blindness Extended
Effects: ["BLINDNESS 0 600"]
Children:
GLOWSTONE_DUST: 3840
SULPHUR: 20288
4102: # Potion of Night Vision
Effects: ["NIGHT_VISION 0 3600"]
Children:
FERMENTED_SPIDER_EYE: 3598
REDSTONE: 4166
SULPHUR: 20486
4166: # Potion of Night Vision Extended
Effects: ["NIGHT_VISION 0 9600"]
Children:
FERMENTED_SPIDER_EYE: 3662
GLOWSTONE_DUST: 4102
SULPHUR: 20550
4352: # Potion of Hunger
Effects: ["HUNGER 0 900"]
Children:
GLOWSTONE_DUST: 4384
REDSTONE: 4416
SULPHUR: 20736
4284: # Potion of Hunger II
Effects: ["HUNGER 1 450"]
Children:
REDSTONE: 4416
SULPHUR: 20768
4416: # Potion of Hunger Extended
Effects: ["HUNGER 0 2400"]
Children:
GLOWSTONE_DUST: 4384
SULPHUR: 20800
4616: # Potion of Weakness
Effects: ["WEAKNESS 0 1800"]
Children:
REDSTONE: 4680
SULPHUR: 21000
4680: # Potion of Weakness Extended
Effects: ["WEAKNESS 0 4800"]
Children:
GLOWSTONE_DUST: 4616
SULPHUR: 21064
4868: # Potion of Poison
Effects: ["POISON 0 900"]
Children:
FERMENTED_SPIDER_EYE: 1804
GLOWSTONE_DUST: 4900
REDSTONE: 4932
SULPHUR: 21252
4900: # Potion of Poison II
Effects: ["POISON 1 450"]
Children:
FERMENTED_SPIDER_EYE: 1836
REDSTONE: 4932
SULPHUR: 21284
4932: # Potion of Poison Extended
Effects: ["POISON 0 2400"]
Children:
FERMENTED_SPIDER_EYE: 1804
GLOWSTONE_DUST: 4900
SULPHUR: 21284
5120: # Potion of Decay
Effects: ["WITHER 0 450"]
Children:
GLOWSTONE_DUST: 5152
REDSTONE: 5184
SULPHUR: 21504
5152: # Potion of Decay II
Effects: ["WITHER 1 225"]
Children:
REDSTONE: 5184
SULPHUR: 21536
5184: # Potion of Decay Extended
Effects: ["WITHER 0 1200"]
Children:
GLOWSTONE_DUST: 5152
SULPHUR: 21568
5376: # Potion of Health Boost
Effects: ["HEALTH_BOOST 0 1800"]
Children:
GLOWSTONE_DUST: 5408
REDSTONE: 5440
SULPHUR: 21760
5408: # Potion of Health Boost II
Effects: ["HEALTH_BOOST 1 900"]
Children:
REDSTONE: 5440
SULPHUR: 21792
5440: # Potion of Health Boost Extended
Effects: ["HEALTH_BOOST 0 4800"]
Children:
GLOWSTONE_DUST: 5408
SULPHUR: 21824
5632: # Potion of Absorption
Effects: ["ABSORPTION 0 1800"]
Children:
GLOWSTONE_DUST: 5664
REDSTONE: 5696
SULPHUR: 22016
5664: # Potion of Absorption II
Effects: ["ABSORPTION 1 900"]
Children:
REDSTONE: 5696
SULPHUR: 22048
5696: # Potion of Absorption Extended
Effects: ["ABSORPTION 0 4800"]
Children:
GLOWSTONE_DUST: 5664
SULPHUR: 22080
5888: # Potion of Saturation
Effects: ["SATURATION 0 8"]
Children:
GLOWSTONE_DUST: 5920
SULPHUR: 22272
5920: # Potion of Saturation II
Effects: ["SATURATION 1 8"]
Children:
REDSTONE: 5888
SULPHUR: 22304
### SPLASH POTIONS #########################################################
16384: # Splash Mundane Potion
Children:
FERMENTED_SPIDER_EYE: 21000
16642: # Splash Potion of Swiftness
Effects: ["SPEED 0 2700"]
Children:
FERMENTED_SPIDER_EYE: 16906
GLOWSTONE_DUST: 16674
REDSTONE: 16706
16674: # Splash Potion of Swiftness II
Effects: ["SPEED 1 1350"]
Children:
FERMENTED_SPIDER_EYE: 16906
REDSTONE: 16706
16706: # Splash Potion of Swiftness Extended
Effects: ["SPEED 0 7200"]
Children:
FERMENTED_SPIDER_EYE: 16906
GLOWSTONE_DUST: 16674
16906: # Splash Potion of Slowness
Effects: ["SLOW 0 1350"]
Children:
REDSTONE: 16970
16970: # Splash Potion of Slowness Extended
Effects: ["SLOW 0 3600"]
Children:
GLOWSTONE_DUST: 16906
17152: # Splash Potion of Haste
Effects: ["FAST_DIGGING 0 2700"]
Children:
GLOWSTONE_DUST: 17184
REDSTONE: 17216
17184: # Splash Potion of Haste II
Effects: ["FAST_DIGGING 1 1350"]
Children:
REDSTONE: 17216
17216: # Splash Potion of Haste Extended
Effects: ["FAST_DIGGING 0 7200"]
Children:
GLOWSTONE_DUST: 17184
17408: # Splash Potion of Dullness
Effects: ["SLOW_DIGGING 0 2700"]
Children:
GLOWSTONE_DUST: 17440
REDSTONE: 17472
17440: # Splash Potion of Dullness II
Effects: ["SLOW_DIGGING 1 1350"]
Children:
REDSTONE: 17472
17472: # Splash Potion of Dullness Extended
Effects: ["SLOW_DIGGING 0 7200"]
Children:
GLOWSTONE_DUST: 17440
17673: # Splash Potion of Strength
Effects: ["INCREASE_DAMAGE 0 2700"]
Children:
FERMENTED_SPIDER_EYE: 21000
GLOWSTONE_DUST: 17705
REDSTONE: 17737
17705: # Splash Potion of Strength II
Effects: ["INCREASE_DAMAGE 1 1350"]
Children:
FERMENTED_SPIDER_EYE: 21000
REDSTONE: 17737
17737: # Splash Potion of Strength Extended
Effects: ["INCREASE_DAMAGE 0 7200"]
Children:
FERMENTED_SPIDER_EYE: 21064
GLOWSTONE_DUST: 17705
17925: # Splash Potion of Healing
Effects: ["HEAL 0"]
Children:
FERMENTED_SPIDER_EYE: 18188
GLOWSTONE_DUST: 17957
17957: # Splash Potion of Healing II
Effects: ["HEAL 1"]
Children:
FERMENTED_SPIDER_EYE: 18220
REDSTONE: 17925
18188: # Splash Potion of Harming
Effects: ["HARM 0"]
Children:
GLOWSTONE_DUST: 18220
18220: # Splash Potion of Harming II
Effects: ["HARM 1"]
Children:
REDSTONE: 18188
18432: # Splash Potion of Leaping
Effects: ["JUMP 0 2700"]
Children:
GLOWSTONE_DUST: 18464
REDSTONE: 18496
18464: # Splash Potion of Leaping II
Effects: ["JUMP 1 1350"]
Children:
REDSTONE: 18496
18496: # Splash Potion of Leaping Extended
Effects: ["JUMP 0 7200"]
Children:
GLOWSTONE_DUST: 18464
18688: # Splash Potion of Nausea
Effects: ["CONFUSION 0 338"]
Children:
REDSTONE: 18752
18752: # Splash Potion of Nausea Extended
Effects: ["CONFUSION 0 900"]
Children:
GLOWSTONE_DUST: 18688
18945: # Splash Potion of Regeneration
Effects: ["REGENERATION 0 675"]
Children:
FERMENTED_SPIDER_EYE: 21000
GLOWSTONE_DUST: 18977
REDSTONE: 19009
18977: # Splash Potion of Regeneration II
Effects: ["REGENERATION 1 338"]
Children:
FERMENTED_SPIDER_EYE: 21000
REDSTONE: 19009
19009: # Splash Potion of Regeneration Extended
Effects: ["REGENERATION 0 1800"]
Children:
FERMENTED_SPIDER_EYE: 21064
GLOWSTONE_DUST: 18977
19200: # Splash Potion of Resistance
Effects: ["DAMAGE_RESISTANCE 0 338"]
Children:
GLOWSTONE_DUST: 19232
REDSTONE: 19264
19232: # Splash Potion of Resistance II
Effects: ["DAMAGE_RESISTANCE 1 169"]
Children:
REDSTONE: 19264
19264: # Splash Potion of Resistance Extended
Effects: ["DAMAGE_RESISTANCE 0 900"]
Children:
GLOWSTONE_DUST: 19232
19459: # Splash Potion of Fire Resistance
Effects: ["FIRE_RESISTANCE 0 2700"]
Children:
FERMENTED_SPIDER_EYE: 16906
REDSTONE: 19523
19523: # Splash Potion of Fire Resistance Extended
Effects: ["FIRE_RESISTANCE 0 7200"]
Children:
FERMENTED_SPIDER_EYE: 16970
GLOWSTONE_DUST: 19459
19725: # Splash Potion of Water Breathing
Effects: ["WATER_BREATHING 0 2700"]
Children:
REDSTONE: 19789
19789: # Splash Potion of Water Breathing Extended
Effects: ["WATER_BREATHING 0 7200"]
Children:
GLOWSTONE_DUST: 19725
19982: # Splash Potion of Invisibility
Effects: ["INVISIBILITY 0 2700"]
Children:
REDSTONE: 20046
20046: # Splash Potion of Invisibility Extended
Effects: ["INVISIBILITY 0 7200"]
Children:
GLOWSTONE_DUST: 19982
20224: # Splash Potion of Blindness
Effects: ["BLINDNESS 0 169"]
Children:
REDSTONE: 20288
20288: # Splash Potion of Blindness Extended
Effects: ["BLINDNESS 0 450"]
Children:
GLOWSTONE_DUST: 20224
20486: # Splash Potion of Night Vision
Effects: ["NIGHT_VISION 0 2700"]
Children:
FERMENTED_SPIDER_EYE: 19982
REDSTONE: 20550
20550: # Splash Potion of Night Vision Extended
Effects: ["NIGHT_VISION 0 7200"]
Children:
FERMENTED_SPIDER_EYE: 20046
GLOWSTONE_DUST: 20486
20736: # Splash Potion of Hunger
Effects: ["HUNGER 0 675"]
Children:
GLOWSTONE_DUST: 20768
REDSTONE: 20800
20768: # Splash Potion of Hunger II
Effects: ["HUNGER 1 338"]
Children:
REDSTONE: 20800
20800: # Splash Potion of Hunger Extended
Effects: ["HUNGER 0 1800"]
Children:
GLOWSTONE_DUST: 20768
21000: # Splash Potion of Weakness
Effects: ["WEAKNESS 0 1350"]
Children:
REDSTONE: 21064
21064: # Splash Potion of Weakness Extended
Effects: ["WEAKNESS 0 3600"]
Children:
GLOWSTONE_DUST: 21000
21252: # Splash Potion of Poison
Effects: ["POISON 0 675"]
Children:
FERMENTED_SPIDER_EYE: 18188
GLOWSTONE_DUST: 21284
REDSTONE: 21316
21284: # Splash Potion of Poison II
Effects: ["POISON 1 338"]
Children:
FERMENTED_SPIDER_EYE: 18220
REDSTONE: 21316
21316: # Splash Potion of Poison Extended
Effects: ["POISON 0 1800"]
Children:
FERMENTED_SPIDER_EYE: 18188
GLOWSTONE_DUST: 21284
21504: # Splash Potion of Decay
Effects: ["WITHER 0 338"]
Children:
GLOWSTONE_DUST: 21536
REDSTONE: 21568
21536: # Splash Potion of Decay II
Effects: ["WITHER 1 169"]
Children:
REDSTONE: 21568
21568: # Splash Potion of Decay Extended
Effects: ["WITHER 0 900"]
Children:
GLOWSTONE_DUST: 21536
21760: # Splash Potion of Health Boost
Effects: ["HEALTH_BOOST 0 1350"]
Children:
GLOWSTONE_DUST: 21792
REDSTONE: 5440
21792: # Splash Potion of Health Boost II
Effects: ["HEALTH_BOOST 1 675"]
Children:
REDSTONE: 21824
21824: # Splash Potion of Health Boost Extended
Effects: ["HEALTH_BOOST 0 3600"]
Children:
GLOWSTONE_DUST: 21792
22016: # Splash Potion of Absorption
Effects: ["ABSORPTION 0 1350"]
Children:
GLOWSTONE_DUST: 22048
REDSTONE: 22080
22048: # Splash Potion of Absorption II
Effects: ["ABSORPTION 1 675"]
Children:
REDSTONE: 22080
22080: # Splash Potion of Absorption Extended
Effects: ["ABSORPTION 0 3600"]
Children:
GLOWSTONE_DUST: 22048
22272: # Splash Potion of Saturation
Effects: ["SATURATION 0 6"]
Children:
GLOWSTONE_DUST: 22304
22304: # Splash Potion of Saturation II
Effects: ["SATURATION 1 6"]
Children:
REDSTONE: 22272