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
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)
Spear abilities can now trigger from off-hand attacks with the Spear
Further improved compatibility with Excellent Enchants (fixed more errors)
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.
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>
<properties>
<!-- <spigot.version>1.20.4-R0.1-SNAPSHOT</spigot.version>-->
<spigot.version>1.21.11-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>-->
<kyori.adventure.version>4.23.0</kyori.adventure.version>
<kyori.adventure.platform.version>4.4.1-SNAPSHOT</kyori.adventure.platform.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;
}
// 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);
return true;
@@ -65,13 +58,6 @@ public class McTopCommand implements TabExecutor {
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);
return true;

View File

@@ -1,13 +1,13 @@
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.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.treasure.Rarity;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
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.ProbabilityUtil;
import com.gmail.nossr50.util.skills.RankUtils;
@@ -118,16 +118,14 @@ public class FishingCommand extends SkillCommand {
@Override
protected void permissionsCheck(Player player) {
canTreasureHunt = Permissions.canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
canMagicHunt = Permissions.canUseSubSkill(player, SubSkillType.FISHING_MAGIC_HUNTER)
&& Permissions.canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
canShake = Permissions.canUseSubSkill(player, SubSkillType.FISHING_SHAKE);
canFishermansDiet = Permissions.canUseSubSkill(player,
canTreasureHunt = canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
canMagicHunt = canUseSubSkill(player, SubSkillType.FISHING_MAGIC_HUNTER)
&& canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
canShake = canUseSubSkill(player, SubSkillType.FISHING_SHAKE);
canFishermansDiet = canUseSubSkill(player,
SubSkillType.FISHING_FISHERMANS_DIET);
canMasterAngler =
mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null
&& Permissions.canUseSubSkill(player, SubSkillType.FISHING_MASTER_ANGLER);
canIceFish = Permissions.canUseSubSkill(player, SubSkillType.FISHING_ICE_FISHING);
canMasterAngler = canUseSubSkill(player, SubSkillType.FISHING_MASTER_ANGLER);
canIceFish = canUseSubSkill(player, SubSkillType.FISHING_ICE_FISHING);
}
@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.PotionUtil.matchPotionType;
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.datatypes.skills.alchemy.AlchemyPotion;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.LogUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
@@ -49,9 +47,6 @@ public class PotionConfig extends LegacyConfigLoader {
private final List<ItemStack> concoctionsIngredientsTierSix = new ArrayList<>();
private final List<ItemStack> concoctionsIngredientsTierSeven = 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(
null,
AlchemyPotionConfigResultType.ERROR);
@@ -258,15 +253,15 @@ public class PotionConfig extends LegacyConfigLoader {
if (potion_section.contains("Effects")) {
for (String effect : potion_section.getStringList("Effects")) {
String[] parts = effect.split(" ");
if (isTrickyTrialsPotionEffect(parts[0]) && !mcMMO.getCompatibilityManager()
.getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
LogUtils.debug(
mcMMO.p.getLogger(),
"Skipping potion effect " + effect + " because it is not"
+ " compatible with the current Minecraft game version.");
return INCOMPATIBLE_POTION_RESULT;
}
// if (isTrickyTrialsPotionEffect(parts[0]) && !mcMMO.getCompatibilityManager()
// .minecraftGameVersion()
// .isAtLeast(1, 21, 0)) {
// LogUtils.debug(
// mcMMO.p.getLogger(),
// "Skipping potion effect " + effect + " because it is not"
// + " compatible with the current Minecraft game version.");
// return INCOMPATIBLE_POTION_RESULT;
// }
PotionEffectType type =
parts.length > 0 ? PotionEffectType.getByName(parts[0]) : null;
@@ -298,9 +293,7 @@ public class PotionConfig extends LegacyConfigLoader {
.getKeys(false)) {
// Breeze Rod was only for potions after 1.21.0
if (isTrickyTrialsIngredient(childIngredient)
&& !mcMMO.getCompatibilityManager()
.getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
&& !mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
continue;
}
ItemStack ingredient = loadIngredient(childIngredient);
@@ -359,8 +352,6 @@ public class PotionConfig extends LegacyConfigLoader {
// set base
setBasePotionType(potionMeta, potionType, extended, upgraded);
// Legacy only
setUpgradedAndExtendedProperties(potionType, potionMeta, upgraded, extended);
return true;
}

View File

@@ -132,7 +132,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ general.getMySQLDatabaseName();
// 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()) {
connectionString += "?verifyServerCertificate=false&useSSL=true&requireSSL=true";
} else {

View File

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

View File

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

View File

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

View File

@@ -56,14 +56,13 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TransientEntityTracker;
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.ChunkManagerFactory;
import com.gmail.nossr50.util.blockmeta.UserBlockTracker;
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.platform.PlatformManager;
import com.gmail.nossr50.util.platform.ServerSoftwareType;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.player.PlayerLevelUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
@@ -94,7 +93,6 @@ import org.jetbrains.annotations.Nullable;
public class mcMMO extends JavaPlugin {
/* Managers & Services */
private static PlatformManager platformManager;
private static ChunkManager chunkManager;
private static RepairableManager repairableManager;
private static SalvageableManager salvageableManager;
@@ -107,6 +105,7 @@ public class mcMMO extends JavaPlugin {
private static ChatManager chatManager;
private static CommandManager commandManager; //ACF
private static TransientEntityTracker transientEntityTracker;
private static MinecraftGameVersion minecraftGameVersion;
private SkillTools skillTools;
@@ -170,8 +169,19 @@ public class mcMMO extends JavaPlugin {
//Filter out any debug messages (if debug/verbose logging is not enabled)
getLogger().setFilter(new LogFilter(this));
//Platform Manager
platformManager = new PlatformManager();
// Determine game version before moving forward
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
foliaLib = new FoliaLib(this);
@@ -248,7 +258,7 @@ public class mcMMO extends JavaPlugin {
"You are potentially running an outdated version of your server software"
+ ", mcMMO will not work unless you update to a newer version!"),
20, 20 * 60 * 30);
if (!getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 20, 4)) {
if (!minecraftGameVersion.isAtLeast(1, 20, 4)) {
foliaLib.getScheduler().runTimer(
() -> getLogger().severe(
"This version of mcMMO requires at least Minecraft 1.20.4 to"
@@ -501,10 +511,6 @@ public class mcMMO extends JavaPlugin {
return upgradeManager;
}
public static @Nullable CompatibilityManager getCompatibilityManager() {
return platformManager.getCompatibilityManager();
}
@Deprecated
public static void setDatabaseManager(DatabaseManager databaseManager) {
mcMMO.databaseManager = databaseManager;
@@ -750,10 +756,6 @@ public class mcMMO extends JavaPlugin {
return worldBlacklist;
}
public static PlatformManager getPlatformManager() {
return platformManager;
}
public static BukkitAudiences getAudiences() {
return audiences;
}
@@ -834,4 +836,13 @@ public class mcMMO extends JavaPlugin {
public @NotNull FoliaLib getFoliaLib() {
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));
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);
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.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.Permissions;
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.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.CombatUtils;
@@ -40,7 +39,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -55,24 +53,17 @@ import org.bukkit.entity.Sheep;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.metadata.Metadatable;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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 lastWarned = 0L;
private final long lastWarnedExhaust = 0L;
private FishHook fishHookReference;
private BoundingBox lastFishingBoundingBox;
private boolean sameTarget;
private Item fishingCatch;
private Location hookLocation;
private int fishCaughtCounter = 1;
private final int masterAnglerMinWaitLowerBound;
private final int masterAnglerMaxWaitLowerBound;
@@ -95,53 +86,18 @@ public class FishingManager extends SkillManager {
}
public boolean canMasterAngler() {
return mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null
&& getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
return getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
}
// public void setFishingRodCastTimestamp()
// {
// 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) {
public void setFishHookReference(Metadatable fishHook) {
if (!fishHook.getMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF).isEmpty()) {
return;
}
fishHook.setMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF,
MetadataConstants.MCMMO_METADATA_VALUE);
this.fishHookReference = fishHook;
fishHookSpawnTimestamp = System.currentTimeMillis();
fishingRodCastTimestamp = System.currentTimeMillis();
}
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) {
return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance()
.getFishingExploitingOptionOverFishLimit();
}
/*Block targetBlock = getPlayer().getTargetBlock(BlockUtils.getTransparentBlocks(), 100);
if (!targetBlock.isLiquid()) {
return false;
}*/
/**
* Determines if the player is exploiting fishing by checking if they have caught
* more fish than the configured limit without moving their fishing spot.
*
* @return true if the player is exploiting fishing, false otherwise
*/
public boolean isExploitingFishing() {
return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance()
.getFishingExploitingOptionOverFishLimit();
}
public static BoundingBox makeBoundingBox(Vector centerOfCastVector) {
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() {
@@ -243,15 +219,6 @@ public class FishingManager extends SkillManager {
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
*
@@ -293,19 +260,15 @@ public class FishingManager extends SkillManager {
* @param fishHook target fish hook
*/
public void processMasterAngler(@NotNull FishHook fishHook, int lureLevel) {
MasterAnglerCompatibilityLayer masterAnglerCompatibilityLayer = (MasterAnglerCompatibilityLayer) mcMMO.getCompatibilityManager()
.getMasterAnglerCompatibilityLayer();
if (masterAnglerCompatibilityLayer != null) {
int maxWaitTicks = masterAnglerCompatibilityLayer.getMaxWaitTime(fishHook);
int minWaitTicks = masterAnglerCompatibilityLayer.getMinWaitTime(fishHook);
int maxWaitTicks = fishHook.getMaxWaitTime();
int minWaitTicks = fishHook.getMinWaitTime();
int masterAnglerRank = RankUtils.getRank(mmoPlayer, SubSkillType.FISHING_MASTER_ANGLER);
int convertedLureBonus = 0;
//This avoids a Minecraft bug where lure levels above 3 break fishing
if (lureLevel > 0) {
masterAnglerCompatibilityLayer.setApplyLure(fishHook, false);
fishHook.setApplyLure(false);
convertedLureBonus = lureLevel * 100;
}
@@ -349,8 +312,7 @@ public class FishingManager extends SkillManager {
}
mmoPlayer.getPlayer().sendMessage(
"ALLOW STACK WITH LURE: " + masterAnglerCompatibilityLayer.getApplyLure(
fishHook));
"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);
@@ -385,10 +347,8 @@ public class FishingManager extends SkillManager {
"Lowest possible min wait ticks " + masterAnglerMaxWaitLowerBound);
}
masterAnglerCompatibilityLayer.setMaxWaitTime(fishHook, reducedMaxWaitTime);
masterAnglerCompatibilityLayer.setMinWaitTime(fishHook, reducedMinWaitTime);
}
fishHook.setMaxWaitTime(reducedMaxWaitTime);
fishHook.setMinWaitTime(reducedMinWaitTime);
}
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
*/
public void processFishing(@NotNull Item fishingCatch) {
this.fishingCatch = fishingCatch;
int fishXp = ExperienceConfig.getInstance()
.getXp(PrimarySkillType.FISHING, fishingCatch.getItemStack().getType());
int treasureXp = 0;
@@ -458,7 +417,6 @@ public class FishingManager extends SkillManager {
if (mcMMO.p.getGeneralConfig().getFishingDropsEnabled() && Permissions.isSubSkillEnabled(
player, SubSkillType.FISHING_TREASURE_HUNTER)) {
treasure = getFishingTreasure();
this.fishingCatch = null;
}
if (treasure != null) {
@@ -541,10 +499,6 @@ public class FishingManager extends SkillManager {
return experience * getVanillaXpMultiplier();
}
public Location getHookLocation() {
return hookLocation;
}
/**
* Handle the Shake ability
*
@@ -692,11 +646,6 @@ public class FishingManager extends SkillManager {
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);
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;
import com.gmail.nossr50.mcMMO;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -10,34 +7,19 @@ import java.util.Locale;
import java.util.Map;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull;
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
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 LONG = "LONG";
public static final String WATER_POTION_TYPE_STR = "WATER";
private static final PotionCompatibilityType COMPATIBILITY_MODE;
static {
potionDataClass = getPotionDataClass();
// 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
// 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_DAMAGE", "HARMING");
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.
*
* @param partialName potion type as a string, can be a substring of the potion type but must
* match exactly
* @return The potion type
* <p>In 1.20.5+, "upgraded" and "extended" are represented by distinct {@link PotionType}
* constants (e.g. STRONG_HEALING, LONG_SWIFTNESS), not flags.
*
* @param partialName potion type as a string, can be a substring of the potion type but must match
* against the potion's key or enum name
* @return The potion type, or null if no match
*/
public static PotionType matchPotionType(String partialName, boolean isUpgraded,
boolean isExtended) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return matchLegacyPotionType(partialName);
} else {
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())
.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);
}
// Allow matching by namespace key ("swiftness", "long_swiftness") or enum name
.filter(potionType -> {
final NamespacedKey key = potionType.getKey();
final String keyStr = key != null ? key.getKey() : "";
return keyStr.toUpperCase(Locale.ENGLISH).contains(updatedName)
|| potionType.name().toUpperCase(Locale.ENGLISH).contains(updatedName);
})
// Enforce strong/long selection by the enum name prefix convention
.filter(potionType -> isUpgraded == potionType.name().startsWith(STRONG + "_"))
.filter(potionType -> isExtended == potionType.name().startsWith(LONG + "_"))
.findAny()
.orElse(null);
}
/**
* Legacy matching for {@link PotionType}
*
* @param name The partial name of the potion
* @return The potion type
* Returns the NamespacedKey key string portion for this potion type (e.g. "swiftness").
*/
private static PotionType matchLegacyPotionType(String name) {
return Arrays.stream(PotionType.values())
.filter(potionType -> getKeyGetKey(potionType).equalsIgnoreCase(name)
|| getKeyGetKey(potionType).equalsIgnoreCase(convertLegacyNames(name))
|| potionType.name().equalsIgnoreCase(name)
|| potionType.name().equalsIgnoreCase(convertLegacyNames(name)))
.findAny().orElse(null);
}
private static String convertUpgradedOrExtended(String potionType, boolean isUpgraded,
boolean isExtended) {
if (isUpgraded) {
potionType = STRONG + "_" + potionType;
}
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
* existence of this method before calling it
*
* @return The getKey method
*/
private static @Nullable Method getKeyMethod() {
try {
return PotionType.class.getMethod("getKey");
} 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 @NotNull String getKeyGetKey(@NotNull PotionType potionType) {
final NamespacedKey key = potionType.getKey();
return key != null ? key.getKey() : potionType.name();
}
public static String convertPotionConfigName(String legacyName) {
@@ -252,318 +83,91 @@ public class PotionUtil {
if (replacementName.contains("_II")) {
replacementName = replacementName.replace("_II", "");
replacementName = "STRONG_" + replacementName;
replacementName = STRONG + "_" + replacementName;
} else if (replacementName.contains("_EXTENDED")) {
replacementName = replacementName.replace("_EXTENDED", "");
replacementName = "LONG_" + replacementName;
replacementName = LONG + "_" + replacementName;
}
return replacementName;
}
public static String convertLegacyNames(String legacyPotionType) {
String modernized = legacyPotionType;
// check for legacy names
for (var key : legacyPotionTypes.keySet()) {
if (modernized.contains(key)) {
// Replace the legacy name with the new name
modernized = modernized.replace(key, legacyPotionTypes.get(key));
break;
}
}
return modernized;
}
public static boolean hasLegacyName(String potionType) {
for (var key : legacyPotionTypes.keySet()) {
if (potionType.contains(key)) {
return true;
}
}
return false;
public static boolean isStrong(@NotNull PotionMeta potionMeta) {
final PotionType base = potionMeta.getBasePotionType();
return base != null && base.name().startsWith(STRONG + "_");
}
public static boolean isStrong(PotionMeta potionMeta) {
if (methodPotionMetaGetBasePotionData == null) {
return isStrongModern(potionMeta);
} 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 isLong(@NotNull PotionMeta potionMeta) {
final PotionType base = potionMeta.getBasePotionType();
return base != null && base.name().startsWith(LONG + "_");
}
public static boolean isPotionTypeWater(@NotNull PotionMeta potionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return isPotionTypeWaterLegacy(potionMeta);
} else {
return isPotionTypeWaterModern(potionMeta);
}
return potionMeta.getBasePotionType() == PotionType.WATER;
}
public static boolean isPotionType(@NotNull PotionMeta potionMeta, String potionType) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return isPotionTypeLegacy(potionMeta, potionType);
} else {
return isPotionTypeModern(potionMeta, potionType);
}
public static boolean hasBasePotionEffects(@NotNull PotionMeta potionMeta) {
final PotionType base = potionMeta.getBasePotionType();
if (base == null) {
return false;
}
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);
}
final List<PotionEffect> effects = base.getPotionEffects();
return effects != null && !effects.isEmpty();
}
/**
* Set the base potion type of a potion meta. Note that extended/upgraded are ignored in 1.20.5
* and later.
*
* @param potionMeta the potion meta
* @param extended true if the potion is extended
* @param upgraded true if the potion is upgraded
* <p>In 1.20.5+, "extended/upgraded" are encoded into {@link PotionType} variants. This method
* attempts to select the appropriate STRONG_/LONG_ variant when requested. If no such variant
* exists, it falls back to the provided base type.</p>
*/
public static void setBasePotionType(PotionMeta potionMeta, PotionType potionType,
boolean extended, boolean upgraded) {
if (methodPotionMetaSetBasePotionType == null) {
setBasePotionTypeLegacy(potionMeta, potionType, extended, upgraded);
} else {
setBasePotionTypeModern(potionMeta, potionType);
}
public static void setBasePotionType(@NotNull PotionMeta potionMeta,
@NotNull PotionType potionType, boolean extended, boolean upgraded) {
final PotionType resolved = resolveVariant(potionType, upgraded, extended);
potionMeta.setBasePotionType(resolved);
}
public static void setUpgradedAndExtendedProperties(PotionType potionType,
PotionMeta potionMeta,
boolean isUpgraded, boolean isExtended) {
if (potionDataClass == null || mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 20, 5)) {
return;
private static @NotNull PotionType resolveVariant(@NotNull PotionType base, boolean upgraded,
boolean extended) {
// Apply the same prefix scheme your code already expects
String name = base.name();
// 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 {
final Object potionData = potionDataClass.getConstructor(PotionType.class,
boolean.class, boolean.class)
.newInstance(potionType, isExtended, isUpgraded);
methodPotionMetaSetBasePotionData.invoke(potionMeta, potionData);
} 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);
}
return PotionType.valueOf(name);
} catch (IllegalArgumentException ignored) {
// Not all potion types have strong/long variants; just use the provided base.
return base;
}
}
}

View File

@@ -8,7 +8,6 @@ import com.gmail.nossr50.commands.McnotifyCommand;
import com.gmail.nossr50.commands.McrefreshCommand;
import com.gmail.nossr50.commands.McscoreboardCommand;
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.PlayerDebugCommand;
import com.gmail.nossr50.commands.chat.McChatSpy;
@@ -65,14 +64,7 @@ public final class CommandRegistrationManager {
private static void registerSkillCommands() {
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType == PrimarySkillType.SPEARS
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 21, 11)) {
continue;
}
if (primarySkillType == PrimarySkillType.MACES
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
.isAtLeast(1, 21, 0)) {
&& !mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)) {
continue;
}
@@ -411,13 +403,6 @@ public final class CommandRegistrationManager {
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() {
PluginCommand command = mcMMO.p.getCommand("mmoxpbar"); //TODO: Localize
command.setDescription(LocaleLoader.getString("Commands.Description.mmoxpbar"));
@@ -473,8 +458,5 @@ public final class CommandRegistrationManager {
// Admin commands
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
@NotNull
ImmutableList<PrimarySkillType> buildCombatSkills() {
var gameVersion = mcMMO.getCompatibilityManager().getMinecraftGameVersion();
if (gameVersion.isAtLeast(1, 21, 11)) {
if (mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)) {
// We are in a game version with Spears and Maces
return ImmutableList.of(
PrimarySkillType.ARCHERY,
@@ -256,7 +254,7 @@ public class SkillTools {
PrimarySkillType.TRIDENTS,
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
return ImmutableList.of(
PrimarySkillType.ARCHERY,

View File

@@ -38,7 +38,7 @@ public class TextComponentFactory {
*
* @param localeKey target locale string address
* @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) {
String preColoredString = LocaleLoader.getString(localeKey, (Object[]) values);
@@ -566,14 +566,6 @@ public class TextComponentFactory {
PrimarySkillType parentSkill) {
for (SubSkillType subSkillType : SubSkillType.values()) {
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 (!InteractionManager.hasSubSkill(subSkillType)) {
textComponents.add(TextComponentFactory.getSubSkillTextComponent(player,

View File

@@ -1,6 +1,5 @@
package com.gmail.nossr50.util.text;
import com.gmail.nossr50.mcMMO;
import java.util.List;
import net.kyori.adventure.text.Component;
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.TextDecoration;
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.Nullable;
@@ -106,20 +104,6 @@ public class TextUtils {
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) {
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.TransientEntityTracker;
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.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
@@ -85,19 +84,18 @@ public abstract class MMOTestEnvironment {
protected ChunkManager chunkManager;
protected MaterialMapStore materialMapStore;
protected CompatibilityManager compatibilityManager;
protected MinecraftGameVersion minecraftGameVersion;
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);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
mcMMO.p = mock(mcMMO.class);
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
chunkManager = mock(ChunkManager.class);
when(mcMMO.getUserBlockTracker()).thenReturn(chunkManager);

View File

@@ -1,5 +1,17 @@
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.config.AdvancedConfig;
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.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.skills.SkillTools;
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.Map;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -33,29 +54,6 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.mariadb.MariaDBContainer;
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)
@Testcontainers
class SQLDatabaseManagerTest {
@@ -80,8 +78,8 @@ class SQLDatabaseManagerTest {
private static GeneralConfig generalConfig;
private static AdvancedConfig advancedConfig;
private static UpgradeManager upgradeManager;
private static CompatibilityManager compatibilityManager;
private static SkillTools skillTools;
private static MinecraftGameVersion minecraftGameVersion;
// --- DB flavors you support ---
enum DbFlavor {
@@ -96,15 +94,13 @@ class SQLDatabaseManagerTest {
@BeforeAll
void setUpAll() {
// GIVEN a fully mocked mcMMO environment
compatibilityManager = mock(CompatibilityManager.class);
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
minecraftGameVersion = mock(MinecraftGameVersion.class);
when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true);
mockedMcMMO = Mockito.mockStatic(mcMMO.class);
mcMMO.p = Mockito.mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
mockGeneralConfigBase();
@@ -115,11 +111,6 @@ class SQLDatabaseManagerTest {
skillTools = new SkillTools(mcMMO.p);
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);
when(mcMMO.getUpgradeManager()).thenReturn(upgradeManager);
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 com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import org.bukkit.potion.PotionEffectType;
import org.junit.jupiter.api.AfterEach;
@@ -28,11 +27,9 @@ class PotionEffectUtilTest {
mockedStaticMcMMO = mockStatic(mcMMO.class);
mcMMO.p = mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(false);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
}
@AfterEach

View File

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

View File

@@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.MinecraftGameVersionFactory;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.bukkit.Bukkit;
@@ -96,9 +97,8 @@ class MinecraftGameVersionTest {
bukkit.when(Bukkit::getVersion).thenReturn(serverSoftwareVersion);
bukkit.when(Bukkit::getBukkitVersion).thenReturn(gameVersion);
PlatformManager manager = new PlatformManager();
Platform platform = manager.getPlatform();
MinecraftGameVersion minecraftVersion = platform.getGameVersion();
final MinecraftGameVersion minecraftVersion
= MinecraftGameVersionFactory.calculateGameVersion(gameVersion);
assertEquals(major, minecraftVersion.getMajorVersion().asInt());
assertEquals(minor, minecraftVersion.getMinorVersion().asInt());
@@ -125,7 +125,8 @@ class MinecraftGameVersionTest {
Arguments.of("1.14-pre5-SNAPSHOT", 1, 14, 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.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.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import java.util.ArrayList;
import java.util.Arrays;
@@ -39,9 +38,7 @@ class SkillToolsTest {
private static MockedStatic<mcMMO> mockedMcMMO;
private static MockedStatic<LocaleLoader> mockedLocaleLoader;
private GeneralConfig generalConfig;
private CompatibilityManager compatibilityManager;
@BeforeAll
void setUpAll() {
@@ -58,10 +55,6 @@ class SkillToolsTest {
when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
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
mockedLocaleLoader.when(() -> LocaleLoader.getString(anyString()))
.thenAnswer(invocation -> invocation.getArgument(0));
@@ -74,8 +67,10 @@ class SkillToolsTest {
}
private SkillTools newSkillToolsForVersion(int major, int minor, int patch) throws Exception {
when(compatibilityManager.getMinecraftGameVersion())
.thenReturn(new MinecraftGameVersion(major, minor, patch));
var mockGameVersion = mock(MinecraftGameVersion.class);
when(mockGameVersion.isAtLeast(major, minor, patch))
.thenReturn(true);
when(mcMMO.getMinecraftGameVersion()).thenReturn(mockGameVersion);
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)
// ------------------------------------------------------------------------