Compare commits

...

8 Commits

Author SHA1 Message Date
nossr50
f71fe0de70 snapshots here we go 2025-10-05 13:55:04 -07:00
nossr50
eafa53e5b4 2.2.043 2025-10-05 13:46:32 -07:00
nossr50
5dfea51c5e slightly better logs 2025-10-05 13:46:13 -07:00
nossr50
00c0b2e5ec fix bug where armor stand could be renamed to heart symbols 2025-10-05 13:30:24 -07:00
nossr50
c79b3fe024 optimize imports 2025-10-05 13:19:17 -07:00
nossr50
24888d13c2 Fix potion names Fixes #5211 Fixes #5180 2025-10-05 13:18:35 -07:00
nossr50
2f624e329d misc optimization 2025-10-05 12:34:18 -07:00
nossr50
07d18e2eba 1.21.9 support for treasures.yml, experience.yml, fishing_treasures.yml, and settings for mannequins and a fix for armor stands 2025-10-05 12:27:20 -07:00
17 changed files with 134 additions and 47 deletions

View File

@ -1,15 +1,29 @@
Version 2.2.043
Added support for the new copper tools and weapons added in Minecraft 1.21.9
Added support for the new copper tools and armor added in Minecraft 1.21.9
Added many missing buttons, trapdoors, doors, fence gates, etc to the ability/tool blacklists (see notes)
Added copper tools and armor to repair.vanilla.yml (see notes)
Added copper tools and armor to salvage.vanilla.yml (see notes)
Added many missing buttons, trapdoors, doors, fence gates, etc to the ability/tool blacklists (see notes)
TOOD: Smelting
Added copper tools and armor to fishing_treasures.yml (see notes)
Added Copper_Nugget to treasures.yml (see notes)
Added Copper_Nugget to experience.yml for Smelting XP
Added Copper_Golem to experience.yml for Combat XP
Fixed mcMMO custom potions not having their name set correctly (see notes)
Fixed ExploitFix.PreventArmorStandInteraction in experience.yml not being respected
Added ExploitFix.PreventMannequinInteraction to experience.yml to prevent mannequins from granting XP or other effects
Fixed bug where Armor Stands would get renamed to heart symbols upon breaking them (see notes)
Tweaked potions loaded msg during mcMMO startup to not include potions requiring newer game versions from being included in the total.
NOTES:
You will need to manually update your repair.vanilla.yml and salvage.vanilla.yml files to get support for copper tools and armor.
You don't need to update your experience.yml, that one updates automatically when you run mcMMO after an update.
You will need to manually update the following files manually repair.vanilla.yml, salvage.vanilla.yml, treasures.yml, and fishing_treasures.yml files to get support for copper tools and armor.
You can find the default config files in the defaults folder at plugins\mcMMO\defaults after running this mcMMO update at least once.
You can use this default file to copy paste if you please, or if you haven't customizes these two config files, simply delete them to have mcMMO regenerate them with the new entries.
You can use this default file to copy paste if you please
OR if you haven't customizes these config files, simply delete them to have mcMMO regenerate them with the new entries.
mcMMO has an internal blacklist of blocks that abilities and tools won't activate or "ready" on, pretty much anything that is interactable should go on this list, and I performed an audit and there were quite a few missing entries, so I've added them in this update, what this means is you won't click on a button and have it ready your tool anymore, as it should have been doing.
Mannequins are treated the same way armor stands are treated, the default behavior is mcMMO won't process on them unless you turn on the setting under ExploitFix in experience.yml, in addition to this their default XP is set to 0.0
mcMMO had a setting 'ExploitFix.PreventArmorStandInteraction' to allow mcMMO to process abilities and XP on armor stands, but it was never hooked up! I fixed that mistake in this update.
The fix for potion names will only apply to newly created potions.
Armor stands that had already been renamed from the heart symbol bug will keep their names, but the bug shouldn't happen anymore
Version 2.2.042
mcMMO now listens to BlockDropItemEvent at LOW priority instead of HIGHEST

View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>2.2.043-SNAPSHOT</version>
<version>2.2.044-SNAPSHOT</version>
<name>mcMMO</name>
<url>https://github.com/mcMMO-Dev/mcMMO</url>
<scm>

View File

