Skip to content

Commit

Permalink
Fix item enchanting pre-1.14 (#2127)
Browse files Browse the repository at this point in the history
If the server spams the window property update packet, then the network ID assigned for each enchanting slot will update too quickly, essentially disabling enchanting. This commit remedies this by only updating the network ID of each slot if a property changed.
  • Loading branch information
Camotoy authored Apr 16, 2021
1 parent beb7e54 commit 852d5b0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.nukkitx.protocol.bedrock.data.inventory.EnchantData;
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession;

import java.util.Arrays;
Expand All @@ -38,7 +37,6 @@
/**
* A mutable "wrapper" around {@link EnchantOptionData}
*/
@Setter
public class GeyserEnchantOption {
private static final List<EnchantData> EMPTY = Collections.emptyList();
/**
Expand All @@ -57,6 +55,12 @@ public class GeyserEnchantOption {
@Getter
private final int javaIndex;

/**
* Whether the enchantment details have actually changed.
* Used to mitigate weird packet spamming pre-1.14, causing the net ID to always update.
*/
private boolean hasChanged;

private int xpCost = 0;
private int javaEnchantIndex = -1;
private int bedrockEnchantIndex = -1;
Expand All @@ -67,8 +71,35 @@ public GeyserEnchantOption(int javaIndex) {
}

public EnchantOptionData build(GeyserSession session) {
this.hasChanged = false;
return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY,
enchantLevel == -1 ? EMPTY : Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY,
javaEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(javaEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId());
}

public boolean hasChanged() {
return hasChanged;
}

public void setXpCost(int xpCost) {
if (this.xpCost != xpCost) {
hasChanged = true;
this.xpCost = xpCost;
}
}

public void setEnchantIndex(int javaEnchantIndex, int bedrockEnchantIndex) {
if (this.javaEnchantIndex != javaEnchantIndex) {
hasChanged = true;
this.javaEnchantIndex = javaEnchantIndex;
this.bedrockEnchantIndex = bedrockEnchantIndex;
}
}

public void setEnchantLevel(int enchantLevel) {
if (this.enchantLevel != enchantLevel) {
hasChanged = true;
this.enchantLevel = enchantLevel;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
import com.nukkitx.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
import org.geysermc.connector.inventory.EnchantingContainer;
import org.geysermc.connector.inventory.GeyserEnchantOption;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.inventory.PlayerInventory;
import org.geysermc.connector.network.session.GeyserSession;
Expand Down Expand Up @@ -67,18 +68,20 @@ public void updateProperty(GeyserSession session, Inventory inventory, int key,
case 6:
// Enchantment type
slotToUpdate = key - 4;
int index = value;
if (index != -1) {
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + JavaEnchantment.values()[index].name().toLowerCase());
// "value" here is the Java enchant ordinal, so that does not need to be changed
// The Bedrock index might need changed, so let's look it up and see.
int bedrockIndex = value;
if (bedrockIndex != -1) {
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + JavaEnchantment.values()[bedrockIndex].name().toLowerCase());
if (enchantment != null) {
// Convert the Java enchantment index to Bedrock's
index = enchantment.ordinal();
bedrockIndex = enchantment.ordinal();
} else {
index = -1;
// There is no Bedrock enchantment equivalent
bedrockIndex = -1;
}
}
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setJavaEnchantIndex(value);
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setBedrockEnchantIndex(index);
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantIndex(value, bedrockIndex);
break;
case 7:
case 8:
Expand All @@ -91,8 +94,9 @@ public void updateProperty(GeyserSession session, Inventory inventory, int key,
default:
return;
}
if (shouldUpdate) {
enchantingInventory.getEnchantOptions()[slotToUpdate] = enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].build(session);
GeyserEnchantOption enchantOption = enchantingInventory.getGeyserEnchantOptions()[slotToUpdate];
if (shouldUpdate && enchantOption.hasChanged()) {
enchantingInventory.getEnchantOptions()[slotToUpdate] = enchantOption.build(session);
PlayerEnchantOptionsPacket packet = new PlayerEnchantOptionsPacket();
packet.getOptions().addAll(Arrays.asList(enchantingInventory.getEnchantOptions()));
session.sendUpstreamPacket(packet);
Expand Down

0 comments on commit 852d5b0

Please sign in to comment.