[SPIGOT-6686] Changes in MaximumRepairCost for Anvil Rename cause inconsistency Created: 02/Aug/21  Updated: 27/Aug/21  Resolved: 27/Aug/21

Status: Resolved
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Doc Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: None

Attachments: PNG File image-2021-08-01-21-47-27-491.png     PNG File image-2021-08-01-21-47-41-880.png    
Version: CraftBukkit version 3207-Spigot-18c71bf-8537925 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT)
Guidelines Read: Yes

 Description   

If you change the value of MaximumRepairCost in PrepareAnvilEvent the client can show in anvil a different cost of the real.

 

Code for test.

@EventHandler
public void onPrepareAnvilEvent(PrepareAnvilEvent event) {
    AnvilInventory inventory = event.getInventory();
    inventory.setMaximumRepairCost(50);

    final Player player = ((Player) event.getView().getPlayer());

    ItemStack leftItem = inventory.getItem(0);
    ItemStack rightItem = inventory.getItem(1);

    //check if both item slots are filled
    if (leftItem != null && rightItem != null) {
        player.sendMessage("TEST 1");
        handleLevelCost(player,event,inventory);
    } else if(leftItem != null) { // Start for detect rename
        if(inventory.getRenameText() != null && !inventory.getRenameText().isEmpty() && event.getResult() != null) { //Only Rename
            handleLevelCost(player,event,inventory);
        }
    }
}

//Detect a player has click the item result in Anvil!
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
    // check whether the event has been cancelled by another plugin
    if (!event.isCancelled()) {
        HumanEntity humanEntity = event.getWhoClicked();

        if (humanEntity instanceof Player) {
            Player player = (Player) humanEntity;
            // Check if this event fired inside an anvil.
            if (event.getInventory() instanceof AnvilInventory) {
                final AnvilInventory anvilInventory = (AnvilInventory) event.getInventory();
                InventoryView view = event.getView();
                int rawSlot = event.getRawSlot();

                // check if we are in the upper inventory of the anvil
                if (rawSlot == view.convertSlot(rawSlot)) {
                    // check if we are talking about the result slot
                    if (rawSlot == 2) {
                        // get all 3 items in the anvil
                        ItemStack[] items = anvilInventory.getContents();

                        if (player.getLevel() < anvilInventory.getRepairCost() && !player.getGameMode().equals(GameMode.CREATIVE)) { // Handle level and vanilla feature for creative
                            player.sendMessage("CANT PAY " + event.getResult()); // This return ALLOW
                        }
                    }
                }
            }
        }
    }
}

private void handleLevelCost(Player player, PrepareAnvilEvent event, AnvilInventory inventory) {
    int finalRepairCost = inventory.getRepairCost();
    player.sendMessage(ChatColor.RED + "Anvil Cost is: " + ChatColor.GREEN + finalRepairCost + ChatColor.RED + " levels.");
}

I test this using a sword and enchanting with every possible book for swords (in vanilla book per book for the RepairCost).. then when try to rename the item the anvil show cost 39 in GUI but the event show cost 64.


 

If you have the levels for rename the item and try to click the item result the anvil take the levels but not rename the item cancel the process.

 



 Comments   
Comment by Doc [ 25/Aug/21 ]

If the PR sync then not problem for me, i prefer only the visual bug for "too expensive" than the bug with costs and levels.

Comment by Marvin Rieple [ 25/Aug/21 ]

Made a PR for this: craftbukkit#923

 

With this the cost is always be synced with the client. It will however still display "too expensive" if the server side cost is higher than 40. This is client side and only a visual bug. Which can not be fixed server side.

Comment by Doc [ 22/Aug/21 ]

well then maybe need set maxrepair in 40 for rename items.. for not add a patch like resend levels lost with runtasklater...

Comment by Marvin Rieple [ 22/Aug/21 ]

The client only calculates the repair cost itself when the item is being renamed. The only thing the server can do is to always send the repair cost (currently it is only send if it changes) resulting in always showing "too expensive". The "too expensive" is also client site, if the required level is over 40 and the player doesn't has instabuild (creative) it shows "too expensive" otherwise it will show the amount.

 

> and the other issue and dont know if is visual or not is when take the item and lost the levels but the item its not taken because the server cancel by player::Level < anvil::Cost.

It is only visual / de sync if the player rejoins the level should be right. This can be fixed by always sending the cost. But the "too expensive" will still show if the level is over 40.

Comment by Doc [ 22/Aug/21 ]

Okay, but its strange this happen only in rename, i tested added enchants and this not happen only the "too expensive", and the other issue and dont know if is visual or not is when take the item and lost the levels but the item its not taken because the server cancel by player::Level < anvil::Cost.

Comment by Marvin Rieple [ 22/Aug/21 ]

This is a client site visual issue, the client will also calculate the repair cost with the maximum repair cost of 40 (hard coded) and display it.

Generated at Tue Apr 22 03:12:16 UTC 2025 using Jira 10.3.5#10030005-sha1:190c783f2bd6c69cd5accdb70f97e48812a78d14.