9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-20 07:29:17 +00:00

物品映射重构1

This commit is contained in:
XiaoMoMi
2025-10-13 02:04:22 +08:00
parent f4224c1676
commit 12435dabfa
10 changed files with 341 additions and 186 deletions

View File

@@ -54,11 +54,15 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
} }
public Object clientItem() { public Object clientItem() {
return clientItem; return this.clientItem;
} }
public Object item() { public Object item() {
return item; return this.item;
}
public boolean hasClientboundMaterial() {
return this.clientItem != this.item;
} }
public static Builder<ItemStack> builder(Object item, Object clientBoundItem) { public static Builder<ItemStack> builder(Object item, Object clientBoundItem) {

View File

@@ -125,23 +125,23 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override @Override
public Item<ItemStack> s2c(Item<ItemStack> item, Player player) { public Item<ItemStack> s2c(Item<ItemStack> item, Player player) {
if (item.isEmpty()) return item; if (item.isEmpty()) return item;
return this.networkItemHandler.s2c(item, player); return this.networkItemHandler.s2c(item, player).orElse(item);
} }
@Override @Override
public Item<ItemStack> c2s(Item<ItemStack> item) { public Item<ItemStack> c2s(Item<ItemStack> item) {
if (item.isEmpty()) return item; if (item.isEmpty()) return item;
return this.networkItemHandler.c2s(item); return this.networkItemHandler.c2s(item).orElse(item);
} }
public ItemStack s2c(ItemStack item, Player player) { public Optional<ItemStack> s2c(ItemStack item, Player player) {
if (item.isEmpty()) return item; if (item.isEmpty()) return Optional.empty();
return s2c(wrap(item), player).getItem(); return this.networkItemHandler.s2c(wrap(item), player).map(Item::getItem);
} }
public ItemStack c2s(ItemStack item) { public Optional<ItemStack> c2s(ItemStack item) {
if (item.isEmpty()) return item; if (item.isEmpty()) return Optional.empty();
return c2s(wrap(item)).getItem(); return this.networkItemHandler.c2s(wrap(item)).map(Item::getItem);
} }
@Override @Override

View File

@@ -23,6 +23,11 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
private final ItemStack item; private final ItemStack item;
private final Object handle; private final Object handle;
public ComponentItemWrapper(final Object handle) {
this.handle = handle;
this.item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(handle);
}
public ComponentItemWrapper(final ItemStack item) { public ComponentItemWrapper(final ItemStack item) {
this.item = ItemStackUtils.ensureCraftItemStack(item); this.item = ItemStackUtils.ensureCraftItemStack(item);
this.handle = FastNMS.INSTANCE.field$CraftItemStack$handle(this.item); this.handle = FastNMS.INSTANCE.field$CraftItemStack$handle(this.item);

View File

@@ -32,54 +32,70 @@ import java.util.function.BiConsumer;
public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> { public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
@Override @Override
public Item<ItemStack> c2s(Item<ItemStack> wrapped) { public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
boolean forceReturn = false;
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem(); Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
if (optionalCustomItem.isPresent()) { if (optionalCustomItem.isPresent()) {
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get(); BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
if (customItem.item() != FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) { if (customItem.item() != FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) {
wrapped = wrapped.unsafeTransmuteCopy(customItem.item(), wrapped.count()); wrapped = wrapped.unsafeTransmuteCopy(customItem.item(), wrapped.count());
forceReturn = true;
} }
} }
CompoundTag networkData = (CompoundTag) wrapped.getTag(NETWORK_ITEM_TAG); CompoundTag networkData = (CompoundTag) wrapped.getTag(NETWORK_ITEM_TAG);
if (networkData == null) return wrapped; if (networkData != null) {
forceReturn = true;
// 移除tag
wrapped.removeTag(NETWORK_ITEM_TAG); wrapped.removeTag(NETWORK_ITEM_TAG);
// 恢复物品
for (Map.Entry<String, Tag> entry : networkData.entrySet()) { for (Map.Entry<String, Tag> entry : networkData.entrySet()) {
if (entry.getValue() instanceof CompoundTag tag) { if (entry.getValue() instanceof CompoundTag tag) {
NetworkItemHandler.apply(entry.getKey(), tag, wrapped); NetworkItemHandler.apply(entry.getKey(), tag, wrapped);
} }
} }
return wrapped; }
return forceReturn ? Optional.empty() : Optional.of(wrapped);
} }
@Override @Override
public Item<ItemStack> s2c(Item<ItemStack> wrapped, Player player) { public Optional<Item<ItemStack>> s2c(Item<ItemStack> wrapped, Player player) {
// todo 处理bundle和container boolean forceReturn = false;
// todo 处理bundle
// todo 处理container
// todo 处理book // todo 处理book
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem(); Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
// 不是自定义物品或修改过的原版物品 // 不是自定义物品或修改过的原版物品
if (optionalCustomItem.isEmpty()) { if (optionalCustomItem.isEmpty()) {
if (!Config.interceptItem()) return wrapped; if (!Config.interceptItem()) {
return new OtherItem(wrapped).process(NetworkTextReplaceContext.of(player)); return forceReturn ? Optional.of(wrapped) : Optional.empty();
}
return new OtherItem(wrapped, forceReturn).process(NetworkTextReplaceContext.of(player));
} }
// 应用 client-bound-material // 应用 client-bound-material
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get(); BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
Object serverItem = FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject()); if (customItem.hasClientboundMaterial() && FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject()) != customItem.clientItem()) {
boolean hasDifferentMaterial = serverItem == customItem.item() && serverItem != customItem.clientItem();
if (hasDifferentMaterial) {
wrapped = wrapped.unsafeTransmuteCopy(customItem.clientItem(), wrapped.count()); wrapped = wrapped.unsafeTransmuteCopy(customItem.clientItem(), wrapped.count());
forceReturn = true;
} }
// 没有客户端侧组件 // 没有客户端侧组件
if (!customItem.hasClientBoundDataModifier()) { if (!customItem.hasClientBoundDataModifier()) {
if (!Config.interceptItem()) return wrapped; if (!Config.interceptItem()) {
return new OtherItem(wrapped).process(NetworkTextReplaceContext.of(player)); return forceReturn ? Optional.of(wrapped) : Optional.empty();
}
return new OtherItem(wrapped, forceReturn).process(NetworkTextReplaceContext.of(player));
} }
// 应用client-bound-data // 应用client-bound-data
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
// 创建context
Tag argumentTag = wrapped.getTag(ArgumentsModifier.ARGUMENTS_TAG); Tag argumentTag = wrapped.getTag(ArgumentsModifier.ARGUMENTS_TAG);
ItemBuildContext context; ItemBuildContext context;
if (argumentTag instanceof CompoundTag arguments) { if (argumentTag instanceof CompoundTag arguments) {
@@ -91,12 +107,15 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemSt
} else { } else {
context = ItemBuildContext.of(player); context = ItemBuildContext.of(player);
} }
// 准备阶段
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) { for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
modifier.prepareNetworkItem(wrapped, context, tag); modifier.prepareNetworkItem(wrapped, context, tag);
} }
// 应用阶段
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) { for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
modifier.apply(wrapped, context); modifier.apply(wrapped, context);
} }
// 如果拦截物品的描述名称等
if (Config.interceptItem()) { if (Config.interceptItem()) {
if (!tag.containsKey("display.Name")) { if (!tag.containsKey("display.Name")) {
processCustomName(wrapped, tag::put, context); processCustomName(wrapped, tag::put, context);
@@ -105,10 +124,12 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemSt
processLore(wrapped, tag::put, context); processLore(wrapped, tag::put, context);
} }
} }
// 如果tag不空则需要返回
if (!tag.isEmpty()) { if (!tag.isEmpty()) {
wrapped.setTag(tag, NETWORK_ITEM_TAG); wrapped.setTag(tag, NETWORK_ITEM_TAG);
forceReturn = true;
} }
return wrapped; return forceReturn ? Optional.of(wrapped) : Optional.empty();
} }
public static boolean processCustomName(Item<ItemStack> item, BiConsumer<String, CompoundTag> callback, Context context) { public static boolean processCustomName(Item<ItemStack> item, BiConsumer<String, CompoundTag> callback, Context context) {
@@ -157,12 +178,14 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemSt
private final Item<ItemStack> item; private final Item<ItemStack> item;
private boolean globalChanged = false; private boolean globalChanged = false;
private CompoundTag networkTag; private CompoundTag networkTag;
private final boolean forceReturn;
public OtherItem(Item<ItemStack> item) { public OtherItem(Item<ItemStack> item, boolean forceReturn) {
this.item = item; this.item = item;
this.forceReturn = forceReturn;
} }
public Item<ItemStack> process(Context context) { public Optional<Item<ItemStack>> process(Context context) {
if (processLore(this.item, (s, c) -> networkTag().put(s, c), context)) { if (processLore(this.item, (s, c) -> networkTag().put(s, c), context)) {
this.globalChanged = true; this.globalChanged = true;
} }
@@ -171,8 +194,12 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemSt
} }
if (this.globalChanged) { if (this.globalChanged) {
this.item.setTag(this.networkTag, NETWORK_ITEM_TAG); this.item.setTag(this.networkTag, NETWORK_ITEM_TAG);
return Optional.of(this.item);
} else if (this.forceReturn) {
return Optional.of(this.item);
} else {
return Optional.empty();
} }
return this.item;
} }
public CompoundTag networkTag() { public CompoundTag networkTag() {

View File

@@ -30,25 +30,47 @@ import java.util.function.Supplier;
public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemStack> { public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemStack> {
@Override @Override
public Item<ItemStack> c2s(Item<ItemStack> wrapped) { public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
boolean forceReturn = false;
// 处理收纳袋
if (wrapped.hasComponent(ComponentTypes.BUNDLE_CONTENTS)) { if (wrapped.hasComponent(ComponentTypes.BUNDLE_CONTENTS)) {
Object bundleContents = wrapped.getExactComponent(ComponentTypes.BUNDLE_CONTENTS); Object bundleContents = wrapped.getExactComponent(ComponentTypes.BUNDLE_CONTENTS);
List<Object> newItems = new ArrayList<>(); List<Object> newItems = new ArrayList<>();
boolean changed = false;
for (Object previousItem : FastNMS.INSTANCE.method$BundleContents$items(bundleContents)) { for (Object previousItem : FastNMS.INSTANCE.method$BundleContents$items(bundleContents)) {
ItemStack itemStack = BukkitItemManager.instance().c2s(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem)); Optional<ItemStack> itemStack = BukkitItemManager.instance().c2s(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem));
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack)); if (itemStack.isPresent()) {
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack.get()));
changed = true;
} else {
newItems.add(previousItem);
} }
}
if (changed) {
wrapped.setExactComponent(ComponentTypes.BUNDLE_CONTENTS, FastNMS.INSTANCE.constructor$BundleContents(newItems)); wrapped.setExactComponent(ComponentTypes.BUNDLE_CONTENTS, FastNMS.INSTANCE.constructor$BundleContents(newItems));
forceReturn = true;
}
} }
// 处理潜影盒等
if (wrapped.hasComponent(ComponentTypes.CONTAINER)) { if (wrapped.hasComponent(ComponentTypes.CONTAINER)) {
Object containerContents = wrapped.getExactComponent(ComponentTypes.CONTAINER); Object containerContents = wrapped.getExactComponent(ComponentTypes.CONTAINER);
List<Object> newItems = new ArrayList<>(); List<Object> newItems = new ArrayList<>();
boolean changed = false;
for (Object previousItem : FastNMS.INSTANCE.field$ItemContainerContents$items(containerContents)) { for (Object previousItem : FastNMS.INSTANCE.field$ItemContainerContents$items(containerContents)) {
ItemStack itemStack = BukkitItemManager.instance().c2s(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem)); Optional<ItemStack> itemStack = BukkitItemManager.instance().c2s(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem));
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack)); if (itemStack.isPresent()) {
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack.get()));
changed = true;
} else {
newItems.add(previousItem);
} }
}
if (changed) {
wrapped.setExactComponent(ComponentTypes.CONTAINER, FastNMS.INSTANCE.method$ItemContainerContents$fromItems(newItems)); wrapped.setExactComponent(ComponentTypes.CONTAINER, FastNMS.INSTANCE.method$ItemContainerContents$fromItems(newItems));
forceReturn = true;
}
} }
// 先尝试恢复client-bound-material // 先尝试恢复client-bound-material
@@ -57,79 +79,112 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get(); BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
if (customItem.item() != FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) { if (customItem.item() != FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject())) {
wrapped = wrapped.unsafeTransmuteCopy(customItem.item(), wrapped.count()); wrapped = wrapped.unsafeTransmuteCopy(customItem.item(), wrapped.count());
forceReturn = true;
} }
} }
// 没有 custom data 则忽略 // 获取custom data
Tag customData = wrapped.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA); Tag customData = wrapped.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA);
if (!(customData instanceof CompoundTag compoundTag)) { if (customData instanceof CompoundTag compoundTag) {
return wrapped;
}
// 未曾应用过 client-bound-data
CompoundTag networkData = compoundTag.getCompound(NETWORK_ITEM_TAG); CompoundTag networkData = compoundTag.getCompound(NETWORK_ITEM_TAG);
if (networkData == null) { if (networkData != null) {
return wrapped; forceReturn = true;
}
// 移除此tag // 移除此tag
compoundTag.remove(NETWORK_ITEM_TAG); compoundTag.remove(NETWORK_ITEM_TAG);
// 恢复物品
for (Map.Entry<String, Tag> entry : networkData.entrySet()) { for (Map.Entry<String, Tag> entry : networkData.entrySet()) {
if (entry.getValue() instanceof CompoundTag tag) { if (entry.getValue() instanceof CompoundTag tag) {
NetworkItemHandler.apply(entry.getKey(), tag, wrapped); NetworkItemHandler.apply(entry.getKey(), tag, wrapped);
} }
} }
// 如果清空了,则直接移除这个组件
if (compoundTag.isEmpty()) wrapped.resetComponent(ComponentTypes.CUSTOM_DATA); if (compoundTag.isEmpty()) wrapped.resetComponent(ComponentTypes.CUSTOM_DATA);
// 否则设置为新的
else wrapped.setNBTComponent(ComponentTypes.CUSTOM_DATA, compoundTag); else wrapped.setNBTComponent(ComponentTypes.CUSTOM_DATA, compoundTag);
return wrapped; }
}
return forceReturn ? Optional.of(wrapped) : Optional.empty();
} }
@Override @Override
public Item<ItemStack> s2c(Item<ItemStack> wrapped, Player player) { public Optional<Item<ItemStack>> s2c(Item<ItemStack> wrapped, Player player) {
boolean forceReturn = false;
// 处理收纳袋
if (wrapped.hasComponent(ComponentTypes.BUNDLE_CONTENTS)) { if (wrapped.hasComponent(ComponentTypes.BUNDLE_CONTENTS)) {
Object bundleContents = wrapped.getExactComponent(ComponentTypes.BUNDLE_CONTENTS); Object bundleContents = wrapped.getExactComponent(ComponentTypes.BUNDLE_CONTENTS);
List<Object> newItems = new ArrayList<>(); List<Object> newItems = new ArrayList<>();
boolean changed = false;
for (Object previousItem : FastNMS.INSTANCE.method$BundleContents$items(bundleContents)) { for (Object previousItem : FastNMS.INSTANCE.method$BundleContents$items(bundleContents)) {
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem), player); Optional<ItemStack> itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem), player);
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack)); if (itemStack.isPresent()) {
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack.get()));
changed = true;
} else {
newItems.add(previousItem);
} }
}
if (changed) {
wrapped.setExactComponent(ComponentTypes.BUNDLE_CONTENTS, FastNMS.INSTANCE.constructor$BundleContents(newItems)); wrapped.setExactComponent(ComponentTypes.BUNDLE_CONTENTS, FastNMS.INSTANCE.constructor$BundleContents(newItems));
forceReturn = true;
}
} }
// 处理潜影盒等
if (wrapped.hasComponent(ComponentTypes.CONTAINER)) { if (wrapped.hasComponent(ComponentTypes.CONTAINER)) {
Object containerContents = wrapped.getExactComponent(ComponentTypes.CONTAINER); Object containerContents = wrapped.getExactComponent(ComponentTypes.CONTAINER);
List<Object> newItems = new ArrayList<>(); List<Object> newItems = new ArrayList<>();
for (Object previousItem : FastNMS.INSTANCE.field$ItemContainerContents$items(containerContents)) { for (Object previousItem : FastNMS.INSTANCE.field$ItemContainerContents$items(containerContents)) {
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem), player); boolean changed = false;
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack)); Optional<ItemStack> itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(previousItem), player);
if (itemStack.isPresent()) {
newItems.add(FastNMS.INSTANCE.field$CraftItemStack$handle(itemStack.get()));
changed = true;
} else {
newItems.add(previousItem);
} }
if (changed) {
wrapped.setExactComponent(ComponentTypes.CONTAINER, FastNMS.INSTANCE.method$ItemContainerContents$fromItems(newItems)); wrapped.setExactComponent(ComponentTypes.CONTAINER, FastNMS.INSTANCE.method$ItemContainerContents$fromItems(newItems));
forceReturn = true;
}
}
} }
// todo 处理book // todo 处理book
// 不是自定义物品或修改过的原版物品 // 不是自定义物品或修改过的原版物品
Item<ItemStack> original = wrapped;
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem(); Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
if (optionalCustomItem.isEmpty()) { if (optionalCustomItem.isEmpty()) {
if (!Config.interceptItem()) return wrapped; if (!Config.interceptItem()) {
return new OtherItem(wrapped).process(NetworkTextReplaceContext.of(player)); return forceReturn ? Optional.of(wrapped) : Optional.empty();
}
return new OtherItem(wrapped, forceReturn).process(NetworkTextReplaceContext.of(player));
} }
// 应用 client-bound-data
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get(); BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();
Object serverItem = FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject()); // 提前复制,这和物品类型相关
boolean hasDifferentMaterial = serverItem == customItem.item() && serverItem != customItem.clientItem(); Item<ItemStack> original = wrapped;
if (hasDifferentMaterial) { // 应用 client-bound-material前提是服务端侧物品类型和客户端侧的不同
if (customItem.hasClientboundMaterial() && FastNMS.INSTANCE.method$ItemStack$getItem(wrapped.getLiteralObject()) != customItem.clientItem()) {
wrapped = wrapped.unsafeTransmuteCopy(customItem.clientItem(), wrapped.count()); wrapped = wrapped.unsafeTransmuteCopy(customItem.clientItem(), wrapped.count());
forceReturn = true;
} }
// 没有 client-bound-data
if (!customItem.hasClientBoundDataModifier()) { if (!customItem.hasClientBoundDataModifier()) {
if (!Config.interceptItem()) return wrapped; if (!Config.interceptItem()) {
return new OtherItem(wrapped).process(NetworkTextReplaceContext.of(player)); return forceReturn ? Optional.of(wrapped) : Optional.empty();
} }
CompoundTag customData = Optional.ofNullable(wrapped.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag()); return new OtherItem(wrapped, forceReturn).process(NetworkTextReplaceContext.of(player));
}
// 获取custom data
CompoundTag customData = Optional.ofNullable(wrapped.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA))
.map(CompoundTag.class::cast)
.orElseGet(CompoundTag::new);
CompoundTag arguments = customData.getCompound(ArgumentsModifier.ARGUMENTS_TAG); CompoundTag arguments = customData.getCompound(ArgumentsModifier.ARGUMENTS_TAG);
// 创建context
ItemBuildContext context; ItemBuildContext context;
if (arguments == null) { if (arguments == null) {
context = ItemBuildContext.of(player); context = ItemBuildContext.of(player);
@@ -140,13 +195,16 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
} }
context = ItemBuildContext.of(player, builder); context = ItemBuildContext.of(player, builder);
} }
// 准备阶段
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) { for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
modifier.prepareNetworkItem(original, context, tag); modifier.prepareNetworkItem(original, context, tag);
} }
// 应用阶段
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) { for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
modifier.apply(wrapped, context); modifier.apply(wrapped, context);
} }
// 如果拦截物品的描述名称等
if (Config.interceptItem()) { if (Config.interceptItem()) {
if (!tag.containsKey(ComponentIds.ITEM_NAME)) { if (!tag.containsKey(ComponentIds.ITEM_NAME)) {
if (VersionHelper.isOrAbove1_21_5()) processModernItemName(wrapped, () -> tag, context); if (VersionHelper.isOrAbove1_21_5()) processModernItemName(wrapped, () -> tag, context);
@@ -161,11 +219,13 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
else processLegacyLore(wrapped, () -> tag, context); else processLegacyLore(wrapped, () -> tag, context);
} }
} }
// 如果tag不空则需要返回
if (!tag.isEmpty()) { if (!tag.isEmpty()) {
customData.put(NETWORK_ITEM_TAG, tag); customData.put(NETWORK_ITEM_TAG, tag);
wrapped.setNBTComponent(ComponentTypes.CUSTOM_DATA, customData); wrapped.setNBTComponent(ComponentTypes.CUSTOM_DATA, customData);
forceReturn = true;
} }
return wrapped; return forceReturn ? Optional.of(wrapped) : Optional.empty();
} }
public static boolean processLegacyLore(Item<ItemStack> item, Supplier<CompoundTag> tag, Context context) { public static boolean processLegacyLore(Item<ItemStack> item, Supplier<CompoundTag> tag, Context context) {
@@ -274,14 +334,16 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
static class OtherItem { static class OtherItem {
private final Item<ItemStack> item; private final Item<ItemStack> item;
private final boolean forceReturn;
private boolean globalChanged = false; private boolean globalChanged = false;
private CompoundTag tag; private CompoundTag tag;
public OtherItem(Item<ItemStack> item) { public OtherItem(Item<ItemStack> item, boolean forceReturn) {
this.item = item; this.item = item;
this.forceReturn = forceReturn;
} }
public Item<ItemStack> process(Context context) { public Optional<Item<ItemStack>> process(Context context) {
if (VersionHelper.isOrAbove1_21_5()) { if (VersionHelper.isOrAbove1_21_5()) {
if (processModernLore(this.item, this::getOrCreateTag, context)) if (processModernLore(this.item, this::getOrCreateTag, context))
this.globalChanged = true; this.globalChanged = true;
@@ -298,11 +360,17 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
this.globalChanged = true; this.globalChanged = true;
} }
if (this.globalChanged) { if (this.globalChanged) {
CompoundTag customData = Optional.ofNullable(this.item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag()); CompoundTag customData = Optional.ofNullable(this.item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA))
.map(CompoundTag.class::cast)
.orElseGet(CompoundTag::new);
customData.put(NETWORK_ITEM_TAG, getOrCreateTag()); customData.put(NETWORK_ITEM_TAG, getOrCreateTag());
this.item.setNBTComponent(ComponentKeys.CUSTOM_DATA, customData); this.item.setNBTComponent(ComponentKeys.CUSTOM_DATA, customData);
return Optional.of(this.item);
} else if (this.forceReturn) {
return Optional.of(this.item);
} else {
return Optional.empty();
} }
return this.item;
} }
private CompoundTag getOrCreateTag() { private CompoundTag getOrCreateTag() {

View File

@@ -3200,12 +3200,26 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
int stateId = buf.readVarInt(); int stateId = buf.readVarInt();
int listSize = buf.readVarInt(); int listSize = buf.readVarInt();
List<ItemStack> items = new ArrayList<>(listSize); List<ItemStack> items = new ArrayList<>(listSize);
boolean changed = false;
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
for (int i = 0; i < listSize; i++) { for (int i = 0; i < listSize; i++) {
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf), serverPlayer); ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, serverPlayer);
if (optional.isPresent()) {
items.add(optional.get());
changed = true;
} else {
items.add(itemStack); items.add(itemStack);
} }
ItemStack carriedItem = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf), serverPlayer); }
ItemStack carriedItem = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
ItemStack newCarriedItem = carriedItem;
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(carriedItem, serverPlayer);
if (optional.isPresent()) {
changed = true;
newCarriedItem = optional.get();
}
if (!changed) return;
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -3216,7 +3230,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
for (ItemStack itemStack : items) { for (ItemStack itemStack : items) {
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack);
} }
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, carriedItem); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, newCarriedItem);
} }
} }
@@ -3235,10 +3249,10 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
try { try {
itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
} catch (Exception e) { } catch (Exception e) {
// 其他插件干的,比如某ty*****er不要赖到ce头上 // 其他插件干的,发送了非法的物品
return; return;
} }
itemStack = BukkitItemManager.instance().s2c(itemStack, serverPlayer); BukkitItemManager.instance().s2c(itemStack, serverPlayer).ifPresent((newItemStack) -> {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -3246,7 +3260,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
buf.writeVarInt(stateId); buf.writeVarInt(stateId);
buf.writeShort(slot); buf.writeShort(slot);
Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, newItemStack);
});
} }
} }
@@ -3258,12 +3273,14 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
if (!(user instanceof BukkitServerPlayer serverPlayer)) return; if (!(user instanceof BukkitServerPlayer serverPlayer)) return;
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf), serverPlayer); ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
BukkitItemManager.instance().s2c(itemStack, serverPlayer).ifPresent((newItemStack) -> {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, newItemStack);
});
} }
} }
@@ -3274,7 +3291,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
if (Config.disableItemOperations()) return; if (Config.disableItemOperations()) return;
if (!(user instanceof BukkitServerPlayer serverPlayer)) return; if (!(user instanceof BukkitServerPlayer serverPlayer)) return;
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
boolean changed = false;
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
int entity = buf.readVarInt(); int entity = buf.readVarInt();
List<com.mojang.datafixers.util.Pair<Object, ItemStack>> slots = Lists.newArrayList(); List<com.mojang.datafixers.util.Pair<Object, ItemStack>> slots = Lists.newArrayList();
@@ -3282,10 +3299,15 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
do { do {
slotMask = buf.readByte(); slotMask = buf.readByte();
Object equipmentSlot = CoreReflections.instance$EquipmentSlot$values[slotMask & 127]; Object equipmentSlot = CoreReflections.instance$EquipmentSlot$values[slotMask & 127];
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf), serverPlayer); ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, serverPlayer);
if (optional.isPresent()) {
changed = true;
itemStack = optional.get();
}
slots.add(com.mojang.datafixers.util.Pair.of(equipmentSlot, itemStack)); slots.add(com.mojang.datafixers.util.Pair.of(equipmentSlot, itemStack));
} while ((slotMask & -128) != 0); } while ((slotMask & -128) != 0);
if (changed) {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -3302,6 +3324,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
} }
} }
} }
}
public static class SetPlayerInventoryListener1_21_2 implements ByteBufferPacketListener { public static class SetPlayerInventoryListener1_21_2 implements ByteBufferPacketListener {
@@ -3312,14 +3335,15 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
int slot = buf.readVarInt(); int slot = buf.readVarInt();
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf), serverPlayer); ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
BukkitItemManager.instance().s2c(itemStack, serverPlayer).ifPresent((newItemStack) -> {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
buf.writeVarInt(slot); buf.writeVarInt(slot);
Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, newItemStack);
});
} }
} }
@@ -3340,18 +3364,18 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
} catch (Exception e) { } catch (Exception e) {
return; return;
} }
itemStack = BukkitItemManager.instance().c2s(itemStack); BukkitItemManager.instance().c2s(itemStack).ifPresent((newItemStack) -> {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
buf.writeShort(slotNum); buf.writeShort(slotNum);
Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object newFriendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
if (VersionHelper.isOrAbove1_20_5()) { if (VersionHelper.isOrAbove1_20_5()) {
FastNMS.INSTANCE.method$FriendlyByteBuf$writeUntrustedItem(newFriendlyBuf, itemStack); FastNMS.INSTANCE.method$FriendlyByteBuf$writeUntrustedItem(newFriendlyBuf, newItemStack);
} else { } else {
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, itemStack); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, newItemStack);
} }
});
} }
} }
@@ -3361,7 +3385,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
public void onPacketReceive(NetWorkUser user, ByteBufPacketEvent event) { public void onPacketReceive(NetWorkUser user, ByteBufPacketEvent event) {
if (Config.disableItemOperations()) return; if (Config.disableItemOperations()) return;
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
boolean changed = false;
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf); Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
int containerId = buf.readContainerId(); int containerId = buf.readContainerId();
int stateId = buf.readVarInt(); int stateId = buf.readVarInt();
@@ -3372,11 +3396,21 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
Int2ObjectMap<ItemStack> changedSlots = new Int2ObjectOpenHashMap<>(i); Int2ObjectMap<ItemStack> changedSlots = new Int2ObjectOpenHashMap<>(i);
for (int j = 0; j < i; ++j) { for (int j = 0; j < i; ++j) {
int k = buf.readShort(); int k = buf.readShort();
ItemStack itemStack = BukkitItemManager.instance().c2s(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf)); ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
Optional<ItemStack> optional = BukkitItemManager.instance().c2s(itemStack);
if (optional.isPresent()) {
changed = true;
itemStack = optional.get();
}
changedSlots.put(k, itemStack); changedSlots.put(k, itemStack);
} }
ItemStack carriedItem = BukkitItemManager.instance().c2s(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf)); ItemStack carriedItem = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
Optional<ItemStack> optional = BukkitItemManager.instance().c2s(carriedItem);
if (optional.isPresent()) {
changed = true;
carriedItem = optional.get();
}
if (changed) {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -3392,7 +3426,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, v); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, v);
}); });
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, carriedItem); FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(newFriendlyBuf, carriedItem);
}
} }
} }

