1
0
mirror of https://github.com/mcMMO-Dev/mcMMO.git synced 2026-02-17 17:32:36 +01:00

refactor a bunch of unused, outdated, or unnecessary tech debt for compatibility for older versions that are no longer supported or were never supported

This commit is contained in:
nossr50
2026-02-07 14:54:25 -08:00
parent db985bcc52
commit c94f10568d
44 changed files with 339 additions and 1746 deletions

View File

@@ -1,11 +1,11 @@
Version 2.2.050 Version 2.2.050
Minimum supported Minecraft version raised to 1.20.4 (see notes) Minimum supported Minecraft version raised to 1.20.5 (see notes)
Improved Spears damage detection (see notes) Improved Spears damage detection (see notes)
Spear abilities can now trigger from off-hand attacks with the Spear Spear abilities can now trigger from off-hand attacks with the Spear
Further improved compatibility with Excellent Enchants (fixed more errors) Further improved compatibility with Excellent Enchants (fixed more errors)
NOTES: NOTES:
From 2.2.050 onwards, mcMMO will require Minecraft versions 1.20.4 or newer. From 2.2.050 onwards, mcMMO will require Minecraft versions 1.20.5 or newer.
Every now and then I raise the minimum supported Minecraft version to reduce maintenance burden of supporting older versions. Every now and then I raise the minimum supported Minecraft version to reduce maintenance burden of supporting older versions.
mcMMO no longer monitors PlayerAnimationEvent, it turns out Spigot has a DamageType just for Spear damage, avoiding the need to track player arm swings. mcMMO no longer monitors PlayerAnimationEvent, it turns out Spigot has a DamageType just for Spear damage, avoiding the need to track player arm swings.

View File

@@ -15,8 +15,8 @@
</scm> </scm>
<properties> <properties>
<!-- <spigot.version>1.20.4-R0.1-SNAPSHOT</spigot.version>--> <spigot.version>1.20.5-R0.1-SNAPSHOT</spigot.version>
<spigot.version>1.21.11-R0.1-SNAPSHOT</spigot.version> <!-- <spigot.version>1.21.11-R0.1-SNAPSHOT</spigot.version>-->
<kyori.adventure.version>4.23.0</kyori.adventure.version> <kyori.adventure.version>4.23.0</kyori.adventure.version>
<kyori.adventure.platform.version>4.4.1-SNAPSHOT</kyori.adventure.platform.version> <kyori.adventure.platform.version>4.4.1-SNAPSHOT</kyori.adventure.platform.version>
<kyori.option.version>1.1.0</kyori.option.version> <kyori.option.version>1.1.0</kyori.option.version>

View File

