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

@ -8,6 +8,7 @@ Key:
- Removal
Version 1.4.08-dev
+ Added new Skill - Alchemy!
+ Added SecondaryAbilityType enum, and new SecondaryAbilityWeightedActivationCheckEvent, fired when a secondary ability checkes its activation chances
+ Added the possibility to gain experience when using Fishing "Shake"
+ Added config options to disable various sound effects

View File

@ -5,7 +5,7 @@
Our latest development builds are available ~~[here](http://ci.mcmmo.info)~~. Unfortunately, the mcMMO site is down; a temporary dev build location is hosted [here](http://ci.ecocitycraft.com/job/mcMMO/).
### Brief Description
The goal of mcMMO is to take core Minecraft game mechanics and expand them into add an extensive and quality RPG experience. Everything in mcMMO has been carefully thought out and is constantly being improved upon. Currently, mcMMO adds thirteen unique skills to train and level in. Each of these skills is highly customizable through our configuration files, allowing server admins to tweak mcMMO to best suit the needs of his or her server. Know that the mcMMO team is dedicated to providing an ever-evolving experience, and that we carefully read all feedback and bug reports in order to evaluate and balance the mechanics of mcMMO in every update.
The goal of mcMMO is to take core Minecraft game mechanics and expand them into add an extensive and quality RPG experience. Everything in mcMMO has been carefully thought out and is constantly being improved upon. Currently, mcMMO adds fourteen unique skills to train and level in. Each of these skills is highly customizable through our configuration files, allowing server admins to tweak mcMMO to best suit the needs of his or her server. Know that the mcMMO team is dedicated to providing an ever-evolving experience, and that we carefully read all feedback and bug reports in order to evaluate and balance the mechanics of mcMMO in every update.
## About the Team
@ -31,6 +31,8 @@ mcMMO is currently developed by a team of individuals from all over the world.
(https://github.com/t00thpick1)
[![riking](https://1.gravatar.com/avatar/aca9f37e569ac3a63929920035a91ba4.png)]
(https://github.com/riking)
[![EasyMFnE](https://www.gravatar.com/avatar/99c9a1fa3bbf957791ceac7b45daadb0.png)]
(https://github.com/EasyMFnE)
## Compiling

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