Yikes that was a lot of merge conflicts.

This commit is contained in:
nossr50 2019-06-12 05:26:45 -07:00
commit a654762f4d
25 changed files with 285 additions and 215 deletions

View File

@ -163,6 +163,68 @@ Version 2.2.0
Added API method to grab the level cap of a skill by its PrimarySkillType ENUM definition
Added API method to check if a skill was being level capped
Added 'UndefinedSkillBehaviour' for trying to use a method that has no behaviour defined for the provided skill
Version 2.1.77
Added minimum quantity back to Repair config
NOTES: I removed this last patch because I did not consider that server admins might be allowing users to repair items without crafting recipes (as of last patch mcMMO determines minimum quantity via counting ingredients in a recipe)
If you do not define minimum quantity in the repair config, mcMMO will grab the minimum quantity automatically as I programmed it to do as of last patch, otherwise if it is defined, mcMMO will respect that and use that for calculations.
The minimum quanitty should be set to the number of ingredients used to craft the recipe, for example 8 for diamond chestplate etc, you do not need to define this unless you are allowing players to repair custom items.
Version 2.1.76
Advanced Salvage has been renamed to Scrap Collector
Scrap Collector has 8 ranks, the first rank is unlocked at level 2 (Level 20 in RetroMode)
You can not salvage without at least 1 rank in Scrap Collector now (formerly Advanced Salvage)
Fixed a bug where Repair was repairing too much
Fixed a bug where Arcane Salvage was used to determine how many materials a player could salvage from an item instead of Scrap Collector (formerly Advanced Salvage)
Fixed a bug where messages about an item being too damage to salvage were being sent twice
Removed the minimum quantity field from the repair config
Removed the item data (metadata) field from repair config as its not used anymore
Salvage will no longer return the max amount of materials possible, instead you are guaranteed one item and then some luck is involved on how many items are returned.
Updated Chinese locale (thanks to the user named 89009332 from github)
New locale strings
Salvage.Skills.Lottery.Normal
Salvage.Skills.Lottery.Perfect
Salvage.Skills.Lottery.Untrained
Salvage.SubSkill.ScrapCollector.Name
Salvage.SubSkill.ScrapCollector.Description
Salvage.SubSkill.ScrapCollector.Stat
(API) SALVAGE_ARCANE_SALVAGE in SubSkillType has been renamed to SALVAGE_SCRAP_COLLECTOR
NOTES:
You do not need to update your configs for this update.
How Salvage works
As an example, say you had enough skill to gain up to 5 items from salvaging something, and that item has enough durability to yield up to 5 materials, salvage will play out like this...
First off, you will be guaranteed 1 material, after this you have 80% chance to get the next material, if successful, another dice roll is conducted but lowers your odds by 20%, you chance to succeed will never fall below 33%
If you fail a dice roll, it will still conduct dice rolls for the remaining maximum amount of materials returned but your odds of success are only lowered upon a successful dice roll, the sum of the successful dice rolls is used to calculate how many items you are given back, the first item is guaranteed and has no dice rolls, which means for example the Diamond Shovel will always succeed.
Version 2.1.75
Fixed a bug that prevented Fortune from working correctly if a Double Drop was triggered
Version 2.1.74
Fixed a NPE that could occur during certain events if a skill was disabled in coreskills.yml (Sorry!)
Version 2.1.73
Fixed a NPE that could occur if an entire skill was disabled in coreskills.yml
Version 2.1.72
Fixed a NPE if a server shutdown with no player data needing to be saved (the error is harmless but spammy)
Fixed a NPE that could occur if Roll was disabled in coreskills.yml
Version 2.1.71
Salvage will now always ask for confirmation before breaking your items (instead of only asking for enchanted items)
Repair will now always ask for confirmation before repairing items (instead of only asking for enchanted items)
Gold & Iron Blocks will no longer trigger tool ready messages
Salvage & Repair anvils will no longer work on multi-item stacks
NOTES: You can still turn the confirmation off in config.yml
Version 2.1.70
Added new DatabaseAPI to the API package, has features relating to database operations
Fixed a bug where shulker boxes (without colors) would activate tool ready messages
Version 2.1.69
Fixed a few places where mcMMO would not save player data immediately which may cause players to lose a few minutes of progress

View File

@ -0,0 +1,33 @@
package com.gmail.nossr50.api;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.mcMMO;
import java.util.UUID;
public class DatabaseAPI {
/**
* Checks if a player exists in the mcMMO Database
* @param uuid player UUID
* @return true if the player exists in the DB, false if they do not
*/
public boolean doesPlayerExistInDB(String uuid) {
return doesPlayerExistInDB(UUID.fromString(uuid));
}
/**
* Checks if a player exists in the mcMMO Database
* @param uuid player UUID
* @return true if the player exists in the DB, false if they do not
*/
public boolean doesPlayerExistInDB(UUID uuid) {
PlayerProfile playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(uuid);
if(playerProfile.isLoaded())
return true;
else
return false;
}
}