@@ -1,30 +0,0 @@
package com.gmail.nossr50.commands.admin;
import com.gmail.nossr50.mcMMO;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class CompatibilityCommand implements CommandExecutor {
/**
* Executes the given command, returning its success.
* <br>
* If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be
* sent to the player.
*
* @param commandSender Source of the command
* @param command Command which was executed
* @param s Alias of the command which was used
* @param strings Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command,
@NotNull String s,
@NotNull String[] strings) {
mcMMO.getCompatibilityManager().reportCompatibilityStatus(commandSender);
return true;
}
}

View File

@@ -44,13 +44,6 @@ public class McTopCommand implements TabExecutor {
return true; return true;
} }
// Check if the command is for Maces but the MC version is not correct
if (skill == PrimarySkillType.MACES
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
return true;
}
display(1, skill, sender, command); display(1, skill, sender, command);
return true; return true;
@@ -65,13 +58,6 @@ public class McTopCommand implements TabExecutor {
return true; return true;
} }
// Check if the command is for Maces but the MC version is not correct
if (skill == PrimarySkillType.MACES
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
return true;
}
display(Math.abs(Integer.parseInt(args[1])), skill, sender, command); display(Math.abs(Integer.parseInt(args[1])), skill, sender, command);
return true; return true;

View File

@@ -1,13 +1,13 @@
package com.gmail.nossr50.commands.skills; package com.gmail.nossr50.commands.skills;
import static com.gmail.nossr50.util.Permissions.canUseSubSkill;
import com.gmail.nossr50.config.treasure.FishingTreasureConfig; import com.gmail.nossr50.config.treasure.FishingTreasureConfig;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.treasure.Rarity; import com.gmail.nossr50.datatypes.treasure.Rarity;
import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.fishing.FishingManager; import com.gmail.nossr50.skills.fishing.FishingManager;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.random.Probability; import com.gmail.nossr50.util.random.Probability;
import com.gmail.nossr50.util.random.ProbabilityUtil; import com.gmail.nossr50.util.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.RankUtils;
@@ -118,16 +118,14 @@ public class FishingCommand extends SkillCommand {
@Override @Override
protected void permissionsCheck(Player player) { protected void permissionsCheck(Player player) {
canTreasureHunt = Permissions.canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER); canTreasureHunt = canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
canMagicHunt = Permissions.canUseSubSkill(player, SubSkillType.FISHING_MAGIC_HUNTER) canMagicHunt = canUseSubSkill(player, SubSkillType.FISHING_MAGIC_HUNTER)
&& Permissions.canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER); && canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
canShake = Permissions.canUseSubSkill(player, SubSkillType.FISHING_SHAKE); canShake = canUseSubSkill(player, SubSkillType.FISHING_SHAKE);
canFishermansDiet = Permissions.canUseSubSkill(player, canFishermansDiet = canUseSubSkill(player,
SubSkillType.FISHING_FISHERMANS_DIET); SubSkillType.FISHING_FISHERMANS_DIET);
canMasterAngler = canMasterAngler = canUseSubSkill(player, SubSkillType.FISHING_MASTER_ANGLER);
mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null canIceFish = canUseSubSkill(player, SubSkillType.FISHING_ICE_FISHING);
&& Permissions.canUseSubSkill(player, SubSkillType.FISHING_MASTER_ANGLER);
canIceFish = Permissions.canUseSubSkill(player, SubSkillType.FISHING_ICE_FISHING);
} }
@Override @Override

View File

@@ -3,13 +3,11 @@ package com.gmail.nossr50.config.skills.alchemy;
import static com.gmail.nossr50.util.ItemUtils.customName; import static com.gmail.nossr50.util.ItemUtils.customName;
import static com.gmail.nossr50.util.PotionUtil.matchPotionType; import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
import static com.gmail.nossr50.util.PotionUtil.setBasePotionType; import static com.gmail.nossr50.util.PotionUtil.setBasePotionType;
import static com.gmail.nossr50.util.PotionUtil.setUpgradedAndExtendedProperties;
import com.gmail.nossr50.config.LegacyConfigLoader; import com.gmail.nossr50.config.LegacyConfigLoader;
import com.gmail.nossr50.datatypes.skills.alchemy.AlchemyPotion; import com.gmail.nossr50.datatypes.skills.alchemy.AlchemyPotion;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.LogUtils;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -49,9 +47,6 @@ public class PotionConfig extends LegacyConfigLoader {
private final List<ItemStack> concoctionsIngredientsTierSix = new ArrayList<>(); private final List<ItemStack> concoctionsIngredientsTierSix = new ArrayList<>();
private final List<ItemStack> concoctionsIngredientsTierSeven = new ArrayList<>(); private final List<ItemStack> concoctionsIngredientsTierSeven = new ArrayList<>();
private final List<ItemStack> concoctionsIngredientsTierEight = new ArrayList<>(); private final List<ItemStack> concoctionsIngredientsTierEight = new ArrayList<>();
private final AlchemyPotionConfigResult INCOMPATIBLE_POTION_RESULT = new AlchemyPotionConfigResult(
null,
AlchemyPotionConfigResultType.INCOMPATIBLE);
private final AlchemyPotionConfigResult ERROR_POTION_RESULT = new AlchemyPotionConfigResult( private final AlchemyPotionConfigResult ERROR_POTION_RESULT = new AlchemyPotionConfigResult(
null, null,
AlchemyPotionConfigResultType.ERROR); AlchemyPotionConfigResultType.ERROR);
@@ -258,15 +253,15 @@ public class PotionConfig extends LegacyConfigLoader {
if (potion_section.contains("Effects")) { if (potion_section.contains("Effects")) {
for (String effect : potion_section.getStringList("Effects")) { for (String effect : potion_section.getStringList("Effects")) {
String[] parts = effect.split(" "); String[] parts = effect.split(" ");
if (isTrickyTrialsPotionEffect(parts[0]) && !mcMMO.getCompatibilityManager() // if (isTrickyTrialsPotionEffect(parts[0]) && !mcMMO.getCompatibilityManager()
.getMinecraftGameVersion() // .minecraftGameVersion()
.isAtLeast(1, 21, 0)) { // .isAtLeast(1, 21, 0)) {
LogUtils.debug( // LogUtils.debug(
mcMMO.p.getLogger(), // mcMMO.p.getLogger(),
"Skipping potion effect " + effect + " because it is not" // "Skipping potion effect " + effect + " because it is not"
+ " compatible with the current Minecraft game version."); // + " compatible with the current Minecraft game version.");
return INCOMPATIBLE_POTION_RESULT; // return INCOMPATIBLE_POTION_RESULT;
} // }
PotionEffectType type = PotionEffectType type =
parts.length > 0 ? PotionEffectType.getByName(parts[0]) : null; parts.length > 0 ? PotionEffectType.getByName(parts[0]) : null;
@@ -298,9 +293,7 @@ public class PotionConfig extends LegacyConfigLoader {
.getKeys(false)) { .getKeys(false)) {
// Breeze Rod was only for potions after 1.21.0 // Breeze Rod was only for potions after 1.21.0
if (isTrickyTrialsIngredient(childIngredient) if (isTrickyTrialsIngredient(childIngredient)
&& !mcMMO.getCompatibilityManager() && !mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
.getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
continue; continue;
} }
ItemStack ingredient = loadIngredient(childIngredient); ItemStack ingredient = loadIngredient(childIngredient);
@@ -359,8 +352,6 @@ public class PotionConfig extends LegacyConfigLoader {
// set base // set base
setBasePotionType(potionMeta, potionType, extended, upgraded); setBasePotionType(potionMeta, potionType, extended, upgraded);
// Legacy only
setUpgradedAndExtendedProperties(potionType, potionMeta, upgraded, extended);
return true; return true;
} }

View File

@@ -132,7 +132,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ general.getMySQLDatabaseName(); + general.getMySQLDatabaseName();
// Temporary hack for 1.17 + SSL support (legacy path kept intact) // Temporary hack for 1.17 + SSL support (legacy path kept intact)
if (!mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 17, 0) if (!mcMMO.getMinecraftGameVersion().isAtLeast(1, 17, 0)
&& general.getMySQLSSL()) { && general.getMySQLSSL()) {
connectionString += "?verifyServerCertificate=false&useSSL=true&requireSSL=true"; connectionString += "?verifyServerCertificate=false&useSSL=true&requireSSL=true";
} else { } else {

View File

@@ -182,8 +182,6 @@ public class McMMOPlayer implements Identified {
} }
private void initManager(PrimarySkillType primarySkillType) throws InvalidSkillException { private void initManager(PrimarySkillType primarySkillType) throws InvalidSkillException {
final var version = mcMMO.getCompatibilityManager().getMinecraftGameVersion();
final SkillManager manager = switch (primarySkillType) { final SkillManager manager = switch (primarySkillType) {
case ACROBATICS -> new AcrobaticsManager(this); case ACROBATICS -> new AcrobaticsManager(this);
case ALCHEMY -> new AlchemyManager(this); case ALCHEMY -> new AlchemyManager(this);
@@ -202,8 +200,10 @@ public class McMMOPlayer implements Identified {
case TRIDENTS -> new TridentsManager(this); case TRIDENTS -> new TridentsManager(this);
case UNARMED -> new UnarmedManager(this); case UNARMED -> new UnarmedManager(this);
case WOODCUTTING -> new WoodcuttingManager(this); case WOODCUTTING -> new WoodcuttingManager(this);
case MACES -> version.isAtLeast(1, 21, 0) ? new MacesManager(this) : null; case MACES -> new MacesManager(this);
case SPEARS -> version.isAtLeast(1, 21, 11) ? new SpearsManager(this) : null; case SPEARS -> mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)
? new SpearsManager(this)
: null;
}; };
if (manager != null) { if (manager != null) {

View File

@@ -1,10 +1,8 @@
package com.gmail.nossr50.datatypes.skills.alchemy; package com.gmail.nossr50.datatypes.skills.alchemy;
import static com.gmail.nossr50.util.PotionUtil.samePotionType;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.PotionUtil;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
@@ -80,12 +78,14 @@ public class AlchemyPotion {
return false; return false;
} }
if (!samePotionType(getAlchemyPotionMeta(), otherPotionMeta)) { @NotNull PotionMeta potionMeta = getAlchemyPotionMeta();
if (!(potionMeta.getBasePotionType() == otherPotionMeta.getBasePotionType())) {
return false; return false;
} }
// Legacy only comparison, compare PotionData // Legacy only comparison, compare PotionData
if (!PotionUtil.isPotionDataEqual(getAlchemyPotionMeta(), otherPotionMeta)) { @NotNull PotionMeta potionMeta1 = getAlchemyPotionMeta();
if (!(potionMeta1.getBasePotionType() == otherPotionMeta.getBasePotionType())) {
return false; return false;
} }

View File

@@ -489,8 +489,7 @@ public class PlayerListener implements Listener {
fishingManager.processExploiting(event.getHook().getLocation().toVector()); fishingManager.processExploiting(event.getHook().getLocation().toVector());
if (fishingManager.isExploitingFishing( if (fishingManager.isExploitingFishing()) {
event.getHook().getLocation().toVector())) {
player.sendMessage(LocaleLoader.getString("Fishing.ScarcityTip", player.sendMessage(LocaleLoader.getString("Fishing.ScarcityTip",
ExperienceConfig.getInstance() ExperienceConfig.getInstance()
.getFishingExploitingOptionMoveRange())); .getFishingExploitingOptionMoveRange()));

View File

@@ -56,14 +56,13 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TransientEntityTracker; import com.gmail.nossr50.util.TransientEntityTracker;
import com.gmail.nossr50.util.TransientMetadataTools; import com.gmail.nossr50.util.TransientMetadataTools;
import com.gmail.nossr50.util.MinecraftGameVersionFactory;
import com.gmail.nossr50.util.blockmeta.ChunkManager; import com.gmail.nossr50.util.blockmeta.ChunkManager;
import com.gmail.nossr50.util.blockmeta.ChunkManagerFactory; import com.gmail.nossr50.util.blockmeta.ChunkManagerFactory;
import com.gmail.nossr50.util.blockmeta.UserBlockTracker; import com.gmail.nossr50.util.blockmeta.UserBlockTracker;
import com.gmail.nossr50.util.commands.CommandRegistrationManager; import com.gmail.nossr50.util.commands.CommandRegistrationManager;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.experience.FormulaManager; import com.gmail.nossr50.util.experience.FormulaManager;
import com.gmail.nossr50.util.platform.PlatformManager; import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.platform.ServerSoftwareType;
import com.gmail.nossr50.util.player.PlayerLevelUtils; import com.gmail.nossr50.util.player.PlayerLevelUtils;
import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager; import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
@@ -94,7 +93,6 @@ import org.jetbrains.annotations.Nullable;
public class mcMMO extends JavaPlugin { public class mcMMO extends JavaPlugin {
/* Managers & Services */ /* Managers & Services */
private static PlatformManager platformManager;
private static ChunkManager chunkManager; private static ChunkManager chunkManager;
private static RepairableManager repairableManager; private static RepairableManager repairableManager;
private static SalvageableManager salvageableManager; private static SalvageableManager salvageableManager;
@@ -107,6 +105,7 @@ public class mcMMO extends JavaPlugin {
private static ChatManager chatManager; private static ChatManager chatManager;
private static CommandManager commandManager; //ACF private static CommandManager commandManager; //ACF
private static TransientEntityTracker transientEntityTracker; private static TransientEntityTracker transientEntityTracker;
private static MinecraftGameVersion minecraftGameVersion;
private SkillTools skillTools; private SkillTools skillTools;
@@ -170,8 +169,19 @@ public class mcMMO extends JavaPlugin {
//Filter out any debug messages (if debug/verbose logging is not enabled) //Filter out any debug messages (if debug/verbose logging is not enabled)
getLogger().setFilter(new LogFilter(this)); getLogger().setFilter(new LogFilter(this));
//Platform Manager // Determine game version before moving forward
platformManager = new PlatformManager(); final String versionStr = Bukkit.getVersion();
try {
minecraftGameVersion = MinecraftGameVersionFactory.calculateGameVersion(versionStr);
} catch (Exception e) {
// if anything goes wrong with our calculations, assume they are running the minimum
// supported version and log the error
getLogger().warning("Could not determine Minecraft version from"
+ " server software version string: " + versionStr +
", Please report this bug to the devs!");
e.printStackTrace();
minecraftGameVersion = new MinecraftGameVersion(1, 20, 5);
}
//Folia lib plugin instance //Folia lib plugin instance
foliaLib = new FoliaLib(this); foliaLib = new FoliaLib(this);
@@ -248,7 +258,7 @@ public class mcMMO extends JavaPlugin {
"You are potentially running an outdated version of your server software" "You are potentially running an outdated version of your server software"
+ ", mcMMO will not work unless you update to a newer version!"), + ", mcMMO will not work unless you update to a newer version!"),
20, 20 * 60 * 30); 20, 20 * 60 * 30);
if (!getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 20, 4)) { if (!minecraftGameVersion.isAtLeast(1, 20, 4)) {
foliaLib.getScheduler().runTimer( foliaLib.getScheduler().runTimer(
() -> getLogger().severe( () -> getLogger().severe(
"This version of mcMMO requires at least Minecraft 1.20.4 to" "This version of mcMMO requires at least Minecraft 1.20.4 to"
@@ -501,10 +511,6 @@ public class mcMMO extends JavaPlugin {
return upgradeManager; return upgradeManager;
} }
public static @Nullable CompatibilityManager getCompatibilityManager() {
return platformManager.getCompatibilityManager();
}
@Deprecated @Deprecated
public static void setDatabaseManager(DatabaseManager databaseManager) { public static void setDatabaseManager(DatabaseManager databaseManager) {
mcMMO.databaseManager = databaseManager; mcMMO.databaseManager = databaseManager;
@@ -750,10 +756,6 @@ public class mcMMO extends JavaPlugin {
return worldBlacklist; return worldBlacklist;
} }
public static PlatformManager getPlatformManager() {
return platformManager;
}
public static BukkitAudiences getAudiences() { public static BukkitAudiences getAudiences() {
return audiences; return audiences;
} }
@@ -834,4 +836,13 @@ public class mcMMO extends JavaPlugin {
public @NotNull FoliaLib getFoliaLib() { public @NotNull FoliaLib getFoliaLib() {
return foliaLib; return foliaLib;
} }
/**
* Get the {@link MinecraftGameVersion}
*
* @return the {@link MinecraftGameVersion}
*/
public static MinecraftGameVersion getMinecraftGameVersion() {
return minecraftGameVersion;
}
} }

View File

@@ -49,12 +49,6 @@ public class McRankCommandDisplayTask extends CancellableRunnable {
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName)); sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName));
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) { for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
// Check if the command is for Maces but the MC version is not correct
if (skill == PrimarySkillType.MACES
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
continue;
}
rank = skills.get(skill); rank = skills.get(skill);
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill",
mcMMO.p.getSkillTools().getLocalizedSkillName(skill), mcMMO.p.getSkillTools().getLocalizedSkillName(skill),

View File

@@ -28,7 +28,6 @@ import com.gmail.nossr50.util.MetadataConstants;
import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.adapter.BiomeAdapter; import com.gmail.nossr50.util.adapter.BiomeAdapter;
import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer;
import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.random.ProbabilityUtil; import com.gmail.nossr50.util.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.CombatUtils; import com.gmail.nossr50.util.skills.CombatUtils;
@@ -40,7 +39,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
@@ -55,31 +53,24 @@ import org.bukkit.entity.Sheep;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.metadata.Metadatable;
import org.bukkit.util.BoundingBox; import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class FishingManager extends SkillManager { public class FishingManager extends SkillManager {
public static final int FISHING_ROD_CAST_CD_MILLISECONDS = 100;
private final long FISHING_COOLDOWN_SECONDS = 1000L;
private long fishingRodCastTimestamp = 0L;
private long fishHookSpawnTimestamp = 0L; private long fishHookSpawnTimestamp = 0L;
private long lastWarned = 0L; private long lastWarned = 0L;
private final long lastWarnedExhaust = 0L;
private FishHook fishHookReference;
private BoundingBox lastFishingBoundingBox; private BoundingBox lastFishingBoundingBox;
private boolean sameTarget; private boolean sameTarget;
private Item fishingCatch;
private Location hookLocation;
private int fishCaughtCounter = 1; private int fishCaughtCounter = 1;
private final int masterAnglerMinWaitLowerBound; private final int masterAnglerMinWaitLowerBound;
private final int masterAnglerMaxWaitLowerBound; private final int masterAnglerMaxWaitLowerBound;
public FishingManager(McMMOPlayer mmoPlayer) { public FishingManager(McMMOPlayer mmoPlayer) {
super(mmoPlayer, PrimarySkillType.FISHING); super(mmoPlayer, PrimarySkillType.FISHING);
//Ticks for minWait and maxWait never go below this value // Ticks for minWait and maxWait never go below this value
int bonusCapMin = mcMMO.p.getAdvancedConfig().getFishingReductionMinWaitCap(); int bonusCapMin = mcMMO.p.getAdvancedConfig().getFishingReductionMinWaitCap();
int bonusCapMax = mcMMO.p.getAdvancedConfig().getFishingReductionMaxWaitCap(); int bonusCapMax = mcMMO.p.getAdvancedConfig().getFishingReductionMaxWaitCap();
@@ -95,53 +86,18 @@ public class FishingManager extends SkillManager {
} }
public boolean canMasterAngler() { public boolean canMasterAngler() {
return mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null return getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
&& getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER); && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
} }
// public void setFishingRodCastTimestamp() public void setFishHookReference(Metadatable fishHook) {
// { if (!fishHook.getMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF).isEmpty()) {
// long currentTime = System.currentTimeMillis();
// //Only track spam casting if the fishing hook is fresh
// if (currentTime > fishHookSpawnTimestamp + 1000)
// return;
//
// if (currentTime < fishingRodCastTimestamp + FISHING_ROD_CAST_CD_MILLISECONDS)
// {
// ItemStack fishingRod = getPlayer().getInventory().getItemInMainHand();
//
// //Ensure correct hand item is damaged
// if (fishingRod.getType() != Material.FISHING_ROD) {
// fishingRod = getPlayer().getInventory().getItemInOffHand();
// }
//
// getPlayer().setFoodLevel(Math.max(getPlayer().getFoodLevel() - 1, 0));
// fishingRod.setDurability((short) (fishingRod.getDurability() + 5));
// getPlayer().updateInventory();
//
// if (lastWarnedExhaust + (1000) < currentTime)
// {
// getPlayer().sendMessage(LocaleLoader.getString("Fishing.Exhausting"));
// lastWarnedExhaust = currentTime;
// SoundManager.sendSound(getPlayer(), getPlayer().getLocation(), SoundType.TIRED);
// }
// }
//
// fishingRodCastTimestamp = System.currentTimeMillis();
// }
public void setFishHookReference(FishHook fishHook) {
if (fishHook.getMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF).size() > 0) {
return; return;
} }
fishHook.setMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF, fishHook.setMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF,
MetadataConstants.MCMMO_METADATA_VALUE); MetadataConstants.MCMMO_METADATA_VALUE);
this.fishHookReference = fishHook;
fishHookSpawnTimestamp = System.currentTimeMillis(); fishHookSpawnTimestamp = System.currentTimeMillis();
fishingRodCastTimestamp = System.currentTimeMillis();
} }
public boolean isFishingTooOften() { public boolean isFishingTooOften() {
@@ -180,21 +136,41 @@ public class FishingManager extends SkillManager {
} }
} }
/**
* Determines if the player is exploiting fishing by checking if they have caught
* more fish than the configured limit without moving their fishing spot.
* This method relies on internal state to determine if the player is exploiting fishing,
* and the centerOfCastVector parameter is no longer used and will be removed in
* a future version.
*
* @param centerOfCastVector unused
* @deprecated since 2.2.050, the parameter is no longer used and will be removed in
* a future version. The method now relies on internal state to determine if the player
* is exploiting fishing.
* @return true if the player is exploiting fishing, false otherwise
*/
@Deprecated(forRemoval = true, since = "2.2.050")
public boolean isExploitingFishing(Vector centerOfCastVector) { public boolean isExploitingFishing(Vector centerOfCastVector) {
return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance()
.getFishingExploitingOptionOverFishLimit();
}
/*Block targetBlock = getPlayer().getTargetBlock(BlockUtils.getTransparentBlocks(), 100); /**
* Determines if the player is exploiting fishing by checking if they have caught
if (!targetBlock.isLiquid()) { * more fish than the configured limit without moving their fishing spot.
return false; *
}*/ * @return true if the player is exploiting fishing, false otherwise
*/
public boolean isExploitingFishing() {
return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance() return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance()
.getFishingExploitingOptionOverFishLimit(); .getFishingExploitingOptionOverFishLimit();
} }
public static BoundingBox makeBoundingBox(Vector centerOfCastVector) { public static BoundingBox makeBoundingBox(Vector centerOfCastVector) {
int exploitingRange = ExperienceConfig.getInstance().getFishingExploitingOptionMoveRange(); int exploitingRange = ExperienceConfig.getInstance().getFishingExploitingOptionMoveRange();
return BoundingBox.of(centerOfCastVector, exploitingRange / 2, 1, exploitingRange / 2); return BoundingBox.of(centerOfCastVector,
(double) exploitingRange / 2, 1,
(double) exploitingRange / 2);
} }
public void setFishingTarget() { public void setFishingTarget() {
@@ -243,15 +219,6 @@ public class FishingManager extends SkillManager {
return mcMMO.p.getAdvancedConfig().getFishingVanillaXPModifier(getLootTier()); return mcMMO.p.getAdvancedConfig().getFishingVanillaXPModifier(getLootTier());
} }
/**
* Gets the Shake Mob probability
*
* @return Shake Mob probability
*/
public double getShakeProbability() {
return getShakeChance();
}
/** /**
* Handle the Fisherman's Diet ability * Handle the Fisherman's Diet ability
* *
@@ -293,102 +260,95 @@ public class FishingManager extends SkillManager {
* @param fishHook target fish hook * @param fishHook target fish hook
*/ */
public void processMasterAngler(@NotNull FishHook fishHook, int lureLevel) { public void processMasterAngler(@NotNull FishHook fishHook, int lureLevel) {
MasterAnglerCompatibilityLayer masterAnglerCompatibilityLayer = (MasterAnglerCompatibilityLayer) mcMMO.getCompatibilityManager() int maxWaitTicks = fishHook.getMaxWaitTime();
.getMasterAnglerCompatibilityLayer(); int minWaitTicks = fishHook.getMinWaitTime();
if (masterAnglerCompatibilityLayer != null) { int masterAnglerRank = RankUtils.getRank(mmoPlayer, SubSkillType.FISHING_MASTER_ANGLER);
int maxWaitTicks = masterAnglerCompatibilityLayer.getMaxWaitTime(fishHook); int convertedLureBonus = 0;
int minWaitTicks = masterAnglerCompatibilityLayer.getMinWaitTime(fishHook);
int masterAnglerRank = RankUtils.getRank(mmoPlayer, SubSkillType.FISHING_MASTER_ANGLER); //This avoids a Minecraft bug where lure levels above 3 break fishing
int convertedLureBonus = 0; if (lureLevel > 0) {
fishHook.setApplyLure(false);
//This avoids a Minecraft bug where lure levels above 3 break fishing convertedLureBonus = lureLevel * 100;
if (lureLevel > 0) {
masterAnglerCompatibilityLayer.setApplyLure(fishHook, false);
convertedLureBonus = lureLevel * 100;
}
boolean boatBonus = isInBoat();
int minWaitReduction = getMasterAnglerTickMinWaitReduction(masterAnglerRank, boatBonus);
int maxWaitReduction = getMasterAnglerTickMaxWaitReduction(masterAnglerRank, boatBonus,
convertedLureBonus);
int reducedMinWaitTime = getReducedTicks(minWaitTicks, minWaitReduction,
masterAnglerMinWaitLowerBound);
int reducedMaxWaitTime = getReducedTicks(maxWaitTicks, maxWaitReduction,
masterAnglerMaxWaitLowerBound);
boolean badValuesFix = false;
//If we find bad values correct it
if (reducedMaxWaitTime < reducedMinWaitTime) {
reducedMaxWaitTime = reducedMinWaitTime + 100;
badValuesFix = true;
}
final McMMOPlayerMasterAnglerEvent event =
new McMMOPlayerMasterAnglerEvent(mmoPlayer, reducedMinWaitTime,
reducedMaxWaitTime, this);
mcMMO.p.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
reducedMaxWaitTime = event.getReducedMaxWaitTime();
reducedMinWaitTime = event.getReducedMinWaitTime();
if (mmoPlayer.isDebugMode()) {
mmoPlayer.getPlayer().sendMessage(ChatColor.GOLD + "Master Angler Debug");
if (badValuesFix) {
mmoPlayer.getPlayer()
.sendMessage(ChatColor.RED + "Bad values were applied and corrected," +
" check your configs, minWaitLowerBound wait should never be lower than min wait.");
}
mmoPlayer.getPlayer().sendMessage(
"ALLOW STACK WITH LURE: " + masterAnglerCompatibilityLayer.getApplyLure(
fishHook));
mmoPlayer.getPlayer().sendMessage("MIN TICK REDUCTION: " + minWaitReduction);
mmoPlayer.getPlayer().sendMessage("MAX TICK REDUCTION: " + maxWaitReduction);
mmoPlayer.getPlayer().sendMessage("BOAT BONUS: " + boatBonus);
if (boatBonus) {
mmoPlayer.getPlayer()
.sendMessage("BOAT MAX TICK REDUCTION: " + maxWaitReduction);
mmoPlayer.getPlayer()
.sendMessage("BOAT MIN TICK REDUCTION: " + maxWaitReduction);
}
mmoPlayer.getPlayer().sendMessage("");
mmoPlayer.getPlayer()
.sendMessage(ChatColor.DARK_AQUA + "BEFORE MASTER ANGLER WAS APPLIED");
mmoPlayer.getPlayer().sendMessage("Original Max Wait Ticks: " + maxWaitTicks);
mmoPlayer.getPlayer().sendMessage("Original Min Wait Ticks: " + minWaitTicks);
mmoPlayer.getPlayer().sendMessage("");
mmoPlayer.getPlayer()
.sendMessage(ChatColor.DARK_AQUA + "AFTER MASTER ANGLER WAS APPLIED");
mmoPlayer.getPlayer().sendMessage("Current Max Wait Ticks: " + reducedMaxWaitTime);
mmoPlayer.getPlayer().sendMessage("Current Min Wait Ticks: " + reducedMinWaitTime);
mmoPlayer.getPlayer().sendMessage("");
mmoPlayer.getPlayer()
.sendMessage(ChatColor.DARK_AQUA + "Caps / Limits (edit in advanced.yml)");
mmoPlayer.getPlayer().sendMessage("Lowest possible minWaitLowerBound wait ticks "
+ masterAnglerMinWaitLowerBound);
mmoPlayer.getPlayer().sendMessage(
"Lowest possible min wait ticks " + masterAnglerMaxWaitLowerBound);
}
masterAnglerCompatibilityLayer.setMaxWaitTime(fishHook, reducedMaxWaitTime);
masterAnglerCompatibilityLayer.setMinWaitTime(fishHook, reducedMinWaitTime);
} }
boolean boatBonus = isInBoat();
int minWaitReduction = getMasterAnglerTickMinWaitReduction(masterAnglerRank, boatBonus);
int maxWaitReduction = getMasterAnglerTickMaxWaitReduction(masterAnglerRank, boatBonus,
convertedLureBonus);
int reducedMinWaitTime = getReducedTicks(minWaitTicks, minWaitReduction,
masterAnglerMinWaitLowerBound);
int reducedMaxWaitTime = getReducedTicks(maxWaitTicks, maxWaitReduction,
masterAnglerMaxWaitLowerBound);
boolean badValuesFix = false;
//If we find bad values correct it
if (reducedMaxWaitTime < reducedMinWaitTime) {
reducedMaxWaitTime = reducedMinWaitTime + 100;
badValuesFix = true;
}
final McMMOPlayerMasterAnglerEvent event =
new McMMOPlayerMasterAnglerEvent(mmoPlayer, reducedMinWaitTime,
reducedMaxWaitTime, this);
mcMMO.p.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
reducedMaxWaitTime = event.getReducedMaxWaitTime();
reducedMinWaitTime = event.getReducedMinWaitTime();
if (mmoPlayer.isDebugMode()) {
mmoPlayer.getPlayer().sendMessage(ChatColor.GOLD + "Master Angler Debug");
if (badValuesFix) {
mmoPlayer.getPlayer()
.sendMessage(ChatColor.RED + "Bad values were applied and corrected," +
" check your configs, minWaitLowerBound wait should never be lower than min wait.");
}
mmoPlayer.getPlayer().sendMessage(
"ALLOW STACK WITH LURE: " + fishHook.getApplyLure());
mmoPlayer.getPlayer().sendMessage("MIN TICK REDUCTION: " + minWaitReduction);
mmoPlayer.getPlayer().sendMessage("MAX TICK REDUCTION: " + maxWaitReduction);
mmoPlayer.getPlayer().sendMessage("BOAT BONUS: " + boatBonus);
if (boatBonus) {
mmoPlayer.getPlayer()
.sendMessage("BOAT MAX TICK REDUCTION: " + maxWaitReduction);
mmoPlayer.getPlayer()
.sendMessage("BOAT MIN TICK REDUCTION: " + maxWaitReduction);
}
mmoPlayer.getPlayer().sendMessage("");
mmoPlayer.getPlayer()
.sendMessage(ChatColor.DARK_AQUA + "BEFORE MASTER ANGLER WAS APPLIED");
mmoPlayer.getPlayer().sendMessage("Original Max Wait Ticks: " + maxWaitTicks);
mmoPlayer.getPlayer().sendMessage("Original Min Wait Ticks: " + minWaitTicks);
mmoPlayer.getPlayer().sendMessage("");
mmoPlayer.getPlayer()
.sendMessage(ChatColor.DARK_AQUA + "AFTER MASTER ANGLER WAS APPLIED");
mmoPlayer.getPlayer().sendMessage("Current Max Wait Ticks: " + reducedMaxWaitTime);
mmoPlayer.getPlayer().sendMessage("Current Min Wait Ticks: " + reducedMinWaitTime);
mmoPlayer.getPlayer().sendMessage("");
mmoPlayer.getPlayer()
.sendMessage(ChatColor.DARK_AQUA + "Caps / Limits (edit in advanced.yml)");
mmoPlayer.getPlayer().sendMessage("Lowest possible minWaitLowerBound wait ticks "
+ masterAnglerMinWaitLowerBound);
mmoPlayer.getPlayer().sendMessage(
"Lowest possible min wait ticks " + masterAnglerMaxWaitLowerBound);
}
fishHook.setMaxWaitTime(reducedMaxWaitTime);
fishHook.setMinWaitTime(reducedMinWaitTime);
} }
public int getReducedTicks(int ticks, int totalBonus, int tickBounds) { public int getReducedTicks(int ticks, int totalBonus, int tickBounds) {
@@ -446,7 +406,6 @@ public class FishingManager extends SkillManager {
* @param fishingCatch The {@link Item} initially caught * @param fishingCatch The {@link Item} initially caught
*/ */
public void processFishing(@NotNull Item fishingCatch) { public void processFishing(@NotNull Item fishingCatch) {
this.fishingCatch = fishingCatch;
int fishXp = ExperienceConfig.getInstance() int fishXp = ExperienceConfig.getInstance()
.getXp(PrimarySkillType.FISHING, fishingCatch.getItemStack().getType()); .getXp(PrimarySkillType.FISHING, fishingCatch.getItemStack().getType());
int treasureXp = 0; int treasureXp = 0;
@@ -458,7 +417,6 @@ public class FishingManager extends SkillManager {
if (mcMMO.p.getGeneralConfig().getFishingDropsEnabled() && Permissions.isSubSkillEnabled( if (mcMMO.p.getGeneralConfig().getFishingDropsEnabled() && Permissions.isSubSkillEnabled(
player, SubSkillType.FISHING_TREASURE_HUNTER)) { player, SubSkillType.FISHING_TREASURE_HUNTER)) {
treasure = getFishingTreasure(); treasure = getFishingTreasure();
this.fishingCatch = null;
} }
if (treasure != null) { if (treasure != null) {
@@ -541,10 +499,6 @@ public class FishingManager extends SkillManager {
return experience * getVanillaXpMultiplier(); return experience * getVanillaXpMultiplier();
} }
public Location getHookLocation() {
return hookLocation;
}
/** /**
* Handle the Shake ability * Handle the Shake ability
* *
@@ -692,11 +646,6 @@ public class FishingManager extends SkillManager {
treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability))); treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability)));
} }
//TODO: Add option to randomize the amount rewarded
/*if (treasureDrop.getAmount() > 1) {
treasureDrop.setAmount(Misc.getRandom().nextInt(treasureDrop.getAmount()) + 1);
}*/
treasure.setDrop(treasureDrop); treasure.setDrop(treasureDrop);
return treasure; return treasure;

View File

@@ -0,0 +1,36 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jetbrains.annotations.NotNull;
public class MinecraftGameVersionFactory {
public static @NotNull MinecraftGameVersion calculateGameVersion(
@NotNull String platformVersionString) {
int major = 0, minor = 0, patch = 0;
LogUtils.debug(mcMMO.p.getLogger(), "Platform String: " + platformVersionString);
// Gets two numbers separated by . and optional third number after next dot. Must end with - or _
Matcher versionMatch = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?[-_].*")
.matcher(platformVersionString);
if (versionMatch.find()) {
major = Integer.parseInt(versionMatch.group(1));
minor = Integer.parseInt(versionMatch.group(2));
if (versionMatch.group(3) != null) {
patch = Integer.parseInt(versionMatch.group(3));
}
}
LogUtils.debug(mcMMO.p.getLogger(), "Minecraft version determined to be - "
+ major + "."
+ minor + "."
+ patch);
return new MinecraftGameVersion(major, minor, patch);
}
}

View File

@@ -1,6 +0,0 @@
package com.gmail.nossr50.util;
public enum PotionCompatibilityType {
PRE_1_20_5,
MODERN
}

View File

@@ -1,8 +1,5 @@
package com.gmail.nossr50.util; package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -10,34 +7,19 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class PotionUtil { public final class PotionUtil {
// Some of the old potion types got renamed, our configs can still contain these old names // Some of the old potion types got renamed, our configs can still contain these old names
private static final Map<String, String> legacyPotionTypes = new HashMap<>(); private static final Map<String, String> legacyPotionTypes = new HashMap<>();
private static final Method methodPotionTypeGetKey;
private static final Method methodPotionTypeGetEffectType;
private static final Method methodPotionTypeGetPotionEffects;
private static final Method methodPotionDataIsUpgraded;
private static final Method methodPotionDataIsExtended;
private static final Method methodPotionDataGetType;
private static final Method methodPotionMetaGetBasePotionData;
private static final Method methodPotionMetaSetBasePotionData;
private static final Method methodPotionMetaGetBasePotionType;
private static final Method methodPotionMetaSetBasePotionType;
private static final Class<?> potionDataClass;
public static final String STRONG = "STRONG"; public static final String STRONG = "STRONG";
public static final String LONG = "LONG"; public static final String LONG = "LONG";
public static final String WATER_POTION_TYPE_STR = "WATER";
private static final PotionCompatibilityType COMPATIBILITY_MODE;
static { static {
potionDataClass = getPotionDataClass();
// Uncraftable doesn't exist in modern versions // Uncraftable doesn't exist in modern versions
// It served as a potion that didn't craft into anything else so it didn't conflict with vanilla systems // It served as a potion that didn't craft into anything else so it didn't conflict with vanilla systems
// Instead we will use Mundane, which doesn't make anything in vanilla systems // Instead we will use Mundane, which doesn't make anything in vanilla systems
@@ -47,199 +29,48 @@ public class PotionUtil {
legacyPotionTypes.put("INSTANT_HEAL", "HEALING"); legacyPotionTypes.put("INSTANT_HEAL", "HEALING");
legacyPotionTypes.put("INSTANT_DAMAGE", "HARMING"); legacyPotionTypes.put("INSTANT_DAMAGE", "HARMING");
legacyPotionTypes.put("REGEN", "REGENERATION"); legacyPotionTypes.put("REGEN", "REGENERATION");
methodPotionTypeGetKey = getKeyMethod();
methodPotionDataIsUpgraded = getPotionDataIsUpgraded();
methodPotionDataIsExtended = getPotionDataIsExtended();
methodPotionMetaGetBasePotionData = getGetBasePotionDataMethod();
methodPotionMetaGetBasePotionType = getGetBasePotionTypeMethod();
methodPotionMetaSetBasePotionType = getMethodPotionMetaSetBasePotionType();
methodPotionDataGetType = getPotionDataGetTypeMethod();
methodPotionTypeGetEffectType = getPotionTypeEffectTypeMethod();
methodPotionTypeGetPotionEffects = getPotionTypeGetPotionEffectsMethod();
methodPotionMetaSetBasePotionData = setBasePotionData();
if (potionDataClass != null
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 20, 5)) {
COMPATIBILITY_MODE = PotionCompatibilityType.PRE_1_20_5;
} else {
COMPATIBILITY_MODE = PotionCompatibilityType.MODERN;
}
} }
private PotionUtil() {}
/** /**
* Derive a potion from a partial name, and whether it should be upgraded or extended. * Derive a potion from a partial name, and whether it should be upgraded or extended.
* *
* @param partialName potion type as a string, can be a substring of the potion type but must * <p>In 1.20.5+, "upgraded" and "extended" are represented by distinct {@link PotionType}
* match exactly * constants (e.g. STRONG_HEALING, LONG_SWIFTNESS), not flags.
* @return The potion type
*/
public static PotionType matchPotionType(String partialName, boolean isUpgraded,
boolean isExtended) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return matchLegacyPotionType(partialName);
} else {
final String updatedName = convertLegacyNames(partialName).toUpperCase(Locale.ENGLISH);
return Arrays.stream(PotionType.values())
.filter(potionType -> getKeyGetKey(potionType)
.toUpperCase(Locale.ENGLISH).contains(updatedName))
.filter(potionType -> isUpgraded == potionType.name()
.toUpperCase(Locale.ENGLISH).startsWith(STRONG + "_"))
.filter(potionType -> isExtended == potionType.name()
.toUpperCase(Locale.ENGLISH).startsWith(LONG + "_"))
.findAny().orElse(null);
}
}
/**
* Legacy matching for {@link PotionType}
* *
* @param name The partial name of the potion * @param partialName potion type as a string, can be a substring of the potion type but must match
* @return The potion type * against the potion's key or enum name
* @return The potion type, or null if no match
*/ */
private static PotionType matchLegacyPotionType(String name) { public static @Nullable PotionType matchPotionType(String partialName, boolean isUpgraded, boolean isExtended) {
if (partialName == null || partialName.isEmpty()) {
return null;
}
final String updatedName = convertLegacyNames(partialName).toUpperCase(Locale.ENGLISH);
return Arrays.stream(PotionType.values()) return Arrays.stream(PotionType.values())
.filter(potionType -> getKeyGetKey(potionType).equalsIgnoreCase(name) // Allow matching by namespace key ("swiftness", "long_swiftness") or enum name
|| getKeyGetKey(potionType).equalsIgnoreCase(convertLegacyNames(name)) .filter(potionType -> {
|| potionType.name().equalsIgnoreCase(name) final NamespacedKey key = potionType.getKey();
|| potionType.name().equalsIgnoreCase(convertLegacyNames(name))) final String keyStr = key != null ? key.getKey() : "";
.findAny().orElse(null); return keyStr.toUpperCase(Locale.ENGLISH).contains(updatedName)
} || potionType.name().toUpperCase(Locale.ENGLISH).contains(updatedName);
})
private static String convertUpgradedOrExtended(String potionType, boolean isUpgraded, // Enforce strong/long selection by the enum name prefix convention
boolean isExtended) { .filter(potionType -> isUpgraded == potionType.name().startsWith(STRONG + "_"))
if (isUpgraded) { .filter(potionType -> isExtended == potionType.name().startsWith(LONG + "_"))
potionType = STRONG + "_" + potionType; .findAny()
} .orElse(null);
if (isExtended) {
potionType = LONG + "_" + potionType;
}
return potionType;
}
public static String getKeyGetKey(PotionType potionType) {
try {
if (getKeyMethod() != null) {
NamespacedKey key = (NamespacedKey) methodPotionTypeGetKey.invoke(potionType);
return key.getKey();
} else {
return potionType.name();
}
} catch (InvocationTargetException | IllegalAccessException e) {
mcMMO.p.getLogger().warning("Failed to get potion key for " + potionType.name());
return potionType.name();
}
}
private static Class<?> getPotionDataClass() {
try {
return Class.forName("org.bukkit.potion.PotionData");
} catch (ClassNotFoundException e) {
return null;
}
} }
/** /**
* Older versions of Spigot do not have getKey() in PotionType We need to check for the * Returns the NamespacedKey key string portion for this potion type (e.g. "swiftness").
* existence of this method before calling it
*
* @return The getKey method
*/ */
private static @Nullable Method getKeyMethod() { public static @NotNull String getKeyGetKey(@NotNull PotionType potionType) {
try { final NamespacedKey key = potionType.getKey();
return PotionType.class.getMethod("getKey"); return key != null ? key.getKey() : potionType.name();
} catch (NoSuchMethodException e) {
return null;
}
}
private static @Nullable Method setBasePotionData() {
try {
return PotionMeta.class.getMethod("setBasePotionData", potionDataClass);
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getMethodPotionMetaSetBasePotionType() {
try {
return PotionMeta.class.getMethod("setBasePotionType", PotionType.class);
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getSetBasePotionData() {
try {
return PotionMeta.class.getMethod("setBasePotionData", potionDataClass);
} catch (NoSuchMethodException e) {
return null;
}
}
private static @Nullable Method getPotionDataIsUpgraded() {
try {
// TODO: <?> Needed?
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
return clazz.getMethod("isUpgraded");
} catch (NoSuchMethodException | ClassNotFoundException e) {
return null;
}
}
private static @Nullable Method getPotionDataIsExtended() {
try {
// TODO: <?> Needed?
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
return clazz.getMethod("isExtended");
} catch (NoSuchMethodException | ClassNotFoundException e) {
return null;
}
}
/**
* Newer versions of Spigot do not have getBasePotionData() in PotionMeta
*
* @return the getBasePotionData method, or null if it does not exist
*/
private static @Nullable Method getGetBasePotionDataMethod() {
try {
return PotionMeta.class.getMethod("getBasePotionData");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getGetBasePotionTypeMethod() {
try {
return PotionMeta.class.getMethod("getBasePotionType");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getPotionDataGetTypeMethod() {
try {
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
return clazz.getMethod("getType");
} catch (NoSuchMethodException | ClassNotFoundException e) {
return null;
}
}
private static Method getPotionTypeEffectTypeMethod() {
try {
return PotionType.class.getMethod("getEffectType");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getPotionTypeGetPotionEffectsMethod() {
try {
return PotionType.class.getMethod("getPotionEffects");
} catch (NoSuchMethodException e) {
return null;
}
} }
public static String convertPotionConfigName(String legacyName) { public static String convertPotionConfigName(String legacyName) {
@@ -252,318 +83,91 @@ public class PotionUtil {
if (replacementName.contains("_II")) { if (replacementName.contains("_II")) {
replacementName = replacementName.replace("_II", ""); replacementName = replacementName.replace("_II", "");
replacementName = "STRONG_" + replacementName; replacementName = STRONG + "_" + replacementName;
} else if (replacementName.contains("_EXTENDED")) { } else if (replacementName.contains("_EXTENDED")) {
replacementName = replacementName.replace("_EXTENDED", ""); replacementName = replacementName.replace("_EXTENDED", "");
replacementName = "LONG_" + replacementName; replacementName = LONG + "_" + replacementName;
} }
return replacementName; return replacementName;
} }
public static String convertLegacyNames(String legacyPotionType) { public static String convertLegacyNames(String legacyPotionType) {
String modernized = legacyPotionType; String modernized = legacyPotionType;
// check for legacy names
for (var key : legacyPotionTypes.keySet()) { for (var key : legacyPotionTypes.keySet()) {
if (modernized.contains(key)) { if (modernized.contains(key)) {
// Replace the legacy name with the new name
modernized = modernized.replace(key, legacyPotionTypes.get(key)); modernized = modernized.replace(key, legacyPotionTypes.get(key));
break; break;
} }
} }
return modernized; return modernized;
} }
public static boolean hasLegacyName(String potionType) { public static boolean isStrong(@NotNull PotionMeta potionMeta) {
for (var key : legacyPotionTypes.keySet()) { final PotionType base = potionMeta.getBasePotionType();
if (potionType.contains(key)) { return base != null && base.name().startsWith(STRONG + "_");
return true;
}
}
return false;
} }
public static boolean isStrong(PotionMeta potionMeta) { public static boolean isLong(@NotNull PotionMeta potionMeta) {
if (methodPotionMetaGetBasePotionData == null) { final PotionType base = potionMeta.getBasePotionType();
return isStrongModern(potionMeta); return base != null && base.name().startsWith(LONG + "_");
} else {
return isStrongLegacy(potionMeta);
}
}
public static boolean isLong(PotionMeta potionMeta) {
if (methodPotionMetaGetBasePotionData == null) {
return isLongModern(potionMeta);
} else {
return isLongLegacy(potionMeta);
}
}
private static boolean isLongLegacy(PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
return (boolean) methodPotionDataIsExtended.invoke(potionData);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static boolean isLongModern(PotionMeta potionMeta) {
try {
return getModernPotionTypeKey(potionMeta).getKey().startsWith(LONG);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static boolean isStrongLegacy(PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
return (boolean) methodPotionDataIsUpgraded.invoke(potionData);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static boolean isStrongModern(PotionMeta potionMeta) {
try {
return getModernPotionTypeKey(potionMeta).getKey().startsWith(STRONG);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static NamespacedKey getModernPotionTypeKey(PotionMeta potionMeta)
throws IllegalAccessException, InvocationTargetException {
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(potionMeta);
return (NamespacedKey) methodPotionTypeGetKey.invoke(potionType);
}
public static boolean isPotionJustWater(PotionMeta potionMeta) {
return isPotionTypeWater(potionMeta)
&& !hasBasePotionEffects(potionMeta)
&& potionMeta.getCustomEffects().isEmpty();
} }
public static boolean isPotionTypeWater(@NotNull PotionMeta potionMeta) { public static boolean isPotionTypeWater(@NotNull PotionMeta potionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) { return potionMeta.getBasePotionType() == PotionType.WATER;
return isPotionTypeWaterLegacy(potionMeta); }
} else {
return isPotionTypeWaterModern(potionMeta); public static boolean hasBasePotionEffects(@NotNull PotionMeta potionMeta) {
final PotionType base = potionMeta.getBasePotionType();
if (base == null) {
return false;
} }
}
public static boolean isPotionType(@NotNull PotionMeta potionMeta, String potionType) { final List<PotionEffect> effects = base.getPotionEffects();
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) { return effects != null && !effects.isEmpty();
return isPotionTypeLegacy(potionMeta, potionType);
} else {
return isPotionTypeModern(potionMeta, potionType);
}
}
public static boolean isPotionTypeWithoutEffects(@NotNull PotionMeta potionMeta,
String potionType) {
return isPotionType(potionMeta, potionType)
&& !hasBasePotionEffects(potionMeta)
&& potionMeta.getCustomEffects().isEmpty();
}
private static boolean isPotionTypeModern(@NotNull PotionMeta potionMeta, String potionType) {
try {
return getModernPotionTypeKey(potionMeta).getKey().equalsIgnoreCase(potionType);
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private static boolean isPotionTypeLegacy(@NotNull PotionMeta potionMeta, String potionType) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
PotionType potionTypeObj = (PotionType) methodPotionDataGetType.invoke(potionData);
return potionTypeObj.name().equalsIgnoreCase(potionType);
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private static boolean isPotionTypeWaterLegacy(@NotNull PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
return potionType.name().equalsIgnoreCase(WATER_POTION_TYPE_STR)
|| PotionType.valueOf(WATER_POTION_TYPE_STR) == potionType;
} catch (InvocationTargetException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
private static boolean isPotionTypeWaterModern(@NotNull PotionMeta potionMeta) {
try {
return getModernPotionTypeKey(potionMeta).getKey()
.equalsIgnoreCase(WATER_POTION_TYPE_STR);
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
public static boolean samePotionType(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return samePotionTypeLegacy(potionMeta, otherPotionMeta);
} else {
return samePotionTypeModern(potionMeta, otherPotionMeta);
}
}
private static boolean samePotionTypeLegacy(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
Object otherPotionData = methodPotionMetaGetBasePotionData.invoke(otherPotionMeta);
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
PotionType otherPotionType = (PotionType) methodPotionDataGetType.invoke(
otherPotionData);
return potionType == otherPotionType;
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private static boolean samePotionTypeModern(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
try {
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(
potionMeta);
PotionType otherPotionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(
otherPotionMeta);
return potionType == otherPotionType;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public static boolean samePotionEffects(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return true;
} else {
return samePotionEffectsModern(potionMeta, otherPotionMeta);
}
}
private static boolean samePotionEffectsModern(PotionMeta potionMeta,
PotionMeta otherPotionMeta) {
return potionMeta.getCustomEffects().equals(otherPotionMeta.getCustomEffects());
}
public static boolean hasBasePotionEffects(PotionMeta potionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return hasBasePotionEffectsLegacy(potionMeta);
} else {
return hasBasePotionEffectsModern(potionMeta);
}
}
private static boolean hasBasePotionEffectsLegacy(PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
return methodPotionTypeGetEffectType.invoke(potionType) != null;
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private static boolean hasBasePotionEffectsModern(PotionMeta potionMeta) {
try {
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(
potionMeta);
List<PotionEffectType> potionEffectTypeList = (List<PotionEffectType>) methodPotionTypeGetPotionEffects.invoke(
potionType);
return potionEffectTypeList != null && !potionEffectTypeList.isEmpty();
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
} }
/** /**
* Set the base potion type of a potion meta. Note that extended/upgraded are ignored in 1.20.5 * Set the base potion type of a potion meta. Note that extended/upgraded are ignored in 1.20.5
* and later. * and later.
* *
* @param potionMeta the potion meta * <p>In 1.20.5+, "extended/upgraded" are encoded into {@link PotionType} variants. This method
* @param extended true if the potion is extended * attempts to select the appropriate STRONG_/LONG_ variant when requested. If no such variant
* @param upgraded true if the potion is upgraded * exists, it falls back to the provided base type.</p>
*/ */
public static void setBasePotionType(PotionMeta potionMeta, PotionType potionType, public static void setBasePotionType(@NotNull PotionMeta potionMeta,
boolean extended, boolean upgraded) { @NotNull PotionType potionType, boolean extended, boolean upgraded) {
if (methodPotionMetaSetBasePotionType == null) { final PotionType resolved = resolveVariant(potionType, upgraded, extended);
setBasePotionTypeLegacy(potionMeta, potionType, extended, upgraded); potionMeta.setBasePotionType(resolved);
} else {
setBasePotionTypeModern(potionMeta, potionType);
}
} }
public static void setUpgradedAndExtendedProperties(PotionType potionType, private static @NotNull PotionType resolveVariant(@NotNull PotionType base, boolean upgraded,
PotionMeta potionMeta, boolean extended) {
boolean isUpgraded, boolean isExtended) { // Apply the same prefix scheme your code already expects
if (potionDataClass == null || mcMMO.getCompatibilityManager().getMinecraftGameVersion() String name = base.name();
.isAtLeast(1, 20, 5)) {
return; // Avoid double-prefixing if caller already passed LONG_/STRONG_ variants
if (name.startsWith(STRONG + "_")) {
upgraded = false;
}
if (name.startsWith(LONG + "_")) {
extended = false;
}
if (upgraded) {
name = STRONG + "_" + name;
}
if (extended) {
name = LONG + "_" + name;
} }
try { try {
final Object potionData = potionDataClass.getConstructor(PotionType.class, return PotionType.valueOf(name);
boolean.class, boolean.class) } catch (IllegalArgumentException ignored) {
.newInstance(potionType, isExtended, isUpgraded); // Not all potion types have strong/long variants; just use the provided base.
methodPotionMetaSetBasePotionData.invoke(potionMeta, potionData); return base;
} catch (IllegalAccessException | InvocationTargetException | InstantiationException
| NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}
private static void setBasePotionTypeLegacy(PotionMeta potionMeta, PotionType potionType,
boolean extended,
boolean upgraded) {
try {
Object potionData = potionDataClass.getConstructor(PotionType.class, boolean.class,
boolean.class)
.newInstance(potionType, extended, upgraded);
methodPotionMetaSetBasePotionData.invoke(potionMeta, potionData);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException |
NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}
private static void setBasePotionTypeModern(PotionMeta potionMeta, PotionType potionType) {
try {
methodPotionMetaSetBasePotionType.invoke(potionMeta, potionType);
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
public static boolean isPotionDataEqual(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.MODERN) {
return true; // we don't compare data on newer versions
} else {
try {
final Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
final Object otherPotionData = methodPotionMetaGetBasePotionData.invoke(
otherPotionMeta);
final PotionType potionType = (PotionType) methodPotionDataGetType.invoke(
potionData);
final PotionType otherPotionType = (PotionType) methodPotionDataGetType.invoke(
otherPotionData);
if (potionType != otherPotionType) {
return false;
}
if (methodPotionDataIsExtended.invoke(potionData)
!= methodPotionDataIsExtended.invoke(otherPotionData)) {
return false;
}
return methodPotionDataIsUpgraded.invoke(potionData)
== methodPotionDataIsUpgraded.invoke(otherPotionData);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
} }
} }
} }

View File

@@ -8,7 +8,6 @@ import com.gmail.nossr50.commands.McnotifyCommand;
import com.gmail.nossr50.commands.McrefreshCommand; import com.gmail.nossr50.commands.McrefreshCommand;
import com.gmail.nossr50.commands.McscoreboardCommand; import com.gmail.nossr50.commands.McscoreboardCommand;
import com.gmail.nossr50.commands.XprateCommand; import com.gmail.nossr50.commands.XprateCommand;
import com.gmail.nossr50.commands.admin.CompatibilityCommand;
import com.gmail.nossr50.commands.admin.McmmoReloadLocaleCommand; import com.gmail.nossr50.commands.admin.McmmoReloadLocaleCommand;
import com.gmail.nossr50.commands.admin.PlayerDebugCommand; import com.gmail.nossr50.commands.admin.PlayerDebugCommand;
import com.gmail.nossr50.commands.chat.McChatSpy; import com.gmail.nossr50.commands.chat.McChatSpy;
@@ -65,14 +64,7 @@ public final class CommandRegistrationManager {
private static void registerSkillCommands() { private static void registerSkillCommands() {
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) { for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType == PrimarySkillType.SPEARS if (primarySkillType == PrimarySkillType.SPEARS
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion() && !mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)) {
.isAtLeast(1, 21, 11)) {
continue;
}
if (primarySkillType == PrimarySkillType.MACES
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
continue; continue;
} }
@@ -411,13 +403,6 @@ public final class CommandRegistrationManager {
command.setExecutor(new McmmoReloadLocaleCommand()); command.setExecutor(new McmmoReloadLocaleCommand());
} }
private static void registerCompatibilityCommand() {
PluginCommand command = mcMMO.p.getCommand("mmocompat"); //TODO: Localize
command.setDescription(LocaleLoader.getString("Commands.Description.mmocompat"));
command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mmocompat"));
command.setExecutor(new CompatibilityCommand());
}
private static void registerXPBarCommand() { private static void registerXPBarCommand() {
PluginCommand command = mcMMO.p.getCommand("mmoxpbar"); //TODO: Localize PluginCommand command = mcMMO.p.getCommand("mmoxpbar"); //TODO: Localize
command.setDescription(LocaleLoader.getString("Commands.Description.mmoxpbar")); command.setDescription(LocaleLoader.getString("Commands.Description.mmoxpbar"));
@@ -473,8 +458,5 @@ public final class CommandRegistrationManager {
// Admin commands // Admin commands
registerReloadLocaleCommand(); registerReloadLocaleCommand();
// Misc
registerCompatibilityCommand();
} }
} }

View File

@@ -1,16 +0,0 @@
package com.gmail.nossr50.util.compat;
/**
* Compatibility Layers should be named after the functionality they serve
*/
public interface CompatibilityLayer {
/**
* Whether this CompatibilityLayer successfully initialized and in theory should be functional
*
* @return true if this CompatibilityLayer is functional
*/
default boolean noErrorsOnInitialize() {
return true;
}
}

View File

@@ -1,163 +0,0 @@
package com.gmail.nossr50.util.compat;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.LogUtils;
import com.gmail.nossr50.util.compat.layers.bungee.AbstractBungeeSerializerCompatibilityLayer;
import com.gmail.nossr50.util.compat.layers.bungee.BungeeLegacySerializerCompatibilityLayer;
import com.gmail.nossr50.util.compat.layers.bungee.BungeeModernSerializerCompatibilityLayer;
import com.gmail.nossr50.util.compat.layers.skills.AbstractMasterAnglerCompatibility;
import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer;
import com.gmail.nossr50.util.nms.NMSVersion;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.text.StringUtils;
import java.util.HashMap;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public class CompatibilityManager {
private @NotNull HashMap<CompatibilityType, Boolean> supportedLayers;
private boolean isFullyCompatibleServerSoftware = true; //true if all compatibility layers load successfully
private final @NotNull MinecraftGameVersion minecraftGameVersion;
private final @NotNull NMSVersion nmsVersion;
/* Compatibility Layers */
private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer;
private AbstractMasterAnglerCompatibility masterAnglerCompatibility;
public CompatibilityManager(@NotNull MinecraftGameVersion minecraftGameVersion) {
LogUtils.debug(mcMMO.p.getLogger(), "Loading compatibility layers...");
this.minecraftGameVersion = minecraftGameVersion;
this.nmsVersion = determineNMSVersion();
init();
LogUtils.debug(mcMMO.p.getLogger(), "Finished loading compatibility layers.");
}
private void init() {
initSupportedLayersMap();
initCompatibilityLayers();
}
private void initSupportedLayersMap() {
supportedLayers = new HashMap<>(); //Init map
for (CompatibilityType compatibilityType : CompatibilityType.values()) {
supportedLayers.put(compatibilityType,
false); //All layers are set to false when initialized
}
}
/**
* Initialize all necessary compatibility layers For any unsupported layers, load a dummy layer
*/
private void initCompatibilityLayers() {
initBungeeSerializerLayer();
initMasterAnglerLayer();
isFullyCompatibleServerSoftware = true;
}
private void initMasterAnglerLayer() {
if (minecraftGameVersion.isAtLeast(1, 16, 3)) {
masterAnglerCompatibility = new MasterAnglerCompatibilityLayer();
} else {
masterAnglerCompatibility = null;
}
}
private void initBungeeSerializerLayer() {
if (minecraftGameVersion.isAtLeast(1, 16, 0)) {
bungeeSerializerCompatibilityLayer = new BungeeModernSerializerCompatibilityLayer();
} else {
bungeeSerializerCompatibilityLayer = new BungeeLegacySerializerCompatibilityLayer();
}
supportedLayers.put(CompatibilityType.BUNGEE_SERIALIZER, true);
}
//TODO: move to text manager
public void reportCompatibilityStatus(@NotNull CommandSender commandSender) {
if (isFullyCompatibleServerSoftware) {
commandSender.sendMessage(LocaleLoader.getString("mcMMO.Template.Prefix",
"mcMMO is fully compatible with the currently running server software."));
} else {
//TODO: Better messages for each incompatible layer
for (CompatibilityType compatibilityType : CompatibilityType.values()) {
if (!supportedLayers.get(compatibilityType)) {
commandSender.sendMessage(LocaleLoader.getString("mcMMO.Template.Prefix",
LocaleLoader.getString("Compatibility.Layer.Unsupported",
StringUtils.getCapitalized(compatibilityType.toString()))));
}
}
}
commandSender.sendMessage(LocaleLoader.getString("mcMMO.Template.Prefix",
"NMS Status - " + nmsVersion));
}
public boolean isCompatibilityLayerOperational(@NotNull CompatibilityType compatibilityType) {
return supportedLayers.get(compatibilityType);
}
public boolean isFullyCompatibleServerSoftware() {
return isFullyCompatibleServerSoftware;
}
public @NotNull NMSVersion getNmsVersion() {
return nmsVersion;
}
private @NotNull NMSVersion determineNMSVersion() {
//This bit here helps prevent mcMMO breaking if it isn't updated but the game continues to update
if (minecraftGameVersion.isAtLeast(1, 17, 0)) {
return NMSVersion.NMS_1_17;
}
//Messy but it works
if (minecraftGameVersion.getMajorVersion().asInt() == 1) {
switch (minecraftGameVersion.getMinorVersion().asInt()) {
case 12:
return NMSVersion.NMS_1_12_2;
case 13:
return NMSVersion.NMS_1_13_2;
case 14:
return NMSVersion.NMS_1_14_4;
case 15:
return NMSVersion.NMS_1_15_2;
case 16:
if (minecraftGameVersion.getPatchVersion().asInt() == 1) {
return NMSVersion.NMS_1_16_1;
} else if (minecraftGameVersion.getPatchVersion().asInt() == 2) {
return NMSVersion.NMS_1_16_2;
} else if (minecraftGameVersion.getPatchVersion().asInt() == 3) {
return NMSVersion.NMS_1_16_3;
} else if (minecraftGameVersion.getPatchVersion().asInt() == 4) {
return NMSVersion.NMS_1_16_4;
} else if (minecraftGameVersion.getPatchVersion().asInt() >= 5) {
return NMSVersion.NMS_1_16_5;
}
case 17:
return NMSVersion.NMS_1_17;
}
}
return NMSVersion.UNSUPPORTED;
}
public AbstractBungeeSerializerCompatibilityLayer getBungeeSerializerCompatibilityLayer() {
return bungeeSerializerCompatibilityLayer;
}
public @Nullable AbstractMasterAnglerCompatibility getMasterAnglerCompatibilityLayer() {
return masterAnglerCompatibility;
}
public @NotNull MinecraftGameVersion getMinecraftGameVersion() {
return minecraftGameVersion;
}
}

View File

@@ -1,7 +0,0 @@
package com.gmail.nossr50.util.compat;
public enum CompatibilityType {
PERSISTENT_DATA,
BUNGEE_SERIALIZER,
MASTER_ANGLER,
}

View File

@@ -1,24 +0,0 @@
package com.gmail.nossr50.util.compat.layers;
import com.gmail.nossr50.util.compat.CompatibilityLayer;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public abstract class AbstractCompatibilityLayer implements CompatibilityLayer {
protected boolean noErrorsOnInitialize = true;
/**
* Initialize the CompatibilityLayer
*
* @return true if the CompatibilityLayer initialized and should be functional
*/
public abstract boolean initializeLayer();
@Override
public boolean noErrorsOnInitialize() {
return noErrorsOnInitialize;
}
}

View File

@@ -1,29 +0,0 @@
package com.gmail.nossr50.util.compat.layers;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.jetbrains.annotations.NotNull;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public abstract class AbstractNMSCompatibilityLayer extends AbstractCompatibilityLayer {
protected final @NotNull NMSVersion nmsVersion;
public AbstractNMSCompatibilityLayer(@NotNull NMSVersion nmsVersion) {
this.nmsVersion = nmsVersion;
}
/**
* Initialize the CompatibilityLayer
*
* @return true if the CompatibilityLayer initialized and should be functional
*/
public abstract boolean initializeLayer();
@Override
public boolean noErrorsOnInitialize() {
return noErrorsOnInitialize;
}
}

View File

@@ -1,42 +0,0 @@
//package com.gmail.nossr50.util.compat.layers.attackcooldown;
//
//import com.gmail.nossr50.util.nms.NMSVersion;
//import org.bukkit.entity.Player;
//import org.jetbrains.annotations.NotNull;
//
//import java.lang.reflect.InvocationTargetException;
//
//public class DummyPlayerAttackCooldownToolLayer extends PlayerAttackCooldownToolLayer {
// public DummyPlayerAttackCooldownToolLayer() {
// super(NMSVersion.UNSUPPORTED);
// }
//
// @Override
// public boolean initializeLayer() {
// return noErrorsOnInitialize;
// }
//
// @Override
// public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// return 1.0F; //Always full strength
// }
//
// @Override
// public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// return 0F;
// }
//
// @Override
// public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// //Do nothing
// }
//
// @Override
// public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// return 0;
// }
//
// @Override
// public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
// }
//}

View File

@@ -1,30 +0,0 @@
package com.gmail.nossr50.util.compat.layers.attackcooldown;
import java.lang.reflect.InvocationTargetException;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public interface PlayerAttackCooldownMethods {
/**
* Grabs the attack strength for a player Should be noted that as of today there is no way to
* capture a players current attack strength in spigot when they attack an entity outside of
* network packet listening
*
* @param player target player
* @return the float value of the player's attack strength
*/
float getAttackStrength(@NotNull Player player)
throws InvocationTargetException, IllegalAccessException;
float getCooldownValue(@NotNull Player player)
throws InvocationTargetException, IllegalAccessException;
void resetAttackStrength(@NotNull Player player)
throws InvocationTargetException, IllegalAccessException;
int getCooldownFieldValue(@NotNull Player player)
throws InvocationTargetException, IllegalAccessException;
void setCooldownFieldValue(@NotNull Player player, int fieldValue)
throws InvocationTargetException, IllegalAccessException;
}

View File

@@ -1,238 +0,0 @@
//package com.gmail.nossr50.util.compat.layers.attackcooldown;
//
//import com.gmail.nossr50.mcMMO;
//import com.gmail.nossr50.util.compat.layers.AbstractNMSCompatibilityLayer;
//import com.gmail.nossr50.util.nms.NMSConstants;
//import com.gmail.nossr50.util.nms.NMSVersion;
//import org.bukkit.entity.Player;
//import org.jetbrains.annotations.NotNull;
//import org.jetbrains.annotations.Nullable;
//
//import java.lang.reflect.Field;
//import java.lang.reflect.InvocationTargetException;
//import java.lang.reflect.Method;
//
/// **
// *
// * These classes are a band-aid solution for adding NMS support into 2.1.XXX
// * In 2.2 we are switching to modules and that will clean things up significantly
// *
// */
//public class PlayerAttackCooldownToolLayer extends AbstractNMSCompatibilityLayer implements PlayerAttackCooldownMethods {
//
// private final String cbNMSVersionPath;
//
// protected Class<?> craftPlayerClass;
// protected Class<?> entityHumanClass;
// protected Class<?> entityLivingClass;
//
// protected Method playerAttackCooldownMethod;
// protected Method playerAttackStrengthMethod;
// protected Method resetPlayerAttackCooldownMethod;
// protected Method setPlayerAttackStrengthMethod;
// protected Method getHandleMethod;
// protected Field attackCooldownField;
// protected String attackStrengthFieldName;
//
// public PlayerAttackCooldownToolLayer(@NotNull NMSVersion nmsVersion) {
// super(nmsVersion);
// mcMMO.p.getLogger().info("Loading Compatibility Layer... (Player Attack Cooldown Exploit Prevention)");
// if (!isCompatibleWithMinecraftVersion(nmsVersion)) {
// mcMMO.p.getLogger().severe("this version of mcMMO does not support NMS for this version of Minecraft, try updating mcMMO or updating Minecraft. Not all versions of Minecraft will have NMS support built into mcMMO.");
// cbNMSVersionPath = "";
// } else {
// if (NMSConstants.getCraftBukkitVersionPath(nmsVersion) != null) {
// cbNMSVersionPath = NMSConstants.getCraftBukkitVersionPath(nmsVersion);
// noErrorsOnInitialize = initializeLayer();
//
// if (noErrorsOnInitialize) {
// mcMMO.p.getLogger().info("Successfully Loaded Compatibility Layer! (Player Attack Cooldown Exploit Prevention)");
// }
// } else {
// mcMMO.p.getLogger().info("Failed to load - CL (Player Attack Cooldown Exploit Prevention) Could not find CB NMS path for CL");
// flagErrorsDuringStartup();
// mcMMO.p.getLogger().warning("Could not wire NMS package path for CraftBukkit!");
// cbNMSVersionPath = "";
// }
// }
// }
//
// public static boolean isCompatibleWithMinecraftVersion(@NotNull NMSVersion nmsVersion) {
// switch(nmsVersion) {
// case NMS_1_13_2:
// case NMS_1_14_4:
// case NMS_1_15_2:
// case NMS_1_16_4:
// case NMS_1_16_5:
// return true;
// default:
// return false;
// }
// }
//
// /**
// * Cache all reflection methods/types/classes needed for the NMS of this CompatibilityLayer
// * @param cooldownMethodName the cooldown method name
// * @param attackStrengthMethodName the attack strength method name
// * @param resetAttackCooldownMethodName the reset attack cooldown method name
// * @param getHandleMethodName the get handle method name
// * @return true if NMS was successfully wired
// */
// public boolean wireNMS(@NotNull String cooldownMethodName, @NotNull String attackStrengthMethodName, @NotNull String resetAttackCooldownMethodName, @NotNull String getHandleMethodName, @NotNull String attackStrengthFieldName) {
// entityHumanClass = initEntityHumanClass();
//
// if (entityHumanClass != null) {
// entityLivingClass = entityHumanClass.getSuperclass();
// }
//
// craftPlayerClass = initCraftPlayerClass();
// this.attackStrengthFieldName = attackStrengthFieldName;
//
// try {
// this.attackCooldownField = entityLivingClass.getDeclaredField(attackStrengthFieldName);
// this.attackCooldownField.setAccessible(true);
// } catch (NoSuchFieldException e) {
// e.printStackTrace();
// }
//
// try {
// this.playerAttackCooldownMethod = entityHumanClass.getMethod(cooldownMethodName);
// this.playerAttackStrengthMethod = entityHumanClass.getMethod(attackStrengthMethodName, float.class);
// this.resetPlayerAttackCooldownMethod = entityHumanClass.getMethod(resetAttackCooldownMethodName);
//
// if (craftPlayerClass != null) {
// this.getHandleMethod = craftPlayerClass.getMethod(getHandleMethodName);
// } else {
// return false;
// }
// return true;
// } catch (NoSuchMethodException e) {
// flagErrorsDuringStartup();
// e.printStackTrace();
// return false;
// }
// }
//
// /**
// * Get the cached player attack cooldown method
// * @return the cached player attack cooldown method
// */
// private @Nullable Method getPlayerAttackCooldownMethod() {
// return playerAttackCooldownMethod;
// }
//
// /**
// * Get the cached player attack strength method
// * @return the cached player attack strength method
// */
// private @Nullable Method getPlayerAttackStrengthMethod() {
// return playerAttackStrengthMethod;
// }
//
// /**
// * Get the cached player attack cooldown reset method
// * @return the cached player attack cooldown reset method
// */
// private @Nullable Method getResetPlayerAttackCooldownMethod() {
// return resetPlayerAttackCooldownMethod;
// }
//
// /**
// * Grab the CraftPlayer class type from NMS
// * @return the CraftPlayer class type from NMS
// */
// private @Nullable Class<?> initCraftPlayerClass() {
// try {
// return Class.forName(NMSConstants.getCraftPlayerClassPath(cbNMSVersionPath));
// } catch (ClassNotFoundException e) {
// flagErrorsDuringStartup();
// e.printStackTrace();
// return null;
// }
// }
//
// /**
// * Grab the EntityHuman class type from NMS
// * @return the EntityHuman class type from NMS
// */
// private @Nullable Class<?> initEntityHumanClass() {
// try {
// return Class.forName(NMSConstants.getEntityHumanClassPath(cbNMSVersionPath));
// } catch (ClassNotFoundException e) {
// flagErrorsDuringStartup();
// e.printStackTrace();
// return null;
// }
// }
//
// private void flagErrorsDuringStartup() {
// noErrorsOnInitialize = false;
// }
//
// /**
// * Grabs the attack strength for a player
// * Should be noted that as of today there is no way to capture a players current attack strength in spigot when they attack an entity outside of network packet listening
// * @param player target player
// * @return the float value of the player's attack strength
// */
// @Override
// public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
//
// return (float) playerAttackStrengthMethod.invoke(entityHuman, 0F); //Add no adjustment ticks
// }
//
// @Override
// public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
//
// return (float) playerAttackCooldownMethod.invoke(entityHuman); //Add no adjustment ticks
// }
//
// @Override
// public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
// Object entityLiving = entityLivingClass.cast(entityHuman);
//
// resetPlayerAttackCooldownMethod.invoke(entityLiving);
// }
//
// @Override
// public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
// Object entityLiving = entityLivingClass.cast(entityHuman);
//
// return attackCooldownField.getInt(entityLiving);
// }
//
// @Override
// public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
//
// attackCooldownField.setInt(entityHuman, fieldValue);
// }
//
// @Override
// public boolean initializeLayer() {
// switch(nmsVersion) {
// case NMS_1_12_2:
// return wireNMS("dr", "n", "ds", "getHandle", "at");
// case NMS_1_13_2:
// return wireNMS("dG", "r", "dH", "getHandle", "at");
// case NMS_1_14_4:
// return wireNMS("dY", "s", "dZ", "getHandle", "at");
// case NMS_1_15_2:
// return wireNMS("ex", "s", "ey", "getHandle", "at");
// case NMS_1_16_4:
// return wireNMS("eR", "getAttackCooldown", "resetAttackCooldown", "getHandle", "at");
// default:
// throw new RuntimeException("Unexpected NMS version support in PlayerAttackCooldown compatibility layer initialization!");
// }
// }
//}
//

View File

@@ -1,11 +0,0 @@
package com.gmail.nossr50.util.compat.layers.bungee;
import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.chat.BaseComponent;
import org.checkerframework.checker.nullness.qual.NonNull;
public abstract class AbstractBungeeSerializerCompatibilityLayer {
public abstract @NonNull Component deserialize(final @NonNull BaseComponent @NonNull [] input);
}

View File

@@ -1,14 +0,0 @@
package com.gmail.nossr50.util.compat.layers.bungee;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import org.checkerframework.checker.nullness.qual.NonNull;
public class BungeeLegacySerializerCompatibilityLayer extends
AbstractBungeeSerializerCompatibilityLayer {
@Override
public @NonNull Component deserialize(@NonNull BaseComponent @NonNull [] input) {
return BungeeComponentSerializer.legacy().deserialize(input);
}
}

View File

@@ -1,14 +0,0 @@
package com.gmail.nossr50.util.compat.layers.bungee;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import org.checkerframework.checker.nullness.qual.NonNull;
public class BungeeModernSerializerCompatibilityLayer extends
AbstractBungeeSerializerCompatibilityLayer {
@Override
public @NonNull Component deserialize(@NonNull BaseComponent @NonNull [] input) {
return BungeeComponentSerializer.get().deserialize(input);
}
}

View File

@@ -1,6 +0,0 @@
package com.gmail.nossr50.util.compat.layers.skills;
import com.gmail.nossr50.util.compat.layers.AbstractCompatibilityLayer;
public abstract class AbstractMasterAnglerCompatibility extends AbstractCompatibilityLayer {
}

View File

@@ -1,79 +0,0 @@
package com.gmail.nossr50.util.compat.layers.skills;
import org.bukkit.entity.FishHook;
import org.jetbrains.annotations.NotNull;
public class MasterAnglerCompatibilityLayer extends AbstractMasterAnglerCompatibility {
@Override
public boolean initializeLayer() {
return true;
}
/**
* Get the minimum number of ticks one has to wait for a fish biting.
* <p>
* The default is 100 ticks (5 seconds).<br> Note that this is before applying lure.
*
* @return Minimum number of ticks one has to wait for a fish biting
*/
public int getMinWaitTime(@NotNull FishHook fishHook) {
return fishHook.getMinWaitTime();
}
/**
* Set the minimum number of ticks one has to wait for a fish biting.
* <p>
* The default is 100 ticks (5 seconds).<br> Note that this is before applying lure.
*
* @param minWaitTime Minimum number of ticks one has to wait for a fish biting
*/
public void setMinWaitTime(@NotNull FishHook fishHook, int minWaitTime) {
fishHook.setMinWaitTime(minWaitTime);
}
/**
* Get the maximum number of ticks one has to wait for a fish biting.
* <p>
* The default is 600 ticks (30 seconds).<br> Note that this is before applying lure.
*
* @return Maximum number of ticks one has to wait for a fish biting
*/
public int getMaxWaitTime(@NotNull FishHook fishHook) {
return fishHook.getMaxWaitTime();
}
/**
* Set the maximum number of ticks one has to wait for a fish biting.
* <p>
* The default is 600 ticks (30 seconds).<br> Note that this is before applying lure.
*
* @param maxWaitTime Maximum number of ticks one has to wait for a fish biting
*/
public void setMaxWaitTime(@NotNull FishHook fishHook, int maxWaitTime) {
fishHook.setMaxWaitTime(maxWaitTime);
}
/**
* Get whether the lure enchantment should be applied to reduce the wait time.
* <p>
* The default is true.<br> Lure reduces the wait time by 100 ticks (5 seconds) for each level
* of the enchantment.
*
* @return Whether the lure enchantment should be applied to reduce the wait time
*/
public boolean getApplyLure(@NotNull FishHook fishHook) {
return fishHook.getApplyLure();
}
/**
* Set whether the lure enchantment should be applied to reduce the wait time.
* <p>
* The default is true.<br> Lure reduces the wait time by 100 ticks (5 seconds) for each level
* of the enchantment.
*
* @param applyLure Whether the lure enchantment should be applied to reduce the wait time
*/
public void setApplyLure(@NotNull FishHook fishHook, boolean applyLure) {
fishHook.setApplyLure(applyLure);
}
}

View File

@@ -1,22 +0,0 @@
package com.gmail.nossr50.util.platform;
import com.gmail.nossr50.util.compat.CompatibilityManager;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public abstract class AbstractPlatform implements Platform {
protected final CompatibilityManager compatibilityManager;
protected final MinecraftGameVersion minecraftGameVersion;
protected final ServerSoftwareType serverSoftwareType;
public AbstractPlatform(MinecraftGameVersion minecraftGameVersion,
ServerSoftwareType serverSoftwareType, CompatibilityManager compatibilityManager) {
this.minecraftGameVersion = minecraftGameVersion;
this.serverSoftwareType = serverSoftwareType;
this.compatibilityManager = compatibilityManager;
}
}

View File

@@ -1,31 +0,0 @@
package com.gmail.nossr50.util.platform;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import org.jetbrains.annotations.NotNull;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public class BukkitPlatform extends AbstractPlatform {
public BukkitPlatform(MinecraftGameVersion minecraftGameVersion) {
super(minecraftGameVersion, ServerSoftwareType.CRAFT_BUKKIT,
new CompatibilityManager(minecraftGameVersion));
}
@Override
public @NotNull ServerSoftwareType getServerSoftwareType() {
return super.serverSoftwareType;
}
@Override
public @NotNull CompatibilityManager getCompatibilityManager() {
return compatibilityManager;
}
@Override
public @NotNull MinecraftGameVersion getGameVersion() {
return super.minecraftGameVersion;
}
}

View File

@@ -1,33 +0,0 @@
package com.gmail.nossr50.util.platform;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import org.jetbrains.annotations.NotNull;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public interface Platform {
/**
* Target {@link ServerSoftwareType} for this {@link Platform}
*
* @return the {@link ServerSoftwareType} for this {@link Platform}
*/
@NotNull ServerSoftwareType getServerSoftwareType();
/**
* Get the {@link CompatibilityManager} for this {@link Platform}
*
* @return the {@link CompatibilityManager} for this platform
*/
@NotNull CompatibilityManager getCompatibilityManager();
/**
* The target game version of this {@link Platform}
*
* @return the target {@link MinecraftGameVersion} of this {@link Platform}
*/
@NotNull MinecraftGameVersion getGameVersion();
}

View File

@@ -1,27 +0,0 @@
package com.gmail.nossr50.util.platform;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public class PlatformBuilder {
private MinecraftGameVersion minecraftGameVersion;
public PlatformBuilder() {
}
public PlatformBuilder setMinecraftGameVersion(
@NotNull MinecraftGameVersion minecraftGameVersion) {
this.minecraftGameVersion = minecraftGameVersion;
return this;
}
public @Nullable Platform build() {
return new BukkitPlatform(minecraftGameVersion);
}
}

View File

@@ -1,72 +0,0 @@
package com.gmail.nossr50.util.platform;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.LogUtils;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
* to modules and that will clean things up significantly
*/
public class PlatformManager {
protected Platform platform; //current platform
public PlatformManager() {
init();
}
private void init() {
platform = loadPlatform();
}
public Platform getPlatform() {
return platform;
}
private @Nullable Platform loadPlatform() {
PlatformBuilder platformBuilder = new PlatformBuilder();
MinecraftGameVersion gameVersion = determineGameVersion(Bukkit.getBukkitVersion());
return platformBuilder
.setMinecraftGameVersion(gameVersion)
.build();
}
//TODO: make this work on things other than bukkit
@Deprecated //Only good for determining bukkit game versions
private @NotNull MinecraftGameVersion determineGameVersion(String platformVersionString) {
int major = 0, minor = 0, patch = 0;
LogUtils.debug(mcMMO.p.getLogger(), "Platform String: " + platformVersionString);
// Gets two numbers separated by . and optional third number after next dot. Must end with - or _
Matcher versionMatch = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?[-_].*")
.matcher(platformVersionString);
if (versionMatch.find()) {
major = Integer.parseInt(versionMatch.group(1));
minor = Integer.parseInt(versionMatch.group(2));
if (versionMatch.group(3) != null) {
patch = Integer.parseInt(versionMatch.group(3));
}
}
LogUtils.debug(mcMMO.p.getLogger(), "Minecraft version determined to be - "
+ major + "."
+ minor + "."
+ patch);
return new MinecraftGameVersion(major, minor, patch);
}
public @Nullable CompatibilityManager getCompatibilityManager() {
return platform.getCompatibilityManager();
}
}

View File

@@ -241,9 +241,7 @@ public class SkillTools {
@VisibleForTesting @VisibleForTesting
@NotNull @NotNull
ImmutableList<PrimarySkillType> buildCombatSkills() { ImmutableList<PrimarySkillType> buildCombatSkills() {
var gameVersion = mcMMO.getCompatibilityManager().getMinecraftGameVersion(); if (mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)) {
if (gameVersion.isAtLeast(1, 21, 11)) {
// We are in a game version with Spears and Maces // We are in a game version with Spears and Maces
return ImmutableList.of( return ImmutableList.of(
PrimarySkillType.ARCHERY, PrimarySkillType.ARCHERY,
@@ -256,7 +254,7 @@ public class SkillTools {
PrimarySkillType.TRIDENTS, PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED PrimarySkillType.UNARMED
); );
} else if (gameVersion.isAtLeast(1, 21, 0)) { } else if (mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
// We are in a game version with Maces // We are in a game version with Maces
return ImmutableList.of( return ImmutableList.of(
PrimarySkillType.ARCHERY, PrimarySkillType.ARCHERY,

View File

@@ -38,7 +38,7 @@ public class TextComponentFactory {
* *
* @param localeKey target locale string address * @param localeKey target locale string address
* @param values vars to be passed to the locale loader * @param values vars to be passed to the locale loader
* @return * @return a text component with the locale string and variables applied
*/ */
public static TextComponent getNotificationMultipleValues(String localeKey, String... values) { public static TextComponent getNotificationMultipleValues(String localeKey, String... values) {
String preColoredString = LocaleLoader.getString(localeKey, (Object[]) values); String preColoredString = LocaleLoader.getString(localeKey, (Object[]) values);
@@ -566,14 +566,6 @@ public class TextComponentFactory {
PrimarySkillType parentSkill) { PrimarySkillType parentSkill) {
for (SubSkillType subSkillType : SubSkillType.values()) { for (SubSkillType subSkillType : SubSkillType.values()) {
if (subSkillType.getParentSkill() == parentSkill) { if (subSkillType.getParentSkill() == parentSkill) {
//TODO: Hacky rewrite later
//Only some versions of MC have this skill
if (subSkillType == SubSkillType.FISHING_MASTER_ANGLER
&& mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer()
== null) {
continue;
}
if (Permissions.isSubSkillEnabled(player, subSkillType)) { if (Permissions.isSubSkillEnabled(player, subSkillType)) {
if (!InteractionManager.hasSubSkill(subSkillType)) { if (!InteractionManager.hasSubSkill(subSkillType)) {
textComponents.add(TextComponentFactory.getSubSkillTextComponent(player, textComponents.add(TextComponentFactory.getSubSkillTextComponent(player,

View File

@@ -1,6 +1,5 @@
package com.gmail.nossr50.util.text; package com.gmail.nossr50.util.text;
import com.gmail.nossr50.mcMMO;
import java.util.List; import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder; import net.kyori.adventure.text.ComponentBuilder;
@@ -10,7 +9,6 @@ import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -106,20 +104,6 @@ public class TextUtils {
textComponent.hoverEvent(HoverEvent.showText(baseComponent)); textComponent.hoverEvent(HoverEvent.showText(baseComponent));
} }
public static BaseComponent[] convertToBungeeComponent(@NotNull String displayName) {
return net.md_5.bungee.api.chat.TextComponent.fromLegacyText(displayName);
}
public static @NotNull TextComponent ofBungeeComponents(@NotNull BaseComponent[] bungeeName) {
return Component.textOfChildren(
mcMMO.getCompatibilityManager().getBungeeSerializerCompatibilityLayer()
.deserialize(bungeeName));
}
public static @NotNull TextComponent ofBungeeRawStrings(@NotNull String bungeeRawString) {
return ofBungeeComponents(convertToBungeeComponent(bungeeRawString));
}
public static @NotNull TextComponent ofLegacyTextRaw(@NotNull String rawString) { public static @NotNull TextComponent ofLegacyTextRaw(@NotNull String rawString) {
return LegacyComponentSerializer.legacySection().deserialize(rawString); return LegacyComponentSerializer.legacySection().deserialize(rawString);
} }

View File

@@ -24,7 +24,6 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TransientEntityTracker; import com.gmail.nossr50.util.TransientEntityTracker;
import com.gmail.nossr50.util.blockmeta.ChunkManager; import com.gmail.nossr50.util.blockmeta.ChunkManager;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.player.UserManager;
@@ -85,19 +84,18 @@ public abstract class MMOTestEnvironment {
protected ChunkManager chunkManager; protected ChunkManager chunkManager;
protected MaterialMapStore materialMapStore; protected MaterialMapStore materialMapStore;
protected CompatibilityManager compatibilityManager; protected MinecraftGameVersion minecraftGameVersion;
protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException { protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException {
compatibilityManager = mock(CompatibilityManager.class);
final MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
// TODO: We should change minecraftGameVersion to be a passed in parameter instead of always returning true
when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true);
mockedMcMMO = mockStatic(mcMMO.class); mockedMcMMO = mockStatic(mcMMO.class);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
mcMMO.p = mock(mcMMO.class); mcMMO.p = mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger); when(mcMMO.p.getLogger()).thenReturn(logger);
// Game version
minecraftGameVersion = mock(MinecraftGameVersion.class);
when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true);
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
// place store // place store
chunkManager = mock(ChunkManager.class); chunkManager = mock(ChunkManager.class);
when(mcMMO.getUserBlockTracker()).thenReturn(chunkManager); when(mcMMO.getUserBlockTracker()).thenReturn(chunkManager);

View File

@@ -1,5 +1,17 @@
package com.gmail.nossr50.database; package com.gmail.nossr50.database;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.gmail.nossr50.api.exceptions.InvalidSkillException; import com.gmail.nossr50.api.exceptions.InvalidSkillException;
import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.GeneralConfig; import com.gmail.nossr50.config.GeneralConfig;
@@ -10,11 +22,20 @@ import com.gmail.nossr50.datatypes.database.UpgradeType;
import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.skills.SkillTools; import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.util.upgrade.UpgradeManager; import com.gmail.nossr50.util.upgrade.UpgradeManager;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -33,29 +54,6 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.mariadb.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import org.testcontainers.mysql.MySQLContainer; import org.testcontainers.mysql.MySQLContainer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@TestInstance(Lifecycle.PER_CLASS) @TestInstance(Lifecycle.PER_CLASS)
@Testcontainers @Testcontainers
class SQLDatabaseManagerTest { class SQLDatabaseManagerTest {
@@ -80,8 +78,8 @@ class SQLDatabaseManagerTest {
private static GeneralConfig generalConfig; private static GeneralConfig generalConfig;
private static AdvancedConfig advancedConfig; private static AdvancedConfig advancedConfig;
private static UpgradeManager upgradeManager; private static UpgradeManager upgradeManager;
private static CompatibilityManager compatibilityManager;
private static SkillTools skillTools; private static SkillTools skillTools;
private static MinecraftGameVersion minecraftGameVersion;
// --- DB flavors you support --- // --- DB flavors you support ---
enum DbFlavor { enum DbFlavor {
@@ -96,15 +94,13 @@ class SQLDatabaseManagerTest {
@BeforeAll @BeforeAll
void setUpAll() { void setUpAll() {
// GIVEN a fully mocked mcMMO environment // GIVEN a fully mocked mcMMO environment
compatibilityManager = mock(CompatibilityManager.class); minecraftGameVersion = mock(MinecraftGameVersion.class);
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true); when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true);
mockedMcMMO = Mockito.mockStatic(mcMMO.class); mockedMcMMO = Mockito.mockStatic(mcMMO.class);
mcMMO.p = Mockito.mock(mcMMO.class); mcMMO.p = Mockito.mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger); when(mcMMO.p.getLogger()).thenReturn(logger);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager); when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
mockGeneralConfigBase(); mockGeneralConfigBase();
@@ -115,11 +111,6 @@ class SQLDatabaseManagerTest {
skillTools = new SkillTools(mcMMO.p); skillTools = new SkillTools(mcMMO.p);
when(mcMMO.p.getSkillTools()).thenReturn(skillTools); when(mcMMO.p.getSkillTools()).thenReturn(skillTools);
compatibilityManager = Mockito.mock(CompatibilityManager.class);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
when(compatibilityManager.getMinecraftGameVersion())
.thenReturn(new MinecraftGameVersion(1, 20, 4));
upgradeManager = Mockito.mock(UpgradeManager.class); upgradeManager = Mockito.mock(UpgradeManager.class);
when(mcMMO.getUpgradeManager()).thenReturn(upgradeManager); when(mcMMO.getUpgradeManager()).thenReturn(upgradeManager);
when(mcMMO.getUpgradeManager().shouldUpgrade(any())).thenReturn(false); when(mcMMO.getUpgradeManager().shouldUpgrade(any())).thenReturn(false);

View File

@@ -9,7 +9,6 @@ import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@@ -28,11 +27,9 @@ class PotionEffectUtilTest {
mockedStaticMcMMO = mockStatic(mcMMO.class); mockedStaticMcMMO = mockStatic(mcMMO.class);
mcMMO.p = mock(mcMMO.class); mcMMO.p = mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger); when(mcMMO.p.getLogger()).thenReturn(logger);
CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class); MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(false); when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(false);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager); when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
} }
@AfterEach @AfterEach

View File

@@ -8,7 +8,6 @@ import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionType;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@@ -23,11 +22,9 @@ class PotionUtilTest {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
mockedStaticMcMMO = mockStatic(mcMMO.class); mockedStaticMcMMO = mockStatic(mcMMO.class);
CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class); MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(true); when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(true);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager); when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
} }
@AfterEach @AfterEach

View File

@@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.MinecraftGameVersionFactory;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -96,9 +97,8 @@ class MinecraftGameVersionTest {
bukkit.when(Bukkit::getVersion).thenReturn(serverSoftwareVersion); bukkit.when(Bukkit::getVersion).thenReturn(serverSoftwareVersion);
bukkit.when(Bukkit::getBukkitVersion).thenReturn(gameVersion); bukkit.when(Bukkit::getBukkitVersion).thenReturn(gameVersion);
PlatformManager manager = new PlatformManager(); final MinecraftGameVersion minecraftVersion
Platform platform = manager.getPlatform(); = MinecraftGameVersionFactory.calculateGameVersion(gameVersion);
MinecraftGameVersion minecraftVersion = platform.getGameVersion();
assertEquals(major, minecraftVersion.getMajorVersion().asInt()); assertEquals(major, minecraftVersion.getMajorVersion().asInt());
assertEquals(minor, minecraftVersion.getMinorVersion().asInt()); assertEquals(minor, minecraftVersion.getMinorVersion().asInt());
@@ -125,7 +125,8 @@ class MinecraftGameVersionTest {
Arguments.of("1.14-pre5-SNAPSHOT", 1, 14, 0), Arguments.of("1.14-pre5-SNAPSHOT", 1, 14, 0),
Arguments.of("1.15-R0.1-SNAPSHOT", 1, 15, 0), Arguments.of("1.15-R0.1-SNAPSHOT", 1, 15, 0),
Arguments.of("1.16.5-R0.1-SNAPSHOT", 1, 16, 5), Arguments.of("1.16.5-R0.1-SNAPSHOT", 1, 16, 5),
Arguments.of("1.17-R0.1-SNAPSHOT", 1, 17, 0) Arguments.of("1.17-R0.1-SNAPSHOT", 1, 17, 0),
Arguments.of("1.21.11-106-0d768aa", 1, 21, 11)
); );
} }

View File

@@ -13,7 +13,6 @@ import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.datatypes.skills.ToolType; import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -39,9 +38,7 @@ class SkillToolsTest {
private static MockedStatic<mcMMO> mockedMcMMO; private static MockedStatic<mcMMO> mockedMcMMO;
private static MockedStatic<LocaleLoader> mockedLocaleLoader; private static MockedStatic<LocaleLoader> mockedLocaleLoader;
private GeneralConfig generalConfig; private GeneralConfig generalConfig;
private CompatibilityManager compatibilityManager;
@BeforeAll @BeforeAll
void setUpAll() { void setUpAll() {
@@ -58,10 +55,6 @@ class SkillToolsTest {
when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig); when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
when(generalConfig.getLocale()).thenReturn("en_US"); when(generalConfig.getLocale()).thenReturn("en_US");
// Compatibility manager + game version
compatibilityManager = mock(CompatibilityManager.class);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
// LocaleLoader just echo key back to keep things simple/deterministic // LocaleLoader just echo key back to keep things simple/deterministic
mockedLocaleLoader.when(() -> LocaleLoader.getString(anyString())) mockedLocaleLoader.when(() -> LocaleLoader.getString(anyString()))
.thenAnswer(invocation -> invocation.getArgument(0)); .thenAnswer(invocation -> invocation.getArgument(0));
@@ -74,8 +67,10 @@ class SkillToolsTest {
} }
private SkillTools newSkillToolsForVersion(int major, int minor, int patch) throws Exception { private SkillTools newSkillToolsForVersion(int major, int minor, int patch) throws Exception {
when(compatibilityManager.getMinecraftGameVersion()) var mockGameVersion = mock(MinecraftGameVersion.class);
.thenReturn(new MinecraftGameVersion(major, minor, patch)); when(mockGameVersion.isAtLeast(major, minor, patch))
.thenReturn(true);
when(mcMMO.getMinecraftGameVersion()).thenReturn(mockGameVersion);
return new SkillTools(mcMMO.p); return new SkillTools(mcMMO.p);
} }
@@ -331,22 +326,6 @@ class SkillToolsTest {
); );
} }
@Test
void combatSkillsShouldMatchDefinitionForVersionWithoutMacesOrSpears() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 20, 4);
assertThat(skillTools.getCombatSkills())
.containsExactly(
PrimarySkillType.ARCHERY,
PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS,
PrimarySkillType.SWORDS,
PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED
);
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// LOCALIZED_SKILL_NAMES basic sanity (size + uniqueness, not content) // LOCALIZED_SKILL_NAMES basic sanity (size + uniqueness, not content)
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------