View File

@@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
import java.util.Optional;
public class CommonItemPacketHandler implements EntityPacketHandler { public class CommonItemPacketHandler implements EntityPacketHandler {
public static final CommonItemPacketHandler INSTANCE = new CommonItemPacketHandler(); public static final CommonItemPacketHandler INSTANCE = new CommonItemPacketHandler();
@@ -24,7 +25,7 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
if (Config.disableItemOperations()) return; if (Config.disableItemOperations()) return;
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt(); int id = buf.readVarInt();
boolean changed = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) { for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i); Object packedItem = packedItems.get(i);
@@ -41,12 +42,16 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
} }
continue; continue;
} }
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack), user); ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, user);
if (optional.isEmpty()) continue;
changed = true;
itemStack = optional.get();
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack))); packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)));
break; break;
} }
if (changed) {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -54,3 +59,4 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf); FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
} }
} }
}

View File

@@ -11,6 +11,7 @@ import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
import java.util.Optional;
public class ItemDisplayPacketHandler implements EntityPacketHandler { public class ItemDisplayPacketHandler implements EntityPacketHandler {
public static final ItemDisplayPacketHandler INSTANCE = new ItemDisplayPacketHandler(); public static final ItemDisplayPacketHandler INSTANCE = new ItemDisplayPacketHandler();
@@ -20,20 +21,23 @@ public class ItemDisplayPacketHandler implements EntityPacketHandler {
if (Config.disableItemOperations()) return; if (Config.disableItemOperations()) return;
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt(); int id = buf.readVarInt();
boolean changed = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) { for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i); Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId != ItemDisplayEntityData.DisplayedItem.id()) continue; if (entityDataId != ItemDisplayEntityData.DisplayedItem.id()) continue;
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack), user); ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, user);
if (optional.isEmpty()) continue;
changed = true;
itemStack = optional.get();
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue( packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)));
entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)
));
break; break;
} }
if (changed) {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -41,3 +45,4 @@ public class ItemDisplayPacketHandler implements EntityPacketHandler {
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf); FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
} }
} }
}