@ -201,6 +201,10 @@ public class ExperienceConfig extends BukkitConfig {
return config.getBoolean("ExploitFix.PreventArmorStandInteraction", true);
}
public boolean isMannequinInteractionPrevented() {
return config.getBoolean("ExploitFix.PreventMannequinInteraction", true);
}
public boolean isFishingExploitingPrevented() {
return config.getBoolean("ExploitFix.Fishing", true);
}

View File

@ -1,6 +1,6 @@
package com.gmail.nossr50.config.skills.alchemy;
import static com.gmail.nossr50.util.ItemUtils.setItemName;
import static com.gmail.nossr50.util.ItemUtils.customName;
import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
import static com.gmail.nossr50.util.PotionUtil.setBasePotionType;
import static com.gmail.nossr50.util.PotionUtil.setUpgradedAndExtendedProperties;
@ -15,6 +15,9 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
@ -158,7 +161,7 @@ public class PotionConfig extends LegacyConfigLoader {
}
}
int totalPotions = potionsLoaded + incompatible + failures;
int totalPotions = potionsLoaded + failures;
mcMMO.p.getLogger()
.info("Loaded " + potionsLoaded + " of " + totalPotions + " Alchemy potions.");
@ -369,7 +372,9 @@ public class PotionConfig extends LegacyConfigLoader {
final String configuredName = section.getString("Name", null);
if (configuredName != null) {
setItemName(potionMeta, configuredName);
final TextComponent textComponent = Component.text(configuredName)
.decoration(TextDecoration.ITALIC, false);
customName(potionMeta, textComponent, configuredName);
}
}

View File

@ -99,7 +99,10 @@ public class TreasureConfig extends BukkitConfig {
type + "." + treasureName + ".Data");
if (material == null) {
reason.add("Invalid material: " + materialName);
LogUtils.debug(mcMMO.p.getLogger(),
String.format("Material '%s' for treasure '%s' is not recognized."
+ " Skipping...", materialName, treasureName));
continue;
}
if (amount <= 0) {

View File

@ -1,13 +1,10 @@
package com.gmail.nossr50.listeners;
import static com.gmail.nossr50.util.MetadataConstants.METADATA_KEY_BONUS_DROPS;
import static com.gmail.nossr50.util.Misc.getBlockCenter;
import com.gmail.nossr50.api.ItemSpawnReason;
import com.gmail.nossr50.config.HiddenConfig;
import com.gmail.nossr50.config.WorldBlacklist;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.meta.BonusDropMeta;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
@ -28,7 +25,6 @@ import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.ContainerMetadataUtils;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.MetadataConstants;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillUtils;

View File

@ -43,7 +43,6 @@ import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.AnimalTamer;
import org.bukkit.entity.Animals;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Endermite;
@ -89,13 +88,18 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
public class EntityListener implements Listener {
private static final String MULTISHOT = "multishot";
private static final String PIERCING = "piercing";
private static final String DEEPSLATE_REDSTONE_ORE = "deepslate_redstone_ore";
private static final Set<String> ARMOR_STAND = Set.of("ARMOR_STAND", "armor_stand");
private static final Set<String> MANNEQUIN = Set.of("mannequin", "MANNEQUIN");
private final mcMMO pluginRef;
/**
* We can use this {@link NamespacedKey} for {@link Enchantment} comparisons to check if a
* {@link Player} has a {@link Trident} enchanted with "Piercing".
*/
private final NamespacedKey piercingEnchantment = NamespacedKey.minecraft("piercing");
private final NamespacedKey piercingEnchantment = NamespacedKey.minecraft(PIERCING);
private final static Set<EntityType> TRANSFORMABLE_ENTITIES
= Set.of(EntityType.SLIME, EntityType.MAGMA_CUBE);
@ -205,7 +209,7 @@ public class EntityListener implements Listener {
CombatUtils.delayArrowMetaCleanup(arrow);
// If fired from an item with multi-shot, we need to track
if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, "multishot")) {
if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, MULTISHOT)) {
arrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW,
MetadataConstants.MCMMO_METADATA_VALUE);
}
@ -221,7 +225,7 @@ public class EntityListener implements Listener {
}
//Check both hands
if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, "piercing")) {
if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, PIERCING)) {
return;
}
@ -282,7 +286,7 @@ public class EntityListener implements Listener {
entity.removeMetadata(MetadataConstants.METADATA_KEY_TRAVELING_BLOCK, pluginRef);
}
} else if ((block.getType() == Material.REDSTONE_ORE || block.getType().getKey().getKey()
.equalsIgnoreCase("deepslate_redstone_ore"))) {
.equalsIgnoreCase(DEEPSLATE_REDSTONE_ORE))) {
//Redstone ore fire this event and should be ignored
} else {
if (mcMMO.getUserBlockTracker().isIneligible(block)) {
@ -352,11 +356,13 @@ public class EntityListener implements Listener {
return;
}
// Don't process this event for marked entities, for players this is handled above,
// However, for entities, we do not wanna cancel this event to allow plugins to observe changes
// properly
if (ExperienceConfig.getInstance().isArmorStandInteractionPrevented()
&& isArmorStandEntity(attacker)) {
return;
}
if (event.getEntity() instanceof ArmorStand) {
if (ExperienceConfig.getInstance().isMannequinInteractionPrevented()
&& isMannequinEntity(attacker)) {
return;
}
@ -1196,4 +1202,12 @@ public class EntityListener implements Listener {
}
}
}
public static boolean isMannequinEntity(Entity attacker) {
return MANNEQUIN.contains(attacker.getType().toString());
}
public static boolean isArmorStandEntity(Entity attacker) {
return ARMOR_STAND.contains(attacker.getType().toString());
}
}

