Skip to content

Commit

Permalink
Fixed Jobs, Anvil and Enchantments
Browse files Browse the repository at this point in the history
  • Loading branch information
dringewald committed Feb 16, 2025
1 parent 2b8d578 commit 2b4d0a4
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 121 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,15 @@ I really **enjoyed** the plugin, so I decided to **update and improve it further
| `powermining.enchant.plow.all` | Allows enchanting all Plows | `op` |

## **📌 Change Log**
### 🆕 **Latest Update - February 15, 2025**
- **💼 Jobs support** - Added support for [Jobs Reborn](https://www.spigotmc.org/resources/jobs-reborn.4216/).
### 🆕 **Latest Update - February 16, 2025**
- **💼 Jobs** - Fixed plugin not working, when [Jobs Reborn](https://www.spigotmc.org/resources/jobs-reborn.4216/) wasn't installed.
- **🔨 Anvils** - Fixed Anvils not adding durability when the Item with lower durability was on the right site.
- **✨ Enchantments** - Fixed Unbreaking enchantment not working correctly.

### **📌 Previous Updates**
#### 📅 **February 15, 2025**
- **💼 Jobs support** - Added support for [Jobs Reborn](https://www.spigotmc.org/resources/jobs-reborn.4216/).

#### 📅 **January 29, 2025**
- **🔄 Updated plugin to fully work in Minecraft 1.21.4** - Earlier versions are not supported (should work, but untested).
- **🔤 Added full Language system** – Everything is translatable (messages, items, commands).
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>jodelle.powermining</groupId>
<artifactId>JodellePowerMining</artifactId>
<version>1.1</version>
<version>1.1.1</version>
<packaging>jar</packaging>

<properties>
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/jodelle/powermining/PowerMining.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
import jodelle.powermining.commands.PowerMiningCommand;
import jodelle.powermining.commands.PowerMiningTabCompleter;
import jodelle.powermining.handlers.*;

import jodelle.powermining.integrations.JobsHook;
import jodelle.powermining.integrations.JobsHookImpl;

import jodelle.powermining.lib.DebuggingMessages;
import jodelle.powermining.lib.Reference;
import jodelle.powermining.listeners.BlockBreakListener;
Expand Down Expand Up @@ -60,6 +64,8 @@ public final class PowerMining extends JavaPlugin {
private List<String> availableLanguages = new ArrayList<>();

private WorldGuardPlugin worldguard;
private JobsHook jobsHook = null;

private boolean isJobsLoaded;

private static PowerMining instance;
Expand Down Expand Up @@ -97,6 +103,11 @@ public void onEnable() {
getLogger().info("Finished processing config file.");
loadDependencies();

// Initialize Jobs integration if Jobs is loaded
if (isJobsLoaded) {
jobsHook = new JobsHookImpl();
}

handlerPlayerInteract = new PlayerInteractHandler();
handlerBlockBreak = new BlockBreakHandler();
handlerCraftItem = new CraftItemHandler();
Expand Down Expand Up @@ -440,6 +451,10 @@ public void setBlockBreakListener(BlockBreakListener listener) {
this.blockBreakListener = listener;
}

public JobsHook getJobsHook() {
return jobsHook;
}

public static PowerMining getInstance() {
return instance;
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/jodelle/powermining/integrations/JobsHook.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package jodelle.powermining.integrations;

import org.bukkit.block.Block;
import org.bukkit.entity.Player;

public interface JobsHook {
void notifyJobs(Player player, Block block);
}
14 changes: 14 additions & 0 deletions src/main/java/jodelle/powermining/integrations/JobsHookImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package jodelle.powermining.integrations;

import com.gamingmesh.jobs.Jobs;
import com.gamingmesh.jobs.actions.BlockActionInfo;
import com.gamingmesh.jobs.container.ActionType;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;

public class JobsHookImpl implements JobsHook {
@Override
public void notifyJobs(Player player, Block block) {
Jobs.action(Jobs.getPlayerManager().getJobsPlayer(player), new BlockActionInfo(block, ActionType.BREAK));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
Expand Down Expand Up @@ -101,20 +102,20 @@ private void applyEnchantments(ItemStack tool, ItemStack book, PrepareAnvilEvent
private void combineToolEnchantments(ItemStack baseTool, ItemStack additionTool, PrepareAnvilEvent event) {
ItemMeta baseMeta = baseTool.getItemMeta();
ItemMeta additionMeta = additionTool.getItemMeta();

if (baseMeta == null || additionMeta == null) {
return; // Skip if metadata is missing
}

ItemStack resultTool = baseTool.clone();
ItemMeta resultMeta = resultTool.getItemMeta();


// Combine enchantments
Map<Enchantment, Integer> additionEnchants = additionMeta.getEnchants();
for (Map.Entry<Enchantment, Integer> entry : additionEnchants.entrySet()) {
Enchantment enchantment = entry.getKey();
int level = entry.getValue();

// Apply the higher level or combine levels if they are the same

if (resultMeta.hasEnchant(enchantment)) {
int currentLevel = resultMeta.getEnchantLevel(enchantment);
if (currentLevel == level && currentLevel < enchantment.getMaxLevel()) {
Expand All @@ -126,8 +127,17 @@ private void combineToolEnchantments(ItemStack baseTool, ItemStack additionTool,
resultMeta.addEnchant(enchantment, level, true);
}
}

// Preserve custom metadata

// Repair durability
if (resultMeta instanceof Damageable) {
Damageable damageable = (Damageable) resultMeta;
int baseDamage = ((Damageable) baseMeta).getDamage();
int repairAmount = additionTool.getType().getMaxDurability() / 2; // Repairs up to 50% of max durability

damageable.setDamage(Math.max(0, baseDamage - repairAmount)); // Prevents negative damage
}

// Apply changes
resultTool.setItemMeta(resultMeta);
event.setResult(resultTool);
}
Expand Down
155 changes: 46 additions & 109 deletions src/main/java/jodelle/powermining/listeners/BlockBreakListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@
import org.bukkit.event.block.BlockExpEvent;
import org.bukkit.inventory.ItemStack;

import com.gamingmesh.jobs.Jobs;
import com.gamingmesh.jobs.actions.BlockActionInfo;
import com.gamingmesh.jobs.container.ActionType;

import java.util.List;

import javax.annotation.Nonnull;
Expand All @@ -44,9 +40,6 @@ public class BlockBreakListener implements Listener {
public final boolean useDurabilityPerBlock;
public final DebuggingMessages debuggingMessages;

private Player player;
private ItemStack handItem;

public BlockBreakListener(@Nonnull PowerMining plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
Expand All @@ -56,21 +49,24 @@ public BlockBreakListener(@Nonnull PowerMining plugin) {

@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
player = event.getPlayer();
handItem = player.getInventory().getItemInMainHand();
Player player = event.getPlayer();
ItemStack handItem = player.getInventory().getItemInMainHand();

if (handItem != null && handItem.getItemMeta() != null && handItem.getItemMeta().hasDisplayName()) {
if (handItem == null || handItem.getType() == Material.AIR) {
return;
}

if (handItem.getItemMeta() != null && handItem.getItemMeta().hasDisplayName()) {
debuggingMessages.sendConsoleMessage(
ChatColor.RED + "Broke a block with item: " + handItem.getItemMeta().getDisplayName());
}

if (basicVerifications()) {
if (basicVerifications(player, handItem)) { // ✅ Pass player & handItem explicitly
return;
}

final Block centerBlock = event.getBlock();
final String playerName = player.getName();

final PlayerInteractListener pil = plugin.getPlayerInteractHandler() != null
? plugin.getPlayerInteractHandler().getListener()
: null;
Expand All @@ -85,38 +81,26 @@ public void onBlockBreak(BlockBreakEvent event) {
int radius = Math.max(0, plugin.getConfig().getInt("Radius", Reference.RADIUS) - 1);
int depth = Math.max(0, plugin.getConfig().getInt("Depth", Reference.DEPTH) - 1);

debuggingMessages.sendConsoleMessage("(processConfig) Value for radius is: (Reference) " + Reference.RADIUS
+ " (Config) " + (plugin.getConfig().getInt("Radius", 2) - 1));
debuggingMessages.sendConsoleMessage("(processConfig) Value for depth is: (Reference) " + Reference.DEPTH
+ " (Config) " + (plugin.getConfig().getInt("Depth", 1) - 1));

List<Block> surroundingBlocks = PowerUtils.getSurroundingBlocks(blockFace, centerBlock, radius, depth);

if (surroundingBlocks.isEmpty()) {
debuggingMessages.sendConsoleMessage(ChatColor.RED + "No surrounding blocks found.");
return;
}

// Handle the center block XP as usual
int centerBlockExp = event.getExpToDrop();

if (!useDurabilityPerBlock && player.getGameMode().equals(GameMode.SURVIVAL)) {
event.setCancelled(true);
// Handle durability for the center block
if (player.getGameMode().equals(GameMode.SURVIVAL)) {
PowerUtils.reduceDurability(player, handItem);
centerBlock.breakNaturally(handItem);
}

if (centerBlockExp > 0) {
BlockExpEvent centerExpEvent = new BlockExpEvent(centerBlock, centerBlockExp);
plugin.getServer().getPluginManager().callEvent(centerExpEvent);

ExperienceOrb centerOrb = centerBlock.getWorld().spawn(centerBlock.getLocation(), ExperienceOrb.class);
centerOrb.setExperience(centerExpEvent.getExpToDrop());
player.getInventory().setItemInMainHand(handItem);
}

// Handle surrounding blocks XP separately
for (Block block : surroundingBlocks) {
int exp = checkAndBreakBlock(block);
int exp = checkAndBreakBlock(player, handItem, block);

if (player.getGameMode().equals(GameMode.SURVIVAL)) {
PowerUtils.reduceDurability(player, handItem);
player.getInventory().setItemInMainHand(handItem);
}

if (exp > 0) {
BlockExpEvent expEvent = new BlockExpEvent(block, exp);
Expand All @@ -133,84 +117,42 @@ public void onBlockBreak(BlockBreakEvent event) {
*
* @param block The block being broken by the player
*/
private int checkAndBreakBlock(@Nonnull Block block) {
Material blockMat = block.getType();
boolean useHammer;
boolean useExcavator = false;
private int checkAndBreakBlock(Player player, ItemStack handItem, @Nonnull Block block) {
if (handItem == null || handItem.getType() == Material.AIR) {
return 0; // No tool, no block breaking
}

if (useHammer = PowerUtils.validateHammer(handItem.getType(), blockMat))
;
else if (useExcavator = PowerUtils.validateExcavator(handItem.getType(), blockMat))
;
Material blockMat = block.getType();
boolean useHammer = PowerUtils.validateHammer(handItem.getType(), blockMat);
boolean useExcavator = !useHammer && PowerUtils.validateExcavator(handItem.getType(), blockMat);

if (useHammer || useExcavator) {
if (!PowerUtils.canBreak(plugin, player, block)) {
return 0;
}

// Notify Jobs Reborn BEFORE breaking the block
if (plugin.isJobsLoaded()) {
debuggingMessages.sendConsoleMessage(
ChatColor.YELLOW + "🔍 Jobs Reborn is loaded, notifying BEFORE breaking...");
debuggingMessages.sendConsoleMessage(ChatColor.YELLOW + "📌 Player: " + player.getName() +
", Block: " + block.getType() + ", Action: BREAK");

Jobs.action(Jobs.getPlayerManager().getJobsPlayer(player),
new BlockActionInfo(block, ActionType.BREAK));
debuggingMessages
.sendConsoleMessage(ChatColor.GREEN + "✅ Jobs Reborn notified for block: " + block.getType());
if (plugin.getJobsHook() != null) {
plugin.getJobsHook().notifyJobs(player, block);
debuggingMessages.sendConsoleMessage(ChatColor.GREEN + "✅ Jobs Reborn notified for block: " + block.getType());
}

// XP Drops
int expToDrop = 0;

// Only assign XP for blocks that naturally drop XP in vanilla Minecraft
switch (blockMat) {
case COAL_ORE:
case DEEPSLATE_COAL_ORE:
expToDrop = (int) (Math.random() * 3); // 0-2 XP
break;

case DIAMOND_ORE:
case DEEPSLATE_DIAMOND_ORE:
expToDrop = 3 + (int) (Math.random() * 5); // 3-7 XP
break;

case EMERALD_ORE:
case DEEPSLATE_EMERALD_ORE:
expToDrop = 3 + (int) (Math.random() * 5); // 3-7 XP
break;

case REDSTONE_ORE:
case DEEPSLATE_REDSTONE_ORE:
expToDrop = 2 + (int) (Math.random() * 4); // 2-6 XP
break;

case LAPIS_ORE:
case DEEPSLATE_LAPIS_ORE:
expToDrop = 2 + (int) (Math.random() * 4); // 2-6 XP
break;

case NETHER_QUARTZ_ORE:
expToDrop = 2 + (int) (Math.random() * 3); // 2-5 XP
break;

case NETHER_GOLD_ORE:
expToDrop = 1 + (int) (Math.random() * 5); // 1-5 XP
break;

case SPAWNER:
expToDrop = 15 + (int) (Math.random() * 30); // 15-43 XP
break;

default:
expToDrop = 0; // No XP for blocks not listed
break;
}
int expToDrop = switch (blockMat) {
case COAL_ORE, DEEPSLATE_COAL_ORE -> (int) (Math.random() * 3); // 0-2 XP
case DIAMOND_ORE, DEEPSLATE_DIAMOND_ORE, EMERALD_ORE, DEEPSLATE_EMERALD_ORE ->
3 + (int) (Math.random() * 5); // 3-7 XP
case REDSTONE_ORE, DEEPSLATE_REDSTONE_ORE, LAPIS_ORE, DEEPSLATE_LAPIS_ORE ->
2 + (int) (Math.random() * 4); // 2-6 XP
case NETHER_QUARTZ_ORE -> 2 + (int) (Math.random() * 3); // 2-5 XP
case NETHER_GOLD_ORE -> 1 + (int) (Math.random() * 5); // 1-5 XP
case SPAWNER -> 15 + (int) (Math.random() * 30); // 15-43 XP
default -> 0; // No XP for blocks not listed
};

// Break the block naturally if conditions are met
if (block.breakNaturally(handItem) && player.getGameMode().equals(GameMode.SURVIVAL)) {
if (useDurabilityPerBlock) {
if (plugin.getConfig().getBoolean("useDurabilityPerBlock")) {
PowerUtils.reduceDurability(player, handItem);
}
}
Expand All @@ -224,32 +166,27 @@ else if (useExcavator = PowerUtils.validateExcavator(handItem.getType(), blockMa
/**
* Perform the basic verifications
*
* @return True if the PowerTool is ready to use
* @return True if the PowerTool is NOT ready to use (acts like a normal tool)
*/
private boolean basicVerifications() {
// If the player is sneaking, we want the tool to act like a normal
// pickaxe/shovel
if (player.isSneaking()) {
private boolean basicVerifications(Player player, ItemStack handItem) {
if (handItem == null || handItem.getType() == Material.AIR) {
return true;
}

Material handItemType = handItem.getType();

if (handItemType.equals(Material.AIR)) {
if (player.isSneaking()) {
return true;
}

// If this is not a power tool, acts like a normal pickaxe
Material handItemType = handItem.getType();

if (!PowerUtils.isPowerTool(handItem)) {
return true;
}

// If the player does not have permission to use the tool, acts like a normal
// pickaxe/shovel

if (!PowerUtils.checkUsePermission(plugin, player, handItemType)) {
return true;
}

return false;
}
}
Loading

0 comments on commit 2b4d0a4

Please sign in to comment.