mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-06-25 10:14:43 +02:00
Introduction of new Alchemy skill!
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
@ -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); }
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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); }
|
||||
|
188
src/main/java/com/gmail/nossr50/config/potion/PotionConfig.java
Normal file
188
src/main/java/com/gmail/nossr50/config/potion/PotionConfig.java
Normal 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: '<MATERIAL>[: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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
101
src/main/java/com/gmail/nossr50/datatypes/AlchemyPotion.java
Normal file
101
src/main/java/com/gmail/nossr50/datatypes/AlchemyPotion.java
Normal 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;
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ public enum DatabaseUpdateType {
|
||||
MOB_HEALTHBARS,
|
||||
PARTY_NAMES,
|
||||
KILL_ORPHANS,
|
||||
DROPPED_SPOUT
|
||||
DROPPED_SPOUT,
|
||||
ALCHEMY
|
||||
;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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>();
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
83
src/main/java/com/gmail/nossr50/skills/alchemy/Alchemy.java
Normal file
83
src/main/java/com/gmail/nossr50/skills/alchemy/Alchemy.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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"); }
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user