View File

@ -87,10 +87,8 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@ -1,8 +1,6 @@
package com.gmail.nossr50.skills.unarmed;
import static com.gmail.nossr50.util.random.ProbabilityUtil.isSkillRNGSuccessful;
import static org.bukkit.Material.INFESTED_STONE_BRICKS;
import static org.bukkit.Material.STONE_BRICKS;
import com.gmail.nossr50.api.ItemSpawnReason;
import com.gmail.nossr50.datatypes.interactions.NotificationType;
@ -24,7 +22,6 @@ import com.gmail.nossr50.util.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;

View File

@ -18,6 +18,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
import net.kyori.adventure.text.Component;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
@ -35,20 +36,20 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class ItemUtils {
// Reflection for setItemName only available in newer APIs
private static final Method setItemName;
// Use custom name if available
private static final Method customName;
static {
setItemName = getSetItemName();
customName = getCustomNameMethod();
}
private ItemUtils() {
// private constructor
}
private static Method getSetItemName() {
private static Method getCustomNameMethod() {
try {
return ItemMeta.class.getMethod("setItemName", String.class);
return ItemMeta.class.getMethod("customName", Component.class);
} catch (NoSuchMethodException e) {
return null;
}
@ -60,17 +61,17 @@ public final class ItemUtils {
* @param itemMeta The item meta to set the name on
* @param name The name to set
*/
public static void setItemName(ItemMeta itemMeta, String name) {
if (setItemName != null) {
public static void customName(ItemMeta itemMeta, Component name, String fallbackName) {
if (customName != null) {
setItemNameModern(itemMeta, name);
} else {
itemMeta.setDisplayName(ChatColor.RESET + name);
itemMeta.setDisplayName(ChatColor.RESET + fallbackName);
}
}
private static void setItemNameModern(ItemMeta itemMeta, String name) {
private static void setItemNameModern(ItemMeta itemMeta, Component name) {
try {
setItemName.invoke(itemMeta, name);
customName.invoke(itemMeta, name);
} catch (IllegalAccessException | InvocationTargetException e) {
mcMMO.p.getLogger().severe("Failed to set item name: " + e.getMessage());
throw new RuntimeException(e);

View File

@ -1408,6 +1408,7 @@ public class MaterialMapStore {
blackList.add("dropper");
blackList.add("hopper");
blackList.add("armor_stand");
blackList.add("mannequin");
}
private void fillAbilityBlackList() {

View File

@ -1,5 +1,8 @@
package com.gmail.nossr50.util;
import static com.gmail.nossr50.listeners.EntityListener.isArmorStandEntity;
import static com.gmail.nossr50.listeners.EntityListener.isMannequinEntity;
import com.gmail.nossr50.datatypes.MobHealthbarType;
import com.gmail.nossr50.datatypes.meta.OldName;
import com.gmail.nossr50.mcMMO;
@ -40,8 +43,12 @@ public final class MobHealthbarUtils {
* @param damage damage done by the attack triggering this
*/
public static void handleMobHealthbars(LivingEntity target, double damage, mcMMO plugin) {
if (mcMMO.isHealthBarPluginEnabled() || !mcMMO.p.getGeneralConfig()
.getMobHealthbarEnabled()) {
if (isArmorStandEntity(target) || isMannequinEntity(target)) {
return;
}
if (mcMMO.isHealthBarPluginEnabled()
|| !mcMMO.p.getGeneralConfig().getMobHealthbarEnabled()) {
return;
}
@ -54,13 +61,13 @@ public final class MobHealthbarUtils {
return;
}
String originalName = target.getName();
final String originalName = target.getName();
String oldName = target.getCustomName();
/*
* Store the name in metadata
*/
if (target.getMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY).size() <= 0) {
if (target.getMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY).isEmpty()) {
target.setMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY,
new OldName(originalName, plugin));
}

View File

@ -58,7 +58,7 @@ import org.jetbrains.annotations.Nullable;
public final class CombatUtils {
private static final ThreadLocal<Boolean> IN_MCMO_DAMAGE
private static final ThreadLocal<Boolean> IN_MCMMO_DAMAGE
= ThreadLocal.withInitial(() -> false);
@ -75,14 +75,14 @@ public final class CombatUtils {
*/
public static void safeDealDamage(@NotNull LivingEntity target, double amount,
@Nullable Entity attacker) {
boolean prev = IN_MCMO_DAMAGE.get();
boolean prev = IN_MCMMO_DAMAGE.get();
if (prev || target.isDead()) {
return;
}
try {
IN_MCMO_DAMAGE.set(true);
IN_MCMMO_DAMAGE.set(true);
if (!hasIgnoreDamageMetadata(target)) {
applyIgnoreDamageMetadata(target);
}
@ -93,7 +93,7 @@ public final class CombatUtils {
target.damage(amount);
}
} finally {
IN_MCMO_DAMAGE.set(false);
IN_MCMMO_DAMAGE.set(false);
if (hasIgnoreDamageMetadata(target)) {
removeIgnoreDamageMetadata(target);
}

View File

@ -7,7 +7,6 @@ import com.gmail.nossr50.util.AttributeMapper;
import com.gmail.nossr50.util.LogUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.jetbrains.annotations.Nullable;

View File

@ -30,6 +30,7 @@ ExploitFix:
PistonCheating: true
SnowGolemExcavation: true
PreventArmorStandInteraction: true
PreventMannequinInteraction: true
# This include NPCs from stuff like Citizens, this is not a setting for Vanilla Minecraft Villagers (Which can be considered NPCs)
# mcMMO normally doesn't process attacks against an Entity if it is an NPC from another plugin
# Of course, mcMMO doesn't know for sure whether something is an NPC, it checks a few known things, see our source code to see how
@ -553,6 +554,7 @@ Experience_Values:
String: 1.8
Other: 1.5
Smelting:
Copper_Nugget: 85
Raw_Copper: 75
Deepslate_Redstone_Ore: 30
Deepslate_Copper_Ore: 100
@ -683,3 +685,5 @@ Experience_Values:
Camel: 1.2
Bogged: 2.0
Breeze: 4.0
Armor_Stand: 0.0
Mannequin: 0.0

View File

@ -63,6 +63,26 @@ Fishing:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_SWORD:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_SHOVEL:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_PICKAXE:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_AXE:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_HOE:
Amount: 1
XP: 200
Rarity: UNCOMMON
GOLDEN_SWORD:
Amount: 1
XP: 200
@ -143,6 +163,22 @@ Fishing:
Amount: 1
XP: 200
Rarity: RARE
COPPER_BOOTS:
Amount: 1
XP: 200
Rarity: COMMON
COPPER_HELMET:
Amount: 1
XP: 200
Rarity: COMMON
COPPER_LEGGINGS:
Amount: 1
XP: 200
Rarity: COMMON
COPPER_CHESTPLATE:
Amount: 1
XP: 200
Rarity: COMMON
IRON_BOOTS:
Amount: 1
XP: 200

View File

@ -296,3 +296,11 @@ Hylian_Luck:
Standard_Mode: 0
Retro_Mode: 0
Drops_From: [Pots]
COPPER_NUGGET:
Amount: 1
XP: 5
Drop_Chance: 100.0
Level_Requirement:
Standard_Mode: 0
Retro_Mode: 0
Drops_From: [Pots]