Skip to content

Commit e6e8a61

Browse files
authored
Add configurable max repair cost (#1)
1 parent 7eb2f4e commit e6e8a61

File tree

4 files changed

+71
-27
lines changed

4 files changed

+71
-27
lines changed

README.MD

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
### About
2-
AnvilUnlocker is a Bukkit plugin allowing anvils to be used past the normal level cap of 40. No permissions, no setup.
2+
AnvilUnlocker is a Bukkit plugin allowing anvils to be used past the normal level cap of 40. No permissions.
33

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

66
### Caveats
7-
* 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.
7+
* 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.
88
* 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.

pom.xml

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@
1111

1212
<properties>
1313
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
14+
<maven.compiler.source>8</maven.compiler.source>
15+
<maven.compiler.target>8</maven.compiler.target>
1416
</properties>
1517

1618
<repositories>
1719
<repository>
18-
<id>spigot-repo</id>
19-
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
20+
<id>spigotmc-repo</id>
21+
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
2022
</repository>
2123
<repository>
2224
<id>dmulloy2-repo</id>
23-
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
25+
<url>https://repo.dmulloy2.net/repository/public/</url>
2426
</repository>
2527
</repositories>
2628

@@ -34,7 +36,14 @@
3436
<dependency>
3537
<groupId>com.comphenix.protocol</groupId>
3638
<artifactId>ProtocolLib</artifactId>
37-
<version>4.5.0</version>
39+
<version>4.8.0</version>
40+
<scope>provided</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.jetbrains</groupId>
44+
<artifactId>annotations</artifactId>
45+
<version>23.0.0</version>
46+
<!-- Annotations is only used during compilation. -->
3847
<scope>provided</scope>
3948
</dependency>
4049
</dependencies>
@@ -48,18 +57,6 @@
4857
<filtering>true</filtering>
4958
</resource>
5059
</resources>
51-
52-
<plugins>
53-
<plugin>
54-
<groupId>org.apache.maven.plugins</groupId>
55-
<artifactId>maven-compiler-plugin</artifactId>
56-
<version>3.8.1</version>
57-
<configuration>
58-
<source>1.8</source>
59-
<target>1.8</target>
60-
</configuration>
61-
</plugin>
62-
</plugins>
6360
</build>
6461

6562
</project>

src/main/java/com/github/jikoo/anvilunlocker/AnvilUnlocker.java

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,81 @@
55
import com.comphenix.protocol.events.PacketContainer;
66
import java.lang.reflect.InvocationTargetException;
77
import org.bukkit.GameMode;
8+
import org.bukkit.Material;
89
import org.bukkit.entity.Player;
910
import org.bukkit.event.EventHandler;
11+
import org.bukkit.event.EventPriority;
1012
import org.bukkit.event.Listener;
1113
import org.bukkit.event.inventory.InventoryCloseEvent;
1214
import org.bukkit.event.inventory.InventoryOpenEvent;
15+
import org.bukkit.event.inventory.PrepareAnvilEvent;
1316
import org.bukkit.inventory.AnvilInventory;
17+
import org.bukkit.inventory.ItemStack;
1418
import org.bukkit.plugin.java.JavaPlugin;
19+
import org.jetbrains.annotations.NotNull;
1520

1621
public class AnvilUnlocker extends JavaPlugin implements Listener {
1722

23+
private int maximumCost = Short.MAX_VALUE;
24+
1825
@Override
1926
public void onEnable() {
27+
saveDefaultConfig();
28+
29+
maximumCost = constrainAnvilMax(getConfig().getInt("maximumCost"));
30+
2031
getServer().getPluginManager().registerEvents(this, this);
2132
}
2233

23-
@EventHandler
24-
public void onInventoryOpen(InventoryOpenEvent event) {
25-
if (event.getInventory() instanceof AnvilInventory && event.getPlayer() instanceof Player
34+
@Override
35+
public void reloadConfig() {
36+
super.reloadConfig();
37+
maximumCost = constrainAnvilMax(getConfig().getInt("maximumCost"));
38+
}
39+
40+
@EventHandler(priority = EventPriority.MONITOR)
41+
private void onInventoryOpen(@NotNull InventoryOpenEvent event) {
42+
if (!(event.getInventory() instanceof AnvilInventory)) {
43+
return;
44+
}
45+
46+
((AnvilInventory) event.getInventory()).setMaximumRepairCost(maximumCost);
47+
48+
if (event.getPlayer() instanceof Player
2649
&& event.getPlayer().getGameMode() != GameMode.CREATIVE) {
27-
((AnvilInventory) event.getInventory()).setMaximumRepairCost(Short.MAX_VALUE);
2850
setInstantBuild((Player) event.getPlayer(), true);
2951
}
3052
}
3153

32-
@EventHandler
33-
public void onInventoryClose(InventoryCloseEvent event) {
34-
if (event.getInventory() instanceof AnvilInventory && event.getPlayer() instanceof Player
54+
@EventHandler(priority = EventPriority.MONITOR)
55+
private void onInventoryClose(@NotNull InventoryCloseEvent event) {
56+
if (event.getInventory() instanceof AnvilInventory
57+
&& event.getPlayer() instanceof Player
3558
&& event.getPlayer().getGameMode() != GameMode.CREATIVE) {
3659
setInstantBuild((Player) event.getPlayer(), false);
3760
}
3861
}
3962

40-
public void setInstantBuild(Player player, boolean instantBuild) {
63+
@EventHandler(priority = EventPriority.MONITOR)
64+
private void onPrepareAnvil(@NotNull PrepareAnvilEvent event) {
65+
if (!(event.getView().getPlayer() instanceof Player)
66+
|| event.getView().getPlayer().getGameMode() == GameMode.CREATIVE) {
67+
return;
68+
}
69+
70+
getServer().getScheduler().runTask(this, () -> {
71+
AnvilInventory anvil = event.getInventory();
72+
ItemStack input2 = anvil.getItem(1);
73+
setInstantBuild(
74+
(Player) event.getView().getPlayer(),
75+
// Prevent "Too Expensive!" with no secondary input.
76+
input2 == null || input2.getType() == Material.AIR
77+
// Display "Too Expensive!" if cost meets or exceeds maximum.
78+
|| anvil.getRepairCost() < anvil.getMaximumRepairCost());
79+
});
80+
}
81+
82+
public void setInstantBuild(@NotNull Player player, boolean instantBuild) {
4183
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ABILITIES);
4284
packet.getBooleans().write(0, player.isInvulnerable());
4385
packet.getBooleans().write(1, player.isFlying());
@@ -53,4 +95,8 @@ public void setInstantBuild(Player player, boolean instantBuild) {
5395
}
5496
}
5597

98+
private static int constrainAnvilMax(int actual) {
99+
return Math.min(Short.MAX_VALUE, Math.max(41, actual));
100+
}
101+
56102
}

src/main/resources/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
maximumCost: 32767

0 commit comments

Comments
 (0)