View File

@ -15,7 +15,7 @@ import java.util.ArrayList;
import java.util.List;
public class SalvageCommand extends SkillCommand {
private boolean canAdvancedSalvage;
private boolean canScrapCollector;
private boolean canArcaneSalvage;
public SalvageCommand() {
@ -30,7 +30,7 @@ public class SalvageCommand extends SkillCommand {
@Override
protected void permissionsCheck(Player player) {
canAdvancedSalvage = canUseSubskill(player, SubSkillType.SALVAGE_ADVANCED_SALVAGE);
canScrapCollector = canUseSubskill(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR);
canArcaneSalvage = canUseSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE);
}
@ -39,9 +39,11 @@ public class SalvageCommand extends SkillCommand {
List<String> messages = new ArrayList<>();
SalvageManager salvageManager = UserManager.getPlayer(player).getSalvageManager();
if (canAdvancedSalvage) {
messages.add(LocaleLoader.getString("Ability.Generic.Template", LocaleLoader.getString("Salvage.Ability.Bonus.0"),
LocaleLoader.getString("Salvage.Ability.Bonus.1", salvageManager.getSalvageableAmount())));
if (canScrapCollector) {
messages.add(getStatMessage(false, true,
SubSkillType.SALVAGE_SCRAP_COLLECTOR,
String.valueOf(RankUtils.getRank(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR)),
RankUtils.getHighestRankStr(SubSkillType.SALVAGE_SCRAP_COLLECTOR)));
}
if (canArcaneSalvage) {

View File

@ -264,6 +264,7 @@ public class MaterialMapStore {
abilityBlackList.add("light_gray_shulker_box");
abilityBlackList.add("white_shulker_box");
abilityBlackList.add("yellow_shulker_box");
abilityBlackList.add("shulker_box");
abilityBlackList.add("wall_sign"); //1.13 and lower?
abilityBlackList.add("sign"); //1.13 and lower?
}
@ -353,6 +354,7 @@ public class MaterialMapStore {
toolBlackList.add("light_gray_shulker_box");
toolBlackList.add("white_shulker_box");
toolBlackList.add("yellow_shulker_box");
toolBlackList.add("shulker_box");
toolBlackList.add("acacia_sign");
toolBlackList.add("acacia_wall_sign");
toolBlackList.add("birch_sign");
@ -389,6 +391,8 @@ public class MaterialMapStore {
toolBlackList.add("oak_wood");
toolBlackList.add("spruce_log");
toolBlackList.add("spruce_wood");
toolBlackList.add("iron_block");
toolBlackList.add("gold_block");
}
private void addToHashSet(String string, HashSet<String> stringHashSet) {

View File

@ -1,7 +1,6 @@
package com.gmail.nossr50.core;
import com.gmail.nossr50.config.ConfigConstants;
import com.gmail.nossr50.config.hocon.HOCONUtil;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.properties.MaxBonusLevel;
@ -84,19 +83,24 @@ public class SkillPropertiesManager {
CommentedConfigurationNode childNode = it.next();
Object lastObjectInPath = childNode.getPath()[childNode.getPath().length + 1];
Object lastObjectInPath = childNode.getPath()[childNode.getPath().length - 1];
String nodeName = lastObjectInPath.toString();
if(nodeName.equalsIgnoreCase(ConfigConstants.MAX_BONUS_LEVEL_FIELD_NAME)) {
switch(nodeName) {
case ConfigConstants.MAX_BONUS_LEVEL_FIELD_NAME:
attemptRegisterMaxBonusLevel(subSkillType, childNode);
} else if(nodeName.equalsIgnoreCase(ConfigConstants.MAX_CHANCE_FIELD_NAME)) {
break;
case ConfigConstants.MAX_CHANCE_FIELD_NAME:
attemptRegisterMaxChance(subSkillType, childNode);
} else if(nodeName.equalsIgnoreCase(ConfigConstants.STATIC_ACTIVATION_FIELD_NAME)) {
break;
case ConfigConstants.STATIC_ACTIVATION_FIELD_NAME:
attemptRegisterStaticChance(subSkillType, childNode);
} else if(nodeName.equalsIgnoreCase(ConfigConstants.MAX_BONUS_PERCENTAGE_FIELD_NAME)) {
break;
case ConfigConstants.MAX_BONUS_PERCENTAGE_FIELD_NAME:
attemptRegisterMaxBonusPercentage(subSkillType, childNode);
break;
}
}
}
}

View File

@ -20,6 +20,7 @@ public enum NotificationType {
SUPER_ABILITY("SuperAbilityInteraction"),
SUPER_ABILITY_ALERT_OTHERS("SuperAbilityAlertOthers"),
ITEM_MESSAGE("ItemMessage"),
CHAT_ONLY("ChatOnly"),
PARTY_MESSAGE("PartyMessage");
final String niceName;

View File

@ -51,7 +51,7 @@ public enum PrimarySkillType {
REPAIR(RepairManager.class, Color.SILVER,
ImmutableList.of(SubSkillType.REPAIR_ARCANE_FORGING, SubSkillType.REPAIR_REPAIR_MASTERY, SubSkillType.REPAIR_SUPER_REPAIR), "Repair"),
SALVAGE(SalvageManager.class, Color.ORANGE,
ImmutableList.of(SubSkillType.SALVAGE_ADVANCED_SALVAGE, SubSkillType.SALVAGE_ARCANE_SALVAGE), "Salvage"),
ImmutableList.of(SubSkillType.SALVAGE_SCRAP_COLLECTOR, SubSkillType.SALVAGE_ARCANE_SALVAGE), "Salvage"),
SMELTING(SmeltingManager.class, Color.YELLOW,
ImmutableList.of(SubSkillType.SMELTING_UNDERSTANDING_THE_ART, /*SubSkillType.SMELTING_FLUX_MINING,*/ SubSkillType.SMELTING_FUEL_EFFICIENCY, SubSkillType.SMELTING_SECOND_SMELT), "Smelting"),
SWORDS(SwordsManager.class, Color.fromRGB(178, 34, 34), SuperAbilityType.SERRATED_STRIKES, ToolType.SWORD,

View File

@ -61,7 +61,7 @@ public enum SubSkillType {
REPAIR_SUPER_REPAIR(1),
/* Salvage */
SALVAGE_ADVANCED_SALVAGE(1),
SALVAGE_SCRAP_COLLECTOR(8),
SALVAGE_ARCANE_SALVAGE(8),
/* Smelting */

View File

@ -1,102 +0,0 @@
package com.gmail.nossr50.dumpster.mods;
/*
public class CustomToolConfig extends Config {
//TODO: Disabled until modded servers come back
public List<Material> customAxes = new ArrayList<Material>();
public List<Material> customBows = new ArrayList<Material>();
public List<Material> customHoes = new ArrayList<Material>();
public List<Material> customPickaxes = new ArrayList<Material>();
public List<Material> customShovels = new ArrayList<Material>();
public List<Material> customSwords = new ArrayList<Material>();
public HashMap<Material, CustomTool> customToolMap = new HashMap<Material, CustomTool>();
public List<Repairable> repairables = new ArrayList<Repairable>();
private boolean needsUpdate = false;
protected CustomToolConfig(String fileName) {
//super(McmmoCore.getDataFolderPath().getPath() + "mods", fileName, false);
super(mcMMO.p.getDataFolder().getPath() + "mods", fileName, false);
loadKeys();
}
@Override
protected void loadKeys() {
loadTool("Axes", customAxes);
loadTool("Bows", customBows);
loadTool("Hoes", customHoes);
loadTool("Pickaxes", customPickaxes);
loadTool("Shovels", customShovels);
loadTool("Swords", customSwords);
if (needsUpdate) {
needsUpdate = false;
backup();
}
}
private void loadTool(String toolType, List<Material> materialList) {
if (needsUpdate) {
return;
}
ConfigurationSection toolSection = config.getConfigurationSection(toolType);
if (toolSection == null) {
return;
}
Set<String> toolConfigSet = toolSection.getKeys(false);
for (String toolName : toolConfigSet) {
if (config.contains(toolType + "." + toolName + "." + ".ID")) {
needsUpdate = true;
return;
}
Material toolMaterial = Material.matchMaterial(toolName);
if (toolMaterial == null) {
plugin.getLogger().warning("Invalid material name. This item will be skipped. - " + toolName);
continue;
}
boolean repairable = getBooleanValue(toolType + "." + toolName + ".Repairable");
Material repairMaterial = Material.matchMaterial(getStringValue(toolType + "." + toolName + ".Repair_Material", ""));
if (repairable && (repairMaterial == null)) {
plugin.getLogger().warning("Incomplete repair information. This item will be unrepairable. - " + toolName);
repairable = false;
}
if (repairable) {
byte repairData = (byte) getIntValue(toolType + "." + toolName + ".Repair_Material_Data_Value", -1);
int repairQuantity = SkillUtils.getRepairAndSalvageQuantities(new ItemStack(toolMaterial), repairMaterial, repairData);
if (repairQuantity == 0) {
repairQuantity = getIntValue(toolType + "." + toolName + ".Repair_Material_Quantity", 2);
}
String repairItemName = getStringValue(toolType + "." + toolName + ".Repair_Material_Pretty_Name");
int repairMinimumLevel = getIntValue(toolType + "." + toolName + ".Repair_MinimumLevel", 0);
double repairXpMultiplier = getDoubleValue(toolType + "." + toolName + ".Repair_XpMultiplier", 1);
short durability = toolMaterial.getMaxDurability();
if (durability == 0) {
durability = (short) getIntValue(toolType + "." + toolName + ".Durability", 60);
}
repairables.add(RepairableFactory.getRepairable(toolMaterial, repairMaterial, repairData, repairItemName, repairMinimumLevel, repairQuantity, durability, ItemType.TOOL, ItemMaterialCategory.OTHER, repairXpMultiplier));
}
double multiplier = getDoubleValue(toolType + "." + toolName + ".XP_Modifier", 1.0);
boolean abilityEnabled = getBooleanValue(toolType + "." + toolName + ".Ability_Enabled", true);
int tier = getIntValue(toolType + "." + toolName + ".Tier", 1);
CustomTool tool = new CustomTool(tier, abilityEnabled, multiplier);
materialList.add(toolMaterial);
customToolMap.put(toolMaterial, tool);
}
}
}*/

View File

@ -72,11 +72,12 @@ public class BlockListener implements Listener {
for (int i = 0; i < bonusCount; i++) {
event.getBlock().getWorld().dropItemNaturally(event.getBlockState().getLocation(), is);
}
}
}
if(event.getBlock().hasMetadata(MetadataConstants.BONUS_DROPS_METAKEY))
event.getBlock().removeMetadata(MetadataConstants.BONUS_DROPS_METAKEY, plugin);
}
}
}
/*@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockDropItemEvent(BlockDropItemEvent event)

View File

@ -15,12 +15,7 @@ public class InteractionManager {
private static HashMap<String, AbstractSubSkill> subSkillNameMap; //Used for mmoinfo optimization
private static ArrayList<AbstractSubSkill> subSkillList;
/**
* Registers subskills with the Interaction registration
*
* @param abstractSubSkill the target subskill to register
*/
public static void registerSubSkill(AbstractSubSkill abstractSubSkill) {
public static void initMaps() {
/* INIT MAPS */
if (interactRegister == null)
interactRegister = new HashMap<>();
@ -30,7 +25,14 @@ public class InteractionManager {
if (subSkillNameMap == null)
subSkillNameMap = new HashMap<>();
}
/**
* Registers subskills with the Interaction registration
* @param abstractSubSkill the target subskill to register
*/
public static void registerSubSkill(AbstractSubSkill abstractSubSkill)
{
//Store a unique copy of each subskill
if (!subSkillList.contains(abstractSubSkill))
subSkillList.add(abstractSubSkill);
@ -70,8 +72,13 @@ public class InteractionManager {
* @param plugin instance of mcMMO plugin
* @param curInteractType the associated interaction type
*/
public static void processEvent(Event event, mcMMO plugin, InteractType curInteractType) {
for (Interaction interaction : interactRegister.get(curInteractType)) {
public static void processEvent(Event event, mcMMO plugin, InteractType curInteractType)
{
if(interactRegister.get(curInteractType) == null)
return;
for(Interaction interaction : interactRegister.get(curInteractType))
{
interaction.doInteraction(event, plugin);
}
}

View File

@ -26,6 +26,7 @@ import com.gmail.nossr50.skills.salvage.SalvageManager;
import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.util.*;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
@ -599,23 +600,30 @@ public class PlayerListener implements Listener {
if (!mcMMO.getConfigManager().getConfigSuperAbilities().isMustSneakToActivate() || player.isSneaking()) {
/* REPAIR CHECKS */
if (type == Repair.getInstance().getAnvilMaterial() && PrimarySkillType.REPAIR.getPermissions(player) && mcMMO.getRepairableManager().isRepairable(heldItem)) {
if (type == Repair.getInstance().getAnvilMaterial()
&& PrimarySkillType.REPAIR.getPermissions(player)
&& mcMMO.getRepairableManager().isRepairable(heldItem)
&& heldItem.getAmount() <= 1) {
RepairManager repairManager = mcMMOPlayer.getRepairManager();
event.setCancelled(true);
// Make sure the player knows what he's doing when trying to repair an enchanted item
if (!(heldItem.getEnchantments().size() > 0) || repairManager.checkConfirmation(true)) {
if (repairManager.checkConfirmation(true)) {
repairManager.handleRepair(heldItem);
player.updateInventory();
}
}
/* SALVAGE CHECKS */
else if (type == Salvage.anvilMaterial && PrimarySkillType.SALVAGE.getPermissions(player) && mcMMO.getSalvageableManager().isSalvageable(heldItem)) {
else if (type == Salvage.anvilMaterial
&& PrimarySkillType.SALVAGE.getPermissions(player)
&& RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR)
&& mcMMO.getSalvageableManager().isSalvageable(heldItem)
&& heldItem.getAmount() <= 1) {
SalvageManager salvageManager = UserManager.getPlayer(player).getSalvageManager();
event.setCancelled(true);
// Make sure the player knows what he's doing when trying to salvage an enchanted item
if (!(heldItem.getEnchantments().size() > 0) || salvageManager.checkConfirmation(true)) {
if (salvageManager.checkConfirmation(true)) {
SkillUtils.handleAbilitySpeedDecrease(player);
salvageManager.handleSalvage(block.getLocation(), heldItem);
player.updateInventory();

View File

@ -503,6 +503,8 @@ public class mcMMO extends JavaPlugin {
*/
if (mcMMO.getConfigManager().getConfigCoreSkills().isAcrobaticsEnabled()) {
InteractionManager.initMaps(); //Init maps
System.out.println("[mcMMO]" + " enabling Acrobatics Skills");
//TODO: Should do this differently

View File

@ -114,9 +114,8 @@ public class RepairManager extends SkillManager {
return;
}
//byte repairMaterialMetadata = repairable.getRepairMaterialMetadata();
ItemStack toRemove = new ItemStack(repairMaterial);
toRemove.setAmount(1);
short startDurability = item.getDurability();
@ -126,26 +125,6 @@ public class RepairManager extends SkillManager {
return;
}
// Check if they have the proper material to repair with
/*if (!inventory.contains(repairMaterial)) {
String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getPrettyItemString(repairMaterial) : repairable.getRepairMaterialPrettyName();
String materialsNeeded = "";
if (repairMaterialMetadata != (byte) -1 && !inventory.containsAtLeast(toRemove, 1)) {
materialsNeeded += ":" + repairMaterialMetadata;
}
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Skills.NeedMore.Extra", prettyName, materialsNeeded);
return;
}*/
// Do not repair stacked items
if (item.getAmount() != 1) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.StackedItems");
return;
}
// Clear ability buffs before trying to repair.
SkillUtils.removeAbilityBuff(item);
@ -165,11 +144,6 @@ public class RepairManager extends SkillManager {
}
// Remove the item
/*if (repairMaterialMetadata == -1) {
toRemove = inventory.getItem(inventory.first(repairMaterial)).clone();
toRemove.setAmount(1);
}*/
inventory.removeItem(toRemove);
// Give out XP like candy

View File

@ -8,7 +8,6 @@ import org.bukkit.Material;
import java.util.Collections;
import java.util.List;
public class Repairable {
private final Material itemMaterial;
private final List<Material> repairMaterials;

View File

@ -89,16 +89,12 @@ public class SalvageManager extends SkillManager {
return;
}
if (item.getDurability() != 0 && (!RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_ADVANCED_SALVAGE) || !Permissions.advancedSalvage(player))) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.Adept.Damaged");
return;
}
int maxAmountSalvageable = Salvage.calculateSalvageableAmount(item.getDurability(), salvageable.getMaximumDurability(), salvageable.getMaximumQuantity());
int salvageableAmount = Salvage.calculateSalvageableAmount(item.getDurability(), salvageable.getMaximumDurability(), salvageable.getMaximumQuantity());
int salvageableAmount = maxAmountSalvageable;
if (salvageableAmount == 0) {
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.TooDamaged");
player.sendMessage(LocaleLoader.getString("Salvage.Skills.TooDamaged"));
return;
}
@ -114,7 +110,30 @@ public class SalvageManager extends SkillManager {
enchantBook = arcaneSalvageCheck(enchants);
}
ItemStack salvageResults = new ItemStack(salvageable.getSalvagedItemMaterial(), salvageableAmount);
//Lottery on Salvageable Amount
int lotteryResults = 1;
int chanceOfSuccess = 80;
for(int x = 1; x < salvageableAmount-1; x++) {
if(RandomChanceUtil.rollDice(chanceOfSuccess, 100)) {
chanceOfSuccess-=20;
Math.max(chanceOfSuccess, 33);
lotteryResults+=1;
}
}
if(lotteryResults == salvageableAmount) {
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Perfect", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType()));
} else if(RankUtils.isPlayerMaxRankInSubSkill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE)) {
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Normal", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType()));
} else {
NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Untrained", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType()));
}
ItemStack salvageResults = new ItemStack(salvageable.getSalvagedItemMaterial(), lotteryResults);
//Call event
if (EventUtils.callSalvageCheckEvent(player, item, salvageResults, enchantBook).isCancelled()) {

View File

@ -1,6 +1,5 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.json.McMMOUrl;
import com.gmail.nossr50.datatypes.json.McMMOWebLinks;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@ -27,17 +26,18 @@ public class TextComponentFactory {
* Makes a text component using strings from a locale and supports passing an undefined number of variables to the LocaleLoader
*
* @param localeKey target locale string address
* @param notificationType type of notification
* @param values vars to be passed to the locale loader
* @return
*/
public static TextComponent getNotificationMultipleValues(String localeKey, NotificationType notificationType, String... values) {
public static TextComponent getNotificationMultipleValues(String localeKey, String... values)
{
String preColoredString = LocaleLoader.getString(localeKey, (Object[]) values);
TextComponent msg = new TextComponent(preColoredString);
return new TextComponent(msg);
}
public static TextComponent getNotificationTextComponentFromLocale(String localeKey, NotificationType notificationType) {
public static TextComponent getNotificationTextComponentFromLocale(String localeKey)
{
return getNotificationTextComponent(LocaleLoader.getString(localeKey));
}

View File

@ -37,7 +37,7 @@ public class NotificationManager {
ChatMessageType destination = AdvancedConfig.getInstance().doesNotificationUseActionBar(notificationType) ? ChatMessageType.ACTION_BAR : ChatMessageType.SYSTEM;
TextComponent message = TextComponentFactory.getNotificationTextComponentFromLocale(key, notificationType);
TextComponent message = TextComponentFactory.getNotificationTextComponentFromLocale(key);
McMMOPlayerNotificationEvent customEvent = checkNotificationEvent(player, notificationType, destination, message);
sendNotification(player, customEvent);
@ -65,13 +65,23 @@ public class NotificationManager {
sendPlayerInformation(targetPlayer, notificationType, key, values);
}
public static void sendPlayerInformation(Player player, NotificationType notificationType, String key, String... values) {
public static void sendPlayerInformationChatOnly(Player player, String key, String... values)
{
if(UserManager.getPlayer(player) == null || !UserManager.getPlayer(player).useChatNotifications())
return;
String preColoredString = LocaleLoader.getString(key, (Object[]) values);
player.sendMessage(preColoredString);
}
public static void sendPlayerInformation(Player player, NotificationType notificationType, String key, String... values)
{
if(UserManager.getPlayer(player) == null || !UserManager.getPlayer(player).useChatNotifications())
return;
ChatMessageType destination = AdvancedConfig.getInstance().doesNotificationUseActionBar(notificationType) ? ChatMessageType.ACTION_BAR : ChatMessageType.SYSTEM;
TextComponent message = TextComponentFactory.getNotificationMultipleValues(key, notificationType, values);
TextComponent message = TextComponentFactory.getNotificationMultipleValues(key, values);
McMMOPlayerNotificationEvent customEvent = checkNotificationEvent(player, notificationType, destination, message);
sendNotification(player, customEvent);

View File

@ -68,6 +68,9 @@ public final class UserManager {
* Save all users ON THIS THREAD.
*/
public static void saveAll() {
if(playerDataSet == null)
return;
ImmutableList<McMMOPlayer> trackedSyncData = ImmutableList.copyOf(playerDataSet);
mcMMO.p.getLogger().info("Saving mcMMOPlayers... (" + trackedSyncData.size() + ")");

View File

@ -397,4 +397,10 @@ public class RankUtils {
return mcMMO.getConfigManager().getConfigLeveling().getLevelCap(subSkillType.getParentSkill());
}
public static boolean isPlayerMaxRankInSubSkill(Player player, SubSkillType subSkillType) {
int playerRank = getRank(player, subSkillType);
int highestRank = getHighestRank(subSkillType);
return playerRank == highestRank;
}
}

View File

@ -13,6 +13,7 @@ import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.player.NotificationManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
@ -24,6 +25,7 @@ import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SkillUtils {
@ -268,36 +270,36 @@ public class SkillUtils {
}
public static int getRepairAndSalvageQuantities(ItemStack item) {
return getRepairAndSalvageQuantities(item, getRepairAndSalvageItem(item), (byte) -1);
return getRepairAndSalvageQuantities(item.getType(), getRepairAndSalvageItem(item));
}
public static int getRepairAndSalvageQuantities(ItemStack item, Material repairMaterial, byte repairMetadata) {
// Workaround for Bukkit bug where damaged items would not return any recipes
item = item.clone();
item.setDurability((short) 0);
public static int getRepairAndSalvageQuantities(Material itemMaterial, Material recipeMaterial) {
int quantity = 0;
List<Recipe> recipes = mcMMO.p.getServer().getRecipesFor(item);
if (recipes.isEmpty()) {
return quantity;
}
for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
Recipe bukkitRecipe = recipeIterator.next();
Recipe recipe = recipes.get(0);
if(bukkitRecipe.getResult().getType() != itemMaterial)
continue;
if (recipe instanceof ShapelessRecipe) {
for (ItemStack ingredient : ((ShapelessRecipe) recipe).getIngredientList()) {
if (ingredient != null && (repairMaterial == null || ingredient.getType() == repairMaterial) && (repairMetadata == -1 || ingredient.getType().equals(repairMaterial))) {
if(bukkitRecipe instanceof ShapelessRecipe) {
for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
if (ingredient != null
&& (recipeMaterial == null || ingredient.getType() == recipeMaterial)
&& (ingredient.getType() == recipeMaterial)) {
quantity += ingredient.getAmount();
}
}
} else if (recipe instanceof ShapedRecipe) {
for (ItemStack ingredient : ((ShapedRecipe) recipe).getIngredientMap().values()) {
if (ingredient != null && (repairMaterial == null || ingredient.getType() == repairMaterial) && (repairMetadata == -1 || ingredient.getType().equals(repairMaterial))) {
} else if(bukkitRecipe instanceof ShapedRecipe) {
for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
if (ingredient != null
&& (recipeMaterial == null || ingredient.getType() == recipeMaterial)
&& (ingredient.getType() == recipeMaterial)) {
quantity += ingredient.getAmount();
}
}
}
}
return quantity;
}

View File

@ -51,6 +51,8 @@ JSON.Notification.SuperAbility={0}
#These are the JSON Strings used for SubSkills
JSON.Acrobatics.Roll.Interaction.Activated=Test [[RED]]Rolled Test
JSON.Acrobatics.SubSkill.Roll.Details.Tips=If you hold sneak while falling you can prevent up to twice the damage that you would normally take!
Anvil.SingleItemStack=[[RED]]You cannot salvage or repair item stacks that have more than one item, split the stack first.
#DO NOT USE COLOR CODES IN THE JSON KEYS
#COLORS ARE DEFINED IN advanced.yml IF YOU WISH TO CHANGE THEM
# BEGIN STYLING
@ -368,14 +370,14 @@ Repair.Arcane.Perfect=[[GREEN]]You have sustained the arcane energies in this it
Salvage.Pretty.Name=Salvage
Salvage.SubSkill.UnderstandingTheArt.Name=Understanding The Art
Salvage.SubSkill.UnderstandingTheArt.Description=You're not just digging through your neighbors trash, you're taking care of the environment.\nPowers up various properties of Salvaging.
Salvage.SubSkill.AdvancedSalvage.Name=Advanced Salvage
Salvage.SubSkill.AdvancedSalvage.Description=Salvage damaged items
Salvage.SubSkill.ScrapCollector.Name=Scrap Collector
Salvage.SubSkill.ScrapCollector.Description=Salvage materials from an item, a perfect salvage depends on skill and luck.
Salvage.SubSkill.ScrapCollector.Stat=Scrap Collector: [[GREEN]]Salvage up to [[YELLOW]]{0}[[GREEN]] items. Some luck is involved.
Salvage.SubSkill.ArcaneSalvage.Name=Arcane Salvaging
Salvage.SubSkill.ArcaneSalvage.Description=Extract enchantments from items
Salvage.SubSkill.ArcaneSalvage.Stat=Arcane Salvaging: [[YELLOW]]Rank {0}/{1}
Salvage.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (ADVANCED SALVAGE)
Salvage.Ability.Bonus.0=Advanced Salvage
Salvage.Ability.Bonus.1={0} Max Materials Recovered from Salvaging
Salvage.Ability.Bonus.0=Scrap Collector
Salvage.Ability.Bonus.1=Salvage up to [[YELLOW]]{0}[[GREEN]] items. Some luck is involved.
Salvage.Arcane.ExtractFull=[[GRAY]]AS Full-Enchant Chance
Salvage.Arcane.ExtractPartial=[[GRAY]]AS Partial-Enchant Chance
Salvage.Skills.Success=[[GREEN]]Item salvaged!
@ -388,6 +390,9 @@ Salvage.Skills.ArcaneSuccess=[[GREEN]]You able to extract all of the knowledge c
Salvage.Listener.Anvil=[[DARK_RED]]You have placed a Salvage anvil, use this to Salvage tools and armor.
Salvage.Listener=Salvage:
Salvage.SkillName=SALVAGE
Salvage.Skills.Lottery.Normal=[[GOLD]]You were able to salvage [[GREEN]]{0}[[GOLD]] materials from [[DARK_AQUA]]{1}[[GOLD]].
Salvage.Skills.Lottery.Perfect=[[GREEN]][[BOLD]]Perfect![[RESET]][[GOLD]] You salvaged [[GREEN]]{1}[[GOLD]] effortlessly, retrieving [[DARK_AQUA]]{0}[[GOLD]] materials.
Salvage.Skills.Lottery.Untrained=[[GRAY]]You aren't properly trained in salvaging. You were only able to recover [[RED]]{0}[[GRAY]] materials from [[GREEN]]{1}[[GRAY]].
#Anvil (Shared between SALVAGE and REPAIR)
Anvil.Unbreakable=This item is unbreakable!
#SWORDS

View File

@ -51,6 +51,8 @@ JSON.Notification.SuperAbility={0}
#These are the JSON Strings used for SubSkills
JSON.Acrobatics.Roll.Interaction.Activated=\u6d4b\u8bd5 [[RED]]\u7ffb\u6eda\u6d4b\u8bd5
JSON.Acrobatics.SubSkill.Roll.Details.Tips=\u5982\u679c\u4f60\u5728\u6454\u843d\u65f6\u6309\u4e0b\u6f5c\u884c\u952e,\u4f60\u5c06\u89e6\u53d1\u4e24\u500d\u7ffb\u6eda\u6548\u679c
Anvil.SingleItemStack=[[RED]]\u4f60\u4e0d\u80fd\u5206\u89e3\u8d27\u4fee\u590d\u6709\u591a\u4e2a\u7269\u54c1\u7684\u7269\u54c1\u5806, \u8bf7\u62c6\u5206\u540e\u518d\u4f7f\u7528.
#DO NOT USE COLOR CODES IN THE JSON KEYS
#COLORS ARE DEFINED IN advanced.yml IF YOU WISH TO CHANGE THEM
# BEGIN STYLING
@ -98,6 +100,8 @@ Commands.Party.Header=[[RED]]-----[][[GREEN]]\u961f\u4f0d[[RED]][]-----
Commands.Party.Features.Header=[[RED]]-----[][[GREEN]]FEATURES[[RED]][]-----
# XP BAR Allows for the following variables -- {0} = Skill Level, {1} Current XP, {2} XP Needed for next level, {3} Power Level, {4} Percentage of Level
# Make sure you turn on Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained if you want the XP bar title to update every time a player gains XP!
XPBar.Template={0}
XPBar.Template.EarlyGameBoost=[[GOLD]]\u6b63\u5728\u5b66\u4e60\u65b0\u6280\u80fd...
XPBar.Acrobatics=\u6742\u6280 Lv.[[GOLD]]{0}
XPBar.Alchemy=\u70bc\u91d1 Lv.[[GOLD]]{0}
XPBar.Archery=\u7bad\u672f Lv.[[GOLD]]{0}
@ -817,6 +821,18 @@ Commands.Event.Stop=[[GREEN]]mcMMO[[DARK_AQUA]] \u4e8b\u4ef6\u7ed3\u675f!
Commands.Event.Stop.Subtitle=[[GREEN]]\u6211\u5e0c\u671b\u4f60\u73a9\u7684\u5f00\u5fc3!
Commands.Event.XP=[[DARK_AQUA]]\u591a\u500d\u7ecf\u9a8c\u901f\u7387\u4e3a [[GOLD]]{0}[[DARK_AQUA]] \u500d
XPRate.Event=[[GOLD]]mcMMO \u73b0\u5728\u6b63\u5904\u4e8e\u591a\u500d\u7ecf\u9a8c\u4e8b\u4ef6\u9636\u6bb5! \u7ecf\u9a8c\u83b7\u53d6\u7387\u4e3a {0}\u500d!
# Admin Notifications
Server.ConsoleName=[[YELLOW]][Server]
Notifications.Admin.XPRate.Start.Self=[[GRAY]]\u4f60\u5df2\u5c06\u5168\u5c40\u591a\u500d\u7ecf\u9a8c\u8bbe\u7f6e\u4e3a [[GOLD]]{0} \u500d
Notifications.Admin.XPRate.End.Self=[[GRAY]]\u4f60\u7ed3\u675f\u4e86\u591a\u500d\u7ecf\u9a8c\u4e8b\u4ef6.
Notifications.Admin.XPRate.End.Others={0} [[GRAY]]\u7ed3\u675f\u4e86\u591a\u500d\u7ecf\u9a8c\u4e8b\u4ef6
Notifications.Admin.XPRate.Start.Others={0} [[GRAY]]\u5df2\u542f\u52a8\u6216\u4fee\u6539\u5177\u6709\u5168\u5c40 {1} \u500d\u7684\u591a\u500d\u7ecf\u9a8c\u4e8b\u4ef6
Notifications.Admin.Format.Others=[[GOLD]]([[GREEN]]mcMMO [[DARK_AQUA]]Admin[[GOLD]]) [[GRAY]]{0}
Notifications.Admin.Format.Self=[[GOLD]]([[GREEN]]mcMMO[[GOLD]]) [[GRAY]]{0}
# Event
#GUIDES
Guides.Available=[[GRAY]]{0} \u7684\u5411\u5bfc - \u8f93\u5165 /{1} ? [\u9875\u6570]
Guides.Header=[[GOLD]]-=[[GREEN]]{0} \u5411\u5bfc[[GOLD]]=-

View File

@ -30,7 +30,7 @@
#
# MinimumQuantity: This is the minimum number of items needed to repair this item ignoring all other repair bonuses.
## This is typically the number of the repair material needed to create a new item, for example for a sword it is 2, for an axe it is 3
## This defaults to 2
## If this isn't set, mcMMO will try to look up the minimum quantity for the item via recipes. It is not necessary to define this field.
#
# XpMultiplier: This is the amount to multiply the xp bonus by.
## This defaults to 1

View File

@ -282,11 +282,25 @@ Smelting:
Rank_7: 850
Rank_8: 1000
Salvage:
AdvancedSalvage:
ScrapCollector:
Standard:
Rank_1: 35
Rank_1: 2
Rank_2: 10
Rank_3: 15
Rank_4: 20
Rank_5: 25
Rank_6: 30
Rank_7: 35
Rank_8: 40
RetroMode:
Rank_1: 350
Rank_1: 20
Rank_2: 100
Rank_3: 150
Rank_4: 200
Rank_5: 250
Rank_6: 300
Rank_7: 350
Rank_8: 400
ArcaneSalvage:
Standard:
Rank_1: 10