mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Fix item enchanting pre-1.14 (#2127)
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.
This commit is contained in:
parent
beb7e54b7a
commit
852d5b050d
2 changed files with 46 additions and 11 deletions
|
@ -28,7 +28,6 @@ package org.geysermc.connector.inventory;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantData;
|
import com.nukkitx.protocol.bedrock.data.inventory.EnchantData;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
|
import com.nukkitx.protocol.bedrock.data.inventory.EnchantOptionData;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -38,7 +37,6 @@ import java.util.List;
|
||||||
/**
|
/**
|
||||||
* A mutable "wrapper" around {@link EnchantOptionData}
|
* A mutable "wrapper" around {@link EnchantOptionData}
|
||||||
*/
|
*/
|
||||||
@Setter
|
|
||||||
public class GeyserEnchantOption {
|
public class GeyserEnchantOption {
|
||||||
private static final List<EnchantData> EMPTY = Collections.emptyList();
|
private static final List<EnchantData> EMPTY = Collections.emptyList();
|
||||||
/**
|
/**
|
||||||
|
@ -57,6 +55,12 @@ public class GeyserEnchantOption {
|
||||||
@Getter
|
@Getter
|
||||||
private final int javaIndex;
|
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 xpCost = 0;
|
||||||
private int javaEnchantIndex = -1;
|
private int javaEnchantIndex = -1;
|
||||||
private int bedrockEnchantIndex = -1;
|
private int bedrockEnchantIndex = -1;
|
||||||
|
@ -67,8 +71,35 @@ public class GeyserEnchantOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnchantOptionData build(GeyserSession session) {
|
public EnchantOptionData build(GeyserSession session) {
|
||||||
|
this.hasChanged = false;
|
||||||
return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY,
|
return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY,
|
||||||
enchantLevel == -1 ? EMPTY : Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY,
|
enchantLevel == -1 ? EMPTY : Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY,
|
||||||
javaEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(javaEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.StackRequ
|
||||||
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
|
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
|
import com.nukkitx.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
|
||||||
import org.geysermc.connector.inventory.EnchantingContainer;
|
import org.geysermc.connector.inventory.EnchantingContainer;
|
||||||
|
import org.geysermc.connector.inventory.GeyserEnchantOption;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.inventory.PlayerInventory;
|
import org.geysermc.connector.inventory.PlayerInventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
@ -67,18 +68,20 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
|
||||||
case 6:
|
case 6:
|
||||||
// Enchantment type
|
// Enchantment type
|
||||||
slotToUpdate = key - 4;
|
slotToUpdate = key - 4;
|
||||||
int index = value;
|
// "value" here is the Java enchant ordinal, so that does not need to be changed
|
||||||
if (index != -1) {
|
// The Bedrock index might need changed, so let's look it up and see.
|
||||||
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + JavaEnchantment.values()[index].name().toLowerCase());
|
int bedrockIndex = value;
|
||||||
|
if (bedrockIndex != -1) {
|
||||||
|
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + JavaEnchantment.values()[bedrockIndex].name().toLowerCase());
|
||||||
if (enchantment != null) {
|
if (enchantment != null) {
|
||||||
// Convert the Java enchantment index to Bedrock's
|
// Convert the Java enchantment index to Bedrock's
|
||||||
index = enchantment.ordinal();
|
bedrockIndex = enchantment.ordinal();
|
||||||
} else {
|
} else {
|
||||||
index = -1;
|
// There is no Bedrock enchantment equivalent
|
||||||
|
bedrockIndex = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setJavaEnchantIndex(value);
|
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantIndex(value, bedrockIndex);
|
||||||
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setBedrockEnchantIndex(index);
|
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -91,8 +94,9 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (shouldUpdate) {
|
GeyserEnchantOption enchantOption = enchantingInventory.getGeyserEnchantOptions()[slotToUpdate];
|
||||||
enchantingInventory.getEnchantOptions()[slotToUpdate] = enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].build(session);
|
if (shouldUpdate && enchantOption.hasChanged()) {
|
||||||
|
enchantingInventory.getEnchantOptions()[slotToUpdate] = enchantOption.build(session);
|
||||||
PlayerEnchantOptionsPacket packet = new PlayerEnchantOptionsPacket();
|
PlayerEnchantOptionsPacket packet = new PlayerEnchantOptionsPacket();
|
||||||
packet.getOptions().addAll(Arrays.asList(enchantingInventory.getEnchantOptions()));
|
packet.getOptions().addAll(Arrays.asList(enchantingInventory.getEnchantOptions()));
|
||||||
session.sendUpstreamPacket(packet);
|
session.sendUpstreamPacket(packet);
|
||||||
|
|
Loading…
Reference in a new issue