Skip to content

Commit

Permalink
Add configurable max repair cost (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
mvez73 authored Apr 24, 2022
1 parent 7eb2f4e commit e6e8a61
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 27 deletions.
6 changes: 3 additions & 3 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
### About
AnvilUnlocker is a Bukkit plugin allowing anvils to be used past the normal level cap of 40. No permissions, no setup.
AnvilUnlocker is a Bukkit plugin allowing anvils to be used past the normal level cap of 40. No permissions.

As this provides a definite gameplay advantage, I will not be modifying this plugin to add permissions.
The level cap is set via configuration option `maximumCost`. Any integer from 41 to 32767 is valid.

### Caveats
* Due to client limitations, repair costs over 40 levels cannot be displayed in red whether or not the client has the experience required to complete the repair. For simplicity and consistency, AnvilUnlocker uses an approach that sends a minimum number of packets but entirely removes the mechanic of the cost turning red when the client lacks the required experience, even when the cost is under 40 levels.
* Due to client limitations, repair costs over 40 levels cannot be displayed in red if the client lacks the experience required to complete the repair. For simplicity and consistency, AnvilUnlocker uses an approach that entirely removes the mechanic of the cost turning red when the client lacks the required experience, even when the cost is under 40 levels.
* Due to the client's inability to display items' costs greater than a short's max value (32767) and subsequent wrapping around, the new maximum is capped to 32767 instead of allowing any valid int value.
29 changes: 13 additions & 16 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
<url>https://repo.dmulloy2.net/repository/public/</url>
</repository>
</repositories>

Expand All @@ -34,7 +36,14 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.5.0</version>
<version>4.8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>23.0.0</version>
<!-- Annotations is only used during compilation. -->
<scope>provided</scope>
</dependency>
</dependencies>
Expand All @@ -48,18 +57,6 @@
<filtering>true</filtering>
</resource>
</resources>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
62 changes: 54 additions & 8 deletions src/main/java/com/github/jikoo/anvilunlocker/AnvilUnlocker.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,81 @@
import com.comphenix.protocol.events.PacketContainer;
import java.lang.reflect.InvocationTargetException;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;

public class AnvilUnlocker extends JavaPlugin implements Listener {

private int maximumCost = Short.MAX_VALUE;

@Override
public void onEnable() {
saveDefaultConfig();

maximumCost = constrainAnvilMax(getConfig().getInt("maximumCost"));

getServer().getPluginManager().registerEvents(this, this);
}

@EventHandler
public void onInventoryOpen(InventoryOpenEvent event) {
if (event.getInventory() instanceof AnvilInventory && event.getPlayer() instanceof Player
@Override
public void reloadConfig() {
super.reloadConfig();
maximumCost = constrainAnvilMax(getConfig().getInt("maximumCost"));
}

@EventHandler(priority = EventPriority.MONITOR)
private void onInventoryOpen(@NotNull InventoryOpenEvent event) {
if (!(event.getInventory() instanceof AnvilInventory)) {
return;
}

((AnvilInventory) event.getInventory()).setMaximumRepairCost(maximumCost);

if (event.getPlayer() instanceof Player
&& event.getPlayer().getGameMode() != GameMode.CREATIVE) {
((AnvilInventory) event.getInventory()).setMaximumRepairCost(Short.MAX_VALUE);
setInstantBuild((Player) event.getPlayer(), true);
}
}

@EventHandler
public void onInventoryClose(InventoryCloseEvent event) {
if (event.getInventory() instanceof AnvilInventory && event.getPlayer() instanceof Player
@EventHandler(priority = EventPriority.MONITOR)
private void onInventoryClose(@NotNull InventoryCloseEvent event) {
if (event.getInventory() instanceof AnvilInventory
&& event.getPlayer() instanceof Player
&& event.getPlayer().getGameMode() != GameMode.CREATIVE) {
setInstantBuild((Player) event.getPlayer(), false);
}
}

public void setInstantBuild(Player player, boolean instantBuild) {
@EventHandler(priority = EventPriority.MONITOR)
private void onPrepareAnvil(@NotNull PrepareAnvilEvent event) {
if (!(event.getView().getPlayer() instanceof Player)
|| event.getView().getPlayer().getGameMode() == GameMode.CREATIVE) {
return;
}

getServer().getScheduler().runTask(this, () -> {
AnvilInventory anvil = event.getInventory();
ItemStack input2 = anvil.getItem(1);
setInstantBuild(
(Player) event.getView().getPlayer(),
// Prevent "Too Expensive!" with no secondary input.
input2 == null || input2.getType() == Material.AIR
// Display "Too Expensive!" if cost meets or exceeds maximum.
|| anvil.getRepairCost() < anvil.getMaximumRepairCost());
});
}

public void setInstantBuild(@NotNull Player player, boolean instantBuild) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ABILITIES);
packet.getBooleans().write(0, player.isInvulnerable());
packet.getBooleans().write(1, player.isFlying());
Expand All @@ -53,4 +95,8 @@ public void setInstantBuild(Player player, boolean instantBuild) {
}
}

private static int constrainAnvilMax(int actual) {
return Math.min(Short.MAX_VALUE, Math.max(41, actual));
}

}
1 change: 1 addition & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
maximumCost: 32767

0 comments on commit e6e8a61

Please sign in to comment.