diff --git a/Changelog.txt b/Changelog.txt index 74d437ad3..21f85e0bc 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -151,6 +151,41 @@ 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.62 + Added a new admin notification system, sensitive commands will print chat messages to "admins" (players with either Operator status or admin chat permission) + Added a setting to disable the new admin notifications to config.yml 'General.AdminNotifications' (this will be more configurable in 2.2) + OPs and players with the admin chat permission will now see details about XP rate event commands regardless of whether or not the XP rate event messages are enabled + Updated hu_HU locale (thanks andris155) + Added XP for mining Magma_Block (default 30 XP - Update your config, see notes) + Diamond tools & armor in the repair config now have a minimum level of 0 (Update your config, temporary hotfix, 2.2 addresses this issue, see notes) + Guardian default combat XP multiplier reduced from 3.0 to 1.0 (update config if you want this change) + New locale string - 'Server.ConsoleName' the name of the server console, this will be used in place of player names when sending admin notifications out if the command was used from console + New locale string - 'Notifications.Admin.Format.Others' style formatting + prefix for admin notifications used in the other new strings below + New locale string - 'Notifications.Admin.Format.Self' style formatting + prefix for admin command confirmations sent to the user who executed the command + New locale string - 'Notifications.Admin.XPRate.Start.Self' sent to the user who modifies the XP rate regardless of whether or not messages for the event are enabled + New locale string - 'Notifications.Admin.XPRate.Start.Others' details of who started an XP rate event are sent to players who have Operator status or admin chat permission when the command to start or modify XP of an event has been issued + New locale string - 'Notifications.Admin.XPRate.End.Self' sent to the user who ended the XP rate event regardless of whether or not messages for the event are enabled + New locale string - 'Notifications.Admin.XPRate.End.Others' details of who ended an XP rate event are sent to players who have Operator status or admin chat permission when the command to end the event has been issued + + NOTES: + Admin notifications currently only reports use of the XP rate command, it will be expanded to support other commands in upcoming patches + Add an entry of 'Magma_Block: 30' under Mining in experience.yml section titled "Experience_Values" (or you can delete the file to generate a new one with default values, 2.2 is coming soon which will have brand new configs so you could just wait for that + 2.2 is the config rewrite, in this rewrite Repair and Salvage configs have been partially rewritten, it is not intended for Diamond Repair to take until level 50 in Standard level scaling to be available, since it'd be redundant to fix this in 2.1.X when 2.2 fixes it and its about to come out, the minimum level has temporarily been changed to 0. You can either update your repair.vanilla.yml config manually or delete it to generate a new one. + + Admin notifications are a step in the right direction for finding naughty admins in mcMMO, I will be changing which permission node is used for players to be considered an admin in the future as not everyone wants or uses admin chat. + I expect to add logging of admin commands which will be viewable in game via command, so you won't have to have access to the servers log files to view who has been executing what. + +Version 2.1.61 + Fixed the locale string formatting of 'Mining.SubSkill.DoubleDrops.Stat' + Updated the Japanese locale (thanks snake0053) + Added toggle to turn off event message broadcasts (XP rate) to config.yml - 'General.EventBroadcasts' + Added toggle to not inform players of events when they join (XP rate, etc) to config.yml 'General.EventInfoOnPlayerJoin' + Added anti-exploit protection for cobble/stone farms which can be automated, to turn this off you can toggle the new config options 'ExploitFix.LavaStoneAndCobbleFarming' in experience.yml + + NOTE: The toggle for event message broadcasts is separate from the titles being shown, that's another config option (titles are the BIG TEXT in the middle of the screen) + NOTE: The new anti-stone/cobble automation will not prevent XP gains from obsidian, since Obsidian requires some effort to farm + Version 2.1.60 Fixed a NPE error if a LivingEntity's target was set to null Fixed a bug where tamed mobs could kill themselves if their owner shot them once diff --git a/src/main/java/com/gmail/nossr50/commands/XprateCommand.java b/src/main/java/com/gmail/nossr50/commands/XprateCommand.java index f36ca3e56..503ac5526 100644 --- a/src/main/java/com/gmail/nossr50/commands/XprateCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/XprateCommand.java @@ -1,6 +1,8 @@ package com.gmail.nossr50.commands; import com.gmail.nossr50.config.AdvancedConfig; +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.datatypes.notifications.SensitiveCommandType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.Permissions; @@ -42,8 +44,14 @@ public class XprateCommand implements TabExecutor { 10, 10 * 20, 20); } - mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop")); - mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop.Subtitle")); + if(Config.getInstance().broadcastEventMessages()) + { + mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop")); + mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop.Subtitle")); + } + + //Admin notification + NotificationManager.processSensitiveCommandNotification(sender, SensitiveCommandType.XPRATE_END); mcMMO.p.toggleXpEventEnabled(); } @@ -78,19 +86,23 @@ public class XprateCommand implements TabExecutor { mcMMO.getDynamicSettingsManager().getExperienceManager().setGlobalXpMult(newXpRate); - if (mcMMO.p.isXPEventEnabled()) { - if (AdvancedConfig.getInstance().useTitlesForXPEvent()) { - NotificationManager.broadcastTitle(mcMMO.p.getServer(), - LocaleLoader.getString("Commands.Event.Start"), - LocaleLoader.getString("Commands.Event.XP", newXpRate), - 10, 10 * 20, 20); - } + if(AdvancedConfig.getInstance().useTitlesForXPEvent()) + { + NotificationManager.broadcastTitle(mcMMO.p.getServer(), + LocaleLoader.getString("Commands.Event.Start"), + LocaleLoader.getString("Commands.Event.XP", newXpRate), + 10, 10*20, 20); + } + + if(Config.getInstance().broadcastEventMessages()) + { mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Start")); mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.XP", newXpRate)); - } else { - sender.sendMessage(LocaleLoader.getString("Commands.xprate.modified", newXpRate)); } + //Admin notification + NotificationManager.processSensitiveCommandNotification(sender, SensitiveCommandType.XPRATE_MODIFY, String.valueOf(newXpRate)); + return true; default: diff --git a/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java index 09299ca3e..636a48307 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java @@ -11,6 +11,7 @@ import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.StringUtils; import com.gmail.nossr50.util.TextComponentFactory; import com.gmail.nossr50.util.commands.CommandUtils; +import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.random.RandomChanceUtil; import com.gmail.nossr50.util.scoreboards.ScoreboardManager; @@ -264,7 +265,7 @@ public abstract class SkillCommand implements TabExecutor { if (isCustom) return LocaleLoader.getString(templateKey, LocaleLoader.getString(statDescriptionKey, vars)); else { - String[] mergedList = addItemToFirstPositionOfArray(LocaleLoader.getString(statDescriptionKey), vars); + String[] mergedList = NotificationManager.addItemToFirstPositionOfArray(LocaleLoader.getString(statDescriptionKey), vars); return LocaleLoader.getString(templateKey, mergedList); } } diff --git a/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java new file mode 100644 index 000000000..3f134cf66 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java @@ -0,0 +1,337 @@ +package com.gmail.nossr50.config.experience; + +import com.gmail.nossr50.config.AutoUpdateConfigLoader; +import com.gmail.nossr50.datatypes.experience.FormulaType; +import com.gmail.nossr50.datatypes.skills.MaterialType; +import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.datatypes.skills.alchemy.PotionStage; +import com.gmail.nossr50.util.StringUtils; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.entity.EntityType; + +import java.util.ArrayList; +import java.util.List; + +public class ExperienceConfig extends AutoUpdateConfigLoader { + private static ExperienceConfig instance; + + private ExperienceConfig() { + super("experience.yml"); + validate(); + } + + public static ExperienceConfig getInstance() { + if (instance == null) { + instance = new ExperienceConfig(); + } + + return instance; + } + + @Override + protected void loadKeys() {} + + @Override + protected boolean validateKeys() { + List reason = new ArrayList(); + + /* + * FORMULA SETTINGS + */ + + /* Curve values */ + if (getMultiplier(FormulaType.EXPONENTIAL) <= 0) { + reason.add("Experience_Formula.Exponential_Values.multiplier should be greater than 0!"); + } + + if (getMultiplier(FormulaType.LINEAR) <= 0) { + reason.add("Experience_Formula.Linear_Values.multiplier should be greater than 0!"); + } + + if (getExponent(FormulaType.EXPONENTIAL) <= 0) { + reason.add("Experience_Formula.Exponential_Values.exponent should be greater than 0!"); + } + + /* Global modifier */ + if (getExperienceGainsGlobalMultiplier() <= 0) { + reason.add("Experience_Formula.Multiplier.Global should be greater than 0!"); + } + + /* PVP modifier */ + if (getPlayerVersusPlayerXP() < 0) { + reason.add("Experience_Formula.Multiplier.PVP should be at least 0!"); + } + + /* Spawned Mob modifier */ + if (getSpawnedMobXpMultiplier() < 0) { + reason.add("Experience_Formula.Mobspawners.Multiplier should be at least 0!"); + } + + /* Bred Mob modifier */ + if (getBredMobXpMultiplier() < 0) { + reason.add("Experience_Formula.Breeding.Multiplier should be at least 0!"); + } + + /* Conversion */ + if (getExpModifier() <= 0) { + reason.add("Conversion.Exp_Modifier should be greater than 0!"); + } + + /* + * XP SETTINGS + */ + + /* Alchemy */ + for (PotionStage potionStage : PotionStage.values()) { + if (getPotionXP(potionStage) < 0) { + reason.add("Experience_Values.Alchemy.Potion_Stage_" + potionStage.toNumerical() + " should be at least 0!"); + } + } + + /* Archery */ + if (getArcheryDistanceMultiplier() < 0) { + reason.add("Experience_Values.Archery.Distance_Multiplier should be at least 0!"); + } + + /* Combat XP Multipliers */ + if (getAnimalsXP() < 0) { + reason.add("Experience_Values.Combat.Multiplier.Animals should be at least 0!"); + } + + if (getDodgeXPModifier() < 0) { + reason.add("Skills.Acrobatics.Dodge_XP_Modifier should be at least 0!"); + } + + if (getRollXPModifier() < 0) { + reason.add("Skills.Acrobatics.Roll_XP_Modifier should be at least 0!"); + } + + if (getFallXPModifier() < 0) { + reason.add("Skills.Acrobatics.Fall_XP_Modifier should be at least 0!"); + } + + /* Fishing */ + // TODO: Add validation for each fish type once enum is available. + + if (getFishingShakeXP() <= 0) { + reason.add("Experience_Values.Fishing.Shake should be greater than 0!"); + } + + /* Repair */ + if (getRepairXPBase() <= 0) { + reason.add("Experience_Values.Repair.Base should be greater than 0!"); + } + + /* Taming */ + if (getTamingXP(EntityType.WOLF) <= 0) { + reason.add("Experience_Values.Taming.Animal_Taming.Wolf should be greater than 0!"); + } + + if (getTamingXP(EntityType.OCELOT) <= 0) { + reason.add("Experience_Values.Taming.Animal_Taming.Ocelot should be greater than 0!"); + } + + return noErrorsInConfig(reason); + } + + public boolean isEarlyGameBoostEnabled() { return config.getBoolean("EarlyGameBoost.Enabled", true); } + public double getEarlyGameBoostMultiplier() { return config.getDouble("EarlyGameBoost.MaxLevelMultiplier", 0.05D); } + + /* + * FORMULA SETTINGS + */ + + /* EXPLOIT TOGGLES */ + public boolean isEndermanEndermiteFarmingPrevented() { return config.getBoolean("ExploitFix.EndermanEndermiteFarms", true); } + public boolean isPistonExploitPrevented() { return config.getBoolean("ExploitFix.Pistons", false); } + + public boolean isFishingExploitingPrevented() { return config.getBoolean("ExploitFix.Fishing", true); } + public boolean isAcrobaticsExploitingPrevented() { return config.getBoolean("ExploitFix.Acrobatics", true); } + + /* Curve settings */ + public FormulaType getFormulaType() { return FormulaType.getFormulaType(config.getString("Experience_Formula.Curve")); } + public boolean getCumulativeCurveEnabled() { return config.getBoolean("Experience_Formula.Cumulative_Curve", false); } + + /* Curve values */ + public double getMultiplier(FormulaType type) { return config.getDouble("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.multiplier"); } + public int getBase(FormulaType type) { return config.getInt("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.base"); } + public double getExponent(FormulaType type) { return config.getDouble("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.exponent"); } + + /* Global modifier */ + public double getExperienceGainsGlobalMultiplier() { return config.getDouble("Experience_Formula.Multiplier.Global", 1.0); } + public void setExperienceGainsGlobalMultiplier(double value) { config.set("Experience_Formula.Multiplier.Global", value); } + + /* PVP modifier */ + public double getPlayerVersusPlayerXP() { return config.getDouble("Experience_Formula.Multiplier.PVP", 1.0); } + + /* Spawned Mob modifier */ + public double getSpawnedMobXpMultiplier() { return config.getDouble("Experience_Formula.Mobspawners.Multiplier", 0.0); } + public double getBredMobXpMultiplier() { return config.getDouble("Experience_Formula.Breeding.Multiplier", 1.0); } + + /* Skill modifiers */ + public double getFormulaSkillModifier(PrimarySkillType skill) { return config.getDouble("Experience_Formula.Modifier." + StringUtils.getCapitalized(skill.toString())); } + + /* Custom XP perk */ + public double getCustomXpPerkBoost() { return config.getDouble("Experience_Formula.Custom_XP_Perk.Boost", 1.25); } + + /* Diminished Returns */ + public float getDiminishedReturnsCap() { return (float) config.getDouble("Dimished_Returns.Guaranteed_Minimum_Percentage", 0.05D); } + public boolean getDiminishedReturnsEnabled() { return config.getBoolean("Diminished_Returns.Enabled", false); } + public int getDiminishedReturnsThreshold(PrimarySkillType skill) { return config.getInt("Diminished_Returns.Threshold." + StringUtils.getCapitalized(skill.toString()), 20000); } + public int getDiminishedReturnsTimeInterval() { return config.getInt("Diminished_Returns.Time_Interval", 10); } + + /* Conversion */ + public double getExpModifier() { return config.getDouble("Conversion.Exp_Modifier", 1); } + + /* + * XP SETTINGS + */ + + /* General Settings */ + public boolean getExperienceGainsPlayerVersusPlayerEnabled() { return config.getBoolean("Experience_Values.PVP.Rewards", true); } + + /* Combat XP Multipliers */ + public double getCombatXP(EntityType entity) { return config.getDouble("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); } + public double getAnimalsXP(EntityType entity) { return config.getDouble("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"), getAnimalsXP()); } + public double getAnimalsXP() { return config.getDouble("Experience_Values.Combat.Multiplier.Animals", 1.0); } + public boolean hasCombatXP(EntityType entity) {return config.contains("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); } + + /* Materials */ + public int getXp(PrimarySkillType skill, Material data) + { + String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; + String explicitString = baseString + StringUtils.getExplicitConfigMaterialString(data); + if (config.contains(explicitString)) + return config.getInt(explicitString); + String friendlyString = baseString + StringUtils.getFriendlyConfigMaterialString(data); + if (config.contains(friendlyString)) + return config.getInt(friendlyString); + String wildcardString = baseString + StringUtils.getWildcardConfigMaterialString(data); + if (config.contains(wildcardString)) + return config.getInt(wildcardString); + return 0; + } + + /* Materials */ + public int getXp(PrimarySkillType skill, BlockData data) + { + String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; + String explicitString = baseString + StringUtils.getExplicitConfigBlockDataString(data); + if (config.contains(explicitString)) + return config.getInt(explicitString); + String friendlyString = baseString + StringUtils.getFriendlyConfigBlockDataString(data); + if (config.contains(friendlyString)) + return config.getInt(friendlyString); + String wildcardString = baseString + StringUtils.getWildcardConfigBlockDataString(data); + if (config.contains(wildcardString)) + return config.getInt(wildcardString); + return 0; + } + + public boolean doesBlockGiveSkillXP(PrimarySkillType skill, Material data) + { + String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; + String explicitString = baseString + StringUtils.getExplicitConfigMaterialString(data); + if (config.contains(explicitString)) + return true; + String friendlyString = baseString + StringUtils.getFriendlyConfigMaterialString(data); + if (config.contains(friendlyString)) + return true; + String wildcardString = baseString + StringUtils.getWildcardConfigMaterialString(data); + return config.contains(wildcardString); + } + + public boolean doesBlockGiveSkillXP(PrimarySkillType skill, BlockData data) + { + String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + "."; + String explicitString = baseString + StringUtils.getExplicitConfigBlockDataString(data); + if (config.contains(explicitString)) + return true; + String friendlyString = baseString + StringUtils.getFriendlyConfigBlockDataString(data); + if (config.contains(friendlyString)) + return true; + String wildcardString = baseString + StringUtils.getWildcardConfigBlockDataString(data); + return config.contains(wildcardString); + } + + /* + * Experience Bar Stuff + */ + + public boolean isPartyExperienceBarsEnabled() + { + return config.getBoolean("Experience_Bars.Update.Party", true); + } + + public boolean isPassiveGainsExperienceBarsEnabled() + { + return config.getBoolean("Experience_Bars.Update.Passive", true); + } + + public boolean getDoExperienceBarsAlwaysUpdateTitle() + { + return config.getBoolean("Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained.Enable", false) || getAddExtraDetails(); + } + + public boolean getAddExtraDetails() { return config.getBoolean("Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained.ExtraDetails", false);} + public boolean isExperienceBarsEnabled() { return config.getBoolean("Experience_Bars.Enable", true); } + public boolean isExperienceBarEnabled(PrimarySkillType primarySkillType) { return config.getBoolean("Experience_Bars."+StringUtils.getCapitalized(primarySkillType.toString())+".Enable", true);} + + public BarColor getExperienceBarColor(PrimarySkillType primarySkillType) + { + String colorValueFromConfig = config.getString("Experience_Bars."+StringUtils.getCapitalized(primarySkillType.toString())+".Color"); + + for(BarColor barColor : BarColor.values()) + { + if(barColor.toString().equalsIgnoreCase(colorValueFromConfig)) + return barColor; + } + + //In case the value is invalid + return BarColor.WHITE; + } + + public BarStyle getExperienceBarStyle(PrimarySkillType primarySkillType) + { + String colorValueFromConfig = config.getString("Experience_Bars."+StringUtils.getCapitalized(primarySkillType.toString())+".BarStyle"); + + for(BarStyle barStyle : BarStyle.values()) + { + if(barStyle.toString().equalsIgnoreCase(colorValueFromConfig)) + return barStyle; + } + + //In case the value is invalid + return BarStyle.SOLID; + } + + /* Acrobatics */ + public int getDodgeXPModifier() { return config.getInt("Experience_Values.Acrobatics.Dodge", 120); } + public int getRollXPModifier() { return config.getInt("Experience_Values.Acrobatics.Roll", 80); } + public int getFallXPModifier() { return config.getInt("Experience_Values.Acrobatics.Fall", 120); } + + public double getFeatherFallXPModifier() { return config.getDouble("Experience_Values.Acrobatics.FeatherFall_Multiplier", 2.0); } + + /* Alchemy */ + public double getPotionXP(PotionStage stage) { return config.getDouble("Experience_Values.Alchemy.Potion_Stage_" + stage.toNumerical(), 10D); } + + /* Archery */ + public double getArcheryDistanceMultiplier() { return config.getDouble("Experience_Values.Archery.Distance_Multiplier", 0.025); } + + public int getFishingShakeXP() { return config.getInt("Experience_Values.Fishing.Shake", 50); } + + /* Repair */ + public double getRepairXPBase() { return config.getDouble("Experience_Values.Repair.Base", 1000.0); } + public double getRepairXP(MaterialType repairMaterialType) { return config.getDouble("Experience_Values.Repair." + StringUtils.getCapitalized(repairMaterialType.toString())); } + + /* Taming */ + public int getTamingXP(EntityType type) + { + return config.getInt("Experience_Values.Taming.Animal_Taming." + StringUtils.getPrettyEntityTypeString(type)); + } + + public boolean preventStoneLavaFarming() { return config.getBoolean("ExploitFix.LavaStoneAndCobbleFarming", true);} +} diff --git a/src/main/java/com/gmail/nossr50/datatypes/notifications/SensitiveCommandType.java b/src/main/java/com/gmail/nossr50/datatypes/notifications/SensitiveCommandType.java new file mode 100644 index 000000000..0e59757c8 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/datatypes/notifications/SensitiveCommandType.java @@ -0,0 +1,7 @@ +package com.gmail.nossr50.datatypes.notifications; + +public enum SensitiveCommandType { + XPRATE_MODIFY, + XPRATE_END, + MMOEDIT +} diff --git a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java index a2462b266..c900727ce 100644 --- a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java @@ -2,6 +2,7 @@ package com.gmail.nossr50.listeners; import com.gmail.nossr50.config.MainConfig; import com.gmail.nossr50.config.WorldBlacklist; +import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.core.MetadataConstants; import com.gmail.nossr50.datatypes.meta.BonusDropMeta; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -165,6 +166,22 @@ public class BlockListener implements Listener { } } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockFormEvent(BlockFormEvent event) + { + /* WORLD BLACKLIST CHECK */ + if(WorldBlacklist.isWorldBlacklisted(event.getBlock().getWorld())) + return; + + if(ExperienceConfig.getInstance().preventStoneLavaFarming()) + { + if(event.getNewState().getType() != Material.OBSIDIAN && BlockUtils.shouldBeWatched(event.getNewState())) + { + mcMMO.getPlaceStore().setTrue(event.getNewState()); + } + } + } + /** * Monitor BlockPlace events. * diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index 6a0399279..600f98b1d 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -5,6 +5,7 @@ import com.gmail.nossr50.chat.ChatManagerFactory; import com.gmail.nossr50.chat.PartyChatManager; import com.gmail.nossr50.config.MainConfig; import com.gmail.nossr50.config.WorldBlacklist; +import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.core.MetadataConstants; import com.gmail.nossr50.datatypes.chat.ChatMode; import com.gmail.nossr50.datatypes.party.Party; @@ -48,6 +49,7 @@ import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.*; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import sun.security.krb5.Config; public class PlayerListener implements Listener { private final mcMMO plugin; @@ -527,6 +529,10 @@ public class PlayerListener implements Listener { if (mcMMO.p.getDescription().getVersion().contains("SNAPSHOT")) { event.getPlayer().sendMessage(ChatColor.RED + "WARNING: " + ChatColor.WHITE + "This dev build version of mcMMO is in the MIDDLE of completely rewriting the configs, there may be game breaking bugs. It is not recommended to play on this version of mcMMO, please grab the latest stable release from https://www.mcmmo.org and use that instead!"); } + + if (plugin.isXPEventEnabled() && Config.getInstance().playerJoinEventInfo()) { + player.sendMessage(LocaleLoader.getString("XPRate.Event", ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier())); + } } /** diff --git a/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java b/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java index 50a45fd75..81752b285 100644 --- a/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java +++ b/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java @@ -1,21 +1,24 @@ package com.gmail.nossr50.util.player; import com.gmail.nossr50.config.AdvancedConfig; +import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.interactions.NotificationType; +import com.gmail.nossr50.datatypes.notifications.SensitiveCommandType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.events.skills.McMMOPlayerNotificationEvent; +import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.Misc; +import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.TextComponentFactory; import com.gmail.nossr50.util.sounds.SoundManager; import com.gmail.nossr50.util.sounds.SoundType; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Server; -import org.bukkit.SoundCategory; +import org.bukkit.*; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; public class NotificationManager { @@ -147,4 +150,82 @@ public class NotificationManager { String.valueOf(RankUtils.getRank(mcMMOPlayer.getPlayer(), subSkillType)))));*/ } + + /** + * Sends a message to all admins with the admin notification formatting from the locale + * Admins are currently players with either Operator status or Admin Chat permission + * @param msg message fetched from locale + */ + private static void sendAdminNotification(String msg) { + //If its not enabled exit + if(!Config.getInstance().adminNotifications()) + return; + + for(Player player : Bukkit.getServer().getOnlinePlayers()) + { + if(player.isOp() || Permissions.adminChat(player)) + { + player.sendMessage(LocaleLoader.getString("Notifications.Admin.Format.Others", msg)); + } + } + + //Copy it out to Console too + mcMMO.p.getLogger().info(LocaleLoader.getString("Notifications.Admin.Format.Others", msg)); + } + + /** + * Sends a confirmation message to the CommandSender who just executed an admin command + * @param commandSender target command sender + * @param msg message fetched from locale + */ + private static void sendAdminCommandConfirmation(CommandSender commandSender, String msg) { + commandSender.sendMessage(LocaleLoader.getString("Notifications.Admin.Format.Self", msg)); + } + + /** + * Convenience method to report info about a command sender using a sensitive command + * @param commandSender the command user + * @param sensitiveCommandType type of command issued + */ + public static void processSensitiveCommandNotification(CommandSender commandSender, SensitiveCommandType sensitiveCommandType, String... args) { + /* + * Determine the 'identity' of the one who executed the command to pass as a parameters + */ + String senderName = LocaleLoader.getString("Server.ConsoleName"); + + if(commandSender instanceof Player) + { + senderName = ((Player) commandSender).getDisplayName() + ChatColor.RESET + "-" + ((Player) commandSender).getUniqueId(); + } + + //Send the notification + switch(sensitiveCommandType) + { + case XPRATE_MODIFY: + sendAdminNotification(LocaleLoader.getString("Notifications.Admin.XPRate.Start.Others", addItemToFirstPositionOfArray(senderName, args))); + sendAdminCommandConfirmation(commandSender, LocaleLoader.getString("Notifications.Admin.XPRate.Start.Self", args)); + break; + case XPRATE_END: + sendAdminNotification(LocaleLoader.getString("Notifications.Admin.XPRate.End.Others", addItemToFirstPositionOfArray(senderName, args))); + sendAdminCommandConfirmation(commandSender, LocaleLoader.getString("Notifications.Admin.XPRate.End.Self", args)); + break; + } + } + + /** + * Takes an array and an object, makes a new array with object in the first position of the new array, + * and the following elements in this new array being a copy of the existing array retaining their order + * @param itemToAdd the string to put at the beginning of the new array + * @param existingArray the existing array to be copied to the new array at position [0]+1 relative to their original index + * @return the new array combining itemToAdd at the start and existing array elements following while retaining their order + */ + public static String[] addItemToFirstPositionOfArray(String itemToAdd, String... existingArray) { + String[] newArray = new String[existingArray.length + 1]; + newArray[0] = itemToAdd; + + System.arraycopy(existingArray, 0, newArray, 1, existingArray.length); + + return newArray; + } + } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 831f4ccbc..8d25dd48e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -15,6 +15,9 @@ General: Locale: en_US AprilFoolsEvent: true MOTD_Enabled: true + EventBroadcasts: true + EventInfoOnPlayerJoin: true + AdminNotifications: true # Send a message to the player when his profile was successfully loaded Show_Profile_Loaded: false # Amount of time (in minutes) to wait between saves of player information diff --git a/src/main/resources/experience.yml b/src/main/resources/experience.yml index 1a4a7d6f8..79fc4118a 100644 --- a/src/main/resources/experience.yml +++ b/src/main/resources/experience.yml @@ -30,6 +30,7 @@ ExploitFix: Fishing: true EndermanEndermiteFarms: true Acrobatics: true + LavaStoneAndCobbleFarming: true Experience_Bars: # Turn this to false if you wanna disable XP bars Enable: true @@ -346,6 +347,7 @@ Experience_Values: Lily_of_the_valley: 150 Wither_rose: 500 Mining: + Magma_Block: 30 Tube_Coral_Block: 75 Brain_Coral_Block: 80 Bubble_Coral_Block: 70 @@ -458,7 +460,7 @@ Experience_Values: Iron_Golem: 2.0 Wither_Skeleton: 4.0 Endermite: 2.0 - Guardian: 3.0 + Guardian: 1.0 Elder_Guardian: 4.0 Shulker: 2.0 Donkey: 1.0 diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index 41e632757..0e755adb5 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -299,7 +299,7 @@ Mining.SubSkill.SuperBreaker.Description=Speed+, Triple Drop Chance Mining.SubSkill.SuperBreaker.Stat=Super Breaker Length Mining.SubSkill.DoubleDrops.Name=Double Drops Mining.SubSkill.DoubleDrops.Description=Double the normal loot -Mining.SubSkill.DoubleDrops.Stat=Double Drop Chance: [[YELLOW]]{0} +Mining.SubSkill.DoubleDrops.Stat=Double Drop Chance Mining.SubSkill.BlastMining.Name=Blast Mining Mining.SubSkill.BlastMining.Description=Bonuses to mining with TNT Mining.SubSkill.BlastMining.Stat=Blast Mining:[[GREEN]] Rank {0}/{1} [[GRAY]]({2}) @@ -821,7 +821,19 @@ Commands.Event.Stop.Subtitle=[[GREEN]]I hope you had fun! Commands.Event.XP=[[DARK_AQUA]]XP Rate is now [[GOLD]]{0}[[DARK_AQUA]]x Commands.xprate.started.0=[[GOLD]]XP EVENT FOR mcMMO HAS STARTED! Commands.xprate.started.1=[[GOLD]]mcMMO XP RATE IS NOW {0}x! + +# Admin Notifications +Server.ConsoleName=[[YELLOW]][Server] +Notifications.Admin.XPRate.Start.Self=[[GRAY]]You have set the global XP rate multiplier to [[GOLD]]{0}x +Notifications.Admin.XPRate.End.Self=[[GRAY]]You ended the XP rate event. +Notifications.Admin.XPRate.End.Others={0} [[GRAY]]has ended the XP rate event +Notifications.Admin.XPRate.Start.Others={0} [[GRAY]]has started or modified an XP rate event with global multiplier {1}x +Notifications.Admin.Format.Others=[[GOLD]]([[GREEN]]mcMMO [[DARK_AQUA]]Admin[[GOLD]]) [[GRAY]]{0} +Notifications.Admin.Format.Self=[[GOLD]]([[GREEN]]mcMMO[[GOLD]]) [[GRAY]]{0} + +# Event XPRate.Event=[[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x! + #GUIDES Guides.Available=[[GRAY]]Guide for {0} available - type /{1} ? [page] Guides.Header=[[GOLD]]-=[[GREEN]]{0} Guide[[GOLD]]=- diff --git a/src/main/resources/locale/locale_hu_HU.properties b/src/main/resources/locale/locale_hu_HU.properties index 57865501c..df9c49f26 100644 --- a/src/main/resources/locale/locale_hu_HU.properties +++ b/src/main/resources/locale/locale_hu_HU.properties @@ -295,7 +295,7 @@ Mining.SubSkill.SuperBreaker.Description=Sebess\u00E9g+, 3x T\u00E1rgy Es\u00E9s Mining.SubSkill.SuperBreaker.Stat=Szuper T\u00F6r\u00E9s Hossz\u00FAs\u00E1g Mining.SubSkill.DoubleDrops.Name=Dupla Es\u00E9s Mining.SubSkill.DoubleDrops.Description=Dupl\u00E1zza a Zs\u00E1km\u00E1ny es\u00E9st -Mining.SubSkill.DoubleDrops.Stat=Dupla T\u00E1rgy Es\u00E9si Es\u00E9ly: [[YELLOW]]{0} +Mining.SubSkill.DoubleDrops.Stat=Dupla T\u00E1rgy Es\u00E9si Es\u00E9ly Mining.SubSkill.BlastMining.Name=Robbant\u00E1sb\u00E1ny\u00E1szat Mining.SubSkill.BlastMining.Description=TNT-vel val\u00F3 b\u00E1ny\u00E1sz\u00E1si b\u00F3nusz Mining.SubSkill.BlastMining.Stat=Robbant\u00E1sb\u00E1ny\u00E1szat:[[GREEN]] Szint {0}/{1} [[GRAY]]({2}) @@ -1066,3 +1066,5 @@ Holiday.AprilFools.Levelup=[[GOLD]]{0} jelenlegi szint [[GREEN]]{1}[[GOLD]]! Holiday.Anniversary=[[BLUE]]Boldog {0}. \u00C9vfordul\u00F3t!\n[[BLUE]]nossr50, \u00E9s az \u00F6sszes fejleszt\u0151 tisztelet\u00E9re itt egy t\u0171zij\u00E1t\u00E9k show! #Reminder Messages Reminder.Squelched=[[GRAY]]Eml\u00E9keztet\u0151: jelenleg nem kapsz \u00E9rtes\u00EDt\u00E9seket az mcMMO-t\u00F3l. Ahhoz, hogy enged\u00E9lyezd az \u00E9rtes\u00EDt\u00E9seket, futtasd \u00FAjra a /mcnotify parancsot. Ez egy automatikus, \u00F3r\u00E1nk\u00E9nti eml\u00E9keztet\u0151. +#Locale +Locale.Reloaded=[[GREEN]]Ford\u00EDt\u00E1s \u00FAjrat\u00F6ltve! diff --git a/src/main/resources/locale/locale_ja_JP.properties b/src/main/resources/locale/locale_ja_JP.properties index 98b05650f..83f78fe42 100644 --- a/src/main/resources/locale/locale_ja_JP.properties +++ b/src/main/resources/locale/locale_ja_JP.properties @@ -605,12 +605,16 @@ Commands.xplock.locked=[[GOLD]]\u3042\u306a\u305f\u306eXP\u30d0\u30fc\u306f\u73f Commands.xplock.unlocked=[[GOLD]]\u3042\u306a\u305f\u306eXP\u30d0\u30fc\u306f\u73fe\u5728[[GREEN]]\u30ed\u30c3\u30af\u89e3\u9664[[GOLD]]\u3055\u308c\u3066\u3044\u307e\u3059\uff01 Commands.xprate.modified=[[RED]]XP\u30ec\u30fc\u30c8\u306f{0}\u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f Commands.xprate.over=[[RED]]mcMMO XP\u30ec\u30fc\u30c8\u30a4\u30d9\u30f3\u30c8\u304c\u7d42\u308f\u308a\u307e\u3057\u305f\uff01 +Commands.xprate.proper.0=[[RED]]XP\u30ec\u30fc\u30c8\u3092\u5909\u66f4\u3059\u308b\u305f\u3081\u306e\u6b63\u3057\u3044\u65b9\u6cd5\u306f\/xprate \u3067\u3059\u3002 +Commands.xprate.proper.1=[[RED]]XP\u30ec\u30fc\u30c8\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u306b\u623b\u3059\u6b63\u3057\u3044\u65b9\u6cd5\u306f\/xprate reset \u3067\u3059\u3002 +Commands.xprate.proper.2=[[RED]]XP\u30ec\u30fc\u30c8\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u306b\u623b\u3059\u6b63\u3057\u3044\u65b9\u6cd5\u306f\/xprate reset \u3067\u3059\u3002 Commands.NegativeNumberWarn=\u8ca0\u306e\u5024\u3092\u4f7f\u308f\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3002 Commands.Event.Start=[[GREEN]]mcMMO[[GOLD]] \u30a4\u30d9\u30f3\u30c8\uff01 +Commands.Event.Stop=[[GREEN]]mcMMO[[DARK_AQUA]] \u30a4\u30d9\u30f3\u30c8\u7d42\u4e86\uff01 +Commands.Event.Stop.Subtitle=[[GREEN]]\u697d\u3057\u3093\u3067\u304f\u308c\u305f\u3053\u3068\u3092\u9858\u3063\u3066\u307e\u3059\uff01 Commands.Event.XP=[[DARK_AQUA]]XP\u30ec\u30fc\u30c8\u306f\u73fe\u5728[[GOLD]]{0}[[DARK_AQUA]]x -Commands.xprate.started.0=[[GOLD]]mcMMO\u306eXP\u30a4\u30d9\u30f3\u30c8\u304c\u958b\u59cb\u3055\u308c\u307e\u3057\u305f\u3002 -Commands.xprate.started.1=[[GOLD]]mcMMO XP\u30ec\u30fc\u30c8\u306f\u73fe\u5728{0}x\u3067\u3059\u3002 -XPRate.Event= [[GOLD]]mcMMO\u306f\u73fe\u5728XP\u30ec\u30fc\u30c8\u30a4\u30d9\u30f3\u30c8\u4e2d\u3067\u3059\u3002 XP\u30ec\u30fc\u30c8\u306f{0}x\u3067\u3059\u3002 +Commands.xprate.started.0=[[GOLD]]mcMMO\u306eXP\u30a4\u30d9\u30f3\u30c8\u304c\u958b\u59cb\u3055\u308c\u307e\u3057\u305f\uff01 +Commands.xprate.started.1=[[GOLD]]mcMMO\u306eXP\u30ec\u30fc\u30c8\u306f3\u500d\u306b\u306a\u308a\u307e\u3057\u305f\uff01 #GUIDES Guides.Header=[[GOLD]]-=[[GREEN]]{0} \u30ac\u30a4\u30c9[[GOLD]]=- @@ -657,9 +661,22 @@ Smelting.SubSkill.FluxMining.Stat=\u30d5\u30e9\u30c3\u30af\u30b9\u30de\u30a4\u30 Smelting.Listener=\u7cbe\u932c: Smelting.SkillName=\u7cbe\u932c +# Admin Notifications +Server.ConsoleName=[[YELLOW]][Server] +Notifications.Admin.XPRate.Start.Self=[[GRAY]]\u3042\u306a\u305f\u306f[[GOLD]]{0}x[[GRAY]]\u306b\u30b0\u30ed\u30fc\u30d0\u30ebXP\u30ec\u30fc\u30c8\u3092\u8a2d\u5b9a\u3057\u307e\u3057\u305f\u3002 +Notifications.Admin.XPRate.End.Self=[[GRAY]]XP\u30ec\u30fc\u30c8\u30a4\u30d9\u30f3\u30c8\u3092\u7d42\u4e86\u3057\u307e\u3057\u305f\u3002 +Notifications.Admin.XPRate.End.Others={0}[[GRAY]]\u306fXP\u30ec\u30fc\u30c8\u30a4\u30d9\u30f3\u30c8\u3092\u7d42\u4e86\u3057\u307e\u3057\u305f +Notifications.Admin.XPRate.Start.Others={0}[[GRAY]]\u304c{1}x\u3067\u30b0\u30ed\u30fc\u30d0\u30ebXP\u30ec\u30fc\u30c8\u30a4\u30d9\u30f3\u30c8\u3092\u958b\u59cb\u307e\u305f\u306f\u5909\u66f4\u3057\u307e\u3057\u305f +Notifications.Admin.Format.Others=[[GOLD]]([[GREEN]]mcMMO [[DARK_AQUA]]\u7ba1\u7406\u8005[[GOLD]]) [[GRAY]]{0} +Notifications.Admin.Format.Self=[[GOLD]]([[GREEN]]mcMMO[[GOLD]]) [[GRAY]]{0} + +# Event +XPRate.Event=[[GOLD]]mcMMO\u306f\u73fe\u5728XP\u30ec\u30fc\u30c8\u30a4\u30d9\u30f3\u30c8\u4e2d\u3067\u3059\uff01XP\u30ec\u30fc\u30c8\u306f{0}x\u3067\u3059\uff01 + #UPDATE CHECKER UpdateChecker.Outdated=\u3042\u306a\u305f\u306f\u53e4\u3044mcMMO\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u4f7f\u3063\u3066\u3044\u307e\u3059\uff01 UpdateChecker.NewAvailable=Spigot\u306b\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u516c\u958b\u3055\u308c\u3066\u3044\u307e\u3059\u3002 + #SCOREBOARD HEADERS Scoreboard.Header.PlayerStats=[[YELLOW]]mcMMO \u7d71\u8a08 Scoreboard.Header.PlayerCooldowns=[[YELLOW]]mcMMO \u30af\u30fc\u30eb\u30c0\u30a6\u30f3 @@ -673,8 +690,15 @@ Scoreboard.Misc.RemainingXP=[[YELLOW]]\u6b8b\u308aXP Scoreboard.Misc.Cooldown=[[LIGHT_PURPLE]]\u30af\u30fc\u30eb\u30c0\u30a6\u30f3 Scoreboard.Misc.Overall=[[GOLD]]\u5408\u8a08 Scoreboard.Misc.Ability=\u30a2\u30d3\u30ea\u30c6\u30a3 + #DATABASE RECOVERY Profile.PendingLoad=[[RED]]mcMMO\u30d7\u30ec\u30a4\u30e4\u30fc\u30c7\u30fc\u30bf\u306f\u307e\u3060\u8aad\u307f\u8fbc\u307e\u308c\u3066\u3044\u307e\u305b\u3093\u3002 Profile.Loading.Success=[[GREEN]]\u3042\u306a\u305f\u306emcMMO\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u304c\u8aad\u307f\u8fbc\u307e\u308c\u307e\u3057\u305f\u3002 Profile.Loading.FailurePlayer=[[RED]]mcMMO\u306e\u30c7\u30fc\u30bf\u306e\u8aad\u307f\u8fbc\u307f\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002[[GREEN]]{0}[[RED]]\u56de\u8aad\u307f\u8fbc\u307f\u3092\u8a66\u3057\u307e\u3057\u305f\u3002[[LIGHT_GRAY]] \u3053\u306e\u554f\u984c\u306b\u3064\u3044\u3066\u30b5\u30fc\u30d0\u30fc\u7ba1\u7406\u8005\u306b\u9023\u7d61\u3057\u3066\u304f\u3060\u3055\u3044\u3002mcMMO\u306f\u3042\u306a\u305f\u304c\u5207\u65ad\u3059\u308b\u307e\u3067\u30c7\u30fc\u30bf\u306e\u8aad\u307f\u8fbc\u307f\u3092\u7e70\u308a\u8fd4\u3057\u307e\u3059\u3002\u30c7\u30fc\u30bf\u304c\u8aad\u307f\u8fbc\u307e\u308c\u3066\u3044\u306a\u3044\u9593XP\u3092\u7372\u5f97\u3067\u304d\u306a\u3044\u304b\u3001\u30b9\u30ad\u30eb\u3092\u4f7f\u3046\u3053\u3068\u304c\u51fa\u6765\u307e\u305b\u3093\u3002 -Profile.Loading.FailureNotice=[[DARK_RED]][A][[RED]] mcMMO\u306f[[YELLOW]]{0}[[RED]]\u306e\u30d7\u30ec\u30fc\u30e4\u30fc\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002 [[LIGHT_PURPLE]]\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u308c\u307e\u3067\u306e\u8a66\u884c\u56de\u6570\u306f{1}\u56de\u3067\u3059\u3002 \ No newline at end of file +Profile.Loading.FailureNotice=[[DARK_RED]][A][[RED]] mcMMO\u306f[[YELLOW]]{0}[[RED]]\u306e\u30d7\u30ec\u30fc\u30e4\u30fc\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002 [[LIGHT_PURPLE]]\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u308c\u307e\u3067\u306e\u8a66\u884c\u56de\u6570\u306f{1}\u56de\u3067\u3059\u3002 + +#Reminder Messages +Reminder.Squelched=[[GRAY]]\u30ea\u30de\u30a4\u30f3\u30c0\u30fc: \u3042\u306a\u305f\u306f\u73fe\u5728mcMMO\u304b\u3089\u901a\u77e5\u3092\u53d7\u3051\u53d6\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u901a\u77e5\u3092\u6709\u52b9\u306b\u3059\u308b\u305f\u3081\u306b\u306f\/mcnotify\u30b3\u30de\u30f3\u30c9\u3092\u3082\u3046\u4e00\u5ea6\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u308c\u306f\u81ea\u52d5\u5316\u3055\u308c\u305f1\u6642\u9593\u3054\u3068\u306e\u901a\u77e5\u3067\u3059\u3002 + +#Locale +Locale.Reloaded=[[GREEN]]\u30ed\u30b1\u30fc\u30eb \u30ea\u30ed\u30fc\u30c9\uff01 \ No newline at end of file diff --git a/src/main/resources/repair.vanilla.yml b/src/main/resources/repair.vanilla.yml index 7a31c0163..c0d8180cd 100644 --- a/src/main/resources/repair.vanilla.yml +++ b/src/main/resources/repair.vanilla.yml @@ -154,32 +154,32 @@ Repairables: ### # Tools DIAMOND_SWORD: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: .5 DIAMOND_SHOVEL: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: .3 DIAMOND_PICKAXE: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: 1 DIAMOND_AXE: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: 1 DIAMOND_HOE: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: .5 # Armor DIAMOND_HELMET: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: 6 DIAMOND_CHESTPLATE: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: 6 DIAMOND_LEGGINGS: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: 6 DIAMOND_BOOTS: - MinimumLevel: 50 + MinimumLevel: 0 XpMultiplier: 6 # # Leather repairables