View File

@@ -14,16 +14,18 @@ import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
import java.util.Optional;
public class ItemFramePacketHandler implements EntityPacketHandler { public class ItemFramePacketHandler implements EntityPacketHandler {
public static final ItemFramePacketHandler INSTANCE = new ItemFramePacketHandler(); public static final ItemFramePacketHandler INSTANCE = new ItemFramePacketHandler();
private static long lastWarningTime = 0; private static long LAST_WARN_TIME = 0;
@Override @Override
public void handleSetEntityData(Player user, ByteBufPacketEvent event) { public void handleSetEntityData(Player user, ByteBufPacketEvent event) {
if (Config.disableItemOperations()) return; if (Config.disableItemOperations()) return;
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
int id = buf.readVarInt(); int id = buf.readVarInt();
boolean changed = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
for (int i = 0; i < packedItems.size(); i++) { for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i); Object packedItem = packedItems.get(i);
@@ -32,22 +34,24 @@ public class ItemFramePacketHandler implements EntityPacketHandler {
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) { if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (time - lastWarningTime > 5000) { if (time - LAST_WARN_TIME > 5000) {
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user; BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
CraftEngine.instance().logger().severe("An issue was detected while applying item-related entity data for '" + serverPlayer.name() + CraftEngine.instance().logger().severe("An issue was detected while applying item-related entity data for '" + serverPlayer.name() +
"'. Please execute the command '/ce debug entity-id " + serverPlayer.world().name() + " " + id + "' and provide a screenshot for further investigation."); "'. Please execute the command '/ce debug entity-id " + serverPlayer.world().name() + " " + id + "' and provide a screenshot for further investigation.");
lastWarningTime = time; LAST_WARN_TIME = time;
} }
continue; continue;
} }
ItemStack itemStack = BukkitItemManager.instance().s2c(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack), user); ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, user);
if (optional.isEmpty()) continue;
changed = true;
itemStack = optional.get();
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue( packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)));
entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)
));
break; break;
} }
if (changed) {
event.setChanged(true); event.setChanged(true);
buf.clear(); buf.clear();
buf.writeVarInt(event.packetID()); buf.writeVarInt(event.packetID());
@@ -55,3 +59,4 @@ public class ItemFramePacketHandler implements EntityPacketHandler {
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf); FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
} }
} }
}

View File

@@ -10,6 +10,7 @@ import net.momirealms.sparrow.nbt.Tag;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Map; import java.util.Map;
import java.util.Optional;
public interface NetworkItemHandler<T> { public interface NetworkItemHandler<T> {
Operation[] BY_INDEX = new Operation[] {Operation.ADD, Operation.REMOVE, Operation.RESET}; Operation[] BY_INDEX = new Operation[] {Operation.ADD, Operation.REMOVE, Operation.RESET};
@@ -17,9 +18,9 @@ public interface NetworkItemHandler<T> {
String NETWORK_OPERATION = "type"; String NETWORK_OPERATION = "type";
String NETWORK_VALUE = "value"; String NETWORK_VALUE = "value";
Item<T> s2c(Item<T> itemStack, Player player); Optional<Item<T>> s2c(Item<T> itemStack, Player player);
Item<T> c2s(Item<T> itemStack); Optional<Item<T>> c2s(Item<T> itemStack);
static CompoundTag pack(Operation operation, @Nullable Tag value) { static CompoundTag pack(Operation operation, @Nullable Tag value) {
if (value == null) { if (value == null) {