9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-25 09:59:20 +00:00

支持封装空物品

This commit is contained in:
XiaoMoMi
2025-07-10 22:43:12 +08:00
parent 07f837d137
commit 2146206415
78 changed files with 454 additions and 156 deletions

View File

@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.entity.furniture.AnchorType;
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
import net.momirealms.craftengine.core.entity.furniture.Furniture;
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
import net.momirealms.craftengine.core.entity.player.InteractionHand;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
@@ -276,7 +277,9 @@ public final class CraftEngineFurniture {
.withParameter(DirectContextParameters.FURNITURE, furniture)
.withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.extraData().item().orElse(null));
if (player != null) {
builder.withParameter(DirectContextParameters.PLAYER, player);
Item<?> itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND);
builder.withParameter(DirectContextParameters.PLAYER, player)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand.isEmpty() ? null : itemInHand);
}
List<Item<ItemStack>> items = lootTable.getRandomItems(builder.build(), world, player);
for (Item<ItemStack> item : items) {

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.bukkit.api;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.inventory.ItemStack;
@@ -31,7 +31,7 @@ public final class CraftEngineItems {
*/
@Nullable
public static CustomItem<ItemStack> byItemStack(@NotNull ItemStack itemStack) {
if (ItemUtils.isEmpty(itemStack)) return null;
if (ItemStackUtils.isEmpty(itemStack)) return null;
return BukkitItemManager.instance().wrap(itemStack).getCustomItem().orElse(null);
}
@@ -42,7 +42,7 @@ public final class CraftEngineItems {
* @return true if it's a custom item
*/
public static boolean isCustomItem(@NotNull ItemStack itemStack) {
if (ItemUtils.isEmpty(itemStack)) return false;
if (ItemStackUtils.isEmpty(itemStack)) return false;
return BukkitItemManager.instance().wrap(itemStack).isCustomItem();
}
@@ -54,7 +54,7 @@ public final class CraftEngineItems {
*/
@Nullable
public static Key getCustomItemId(@NotNull ItemStack itemStack) {
if (ItemUtils.isEmpty(itemStack)) return null;
if (ItemStackUtils.isEmpty(itemStack)) return null;
return BukkitItemManager.instance().wrap(itemStack).customId().orElse(null);
}
}

View File

@@ -21,6 +21,7 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.util.Cancellable;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.WorldPosition;
@@ -125,7 +126,7 @@ public final class BlockEventListener implements Listener {
WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (itemInHand != null) {
if (!ItemUtils.isEmpty(itemInHand)) {
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
if (optionalCustomItem.isPresent()) {
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
@@ -167,7 +168,7 @@ public final class BlockEventListener implements Listener {
.withParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, state)
.withParameter(DirectContextParameters.EVENT, cancellable)
.withParameter(DirectContextParameters.POSITION, position)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, ItemUtils.isEmpty(itemInHand) ? null : itemInHand)
);
state.owner().value().execute(context, EventTrigger.BREAK);
if (cancellable.isCancelled()) {
@@ -189,7 +190,7 @@ public final class BlockEventListener implements Listener {
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
.withParameter(DirectContextParameters.POSITION, position)
.withParameter(DirectContextParameters.PLAYER, serverPlayer)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand).build();
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, ItemUtils.isEmpty(itemInHand) ? null : itemInHand).build();
for (LootTable<?> lootTable : it.lootTables()) {
for (Item<?> item : lootTable.getRandomItems(lootContext, world, serverPlayer)) {
world.dropItemNaturally(position, item);

View File

@@ -22,6 +22,7 @@ import net.momirealms.craftengine.core.plugin.context.SimpleContext;
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.RandomUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.world.Vec3d;
@@ -127,7 +128,7 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
@Override
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
Item<?> item = context.getItem();
if (item == null || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
if (ItemUtils.isEmpty(item) || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
return InteractionResult.PASS;
if (isMaxAge(state))
return InteractionResult.PASS;

View File

@@ -83,7 +83,7 @@ public class GrassBlockBehavior extends BukkitBlockBehavior {
@Override
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
Item<?> item = context.getItem();
if (item == null || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
if (ItemUtils.isEmpty(item) || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
return InteractionResult.PASS;
BlockPos pos = context.getClickedPos();
BukkitBlockInWorld upper = (BukkitBlockInWorld) context.getLevel().getBlockAt(pos.x(), pos.y() + 1, pos.z());

View File

@@ -20,6 +20,7 @@ import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemKeys;
import net.momirealms.craftengine.core.item.context.UseOnContext;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.RandomUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
@@ -147,7 +148,7 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
@Override
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
Item<?> item = context.getItem();
if (item == null || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
if (ItemUtils.isEmpty(item) || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
return InteractionResult.PASS;
boolean sendSwing = false;
Object visualState = state.vanillaBlockState().handle();

View File

@@ -16,10 +16,7 @@ import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.behavior.BlockBoundItemBehavior;
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.BlockPos;
import org.bukkit.inventory.ItemStack;
@@ -41,7 +38,7 @@ public class SlabBlockBehavior extends BukkitBlockBehavior {
public boolean canBeReplaced(BlockPlaceContext context, ImmutableBlockState state) {
SlabType type = state.get(this.typeProperty);
Item<ItemStack> item = (Item<ItemStack>) context.getItem();
if (type == SlabType.DOUBLE || item == null) return false;
if (type == SlabType.DOUBLE || ItemUtils.isEmpty(item)) return false;
Optional<CustomItem<ItemStack>> itemInHand = item.getCustomItem();
if (itemInHand.isEmpty()) return false;
CustomItem<ItemStack> customItem = itemInHand.get();

View File

@@ -15,6 +15,7 @@ import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.context.UseOnContext;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
@@ -49,7 +50,7 @@ public class StackableBlockBehavior extends BukkitBlockBehavior {
return InteractionResult.PASS;
}
Item<ItemStack> item = (Item<ItemStack>) context.getItem();
if (item == null) {
if (ItemUtils.isEmpty(item)) {
return InteractionResult.PASS;
}
if (!this.items.contains(item.id())) {

View File

@@ -11,6 +11,7 @@ import net.momirealms.craftengine.core.entity.projectile.ProjectileManager;
import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.bukkit.Bukkit;
import org.bukkit.World;
@@ -119,7 +120,7 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
return;
}
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(projectileItem);
if (wrapped == null) return;
if (ItemUtils.isEmpty(wrapped)) return;
wrapped.getCustomItem().ifPresent(it -> {
ProjectileMeta meta = it.settings().projectileMeta();
if (meta != null) {

View File

@@ -9,6 +9,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.paper.PaperReflections;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
import net.momirealms.craftengine.core.font.*;
import net.momirealms.craftengine.core.item.Item;
@@ -130,7 +131,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
return;
}
ItemStack result = event.getResult();
if (result == null) return;
if (ItemStackUtils.isEmpty(result)) return;
Player player;
try {
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
@@ -149,7 +150,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
if (renameText == null || renameText.isEmpty()) return;
Component itemName = Component.text(renameText);
EmojiComponentProcessResult replaceProcessResult = replaceComponentEmoji(itemName, plugin.adapt(player), renameText);
EmojiComponentProcessResult replaceProcessResult = replaceComponentEmoji(itemName, this.plugin.adapt(player), renameText);
if (replaceProcessResult.changed()) {
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(result);
wrapped.customNameJson(AdventureHelper.componentToJson(replaceProcessResult.newText()));

View File

@@ -14,8 +14,9 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MItems;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.*;
@@ -35,6 +36,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
@@ -56,6 +58,8 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
private final ArmorEventListener armorEventListener;
private final NetworkItemHandler<ItemStack> networkItemHandler;
private final Object bedrockItemHolder;
private final Item<ItemStack> empty;
private final ItemStack emptyStack;
private Set<Key> lastRegisteredPatterns = Set.of();
public BukkitItemManager(BukkitCraftEngine plugin) {
@@ -71,6 +75,8 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
this.bedrockItemHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(Key.of("minecraft:bedrock")))).get();;
this.registerCustomTrimMaterial();
this.loadLastRegisteredPatterns();
this.empty = this.wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.instance$ItemStack$EMPTY));
this.emptyStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(MItems.AIR, 1));
}
@Override
@@ -143,7 +149,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override
public int fuelTime(ItemStack itemStack) {
if (ItemUtils.isEmpty(itemStack)) return 0;
if (ItemStackUtils.isEmpty(itemStack)) return 0;
Optional<CustomItem<ItemStack>> customItem = wrap(itemStack).getCustomItem();
return customItem.map(it -> it.settings().fuelTime()).orElse(0);
}
@@ -290,7 +296,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
@Override
public ItemStack buildCustomItemStack(Key id, Player player) {
return Optional.ofNullable(customItems.get(id)).map(it -> it.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), 1)).orElse(null);
return Optional.ofNullable(this.customItems.get(id)).map(it -> it.buildItemStack(new ItemBuildContext(player, ContextHolder.EMPTY), 1)).orElse(null);
}
@Override
@@ -306,13 +312,11 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
private ItemStack createVanillaItemStack(Key id) {
NamespacedKey key = NamespacedKey.fromString(id.toString());
if (key == null) {
this.plugin.logger().warn(id + " is not a valid namespaced key");
return new ItemStack(Material.AIR);
return this.emptyStack;
}
Object item = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(id));
if (item == null) {
this.plugin.logger().warn(id + " is not a valid material");
return new ItemStack(Material.AIR);
return this.emptyStack;
}
return FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(item, 1));
}
@@ -326,8 +330,8 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
}
@Override
public Item<ItemStack> wrap(ItemStack itemStack) {
if (ItemUtils.isEmpty(itemStack)) return null;
public @NotNull Item<ItemStack> wrap(ItemStack itemStack) {
if (itemStack == null) return this.empty;
return this.factory.wrap(itemStack);
}

View File

@@ -8,7 +8,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.item.ItemWrapper;
import net.momirealms.craftengine.core.util.Key;
@@ -22,12 +22,12 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
private final Object handle;
public ComponentItemWrapper(final ItemStack item) {
this.item = ItemUtils.ensureCraftItemStack(item);
this.item = ItemStackUtils.ensureCraftItemStack(item);
this.handle = FastNMS.INSTANCE.field$CraftItemStack$handle(this.item);
}
public ComponentItemWrapper(final ItemStack item, int count) {
this.item = ItemUtils.ensureCraftItemStack(item);
this.item = ItemStackUtils.ensureCraftItemStack(item);
this.item.setAmount(count);
this.handle = FastNMS.INSTANCE.field$CraftItemStack$handle(this.item);
}

View File

@@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.item;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.item.ItemWrapper;
import net.momirealms.sparrow.nbt.Tag;
import org.bukkit.inventory.ItemStack;
@@ -13,7 +13,7 @@ public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
private final ItemStack itemStack;
public LegacyItemWrapper(ItemStack item) {
this.itemStack = ItemUtils.ensureCraftItemStack(item);
this.itemStack = ItemStackUtils.ensureCraftItemStack(item);
this.nmsStack = FastNMS.INSTANCE.field$CraftItemStack$handle(this.itemStack);
}

View File

@@ -19,6 +19,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
import net.momirealms.craftengine.core.item.context.UseOnContext;
import net.momirealms.craftengine.core.pack.Pack;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.BlockPos;
@@ -67,7 +68,7 @@ public class AxeItemBehavior extends ItemBehavior {
Key stripped = behaviorOptional.get().stripped();
Item<ItemStack> offHandItem = (Item<ItemStack>) player.getItemInHand(InteractionHand.OFF_HAND);
// is using a shield
if (context.getHand() == InteractionHand.MAIN_HAND && offHandItem != null && canBlockAttack(offHandItem) && !player.isSecondaryUseActive()) {
if (context.getHand() == InteractionHand.MAIN_HAND && !ItemUtils.isEmpty(offHandItem) && canBlockAttack(offHandItem) && !player.isSecondaryUseActive()) {
return InteractionResult.PASS;
}
@@ -90,6 +91,8 @@ public class AxeItemBehavior extends ItemBehavior {
}
Item<ItemStack> item = (Item<ItemStack>) context.getItem();
// 理论不可能出现
if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL;
BlockPos pos = context.getClickedPos();
context.getLevel().playBlockSound(Vec3d.atCenterOf(pos), AXE_STRIP_SOUND, 1, 1);
FastNMS.INSTANCE.method$LevelWriter$setBlock(context.getLevel().serverWorld(), LocationUtils.toBlockPos(pos), newState.customBlockState().handle(), UpdateOption.UPDATE_ALL_IMMEDIATE.flags());

View File

@@ -128,6 +128,8 @@ public class FurnitureItemBehavior extends ItemBehavior {
}
Item<?> item = context.getItem();
// 不可能
if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL;
BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place(
furnitureLocation.clone(), customFurniture,

View File

@@ -1,9 +1,13 @@
package net.momirealms.craftengine.bukkit.item.factory;
import com.google.gson.JsonElement;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
import net.momirealms.craftengine.bukkit.util.ItemTags;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.item.ItemFactory;
import net.momirealms.craftengine.core.item.ItemKeys;
import net.momirealms.craftengine.core.item.ItemWrapper;
import net.momirealms.craftengine.core.item.data.JukeboxPlayable;
import net.momirealms.craftengine.core.item.setting.EquipmentData;
@@ -55,13 +59,14 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
@Override
protected boolean isBlockItem(W item) {
// todo 这个 isBlockItem 他考虑组件了吗???
return item.getItem().getType().isBlock();
return CoreReflections.clazz$BlockItem.isInstance(FastNMS.INSTANCE.method$ItemStack$getItem(item.getLiteralObject()));
}
@Override
protected Key vanillaId(W item) {
return Key.of(item.getItem().getType().getKey().asString());
Object i = FastNMS.INSTANCE.method$ItemStack$getItem(item.getLiteralObject());
if (i == null) return ItemKeys.AIR;
return KeyUtils.resourceLocationToKey(FastNMS.INSTANCE.method$Registry$getKey(MBuiltInRegistries.ITEM, i));
}
@Override

View File

@@ -4,6 +4,7 @@ import com.google.gson.JsonElement;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
import net.momirealms.craftengine.bukkit.item.LegacyItemWrapper;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
@@ -31,6 +32,11 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
super(plugin);
}
@Override
protected boolean isEmpty(ComponentItemWrapper item) {
return item.getItem().isEmpty();
}
@Override
protected void customId(ComponentItemWrapper item, Key id) {
FastNMS.INSTANCE.setCustomItemId(item.getLiteralObject(), id.toString());

View File

@@ -57,6 +57,11 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
return item.remove(path);
}
@Override
protected boolean isEmpty(LegacyItemWrapper item) {
return item.getItem().isEmpty();
}
@Override
protected Optional<Key> customId(LegacyItemWrapper item) {
Object id = item.getJavaTag(IdModifier.CRAFT_ENGINE_ID);

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.bukkit.item.listener;
import net.momirealms.craftengine.bukkit.api.CraftEngineItems;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.bukkit.Material;
import org.bukkit.entity.Horse;
@@ -60,7 +60,7 @@ public class ArmorEventListener implements Listener {
} else if (event.getClickedInventory() == horseInventory) {
ItemStack itemInCursor = event.getCursor();
if (event.getAction() == InventoryAction.SWAP_WITH_CURSOR || event.getAction() == InventoryAction.PLACE_ALL || event.getAction() == InventoryAction.PLACE_ONE) {
if (!ItemUtils.isEmpty(itemInCursor) && CraftEngineItems.isCustomItem(itemInCursor)) {
if (!ItemStackUtils.isEmpty(itemInCursor) && CraftEngineItems.isCustomItem(itemInCursor)) {
event.setCancelled(true);
return;
}
@@ -69,13 +69,13 @@ public class ArmorEventListener implements Listener {
int slot = event.getHotbarButton();
if (slot != -1) {
ItemStack itemInHotBar = event.getWhoClicked().getInventory().getItem(slot);
if (!ItemUtils.isEmpty(itemInHotBar) && CraftEngineItems.isCustomItem(itemInHotBar)) {
if (!ItemStackUtils.isEmpty(itemInHotBar) && CraftEngineItems.isCustomItem(itemInHotBar)) {
event.setCancelled(true);
return;
}
} else {
ItemStack offHand = event.getWhoClicked().getInventory().getItemInOffHand();
if (!ItemUtils.isEmpty(offHand) && CraftEngineItems.isCustomItem(offHand)) {
if (!ItemStackUtils.isEmpty(offHand) && CraftEngineItems.isCustomItem(offHand)) {
event.setCancelled(true);
return;
}
@@ -92,7 +92,7 @@ public class ArmorEventListener implements Listener {
}
for (Map.Entry<Integer, ItemStack> item : event.getNewItems().entrySet()) {
if (item.getKey() == 0 || item.getKey() == 1) {
if (!ItemUtils.isEmpty(item.getValue()) && CraftEngineItems.isCustomItem(item.getValue())) {
if (!ItemStackUtils.isEmpty(item.getValue()) && CraftEngineItems.isCustomItem(item.getValue())) {
event.setCancelled(true);
return;
}

View File

@@ -9,6 +9,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkRefl
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
@@ -44,7 +45,7 @@ public class DebugStickListener implements Listener {
Block clickedBlock = event.getClickedBlock();
if (clickedBlock == null) return;
ItemStack itemInHand = event.getItem();
if (itemInHand == null) return;
if (ItemStackUtils.isEmpty(itemInHand)) return;
Material material = itemInHand.getType();
if (material != Material.DEBUG_STICK) return;
Player bukkitPlayer = event.getPlayer();

View File

@@ -71,7 +71,7 @@ public class ItemEventListener implements Listener {
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(hand);
if (itemInHand == null) return;
if (ItemUtils.isEmpty(itemInHand)) return;
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
if (optionalCustomItem.isEmpty()) return;
@@ -158,7 +158,7 @@ public class ItemEventListener implements Listener {
.withParameter(DirectContextParameters.HAND, hand)
.withParameter(DirectContextParameters.EVENT, dummy)
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(block.getLocation()))
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, ItemUtils.isEmpty(itemInHand) ? null : itemInHand)
);
if (action.isRightClick()) customBlock.execute(context, EventTrigger.RIGHT_CLICK);
else customBlock.execute(context, EventTrigger.LEFT_CLICK);
@@ -213,8 +213,8 @@ public class ItemEventListener implements Listener {
}
}
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand == null ? Optional.empty() : itemInHand.getCustomItem();
boolean hasItem = itemInHand != null;
boolean hasItem = !itemInHand.isEmpty();
Optional<CustomItem<ItemStack>> optionalCustomItem = hasItem ? itemInHand.getCustomItem() : Optional.empty();
boolean hasCustomItem = optionalCustomItem.isPresent();
// interact block with items
@@ -342,7 +342,7 @@ public class ItemEventListener implements Listener {
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
Item<ItemStack> itemInHand = serverPlayer.getItemInHand(hand);
// should never be null
if (itemInHand == null) return;
if (ItemUtils.isEmpty(itemInHand)) return;
// todo 真的需要这个吗
if (cancelEventIfHasInteraction(event, serverPlayer, hand)) {
@@ -384,7 +384,7 @@ public class ItemEventListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
public void onConsumeItem(PlayerItemConsumeEvent event) {
ItemStack consumedItem = event.getItem();
if (ItemUtils.isEmpty(consumedItem)) return;
if (ItemStackUtils.isEmpty(consumedItem)) return;
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(consumedItem);
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
if (optionalCustomItem.isEmpty()) {
@@ -417,7 +417,7 @@ public class ItemEventListener implements Listener {
if (VersionHelper.isOrAbove1_20_5()) return;
if (!(event.getEntity() instanceof Player player)) return;
ItemStack consumedItem = event.getItem();
if (ItemUtils.isEmpty(consumedItem)) return;
if (ItemStackUtils.isEmpty(consumedItem)) return;
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(consumedItem);
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
if (optionalCustomItem.isEmpty()) {
@@ -487,9 +487,9 @@ public class ItemEventListener implements Listener {
ItemStack lazuli = inventory.getSecondary();
if (lazuli != null) return;
ItemStack item = inventory.getItem();
if (item == null) return;
if (ItemStackUtils.isEmpty(item)) return;
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(item);
if (wrapped == null) return;
if (ItemUtils.isEmpty(wrapped)) return;
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
if (optionalCustomItem.isEmpty()) return;
BukkitCustomItem customItem = (BukkitCustomItem) optionalCustomItem.get();

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.bukkit.item.recipe;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.ItemManager;
@@ -58,7 +58,7 @@ public class CrafterEventListener implements Listener {
List<OptimizedIDItem<ItemStack>> optimizedIDItems = new ArrayList<>();
for (ItemStack itemStack : ingredients) {
if (ItemUtils.isEmpty(itemStack)) {
if (ItemStackUtils.isEmpty(itemStack)) {
optimizedIDItems.add(EMPTY);
} else {
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);

View File

@@ -12,7 +12,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRecipeTypes;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
import net.momirealms.craftengine.core.item.*;
import net.momirealms.craftengine.core.item.equipment.TrimBasedEquipment;
@@ -76,8 +76,8 @@ public class RecipeEventListener implements Listener {
if (clickedInventory == player.getInventory()) {
if (event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT) {
ItemStack item = event.getCurrentItem();
if (ItemUtils.isEmpty(item)) return;
if (fuelStack == null || fuelStack.getType() == Material.AIR) {
if (ItemStackUtils.isEmpty(item)) return;
if (ItemStackUtils.isEmpty(fuelStack)) {
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(item);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) return;
@@ -98,10 +98,10 @@ public class RecipeEventListener implements Listener {
int fuelTime = this.itemManager.fuelTime(item);
if (fuelTime == 0) {
if (ItemUtils.isCustomItem(item) && item.getType().isFuel()) {
if (ItemStackUtils.isCustomItem(item) && item.getType().isFuel()) {
event.setCancelled(true);
ItemStack smelting = furnaceInventory.getSmelting();
if (ItemUtils.isEmpty(smelting)) {
if (ItemStackUtils.isEmpty(smelting)) {
furnaceInventory.setSmelting(item.clone());
item.setAmount(0);
} else if (smelting.isSimilar(item)) {
@@ -162,11 +162,11 @@ public class RecipeEventListener implements Listener {
} else {
item = player.getInventory().getItem(hotBarSlot);
}
if (item == null) return;
if (ItemStackUtils.isEmpty(item)) return;
int fuelTime = this.plugin.itemManager().fuelTime(item);
// only handle custom items
if (fuelTime == 0) {
if (ItemUtils.isCustomItem(item) && item.getType().isFuel()) {
if (ItemStackUtils.isCustomItem(item) && item.getType().isFuel()) {
event.setCancelled(true);
}
return;
@@ -189,11 +189,11 @@ public class RecipeEventListener implements Listener {
case LEFT, RIGHT -> {
ItemStack itemOnCursor = event.getCursor();
// pick item
if (ItemUtils.isEmpty(itemOnCursor)) return;
if (ItemStackUtils.isEmpty(itemOnCursor)) return;
int fuelTime = this.plugin.itemManager().fuelTime(itemOnCursor);
// only handle custom items
if (fuelTime == 0) {
if (ItemUtils.isCustomItem(itemOnCursor) && itemOnCursor.getType().isFuel()) {
if (ItemStackUtils.isCustomItem(itemOnCursor) && itemOnCursor.getType().isFuel()) {
event.setCancelled(true);
}
return;
@@ -346,7 +346,7 @@ public class RecipeEventListener implements Listener {
}
ItemStack itemStack = event.getItem();
if (ItemUtils.isEmpty(itemStack)) return;
if (ItemStackUtils.isEmpty(itemStack)) return;
try {
@SuppressWarnings("unchecked")
Optional<Object> optionalMCRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(
@@ -446,7 +446,7 @@ public class RecipeEventListener implements Listener {
public void onPrepareResult(PrepareResultEvent event) {
// if (!ConfigManager.enableRecipeSystem()) return;
if (event.getInventory() instanceof CartographyInventory cartographyInventory) {
if (ItemUtils.hasCustomItem(cartographyInventory.getStorageContents())) {
if (ItemStackUtils.hasCustomItem(cartographyInventory.getStorageContents())) {
event.setResult(new ItemStack(Material.AIR));
}
}
@@ -523,7 +523,7 @@ public class RecipeEventListener implements Listener {
AnvilInventory inventory = event.getInventory();
ItemStack first = inventory.getFirstItem();
ItemStack second = inventory.getSecondItem();
if (first == null || second == null) return;
if (ItemStackUtils.isEmpty(first) || ItemStackUtils.isEmpty(second)) return;
Item<ItemStack> wrappedSecond = BukkitItemManager.instance().wrap(second);
// 如果材料不是自定义的,那么忽略
@@ -678,7 +678,7 @@ public class RecipeEventListener implements Listener {
private void processRename(PrepareAnvilEvent event) {
AnvilInventory inventory = event.getInventory();
ItemStack first = inventory.getFirstItem();
if (ItemUtils.isEmpty(first)) {
if (ItemStackUtils.isEmpty(first)) {
return;
}
if (event.getResult() == null) {
@@ -721,7 +721,7 @@ public class RecipeEventListener implements Listener {
if (!(recipe instanceof ComplexRecipe complexRecipe))
return;
CraftingInventory inventory = event.getInventory();
boolean hasCustomItem = ItemUtils.hasCustomItem(inventory.getMatrix());
boolean hasCustomItem = ItemStackUtils.hasCustomItem(inventory.getMatrix());
if (!hasCustomItem) {
return;
}
@@ -835,7 +835,7 @@ public class RecipeEventListener implements Listener {
boolean hasReplacement = false;
for (int i = 0; i < usedItems.length; i++) {
ItemStack usedItem = usedItems[i];
if (ItemUtils.isEmpty(usedItem)) continue;
if (ItemStackUtils.isEmpty(usedItem)) continue;
if (usedItem.getAmount() != 1) continue;
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(usedItem);
if (wrapped == null) continue;
@@ -889,7 +889,7 @@ public class RecipeEventListener implements Listener {
List<OptimizedIDItem<ItemStack>> optimizedIDItems = new ArrayList<>();
for (ItemStack itemStack : ingredients) {
if (ItemUtils.isEmpty(itemStack)) {
if (ItemStackUtils.isEmpty(itemStack)) {
optimizedIDItems.add(EMPTY);
} else {
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
@@ -964,7 +964,7 @@ public class RecipeEventListener implements Listener {
SmithingInventory inventory = event.getInventory();
if (!(inventory.getRecipe() instanceof SmithingTrimRecipe)) return;
ItemStack equipment = inventory.getInputEquipment();
if (equipment == null) return;
if (ItemStackUtils.isEmpty(equipment)) return;
Item<ItemStack> wrappedEquipment = this.itemManager.wrap(equipment);
Optional<CustomItem<ItemStack>> optionalCustomItem = wrappedEquipment.getCustomItem();
if (optionalCustomItem.isEmpty()) return;
@@ -1036,7 +1036,7 @@ public class RecipeEventListener implements Listener {
}
private OptimizedIDItem<ItemStack> getOptimizedIDItem(@Nullable ItemStack itemStack) {
if (ItemUtils.isEmpty(itemStack)) {
if (ItemStackUtils.isEmpty(itemStack)) {
return EMPTY;
} else {
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);

View File

@@ -54,6 +54,7 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
HandlerList.unregisterAll(this);
}
@SuppressWarnings("UnstableApiUsage")
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onEntityDeath(EntityDeathEvent event) {
Entity entity = event.getEntity();

View File

@@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.util.AdventureHelper;
@@ -26,7 +26,7 @@ public class DebugItemDataCommand extends BukkitCommandFeature<CommandSender> {
.senderType(Player.class)
.handler(context -> {
ItemStack itemInHand = context.sender().getInventory().getItemInMainHand();
if (ItemUtils.isEmpty(itemInHand)) {
if (ItemStackUtils.isEmpty(itemInHand)) {
return;
}
Map<String, Object> readableMap = toMap(itemInHand);

View File

@@ -30,7 +30,7 @@ public class SearchUsagePlayerCommand extends BukkitCommandFeature<CommandSender
Player player = context.sender();
BukkitServerPlayer serverPlayer = plugin().adapt(player);
Item<?> item = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (item == null) {
if (item.isEmpty()) {
handleFeedback(context, MessageConstants.COMMAND_SEARCH_USAGE_NO_ITEM);
return;
}

View File

@@ -2,7 +2,7 @@ package net.momirealms.craftengine.bukkit.plugin.gui;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.gui.Click;
@@ -71,7 +71,7 @@ public class BukkitClick implements Click {
@Override
public Item<?> itemOnCursor() {
ItemStack itemStack = this.event.getCursor();
if (ItemUtils.isEmpty(itemStack)) return null;
if (ItemStackUtils.isEmpty(itemStack)) return null;
return BukkitItemManager.instance().wrap(itemStack);
}

View File

@@ -118,7 +118,7 @@ public final class BlockStateGenerator {
World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(serverLevel));
ContextHolder.Builder lootBuilder = new ContextHolder.Builder()
.withParameter(DirectContextParameters.POSITION, new WorldPosition(world, FastNMS.INSTANCE.field$Vec3$x(vec3), FastNMS.INSTANCE.field$Vec3$y(vec3), FastNMS.INSTANCE.field$Vec3$z(vec3)));
if (item != null) {
if (!item.isEmpty()) {
lootBuilder.withParameter(DirectContextParameters.ITEM_IN_HAND, item);
}

View File

@@ -175,6 +175,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
registerS2CByteBufPacketConsumer(PacketConsumers.SET_SCORE_1_20_3, VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1);
registerS2CByteBufPacketConsumer(PacketConsumers.ADD_RECIPE_BOOK, this.packetIds.clientboundRecipeBookAddPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.PLACE_GHOST_RECIPE, this.packetIds.clientboundPlaceGhostRecipePacket());
registerS2CByteBufPacketConsumer(PacketConsumers.UPDATE_RECIPES, this.packetIds.clientboundUpdateRecipesPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY, this.packetIds.clientboundAddEntityPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());

View File

@@ -42,8 +42,8 @@ import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
import net.momirealms.craftengine.core.item.context.UseOnContext;
import net.momirealms.craftengine.core.item.recipe.network.RecipeBookEntry;
import net.momirealms.craftengine.core.item.recipe.network.display.RecipeDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.RecipeBookEntry;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.RecipeDisplay;
import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
import net.momirealms.craftengine.core.plugin.CraftEngine;
@@ -1306,7 +1306,7 @@ public class PacketConsumers {
int slot = VersionHelper.isOrAbove1_20_5() ? (short) NetworkReflections.methodHandle$ServerboundSetCreativeModeSlotPacket$slotNumGetter.invokeExact(packet) : (int) NetworkReflections.methodHandle$ServerboundSetCreativeModeSlotPacket$slotNumGetter.invokeExact(packet);
if (slot < 36 || slot > 44) return;
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(NetworkReflections.methodHandle$ServerboundSetCreativeModeSlotPacket$itemStackGetter.invokeExact(packet));
if (ItemUtils.isEmpty(item)) return;
if (ItemStackUtils.isEmpty(item)) return;
if (slot - 36 != bukkitPlayer.getInventory().getHeldItemSlot()) {
return;
}
@@ -1329,7 +1329,7 @@ public class PacketConsumers {
Key blockItemId = KeyUtils.resourceLocationToKey(FastNMS.INSTANCE.method$Registry$getKey(MBuiltInRegistries.ITEM, vanillaBlockItem));
if (!addItemId.equals(blockItemId)) return;
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, player);
if (ItemUtils.isEmpty(itemStack)) {
if (ItemStackUtils.isEmpty(itemStack)) {
CraftEngine.instance().logger().warn("Item: " + itemId + " is not a valid item");
return;
}
@@ -1338,7 +1338,7 @@ public class PacketConsumers {
int emptySlot = -1;
for (int i = 0; i < 9 + 27; i++) {
ItemStack invItem = inventory.getItem(i);
if (ItemUtils.isEmpty(invItem)) {
if (ItemStackUtils.isEmpty(invItem)) {
if (emptySlot == -1 && i < 9) emptySlot = i;
continue;
}
@@ -1361,7 +1361,7 @@ public class PacketConsumers {
}
} else {
if (item.getAmount() == 1) {
if (ItemUtils.isEmpty(inventory.getItem(slot - 36))) {
if (ItemStackUtils.isEmpty(inventory.getItem(slot - 36))) {
BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> inventory.setItem(slot - 36, itemStack));
return;
}
@@ -2125,11 +2125,11 @@ public class PacketConsumers {
ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
if (VersionHelper.isOrAbove1_21_5()) {
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemStack);
if (wrapped != null && wrapped.isCustomItem()) {
if (!wrapped.isEmpty() && wrapped.isCustomItem()) {
Object containerMenu = FastNMS.INSTANCE.field$Player$containerMenu(serverPlayer.serverPlayer());
if (containerMenu != null) {
ItemStack carried = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.method$AbstractContainerMenu$getCarried(containerMenu));
if (ItemUtils.isEmpty(carried)) {
if (ItemStackUtils.isEmpty(carried)) {
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
@@ -2515,4 +2515,13 @@ public class PacketConsumers {
CraftEngine.instance().logger().warn("Failed to handle ClientboundPlaceGhostRecipePacket", e);
}
};
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> UPDATE_RECIPES = (user, event) -> {
try {
if (VersionHelper.isOrAbove1_21_2()) return;
FriendlyByteBuf buf = event.getBuffer();
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundUpdateRecipesPacket", e);
}
};
}

View File

@@ -63,4 +63,6 @@ public interface PacketIds {
int serverboundSetCreativeModeSlotPacket();
int serverboundInteractPacket();
int clientboundUpdateRecipesPacket();
}

View File

@@ -159,4 +159,9 @@ public class PacketIds1_20 implements PacketIds {
public int clientboundPlaceGhostRecipePacket() {
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ClientboundPlaceGhostRecipePacket);
}
@Override
public int clientboundUpdateRecipesPacket() {
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ClientboundUpdateRecipesPacket);
}
}

View File

@@ -144,6 +144,11 @@ public class PacketIds1_20_5 implements PacketIds {
return PacketIdFinder.clientboundByName("minecraft:place_ghost_recipe");
}
@Override
public int clientboundUpdateRecipesPacket() {
return PacketIdFinder.clientboundByName("minecraft:update_recipes");
}
@Override
public int serverboundContainerClickPacket() {
return PacketIdFinder.serverboundByName("minecraft:container_click");

View File

@@ -3764,4 +3764,11 @@ public final class CoreReflections {
clazz$Level, clazz$BlockPos, clazz$BlockState, clazz$Player
)
);
public static final Class<?> clazz$BlockItem = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.item.ItemBlock",
"world.item.BlockItem"
)
);
}

View File

@@ -1573,4 +1573,11 @@ public final class NetworkReflections {
"network.protocol.game.ClientboundPlaceGhostRecipePacket"
)
);
public static final Class<?> clazz$ClientboundUpdateRecipesPacket = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"network.protocol.game.PacketPlayOutRecipeUpdate",
"network.protocol.game.ClientboundUpdateRecipesPacket"
)
);
}

View File

@@ -47,6 +47,7 @@ import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.RayTraceResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
@@ -593,7 +594,7 @@ public class BukkitServerPlayer extends Player {
CoreReflections.field$ServerPlayerGameMode$isDestroyingBlock.set(gameMode, false);
// check item in hand
Item<ItemStack> item = this.getItemInHand(InteractionHand.MAIN_HAND);
if (item != null) {
if (!item.isEmpty()) {
Material itemMaterial = item.getItem().getType();
// creative mode + invalid item in hand
if (canInstabuild() && (itemMaterial == Material.DEBUG_STICK
@@ -611,7 +612,7 @@ public class BukkitServerPlayer extends Player {
ImmutableBlockState customState = optionalCustomState.get();
BlockSettings blockSettings = customState.settings();
if (blockSettings.requireCorrectTool()) {
if (item != null) {
if (!item.isEmpty()) {
// it's correct on plugin side
if (blockSettings.isCorrectTool(item.id())) {
// but not on serverside
@@ -763,7 +764,7 @@ public class BukkitServerPlayer extends Player {
return DirectionUtils.toDirection(platformPlayer().getFacing());
}
@Nullable
@NotNull
@Override
public Item<ItemStack> getItemInHand(InteractionHand hand) {
PlayerInventory inventory = platformPlayer().getInventory();

View File

@@ -50,11 +50,9 @@ public class BlockStateUtils {
public static boolean isCorrectTool(@NotNull ImmutableBlockState state, @Nullable Item<ItemStack> itemInHand) {
BlockSettings settings = state.settings();
if (settings.requireCorrectTool()) {
if (itemInHand == null) return false;
if (!settings.isCorrectTool(itemInHand.id()) &&
(!settings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(itemInHand.getLiteralObject(), state.customBlockState().handle()))) {
return false;
}
if (itemInHand == null || itemInHand.isEmpty()) return false;
return settings.isCorrectTool(itemInHand.id()) ||
(settings.respectToolComponent() && FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(itemInHand.getLiteralObject(), state.customBlockState().handle()));
}
return true;
}

View File

@@ -20,6 +20,7 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Bell;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
@@ -292,7 +293,7 @@ public class InteractUtils {
}
}
public static boolean isInteractable(Player player, BlockData state, BlockHitResult hit, Item<ItemStack> item) {
public static boolean isInteractable(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state);
if (INTERACTIONS.containsKey(blockType)) {
return INTERACTIONS.get(blockType).apply(player, item, state, hit);
@@ -301,7 +302,7 @@ public class InteractUtils {
}
}
public static boolean willConsume(Player player, BlockData state, BlockHitResult hit, Item<ItemStack> item) {
public static boolean willConsume(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
if (item == null) return false;
Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state);
if (WILL_CONSUME.containsKey(blockType)) {

View File

@@ -13,14 +13,14 @@ public class InventoryUtils {
int j;
for (j = 0; j < 9; ++j) {
i = (selectedSlot + j) % 9;
if (ItemUtils.isEmpty(inventory.getItem(i))) {
if (ItemStackUtils.isEmpty(inventory.getItem(i))) {
return i;
}
}
for (j = 0; j < 9; ++j) {
i = (selectedSlot + j) % 9;
ItemStack item = inventory.getItem(i);
if (ItemUtils.isEmpty(item) || item.getEnchantments().isEmpty()) {
if (ItemStackUtils.isEmpty(item) || item.getEnchantments().isEmpty()) {
return i;
}
}
@@ -31,7 +31,7 @@ public class InventoryUtils {
ItemStack[] items = inventory.getStorageContents();
for (int i = 0; i < items.length; ++i) {
ItemStack stack = items[i];
if (ItemUtils.isEmpty(stack)) continue;
if (ItemStackUtils.isEmpty(stack)) continue;
if (stack.isSimilar(itemStack)) {
return i;
}

View File

@@ -7,9 +7,9 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
public class ItemUtils {
public class ItemStackUtils {
private ItemUtils() {}
private ItemStackUtils() {}
@Contract("null -> true")
public static boolean isEmpty(final ItemStack item) {
@@ -20,7 +20,7 @@ public class ItemUtils {
public static boolean hasCustomItem(ItemStack[] stack) {
for (ItemStack itemStack : stack) {
if (!ItemUtils.isEmpty(itemStack)) {
if (!ItemStackUtils.isEmpty(itemStack)) {
if (BukkitItemManager.instance().wrap(itemStack).customId().isPresent()) {
return true;
}
@@ -30,7 +30,7 @@ public class ItemUtils {
}
public static boolean isCustomItem(ItemStack stack) {
if (!ItemUtils.isEmpty(stack)) {
if (!ItemStackUtils.isEmpty(stack)) {
return BukkitItemManager.instance().wrap(stack).customId().isPresent();
}
return false;

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.bukkit.util;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
import net.momirealms.craftengine.core.util.Key;
@@ -18,15 +19,9 @@ public class ItemTags {
public static Object getOrCreate(Key key) {
Object value = CACHE.get(key);
if (value == null) {
try {
value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.ITEM, KeyUtils.toResourceLocation(key));
CACHE.put(key, value);
return value;
} catch (Exception e) {
throw new RuntimeException("Failed to create block tag: " + key, e);
}
} else {
return value;
value = FastNMS.INSTANCE.method$TagKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(key));
CACHE.put(key, value);
}
return value;
}
}

View File

@@ -72,7 +72,7 @@ public class BukkitWorld implements World {
@Override
public void dropItemNaturally(Position location, Item<?> item) {
ItemStack itemStack = (ItemStack) item.getItem();
if (ItemUtils.isEmpty(itemStack)) return;
if (ItemStackUtils.isEmpty(itemStack)) return;
if (VersionHelper.isOrAbove1_21_2()) {
platformWorld().dropItemNaturally(new Location(null, location.x(), location.y(), location.z()), (ItemStack) item.getItem());
} else {

View File

@@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.sound.SoundSource;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.BlockPos;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -17,7 +18,7 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
public abstract boolean isSecondaryUseActive();
@Nullable
@NotNull
public abstract Item<?> getItemInHand(InteractionHand hand);
@Override

View File

@@ -23,6 +23,11 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
this.item = item;
}
@Override
public boolean isEmpty() {
return this.factory.isEmpty(this.item);
}
@Override
public Item<I> itemModel(String data) {
this.factory.itemModel(this.item, data);

View File

@@ -24,6 +24,8 @@ import java.util.Optional;
*/
public interface Item<I> {
boolean isEmpty();
Optional<CustomItem<I>> getCustomItem();
Optional<List<ItemBehavior>> getItemBehavior();

View File

@@ -202,4 +202,6 @@ public abstract class ItemFactory<W extends ItemWrapper<I>, I> {
protected abstract W transmuteCopy(W item, Key newItem, int amount);
protected abstract W unsafeTransmuteCopy(W item, Object newItem, int count);
protected abstract boolean isEmpty(W item);
}

View File

@@ -13,6 +13,7 @@ import net.momirealms.craftengine.core.registry.Holder;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.Key;
import org.incendo.cloud.suggestion.Suggestion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -36,14 +37,17 @@ public interface ItemManager<T> extends Manageable, ModelGenerator {
Collection<Key> vanillaItems();
@Nullable
T buildCustomItemStack(Key id, @Nullable Player player);
@Nullable
T buildItemStack(Key id, @Nullable Player player);
Item<T> createCustomWrappedItem(Key id, @Nullable Player player);
Item<T> createWrappedItem(Key id, @Nullable Player player);
@NotNull
Item<T> wrap(T itemStack);
Item<T> fromByteArray(byte[] bytes);

View File

@@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.world.BlockHitResult;
import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class UseOnContext {
private final Player player;
@@ -24,7 +26,7 @@ public class UseOnContext {
this(player.world(), player, hand, stack, hit);
}
public UseOnContext(World world, Player player, InteractionHand hand, Item<?> stack, BlockHitResult hit) {
public UseOnContext(@NotNull World world, Player player, InteractionHand hand, @NotNull Item<?> stack, BlockHitResult hit) {
this.player = player;
this.hand = hand;
this.hitResult = hit;
@@ -52,6 +54,7 @@ public class UseOnContext {
return this.hitResult.isInside();
}
@NotNull
public Item<?> getItem() {
return this.itemStack;
}

View File

@@ -4,5 +4,11 @@ public enum CraftingRecipeCategory {
BUILDING,
REDSTONE,
EQUIPMENT,
MISC
MISC;
public static final CraftingRecipeCategory[] VALUES = CraftingRecipeCategory.values();
public static CraftingRecipeCategory byId(final int id) {
return VALUES[id];
}
}

View File

@@ -0,0 +1,33 @@
package net.momirealms.craftengine.core.item.recipe.network.legacy;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Obsolete
public class LegacyIngredient {
private final Item<Object>[] items;
public LegacyIngredient(Item<Object>[] items) {
this.items = items;
}
public Item<?>[] items() {
return items;
}
@SuppressWarnings("unchecked")
public static LegacyIngredient read(FriendlyByteBuf buf) {
Item<Object>[] items = buf.readArray(byteBuf -> CraftEngine.instance().itemManager().decode(byteBuf), Item.class);
return new LegacyIngredient(items);
}
public void applyClientboundData(Player player) {
for (int i = 0; i < items.length; i++) {
Item<Object> item = items[i];
this.items[i] = CraftEngine.instance().itemManager().s2c(item, player);
}
}
}

View File

@@ -0,0 +1,34 @@
package net.momirealms.craftengine.core.item.recipe.network.legacy;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.Function;
@ApiStatus.Obsolete
public interface LegacyRecipe {
void write(FriendlyByteBuf buf);
static LegacyRecipe read(FriendlyByteBuf buf) {
if (VersionHelper.isOrAbove1_20_5()) {
Key id = buf.readKey();
Key type = buf.readKey();
return BuiltInRegistries.LEGACY_RECIPE_TYPE.getValue(type).read(id, buf);
} else {
Key type = buf.readKey();
Key id = buf.readKey();
return BuiltInRegistries.LEGACY_RECIPE_TYPE.getValue(type).read(id, buf);
}
}
record Type(Function<FriendlyByteBuf, LegacyRecipe> reader) {
public LegacyRecipe read(Key id, FriendlyByteBuf buf) {
return this.reader.apply(buf);
}
}
}

View File

@@ -0,0 +1,34 @@
package net.momirealms.craftengine.core.item.recipe.network.legacy;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Obsolete
public final class LegacyRecipeTypes {
private LegacyRecipeTypes() {}
public static final Key SHAPED_RECIPE = Key.of("crafting_shaped");
public static final Key SHAPELESS_RECIPE = Key.of("crafting_shapeless");
public static final Key ARMOR_DYE = Key.of("crafting_special_armordye");
public static final Key BOOK_CLONING = Key.of("crafting_special_bookcloning");
public static final Key MAP_CLONING = Key.of("crafting_special_mapcloning");
public static final Key MAP_EXTENDING = Key.of("crafting_special_mapextending");
public static final Key FIREWORK_ROCKET = Key.of("crafting_special_firework_rocket");
public static final Key FIREWORK_STAR = Key.of("crafting_special_firework_star");
public static final Key FIREWORK_STAR_FADE = Key.of("crafting_special_firework_star_fade");
public static final Key TIPPED_ARROW = Key.of("crafting_special_tippedarrow");
public static final Key BANNER_DUPLICATE = Key.of("crafting_special_bannerduplicate");
public static final Key SHIELD_DECORATION = Key.of("crafting_special_shielddecoration");
public static final Key SHULKER_BOX_COLORING = Key.of("crafting_special_shulkerboxcoloring");
public static final Key SUSPICIOUS_STEW = Key.of("crafting_special_suspiciousstew");
public static final Key REPAIR_ITEM = Key.of("crafting_special_repairitem");
public static final Key SMELTING_RECIPE = Key.of("smelting");
public static final Key BLASTING_RECIPE = Key.of("blasting");
public static final Key SMOKING_RECIPE = Key.of("smoking");
public static final Key CAMPFIRE_COOKING_RECIPE = Key.of("campfire_cooking");
public static final Key STONECUTTER = Key.of("stonecutting");
public static final Key SMITHING_TRANSFORM = Key.of("smithing_transform");
public static final Key SMITHING_TRIM = Key.of("smithing_trim");
public static final Key DECORATED_POT_RECIPE = Key.of("crafting_decorated_pot");
}

View File

@@ -0,0 +1,75 @@
package net.momirealms.craftengine.core.item.recipe.network.legacy;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
import org.jetbrains.annotations.ApiStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
@ApiStatus.Obsolete
public class LegacyShapedRecipe implements LegacyRecipe {
private final int width;
private final int height;
private final List<LegacyIngredient> ingredients;
private final Item<?> result;
private final Key id;
private final String group;
private final CraftingRecipeCategory category;
private final boolean showNotification;
public LegacyShapedRecipe(int width, int height, List<LegacyIngredient> ingredients, Item<?> result, Key id, String group, CraftingRecipeCategory category, boolean showNotification) {
this.category = category;
this.width = width;
this.height = height;
this.ingredients = ingredients;
this.result = result;
this.id = id;
this.group = group;
this.showNotification = showNotification;
}
private static final BiFunction<Key, FriendlyByteBuf, LegacyShapedRecipe> READER = VersionHelper.isOrAbove1_20_3() ?
(id, buf) -> {
String group = buf.readUtf();
int category = buf.readVarInt();
int width = buf.readVarInt();
int height = buf.readVarInt();
int size = width * height;
List<LegacyIngredient> ingredients = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
ingredients.set(i, LegacyIngredient.read(buf));
}
Item<?> result = CraftEngine.instance().itemManager().decode(buf);
boolean flag = buf.readBoolean();
return new LegacyShapedRecipe(width, height, ingredients, result, id, group, CraftingRecipeCategory.byId(category), flag);
} :
(id, buf) -> {
int width = buf.readVarInt();
int height = buf.readVarInt();
String group = buf.readUtf();
int category = buf.readVarInt();
int size = width * height;
List<LegacyIngredient> ingredients = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
ingredients.set(i, LegacyIngredient.read(buf));
}
Item<?> result = CraftEngine.instance().itemManager().decode(buf);
boolean flag = buf.readBoolean();
return new LegacyShapedRecipe(width, height, ingredients, result, id, group, CraftingRecipeCategory.byId(category), flag);
};
public static LegacyShapedRecipe read(Key id, FriendlyByteBuf buf) {
return READER.apply(id, buf);
}
@Override
public void write(FriendlyByteBuf buf) {
}
}

View File

@@ -1,8 +1,8 @@
package net.momirealms.craftengine.core.item.recipe.network;
package net.momirealms.craftengine.core.item.recipe.network.modern;
import com.mojang.datafixers.util.Either;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.network.display.RecipeDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.RecipeDisplay;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.Key;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network;
package net.momirealms.craftengine.core.item.recipe.network.modern;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network;
package net.momirealms.craftengine.core.item.recipe.network.modern;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceKey;
public final class RecipeDisplays {
private RecipeDisplays() {}
public static final Key CRAFTING_SHAPELESS = Key.of("crafting_shapeless");
public static final Key CRAFTING_SHAPED = Key.of("crafting_shaped");
public static final Key FURNACE = Key.of("furnace");

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.item.recipe.network.display;
package net.momirealms.craftengine.core.item.recipe.network.modern.display;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceKey;
public final class SlotDisplays {
private SlotDisplays() {}
public static final Key EMPTY = Key.of("empty");
public static final Key ANY_FUEL = Key.of("any_fuel");
public static final Key ITEM = Key.of("item");

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import com.mojang.datafixers.util.Either;
import net.kyori.adventure.text.Component;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.Key;

View File

@@ -1,4 +1,4 @@
package net.momirealms.craftengine.core.item.recipe.network.display.slot;
package net.momirealms.craftengine.core.item.recipe.network.modern.display.slot;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -7,8 +7,8 @@ import net.momirealms.craftengine.core.entity.projectile.ProjectileManager;
import net.momirealms.craftengine.core.font.FontManager;
import net.momirealms.craftengine.core.item.ItemManager;
import net.momirealms.craftengine.core.item.recipe.RecipeManager;
import net.momirealms.craftengine.core.item.recipe.network.display.RecipeDisplays;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplays;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.RecipeDisplays;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplays;
import net.momirealms.craftengine.core.loot.VanillaLootManager;
import net.momirealms.craftengine.core.pack.PackManager;
import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender;

View File

@@ -8,8 +8,9 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
import net.momirealms.craftengine.core.item.recipe.network.display.RecipeDisplay;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipe;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.RecipeDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.loot.LootContext;
import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory;
import net.momirealms.craftengine.core.loot.function.ApplyBonusCountFunction;
@@ -74,6 +75,7 @@ public class BuiltInRegistries {
public static final Registry<EquipmentFactory> EQUIPMENT_FACTORY = createRegistry(Registries.EQUIPMENT_FACTORY);
public static final Registry<SlotDisplay.Type> SLOT_DISPLAY_TYPE = createRegistry(Registries.SLOT_DISPLAY_TYPE);
public static final Registry<RecipeDisplay.Type> RECIPE_DISPLAY_TYPE = createRegistry(Registries.RECIPE_DISPLAY_TYPE);
public static final Registry<LegacyRecipe.Type> LEGACY_RECIPE_TYPE = createRegistry(Registries.LEGACY_RECIPE_TYPE);
private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) {
return new MappedRegistry<>(key);

View File

@@ -8,8 +8,9 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
import net.momirealms.craftengine.core.item.equipment.EquipmentFactory;
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
import net.momirealms.craftengine.core.item.recipe.network.display.RecipeDisplay;
import net.momirealms.craftengine.core.item.recipe.network.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipe;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.RecipeDisplay;
import net.momirealms.craftengine.core.item.recipe.network.modern.display.slot.SlotDisplay;
import net.momirealms.craftengine.core.loot.LootContext;
import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory;
import net.momirealms.craftengine.core.loot.function.ApplyBonusCountFunction;
@@ -75,4 +76,5 @@ public class Registries {
public static final ResourceKey<Registry<EquipmentFactory>> EQUIPMENT_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("equipment_factory"));
public static final ResourceKey<Registry<SlotDisplay.Type>> SLOT_DISPLAY_TYPE = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("slot_display_type"));
public static final ResourceKey<Registry<RecipeDisplay.Type>> RECIPE_DISPLAY_TYPE = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("recipe_display_type"));
public static final ResourceKey<Registry<LegacyRecipe.Type>> LEGACY_RECIPE_TYPE = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("legacy_recipe_type"));
}

View File

@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
@@ -48,20 +49,34 @@ public class FriendlyByteBuf extends ByteBuf {
public <T, C extends Collection<T>> C readCollection(IntFunction<C> collectionFactory, Reader<T> reader) {
int i = this.readVarInt();
C c0 = (C)(collectionFactory.apply(i));
C collection = collectionFactory.apply(i);
for(int j = 0; j < i; ++j) {
c0.add(reader.apply(this));
collection.add(reader.apply(this));
}
return c0;
return collection;
}
public <T> void writeCollection(Collection<T> collection, Writer<T> writer) {
this.writeVarInt(collection.size());
for (T t : collection) {
writer.accept(this, t);
}
}
for (T t0 : collection) {
writer.accept(this, t0);
@SuppressWarnings("unchecked")
public <T> T[] readArray(Reader<T> reader, Class<T> type) {
int i = this.readVarInt();
T[] array = (T[]) Array.newInstance(type, i);
for(int j = 0; j < i; ++j) {
array[j] = reader.apply(this);
}
return array;
}
public <T> void writeArray(T[] array, Writer<T> writer) {
this.writeVarInt(array.length);
for(T t : array) {
writer.accept(this, t);
}
}

View File

@@ -0,0 +1,12 @@
package net.momirealms.craftengine.core.util;
import net.momirealms.craftengine.core.item.Item;
public final class ItemUtils {
private ItemUtils() {
}
public static boolean isEmpty(Item<?> item) {
return item == null || item.isEmpty();
}
}