mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
@@ -58,6 +58,8 @@ dependencies {
|
||||
compileOnly("org.bstats:bstats-bukkit:${rootProject.properties["bstats_version"]}")
|
||||
// Aho-Corasick java implementation
|
||||
compileOnly("org.ahocorasick:ahocorasick:${rootProject.properties["ahocorasick_version"]}")
|
||||
// authlib
|
||||
compileOnly("com.mojang:authlib:${rootProject.properties["authlib_version"]}")
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -96,6 +98,7 @@ tasks {
|
||||
relocate("com.ezylang.evalex", "net.momirealms.craftengine.libraries.evalex")
|
||||
relocate("com.google.common.jimfs", "net.momirealms.craftengine.libraries.jimfs")
|
||||
relocate("org.apache.commons", "net.momirealms.craftengine.libraries.commons")
|
||||
relocate("io.leangen.geantyref", "net.momirealms.craftengine.libraries.geantyref")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ dependencies {
|
||||
// ModelEngine
|
||||
compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.8")
|
||||
// BetterModels
|
||||
compileOnly("io.github.toxicity188:BetterModel:1.4.2")
|
||||
compileOnly("io.github.toxicity188:BetterModel:1.7.0")
|
||||
// MMOItems
|
||||
compileOnly("net.Indyuce:MMOItems-API:6.10-SNAPSHOT")
|
||||
compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT")
|
||||
|
||||
@@ -210,7 +210,6 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
||||
Plugin fastAsyncWorldEdit = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit");
|
||||
String version = VersionHelper.isPaper() ? fastAsyncWorldEdit.getPluginMeta().getVersion() : fastAsyncWorldEdit.getDescription().getVersion();
|
||||
if (!this.fastAsyncWorldEditVersionCheck(version)) {
|
||||
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
this.plugin.logger().severe("");
|
||||
if (Locale.getDefault() == Locale.SIMPLIFIED_CHINESE) {
|
||||
|
||||
@@ -4,20 +4,33 @@ import net.momirealms.craftengine.core.item.ExternalItemProvider;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class CustomFishingProvider implements ExternalItemProvider<ItemStack> {
|
||||
@Override
|
||||
public String plugin() {
|
||||
return "CustomFishing";
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Nullable
|
||||
@Override
|
||||
public ItemStack build(String id, ItemBuildContext context) {
|
||||
return BukkitCustomFishingPlugin.getInstance().getItemManager()
|
||||
.buildInternal(Context.player(((Player) context.player().platformPlayer())), id);
|
||||
Context<Player> ctx = Context.player(
|
||||
(Player) Optional.ofNullable(context.player())
|
||||
.map(net.momirealms.craftengine.core.entity.player.Player::platformPlayer)
|
||||
.orElse(null)
|
||||
);
|
||||
return BukkitCustomFishingPlugin.getInstance().getItemManager().buildInternal(ctx.arg(ContextKeys.ID, id), id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String id(ItemStack item) {
|
||||
return BukkitCustomFishingPlugin.getInstance().getItemManager().getCustomFishingItemID(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class MMOItemsProvider implements ExternalItemProvider<ItemStack> {
|
||||
@@ -23,7 +21,12 @@ public class MMOItemsProvider implements ExternalItemProvider<ItemStack> {
|
||||
@Override
|
||||
public @Nullable ItemStack build(String id, ItemBuildContext context) {
|
||||
String[] split = id.split(":", 2);
|
||||
MMOItem mmoItem = MMOItems.plugin.getMMOItem(Type.get(split[0]), split[1].toUpperCase(Locale.ENGLISH));
|
||||
MMOItem mmoItem = MMOItems.plugin.getMMOItem(Type.get(split[0]), split[1].toUpperCase());
|
||||
return mmoItem == null ? new ItemStack(Material.AIR) : requireNonNull(mmoItem.newBuilder().build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String id(ItemStack item) {
|
||||
return MMOItems.getType(item) + ":" + MMOItems.getID(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,12 @@ public class MythicMobsProvider implements ExternalItemProvider<ItemStack> {
|
||||
}
|
||||
return mythicBukkit.getItemManager().getItemStack(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String id(ItemStack item) {
|
||||
if (mythicBukkit == null || mythicBukkit.isClosed()) {
|
||||
this.mythicBukkit = MythicBukkit.inst();
|
||||
}
|
||||
return mythicBukkit.getItemManager().getMythicTypeFromItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,4 +19,9 @@ public class NeigeItemsProvider implements ExternalItemProvider<ItemStack> {
|
||||
public ItemStack build(String id, ItemBuildContext context) {
|
||||
return ItemManager.INSTANCE.getItemStack(id, Optional.ofNullable(context.player()).map(it -> (Player) it.platformPlayer()).orElse(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String id(ItemStack item) {
|
||||
return ItemManager.INSTANCE.getItemId(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.model.bettermodel;
|
||||
|
||||
import kr.toxicity.model.api.BetterModel;
|
||||
import kr.toxicity.model.api.data.renderer.BlueprintRenderer;
|
||||
import kr.toxicity.model.api.data.renderer.ModelRenderer;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class BetterModelUtils {
|
||||
|
||||
public static void bindModel(Entity base, String id) {
|
||||
BlueprintRenderer renderer = BetterModel.inst().modelManager().renderer(id);
|
||||
ModelRenderer renderer = BetterModel.plugin().modelManager().renderer(id);
|
||||
if (renderer == null) {
|
||||
throw new NullPointerException("Could not find BetterModel blueprint " + id);
|
||||
}
|
||||
|
||||
@@ -29,12 +29,10 @@ public class CraftEngineItemDrop extends ItemDrop implements IItemDrop {
|
||||
public CraftEngineItemDrop(String line, MythicLineConfig config, CustomItem<ItemStack> customItem) {
|
||||
super(line, config);
|
||||
this.customItem = customItem;
|
||||
CraftEngine.instance().debug(() -> "[MM调试] " + customItem.id() + " 注册成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractItemStack getDrop(DropMetadata dropMetadata, double amount) {
|
||||
CraftEngine.instance().debug(() -> "[MM调试] getDrop() dropMetadata={" + dropMetadata + "}, amount={" + amount + "}");
|
||||
ItemBuildContext context = ItemBuildContext.EMPTY;
|
||||
SkillCaster caster = dropMetadata.getCaster();
|
||||
if (caster != null && caster.getEntity() instanceof AbstractPlayer abstractPlayer) {
|
||||
|
||||
@@ -20,7 +20,6 @@ public class MythicMobsListener implements Listener {
|
||||
public void onMythicDropLoad(MythicDropLoadEvent event) {
|
||||
if (!event.getDropName().equalsIgnoreCase("craftengine")) return;
|
||||
String argument = event.getArgument();
|
||||
plugin.debug(() -> "[MM调试] " + argument);
|
||||
Key itemId = Key.of(argument);
|
||||
this.plugin.itemManager().getCustomItem(itemId).ifPresent(customItem -> {
|
||||
String line = event.getContainer().getConfigLine();
|
||||
|
||||
@@ -211,7 +211,6 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
int newStateId = ordinalToIbdID[newBlock.getOrdinal()];
|
||||
int oldStateId = ordinalToIbdID[oldBlock.getOrdinal()];
|
||||
this.brokenChunks.add(ChunkPos.of(chunkX, chunkZ));
|
||||
//CraftEngine.instance().debug(() -> "Processing block at " + blockX + ", " + blockY + ", " + blockZ + ": " + oldStateId + " -> " + newStateId);
|
||||
if (BlockStateUtils.isVanillaBlock(newStateId) && BlockStateUtils.isVanillaBlock(oldStateId)) return;
|
||||
try {
|
||||
CEChunk ceChunk = Optional.ofNullable(this.ceWorld.getChunkAtIfLoaded(chunkX, chunkZ))
|
||||
@@ -231,7 +230,6 @@ public class FastAsyncWorldEditDelegate extends AbstractDelegateExtent {
|
||||
private void saveAllChunks() {
|
||||
try {
|
||||
for (CEChunk ceChunk : this.chunksToSave) {
|
||||
CraftEngine.instance().debug(() -> "Saving chunk " + ceChunk.chunkPos());
|
||||
this.ceWorld.worldDataStorage().writeChunkAt(ceChunk.chunkPos(), ceChunk);
|
||||
}
|
||||
this.chunksToSave.clear();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryEvent;
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent;
|
||||
import org.bukkit.inventory.AnvilInventory;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@@ -65,4 +66,8 @@ public class LegacyInventoryUtils {
|
||||
public static void openWorkbench(Player player) {
|
||||
player.openWorkbench(null, true);
|
||||
}
|
||||
|
||||
public static Player getPlayerFromInventoryEvent(InventoryEvent event) {
|
||||
return (Player) event.getView().getPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,5 +76,6 @@ tasks {
|
||||
relocate("software.amazon.eventstream", "net.momirealms.craftengine.libraries.eventstream")
|
||||
relocate("com.google.common.jimfs", "net.momirealms.craftengine.libraries.jimfs")
|
||||
relocate("org.apache.commons", "net.momirealms.craftengine.libraries.commons")
|
||||
relocate("io.leangen.geantyref", "net.momirealms.craftengine.libraries.geantyref")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@ paper {
|
||||
// external models
|
||||
register("ModelEngine") { required = false }
|
||||
register("BetterModel") { required = false }
|
||||
register("FreeMinecraftModels") { required = false }
|
||||
|
||||
// external items
|
||||
register("NeigeItems") { required = false }
|
||||
@@ -149,5 +148,6 @@ tasks {
|
||||
relocate("software.amazon.eventstream", "net.momirealms.craftengine.libraries.eventstream")
|
||||
relocate("com.google.common.jimfs", "net.momirealms.craftengine.libraries.jimfs")
|
||||
relocate("org.apache.commons", "net.momirealms.craftengine.libraries.commons")
|
||||
relocate("io.leangen.geantyref", "net.momirealms.craftengine.libraries.geantyref")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ public final class CraftEngineBlocks {
|
||||
world.playBlockSound(position, state.settings().sounds().breakSound());
|
||||
}
|
||||
if (sendParticles) {
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(world.serverWorld(), WorldEvents.BLOCK_BREAK_EFFECT, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), state.customBlockState().registryId());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(world.serverWorld(), WorldEvents.BLOCK_BREAK_EFFECT, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), state.customBlockState().registryId());
|
||||
}
|
||||
FastNMS.INSTANCE.method$Level$removeBlock(world.serverWorld(), LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), isMoving);
|
||||
return true;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -35,7 +36,6 @@ import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.world.GenericGameEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -52,14 +52,6 @@ public final class BlockEventListener implements Listener {
|
||||
this.enableNoteBlockCheck = enableNoteBlockCheck;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Object packet = this.manager.cachedUpdateTagsPacket;
|
||||
if (packet != null) {
|
||||
this.plugin.adapt(event.getPlayer()).sendPacket(packet, false);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerAttack(EntityDamageByEntityEvent event) {
|
||||
if (!VersionHelper.isOrAbove1_20_5()) {
|
||||
@@ -125,7 +117,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 +159,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 +181,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);
|
||||
|
||||
@@ -94,7 +94,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
private BlockEventListener blockEventListener;
|
||||
private FallingBlockRemoveListener fallingBlockRemoveListener;
|
||||
// cached tag packet
|
||||
Object cachedUpdateTagsPacket;
|
||||
private Object cachedUpdateTagsPacket;
|
||||
|
||||
private final List<Tuple<Object, Key, Boolean>> blocksToDeceive = new ArrayList<>();
|
||||
|
||||
@@ -276,7 +276,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
|
||||
private void registerEmptyBlock() {
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).registerForHolder(new ResourceKey<>(BuiltInRegistries.BLOCK.key().location(), Key.withDefaultNamespace("empty")));
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).registerForHolder(ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), Key.withDefaultNamespace("empty")));
|
||||
EmptyBlock emptyBlock = new EmptyBlock(Key.withDefaultNamespace("empty"), holder);
|
||||
holder.bindValue(emptyBlock);
|
||||
}
|
||||
@@ -397,6 +397,10 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
}
|
||||
}
|
||||
|
||||
public Object cachedUpdateTagsPacket() {
|
||||
return cachedUpdateTagsPacket;
|
||||
}
|
||||
|
||||
public class BlockParser implements ConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[]{"blocks", "block"};
|
||||
|
||||
@@ -500,13 +504,9 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
Object clientBoundTags = settings.get("client-bound-tags");
|
||||
if (clientBoundTags instanceof List<?> list) {
|
||||
List<String> clientSideTags = MiscUtils.getAsStringList(list).stream().filter(ResourceLocation::isValid).toList();
|
||||
try {
|
||||
Object nmsBlock = CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id));
|
||||
FastNMS.INSTANCE.method$IdMap$getId(MBuiltInRegistries.BLOCK, nmsBlock).ifPresent(i ->
|
||||
BukkitBlockManager.this.clientBoundTags.put(i, clientSideTags));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
BukkitBlockManager.this.plugin.logger().warn("Unable to get block " + id, e);
|
||||
}
|
||||
Object nmsBlock = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, KeyUtils.toResourceLocation(id));
|
||||
FastNMS.INSTANCE.method$IdMap$getId(MBuiltInRegistries.BLOCK, nmsBlock).ifPresent(i ->
|
||||
BukkitBlockManager.this.clientBoundTags.put(i, clientSideTags));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,7 +657,7 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
private void recordVanillaNoteBlocks() {
|
||||
try {
|
||||
Object resourceLocation = KeyUtils.toResourceLocation(BlockKeys.NOTE_BLOCK);
|
||||
Object block = CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, resourceLocation);
|
||||
Object block = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, resourceLocation);
|
||||
Object stateDefinition = CoreReflections.field$Block$StateDefinition.get(block);
|
||||
@SuppressWarnings("unchecked")
|
||||
ImmutableList<Object> states = (ImmutableList<Object>) CoreReflections.field$StateDefinition$states.get(stateDefinition);
|
||||
@@ -841,8 +841,8 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
return FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath(key.namespace(), key.value());
|
||||
}
|
||||
|
||||
private Object getBlockFromRegistry(Object resourceLocation) throws Exception {
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, resourceLocation);
|
||||
private Object getBlockFromRegistry(Object resourceLocation) {
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, resourceLocation);
|
||||
}
|
||||
|
||||
private Key createRealBlockKey(Key replacedBlock, int index) {
|
||||
|
||||
@@ -130,8 +130,8 @@ public final class BukkitCustomBlock extends AbstractCustomBlock {
|
||||
CoreReflections.field$BlockBehaviour$explosionResistance.set(nmsBlock, settings.resistance());
|
||||
CoreReflections.field$BlockBehaviour$soundType.set(nmsBlock, SoundUtils.toSoundType(settings.sounds()));
|
||||
// 1.21.2以前要在init cache之前设定 isConditionallyFullOpaque
|
||||
boolean isConditionallyFullOpaque = canOcclude & useShapeForLightOcclusion;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) {
|
||||
boolean isConditionallyFullOpaque = canOcclude & useShapeForLightOcclusion;
|
||||
CoreReflections.field$BlockStateBase$isConditionallyFullOpaque.set(nmsState, isConditionallyFullOpaque);
|
||||
}
|
||||
// init cache
|
||||
@@ -162,6 +162,9 @@ public final class BukkitCustomBlock extends AbstractCustomBlock {
|
||||
} else {
|
||||
CoreReflections.field$BlockStateBase$Cache$propagatesSkylightDown.set(cache, CoreReflections.field$BlockStateBase$Cache$propagatesSkylightDown.getBoolean(CoreReflections.field$BlockStateBase$cache.get(immutableBlockState.vanillaBlockState().handle())));
|
||||
}
|
||||
if (!isConditionallyFullOpaque) {
|
||||
CoreReflections.field$BlockStateBase$opacityIfCached.set(nmsState, blockLight);
|
||||
}
|
||||
}
|
||||
// set fluid later
|
||||
if (settings.fluidState()) {
|
||||
@@ -251,9 +254,8 @@ public final class BukkitCustomBlock extends AbstractCustomBlock {
|
||||
@Override
|
||||
public @NotNull CustomBlock build() {
|
||||
// create or get block holder
|
||||
Holder.Reference<CustomBlock> holder = BuiltInRegistries.BLOCK.get(id).orElseGet(() ->
|
||||
((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).registerForHolder(new ResourceKey<>(BuiltInRegistries.BLOCK.key().location(), id)));
|
||||
return new BukkitCustomBlock(id, holder, properties, appearances, variantMapper, settings, events, behavior, lootTable);
|
||||
Holder.Reference<CustomBlock> holder = ((WritableRegistry<CustomBlock>) BuiltInRegistries.BLOCK).getOrRegisterForHolder(ResourceKey.create(BuiltInRegistries.BLOCK.key().location(), this.id));
|
||||
return new BukkitCustomBlock(this.id, holder, this.properties, this.appearances, this.variantMapper, this.settings, this.events, this.behavior, this.lootTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
||||
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object world = args[1];
|
||||
Object blockPos = args[2];
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,7 +66,7 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
||||
return state;
|
||||
}
|
||||
if (this.delay != 0) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(level, blockPos, thisBlock, this.delay);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(level, blockPos, thisBlock, this.delay);
|
||||
return state;
|
||||
}
|
||||
if (!canSurvive(thisBlock, new Object[] {state, level, blockPos}, () -> true)) {
|
||||
@@ -75,7 +75,7 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
world.playBlockSound(position, customState.settings().sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return state;
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MItems;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.MirrorUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.RotationUtils;
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior;
|
||||
@@ -154,7 +155,7 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
Object fluidType = FastNMS.INSTANCE.method$FluidState$getType(args[3]);
|
||||
if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == MFluids.WATER) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3);
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[0], args[1], fluidType, 5);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleFluidTick(args[0], args[1], fluidType, 5);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -172,4 +173,15 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
protected static final int updateShape$blockPos = VersionHelper.isOrAbove1_21_2() ? 3 : 4;
|
||||
protected static final int updateShape$neighborState = VersionHelper.isOrAbove1_21_2() ? 6 : 2;
|
||||
protected static final int updateShape$direction = VersionHelper.isOrAbove1_21_2() ? 4 : 1;
|
||||
|
||||
protected static final int isPathFindable$type = VersionHelper.isOrAbove1_20_5() ? 1 : 3;
|
||||
|
||||
@Override
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
|
||||
if (optionalCustomState.isEmpty()) return false;
|
||||
BlockStateWrapper vanillaState = optionalCustomState.get().vanillaBlockState();
|
||||
if (vanillaState == null) return false;
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$isPathFindable(vanillaState.handle(), VersionHelper.isOrAbove1_20_5() ? null : args[1], VersionHelper.isOrAbove1_20_5() ? null : args[2], args[isPathFindable$type]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key SLAB_BLOCK = Key.from("craftengine:slab_block");
|
||||
public static final Key STAIRS_BLOCK = Key.from("craftengine:stairs_block");
|
||||
public static final Key PRESSURE_PLATE_BLOCK = Key.from("craftengine:pressure_plate_block");
|
||||
public static final Key DOUBLE_BLOCK = Key.from("craftengine:double_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -50,5 +51,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(SLAB_BLOCK, SlabBlockBehavior.FACTORY);
|
||||
register(STAIRS_BLOCK, StairsBlockBehavior.FACTORY);
|
||||
register(PRESSURE_PLATE_BLOCK, PressurePlateBlockBehavior.FACTORY);
|
||||
register(DOUBLE_BLOCK, DoubleBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
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.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
@@ -15,8 +18,10 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.block.state.properties.DoorHinge;
|
||||
import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
@@ -32,6 +37,7 @@ import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Door;
|
||||
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -111,13 +117,44 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
world.playBlockSound(position, customState.settings().sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return blockState;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object playerWillDestroy(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level = args[0];
|
||||
Object pos = args[1];
|
||||
Object state = args[2];
|
||||
Object player = args[3];
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return superMethod.call();
|
||||
org.bukkit.entity.Player bukkitPlayer = FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(player);
|
||||
BukkitServerPlayer cePlayer = BukkitCraftEngine.instance().adapt(bukkitPlayer);
|
||||
Item<ItemStack> item = cePlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
if (cePlayer.canInstabuild() || !BlockStateUtils.isCorrectTool(blockState, item)) {
|
||||
preventDropFromBottomPart(level, pos, blockState, player);
|
||||
}
|
||||
return superMethod.call();
|
||||
}
|
||||
|
||||
private void preventDropFromBottomPart(Object level, Object pos, ImmutableBlockState state, Object player) {
|
||||
DoubleBlockHalf half = state.get(this.halfProperty);
|
||||
if (half == DoubleBlockHalf.UPPER) {
|
||||
Object blockPos = FastNMS.INSTANCE.method$BlockPos$relative(pos, CoreReflections.instance$Direction$DOWN);
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, blockPos);
|
||||
ImmutableBlockState belowState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (belowState == null || belowState.isEmpty()) return;
|
||||
Optional<DoorBlockBehavior> belowDoorBehavior = belowState.behavior().getAs(DoorBlockBehavior.class);
|
||||
if (belowDoorBehavior.isEmpty() || belowState.get(this.halfProperty) != DoubleBlockHalf.LOWER) return;
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, MBlocks.AIR$defaultState, UpdateOption.builder().updateSuppressDrops().updateClients().updateNeighbors().build().flags());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, player, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, belowState.customBlockState().registryId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExplosionHit(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
if (this.canOpenByWindCharge && FastNMS.INSTANCE.method$Explosion$canTriggerBlocks(args[3])) {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
|
||||
public class DoubleBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Property<DoubleBlockHalf> halfProperty;
|
||||
|
||||
public DoubleBlockBehavior(CustomBlock customBlock, Property<DoubleBlockHalf> halfProperty) {
|
||||
super(customBlock);
|
||||
this.halfProperty = halfProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
Object blockState = args[0];
|
||||
|
||||
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (customState == null || customState.isEmpty()) return blockState;
|
||||
DoubleBlockHalf half = customState.get(this.halfProperty);
|
||||
if (half == null) return blockState;
|
||||
|
||||
// 获取另一半
|
||||
Object anotherHalfPos = FastNMS.INSTANCE.method$BlockPos$relative(blockPos,
|
||||
half == DoubleBlockHalf.UPPER
|
||||
? CoreReflections.instance$Direction$DOWN
|
||||
: CoreReflections.instance$Direction$UP
|
||||
);
|
||||
Object anotherHalfState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, anotherHalfPos);
|
||||
ImmutableBlockState anotherHalfCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(anotherHalfState));
|
||||
if (anotherHalfCustomState != null && !anotherHalfCustomState.isEmpty()) return blockState;
|
||||
|
||||
// 破坏
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
world.playBlockSound(position, customState.settings().sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlacedBy(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
World level = context.getLevel();
|
||||
BlockPos anotherHalfPos = context.getClickedPos().relative(Direction.UP);
|
||||
BlockStateWrapper blockStateWrapper = state.with(this.halfProperty, DoubleBlockHalf.UPPER).customBlockState();
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level.serverWorld(), LocationUtils.toBlockPos(anotherHalfPos), blockStateWrapper.handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
World world = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
if (pos.y() < context.getLevel().worldHeight().getMaxBuildHeight() && world.getBlockAt(pos.above()).canBeReplaced(context)) {
|
||||
return state.with(this.halfProperty, DoubleBlockHalf.LOWER);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Property<DoubleBlockHalf> half = (Property<DoubleBlockHalf>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("half"), "warning.config.block.behavior.double.missing_half");
|
||||
return new DoubleBlockBehavior(block, half);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,14 +37,14 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
public void onPlace(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object world = args[1];
|
||||
Object blockPos = args[2];
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object world = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
return args[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
@@ -107,12 +107,11 @@ public class GrassBlockBehavior extends BukkitBlockBehavior {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void performBoneMeal(Object thisBlock, Object[] args) throws Exception {
|
||||
Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.PLACED_FEATURE);
|
||||
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.PLACED_FEATURE);
|
||||
if (registry == null) return;
|
||||
Optional<Object> holder = (Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(registry, FeatureUtils.createPlacedFeatureKey(boneMealFeature()));
|
||||
Optional<Object> holder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(registry, FeatureUtils.createPlacedFeatureKey(boneMealFeature()));
|
||||
if (holder.isEmpty()) {
|
||||
CraftEngine.instance().logger().warn("Placed feature not found: " + boneMealFeature());
|
||||
return;
|
||||
|
||||
@@ -59,7 +59,7 @@ public class LampBlockBehavior extends BukkitBlockBehavior {
|
||||
boolean lit = customState.get(this.litProperty);
|
||||
if (lit != FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||
if (lit) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 4);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(world, blockPos, thisBlock, 4);
|
||||
} else {
|
||||
if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) {
|
||||
return;
|
||||
|
||||
@@ -66,7 +66,7 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
|
||||
LeavesBlockBehavior behavior = optionalBehavior.get();
|
||||
int distance = behavior.getDistanceAt(neighborState) + 1;
|
||||
if (distance != 1 || behavior.getDistance(optionalCustomState.get()) != distance) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 1);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(world, blockPos, thisBlock, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
}
|
||||
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) {
|
||||
Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(world, belowPos);
|
||||
Object fluidStateAbove = FastNMS.INSTANCE.method$Level$getFluidState(world, LocationUtils.above(belowPos));
|
||||
Object fluidState = FastNMS.INSTANCE.method$BlockGetter$getFluidState(world, belowPos);
|
||||
Object fluidStateAbove = FastNMS.INSTANCE.method$BlockGetter$getFluidState(world, LocationUtils.above(belowPos));
|
||||
if (FastNMS.INSTANCE.method$FluidState$getType(fluidStateAbove) != MFluids.EMPTY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(world, belowPos);
|
||||
Object fluidStateAbove = FastNMS.INSTANCE.method$Level$getFluidState(world, LocationUtils.above(belowPos));
|
||||
Object fluidState = FastNMS.INSTANCE.method$BlockGetter$getFluidState(world, belowPos);
|
||||
Object fluidStateAbove = FastNMS.INSTANCE.method$BlockGetter$getFluidState(world, LocationUtils.above(belowPos));
|
||||
if (FastNMS.INSTANCE.method$FluidState$getType(fluidStateAbove) != MFluids.EMPTY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
world.playBlockSound(position, customState.settings().sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return state;
|
||||
@@ -106,7 +106,7 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
this.checkPressed(args[3], args[1], args[2], state, signalForState, thisBlock);
|
||||
} else {
|
||||
// todo 为什么
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(args[1], args[2], thisBlock, this.pressedTime);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(args[1], args[2], thisBlock, this.pressedTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
if (isActive) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(level, pos, thisBlock, this.pressedTime);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(level, pos, thisBlock, this.pressedTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,21 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object level = args[1];
|
||||
Object pos = args[2];
|
||||
Object newState = args[3];
|
||||
boolean movedByPiston = (boolean) args[4];
|
||||
if (!movedByPiston && !FastNMS.INSTANCE.method$BlockStateBase$is(state, FastNMS.INSTANCE.method$BlockState$getBlock(newState))) {
|
||||
if (this.getSignalForState(state) > 0) {
|
||||
this.updateNeighbours(level, pos, thisBlock);
|
||||
}
|
||||
superMethod.call();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNeighbours(Object level, Object pos, Object thisBlock) {
|
||||
FastNMS.INSTANCE.method$Level$updateNeighborsAt(level, pos, thisBlock);
|
||||
FastNMS.INSTANCE.method$Level$updateNeighborsAt(level, LocationUtils.below(pos), thisBlock);
|
||||
|
||||
@@ -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;
|
||||
@@ -79,17 +80,16 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
private void generateTree(Object world, Object blockPos, Object blockState, Object randomSource) throws Exception {
|
||||
Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.CONFIGURED_FEATURE);
|
||||
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.CONFIGURED_FEATURE);
|
||||
if (registry == null) return;
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> holder = (Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(registry, FeatureUtils.createConfiguredFeatureKey(treeFeature()));
|
||||
Optional<Object> holder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(registry, FeatureUtils.createConfiguredFeatureKey(treeFeature()));
|
||||
if (holder.isEmpty()) {
|
||||
CraftEngine.instance().logger().warn("Configured feature not found: " + treeFeature());
|
||||
return;
|
||||
}
|
||||
Object chunkGenerator = CoreReflections.method$ServerChunkCache$getGenerator.invoke(FastNMS.INSTANCE.method$ServerLevel$getChunkSource(world));
|
||||
Object configuredFeature = CoreReflections.method$Holder$value.invoke(holder.get());
|
||||
Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(world, blockPos);
|
||||
Object fluidState = FastNMS.INSTANCE.method$BlockGetter$getFluidState(world, blockPos);
|
||||
Object legacyState = CoreReflections.method$FluidState$createLegacyBlock.invoke(fluidState);
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, legacyState, UpdateOption.UPDATE_NONE.flags());
|
||||
if ((boolean) CoreReflections.method$ConfiguredFeature$place.invoke(configuredFeature, world, chunkGenerator, randomSource, blockPos)) {
|
||||
@@ -148,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();
|
||||
|
||||
@@ -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();
|
||||
@@ -69,7 +66,7 @@ public class SlabBlockBehavior extends BukkitBlockBehavior {
|
||||
blockState = blockState.with(super.waterloggedProperty, false);
|
||||
return blockState.with(this.typeProperty, SlabType.DOUBLE);
|
||||
} else {
|
||||
Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(context.getLevel().serverWorld(), LocationUtils.toBlockPos(clickedPos));
|
||||
Object fluidState = FastNMS.INSTANCE.method$BlockGetter$getFluidState(context.getLevel().serverWorld(), LocationUtils.toBlockPos(clickedPos));
|
||||
if (super.waterloggedProperty != null)
|
||||
state = state.with(super.waterloggedProperty, FastNMS.INSTANCE.method$FluidState$getType(fluidState) == MFluids.WATER);
|
||||
Direction clickedFace = context.getClickedFace();
|
||||
@@ -98,7 +95,7 @@ public class SlabBlockBehavior extends BukkitBlockBehavior {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return blockState;
|
||||
if (optionalCustomState.get().get(super.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5);
|
||||
}
|
||||
return blockState;
|
||||
}
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -45,7 +45,7 @@ public class StairsBlockBehavior extends BukkitBlockBehavior {
|
||||
.with(this.facingProperty, context.getHorizontalDirection().toHorizontalDirection())
|
||||
.with(this.halfProperty, clickedFace != Direction.DOWN && (clickedFace == Direction.UP || !(context.getClickLocation().y - clickedPos.y() > 0.5)) ? SingleBlockHalf.BOTTOM : SingleBlockHalf.TOP);
|
||||
if (super.waterloggedProperty != null) {
|
||||
Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(context.getLevel().serverWorld(), LocationUtils.toBlockPos(clickedPos));
|
||||
Object fluidState = FastNMS.INSTANCE.method$BlockGetter$getFluidState(context.getLevel().serverWorld(), LocationUtils.toBlockPos(clickedPos));
|
||||
blockState = blockState.with(this.waterloggedProperty, FastNMS.INSTANCE.method$FluidState$getType(fluidState) == MFluids.WATER);
|
||||
}
|
||||
return blockState.with(this.shapeProperty, getStairsShape(blockState, context.getLevel().serverWorld(), clickedPos));
|
||||
@@ -60,7 +60,7 @@ public class StairsBlockBehavior extends BukkitBlockBehavior {
|
||||
if (optionalCustomState.isEmpty()) return blockState;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
if (super.waterloggedProperty != null && customState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
}
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
StairsShape stairsShape = getStairsShape(customState, level, LocationUtils.fromBlockPos(blockPos));
|
||||
|
||||
@@ -77,7 +77,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
if (super.waterloggedProperty != null) {
|
||||
BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> {
|
||||
if (customState.get(super.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
if (FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, clickedPos)) {
|
||||
state = state.with(this.poweredProperty, true).with(this.openProperty, true);
|
||||
}
|
||||
if (this.waterloggedProperty != null && FastNMS.INSTANCE.method$FluidState$getType(FastNMS.INSTANCE.method$Level$getFluidState(level, clickedPos)) == MFluids.WATER) {
|
||||
if (this.waterloggedProperty != null && FastNMS.INSTANCE.method$FluidState$getType(FastNMS.INSTANCE.method$BlockGetter$getFluidState(level, clickedPos)) == MFluids.WATER) {
|
||||
state = state.with(this.waterloggedProperty, true);
|
||||
}
|
||||
return state;
|
||||
@@ -197,7 +197,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
if (this.waterloggedProperty != null && customState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(level, blockPos, MFluids.WATER, 5);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleFluidTick(level, blockPos, MFluids.WATER, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExplosionHit(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
public void onExplosionHit(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
behavior.onExplosionHit(thisBlock, args, superMethod);
|
||||
}
|
||||
@@ -225,6 +225,13 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
behavior.onRemove(thisBlock, args, superMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSignal(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
@@ -256,4 +263,23 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object playerWillDestroy(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object previous = args[0];
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
Object processed = behavior.playerWillDestroy(thisBlock, args, superMethod);
|
||||
if (processed != previous) {
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnAfterBreak(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
for (AbstractBlockBehavior behavior : this.behaviors) {
|
||||
behavior.spawnAfterBreak(thisBlock, args, superMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,7 @@ public class BukkitFurniture implements Furniture {
|
||||
@NotNull
|
||||
public Object spawnPacket(Player player) {
|
||||
// TODO hasPermission might be slow, can we use a faster way in the future?
|
||||
// TODO Make it based on conditions. So we can dynamically control which furniture should be sent to the player
|
||||
if (!this.minimized || player.hasPermission(FurnitureManager.FURNITURE_ADMIN_NODE)) {
|
||||
return this.cachedSpawnPacket;
|
||||
} else {
|
||||
|
||||
@@ -13,9 +13,6 @@ import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureElement;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.data.FireworkExplosion;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.Material;
|
||||
@@ -72,7 +69,6 @@ public class BukkitFurnitureElement extends AbstractFurnitureElement {
|
||||
List<Object> cachedValues = new ArrayList<>(this.commonValues);
|
||||
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(item(), null);
|
||||
if (item == null) {
|
||||
CraftEngine.instance().debug(() -> "Failed to create furniture element because item " + item() + " not found");
|
||||
item = BukkitItemManager.instance().wrap(new ItemStack(Material.BARRIER));
|
||||
} else {
|
||||
if (color != null) {
|
||||
|
||||
@@ -92,8 +92,8 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
double maxX = x + halfSize + offset.x();
|
||||
double minY = y + offset.y();
|
||||
double maxY = y + baseSize + offset.y();
|
||||
double minZ = z - halfSize + offset.z();
|
||||
double maxZ = z + halfSize + offset.z();
|
||||
double minZ = z - halfSize - offset.z();
|
||||
double maxZ = z + halfSize - offset.z();
|
||||
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
@@ -119,9 +119,9 @@ public class HappyGhastHitBox extends AbstractHitBox {
|
||||
}
|
||||
double scale = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("scale", 1), "scale");
|
||||
boolean hardCollision = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("hard-collision", true), "hard-collision");
|
||||
boolean canUseOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", false), "can-use-item-on");
|
||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", false), "can-be-hit-by-projectile");
|
||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", false), "blocks-building");
|
||||
boolean canUseOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||
return new HappyGhastHitBox(
|
||||
HitBoxFactory.getSeats(arguments),
|
||||
MiscUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position"),
|
||||
|
||||
@@ -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;
|
||||
@@ -47,11 +48,22 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
|
||||
@Override
|
||||
public void delayedInit() {
|
||||
Bukkit.getPluginManager().registerEvents(this, this.plugin.javaPlugin());
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof Projectile projectile) {
|
||||
handleProjectileLoad(projectile);
|
||||
if (VersionHelper.isFolia()) {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof Projectile projectile) {
|
||||
projectile.getScheduler().run(this.plugin.javaPlugin(), (t) -> handleProjectileLoad(projectile), () -> {});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
if (entity instanceof Projectile projectile) {
|
||||
handleProjectileLoad(projectile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,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) {
|
||||
@@ -153,8 +165,13 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
|
||||
this.cachedServerEntity = serverEntity;
|
||||
}
|
||||
|
||||
if (!CoreReflections.clazz$AbstractArrow.isInstance(nmsEntity) || !this.checkInGround) {
|
||||
if (!CoreReflections.clazz$AbstractArrow.isInstance(nmsEntity)) {
|
||||
updateProjectileUpdateInterval(1);
|
||||
} else if (!this.checkInGround) {
|
||||
updateProjectileUpdateInterval(1);
|
||||
if (FastNMS.INSTANCE.field$Entity$wasTouchingWater(nmsEntity)) {
|
||||
this.projectile.getWorld().spawnParticle(ParticleUtils.BUBBLE, this.projectile.getLocation(), 3, 0.1, 0.1, 0.1, 0);
|
||||
}
|
||||
} else {
|
||||
boolean inGround = FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity);
|
||||
if (canSpawnParticle(nmsEntity, inGround)) {
|
||||
|
||||
@@ -6,9 +6,10 @@ import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent;
|
||||
import io.papermc.paper.event.player.AsyncChatDecorateEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
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.InventoryUtils;
|
||||
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,15 +131,8 @@ public class BukkitFontManager extends AbstractFontManager implements Listener {
|
||||
return;
|
||||
}
|
||||
ItemStack result = event.getResult();
|
||||
if (result == null) return;
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ItemStackUtils.isEmpty(result)) return;
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
String renameText;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
@@ -149,7 +143,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()));
|
||||
|
||||
@@ -8,8 +8,8 @@ import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.UniqueKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -21,7 +21,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
private final Object item;
|
||||
private final Object clientItem;
|
||||
|
||||
public BukkitCustomItem(Holder<Key> id, Object item, Object clientItem, Key materialKey, Key clientBoundMaterialKey,
|
||||
public BukkitCustomItem(UniqueKey id, Object item, Object clientItem, Key materialKey, Key clientBoundMaterialKey,
|
||||
List<ItemBehavior> behaviors,
|
||||
List<ItemDataModifier<ItemStack>> modifiers, List<ItemDataModifier<ItemStack>> clientBoundModifiers,
|
||||
ItemSettings settings,
|
||||
@@ -64,7 +64,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder<ItemStack> {
|
||||
private Holder<Key> id;
|
||||
private UniqueKey id;
|
||||
private Key itemKey;
|
||||
private final Object item;
|
||||
private Key clientBoundItemKey;
|
||||
@@ -81,7 +81,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ItemStack> id(Holder<Key> id) {
|
||||
public Builder<ItemStack> id(UniqueKey id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
@@ -149,6 +149,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
@Override
|
||||
public CustomItem<ItemStack> build() {
|
||||
this.modifiers.addAll(this.settings.modifiers());
|
||||
this.clientBoundModifiers.addAll(this.settings.clientBoundModifiers());
|
||||
return new BukkitCustomItem(this.id, this.item, this.clientBoundItem, this.itemKey, this.clientBoundItemKey, List.copyOf(this.behaviors),
|
||||
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory;
|
||||
@@ -11,31 +15,30 @@ 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.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.*;
|
||||
import net.momirealms.craftengine.core.item.modifier.IdModifier;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.pack.AbstractPackManager;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
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.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
static {
|
||||
@@ -50,6 +53,10 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
private final DebugStickListener debugStickListener;
|
||||
private final ArmorEventListener armorEventListener;
|
||||
private final NetworkItemHandler<ItemStack> networkItemHandler;
|
||||
private final Object bedrockItemHolder;
|
||||
private final Item<ItemStack> emptyItem;
|
||||
private final UniqueIdItem<ItemStack> emptyUniqueItem;
|
||||
private Set<Key> lastRegisteredPatterns = Set.of();
|
||||
|
||||
public BukkitItemManager(BukkitCraftEngine plugin) {
|
||||
super(plugin);
|
||||
@@ -61,6 +68,18 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
this.armorEventListener = new ArmorEventListener();
|
||||
this.networkItemHandler = VersionHelper.isOrAbove1_20_5() ? new ModernNetworkItemHandler() : new LegacyNetworkItemHandler();
|
||||
this.registerAllVanillaItems();
|
||||
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();
|
||||
|
||||
ItemStack emptyStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.instance$ItemStack$EMPTY);
|
||||
this.emptyItem = this.wrap(emptyStack);
|
||||
this.emptyUniqueItem = new UniqueIdItem<>(UniqueKey.AIR, this.emptyItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniqueIdItem<ItemStack> uniqueEmptyItem() {
|
||||
return this.emptyUniqueItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,6 +89,17 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
Bukkit.getPluginManager().registerEvents(this.armorEventListener, this.plugin.javaPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> decode(FriendlyByteBuf byteBuf) {
|
||||
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(byteBuf);
|
||||
return this.wrap(FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(FriendlyByteBuf byteBuf, Item<ItemStack> item) {
|
||||
FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(FastNMS.INSTANCE.constructor$FriendlyByteBuf(byteBuf), item.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkItemHandler<ItemStack> networkItemHandler() {
|
||||
return this.networkItemHandler;
|
||||
@@ -79,15 +109,25 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> s2c(Item<ItemStack> item, Player player) {
|
||||
if (item.isEmpty()) return item;
|
||||
return this.networkItemHandler.s2c(item, player).orElse(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> c2s(Item<ItemStack> item) {
|
||||
if (item.isEmpty()) return item;
|
||||
return this.networkItemHandler.c2s(item).orElse(item);
|
||||
}
|
||||
|
||||
public Optional<ItemStack> s2c(ItemStack itemStack, Player player) {
|
||||
try {
|
||||
Item<ItemStack> wrapped = wrap(itemStack);
|
||||
if (wrapped == null) return Optional.empty();
|
||||
if (wrapped.isEmpty()) return Optional.empty();
|
||||
return this.networkItemHandler.s2c(wrapped, player).map(Item::getItem);
|
||||
} catch (Throwable e) {
|
||||
if (Config.debug()) {
|
||||
this.plugin.logger().warn("Failed to handle s2c items.", e);
|
||||
}
|
||||
Debugger.ITEM.warn(() -> "Failed to handle s2c items.", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -95,12 +135,10 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
public Optional<ItemStack> c2s(ItemStack itemStack) {
|
||||
try {
|
||||
Item<ItemStack> wrapped = wrap(itemStack);
|
||||
if (wrapped == null) return Optional.empty();
|
||||
if (wrapped.isEmpty()) return Optional.empty();
|
||||
return this.networkItemHandler.c2s(wrapped).map(Item::getItem);
|
||||
} catch (Throwable e) {
|
||||
if (Config.debug()) {
|
||||
this.plugin.logger().warn("Failed to handle c2s items.", e);
|
||||
}
|
||||
Debugger.COMMON.warn(() -> "Failed to handle c2s items.", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -116,7 +154,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);
|
||||
}
|
||||
@@ -132,6 +170,127 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
HandlerList.unregisterAll(this.itemEventListener);
|
||||
HandlerList.unregisterAll(this.debugStickListener);
|
||||
HandlerList.unregisterAll(this.armorEventListener);
|
||||
this.persistLastRegisteredPatterns();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerArmorTrimPattern(Collection<Key> equipments) {
|
||||
if (equipments.isEmpty()) return;
|
||||
this.lastRegisteredPatterns = new HashSet<>(equipments);
|
||||
// 可能还没加载
|
||||
if (Config.sacrificedAssetId() != null)
|
||||
this.lastRegisteredPatterns.add(Config.sacrificedAssetId());
|
||||
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_PATTERN);
|
||||
try {
|
||||
CoreReflections.field$MappedRegistry$frozen.set(registry, false);
|
||||
for (Key assetId : this.lastRegisteredPatterns) {
|
||||
Object resourceLocation = KeyUtils.toResourceLocation(assetId);
|
||||
Object previous = FastNMS.INSTANCE.method$Registry$getValue(registry, resourceLocation);
|
||||
if (previous == null) {
|
||||
Object trimPattern = createTrimPattern(assetId);
|
||||
Object holder = CoreReflections.method$Registry$registerForHolder.invoke(null, registry, resourceLocation, trimPattern);
|
||||
CoreReflections.method$Holder$Reference$bindValue.invoke(holder, trimPattern);
|
||||
CoreReflections.field$Holder$Reference$tags.set(holder, Set.of());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to register armor trim pattern.", e);
|
||||
} finally {
|
||||
try {
|
||||
CoreReflections.field$MappedRegistry$frozen.set(registry, true);
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void persistLastRegisteredPatterns() {
|
||||
Path persistTrimPatternPath = this.plugin.dataFolderPath()
|
||||
.resolve("cache")
|
||||
.resolve("trim_patterns.json");
|
||||
try {
|
||||
Files.createDirectories(persistTrimPatternPath.getParent());
|
||||
JsonObject json = new JsonObject();
|
||||
JsonArray jsonElements = new JsonArray();
|
||||
for (Key key : this.lastRegisteredPatterns) {
|
||||
jsonElements.add(new JsonPrimitive(key.toString()));
|
||||
}
|
||||
json.add("patterns", jsonElements);
|
||||
if (jsonElements.isEmpty()) {
|
||||
if (Files.exists(persistTrimPatternPath)) {
|
||||
Files.delete(persistTrimPatternPath);
|
||||
}
|
||||
} else {
|
||||
GsonHelper.writeJsonFile(json, persistTrimPatternPath);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.plugin.logger().warn("Failed to persist registered trim patterns.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 需要持久化存储上一次注册的新trim类型,如果注册晚了,加载世界可能导致一些物品损坏
|
||||
private void loadLastRegisteredPatterns() {
|
||||
Path persistTrimPatternPath = this.plugin.dataFolderPath()
|
||||
.resolve("cache")
|
||||
.resolve("trim_patterns.json");
|
||||
if (Files.exists(persistTrimPatternPath) && Files.isRegularFile(persistTrimPatternPath)) {
|
||||
try {
|
||||
JsonObject cache = GsonHelper.readJsonFile(persistTrimPatternPath).getAsJsonObject();
|
||||
JsonArray patterns = cache.getAsJsonArray("patterns");
|
||||
Set<Key> trims = new HashSet<>();
|
||||
for (JsonElement element : patterns) {
|
||||
if (element instanceof JsonPrimitive primitive) {
|
||||
trims.add(Key.of(primitive.getAsString()));
|
||||
}
|
||||
}
|
||||
this.registerArmorTrimPattern(trims);
|
||||
this.lastRegisteredPatterns = trims;
|
||||
} catch (IOException e) {
|
||||
this.plugin.logger().warn("Failed to load registered trim patterns.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerCustomTrimMaterial() {
|
||||
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_MATERIAL);
|
||||
Object resourceLocation = KeyUtils.toResourceLocation(Key.of("minecraft", AbstractPackManager.NEW_TRIM_MATERIAL));
|
||||
Object previous = FastNMS.INSTANCE.method$Registry$getValue(registry, resourceLocation);
|
||||
if (previous == null) {
|
||||
try {
|
||||
CoreReflections.field$MappedRegistry$frozen.set(registry, false);
|
||||
Object trimMaterial = createTrimMaterial();
|
||||
Object holder = CoreReflections.method$Registry$registerForHolder.invoke(null, registry, resourceLocation, trimMaterial);
|
||||
CoreReflections.method$Holder$Reference$bindValue.invoke(holder, trimMaterial);
|
||||
CoreReflections.field$Holder$Reference$tags.set(holder, Set.of());
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to register trim material.", e);
|
||||
} finally {
|
||||
try {
|
||||
CoreReflections.field$MappedRegistry$frozen.set(registry, true);
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object createTrimPattern(Key key) throws ReflectiveOperationException {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
return CoreReflections.constructor$TrimPattern.newInstance(KeyUtils.toResourceLocation(key), CoreReflections.instance$Component$empty, false);
|
||||
} else if (VersionHelper.isOrAbove1_20_2()) {
|
||||
return CoreReflections.constructor$TrimPattern.newInstance(KeyUtils.toResourceLocation(key), this.bedrockItemHolder, CoreReflections.instance$Component$empty, false);
|
||||
} else {
|
||||
return CoreReflections.constructor$TrimPattern.newInstance(KeyUtils.toResourceLocation(key), this.bedrockItemHolder, CoreReflections.instance$Component$empty);
|
||||
}
|
||||
}
|
||||
|
||||
private Object createTrimMaterial() throws ReflectiveOperationException {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
Object assetGroup = CoreReflections.method$MaterialAssetGroup$create.invoke(null, "custom");
|
||||
return CoreReflections.constructor$TrimMaterial.newInstance(assetGroup, CoreReflections.instance$Component$empty);
|
||||
} else if (VersionHelper.isOrAbove1_21_4()) {
|
||||
return CoreReflections.constructor$TrimMaterial.newInstance("custom", this.bedrockItemHolder, Map.of(), CoreReflections.instance$Component$empty);
|
||||
} else {
|
||||
return CoreReflections.constructor$TrimMaterial.newInstance("custom", this.bedrockItemHolder, 0f, Map.of(), CoreReflections.instance$Component$empty);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -142,12 +301,16 @@ 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
|
||||
public ItemStack buildItemStack(Key id, @Nullable Player player) {
|
||||
return Optional.ofNullable(buildCustomItemStack(id, player)).orElseGet(() -> createVanillaItemStack(id));
|
||||
ItemStack customItem = buildCustomItemStack(id, player);
|
||||
if (customItem != null) {
|
||||
return customItem;
|
||||
}
|
||||
return createVanillaItemStack(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,31 +318,30 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
return Optional.ofNullable(customItems.get(id)).map(it -> it.buildItem(player)).orElse(null);
|
||||
}
|
||||
|
||||
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);
|
||||
@Override
|
||||
public Item<ItemStack> createWrappedItem(Key id, @Nullable Player player) {
|
||||
CustomItem<ItemStack> customItem = this.customItems.get(id);
|
||||
if (customItem != null) {
|
||||
return customItem.buildItem(player);
|
||||
}
|
||||
ItemStack itemStack = this.createVanillaItemStack(id);
|
||||
if (itemStack != null) {
|
||||
return wrap(itemStack);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ItemStack createVanillaItemStack(Key id) {
|
||||
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 null;
|
||||
}
|
||||
return FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(item, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> createWrappedItem(Key id, @Nullable Player player) {
|
||||
return Optional.ofNullable(this.customItems.get(id)).map(it -> it.buildItem(player)).orElseGet(() -> {
|
||||
ItemStack itemStack = createVanillaItemStack(id);
|
||||
return wrap(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.emptyItem;
|
||||
return this.factory.wrap(itemStack);
|
||||
}
|
||||
|
||||
@@ -197,7 +359,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(Holder<Key> id, Key materialId, Key clientBoundMaterialId) {
|
||||
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(UniqueKey id, Key materialId, Key clientBoundMaterialId) {
|
||||
Object item = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(materialId));
|
||||
Object clientBoundItem = materialId == clientBoundMaterialId ? item : FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(clientBoundMaterialId));
|
||||
if (item == null) {
|
||||
@@ -220,14 +382,12 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
Key itemKey = KeyUtils.resourceLocationToKey(resourceLocation);
|
||||
if (itemKey.namespace().equals("minecraft")) {
|
||||
VANILLA_ITEMS.add(itemKey);
|
||||
Holder.Reference<Key> holder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(itemKey)
|
||||
.orElseGet(() -> ((WritableRegistry<Key>) BuiltInRegistries.OPTIMIZED_ITEM_ID)
|
||||
.register(new ResourceKey<>(BuiltInRegistries.OPTIMIZED_ITEM_ID.key().location(), itemKey), itemKey));
|
||||
Object mcHolder = ((Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.ITEM, resourceLocation))).get();
|
||||
UniqueKey uniqueKey = UniqueKey.create(itemKey);
|
||||
Object mcHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, resourceLocation)).get();
|
||||
Set<Object> tags = (Set<Object>) CoreReflections.field$Holder$Reference$tags.get(mcHolder);
|
||||
for (Object tag : tags) {
|
||||
Key tagId = Key.of(CoreReflections.field$TagKey$location.get(tag).toString());
|
||||
VANILLA_ITEM_TAGS.computeIfAbsent(tagId, (key) -> new ArrayList<>()).add(holder);
|
||||
VANILLA_ITEM_TAGS.computeIfAbsent(tagId, (key) -> new ArrayList<>()).add(uniqueKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,4 +395,46 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
plugin.logger().warn("Failed to init vanilla items", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 1.20-1.21.4 template 不为空
|
||||
// 1.21.5+ pattern 不为空
|
||||
@Override
|
||||
public Item<ItemStack> applyTrim(Item<ItemStack> base, Item<ItemStack> addition, Item<ItemStack> template, Key pattern) {
|
||||
Optional<?> optionalMaterial = FastNMS.INSTANCE.method$TrimMaterials$getFromIngredient(addition.getLiteralObject());
|
||||
Optional<?> optionalPattern = VersionHelper.isOrAbove1_21_5() ?
|
||||
FastNMS.INSTANCE.method$Registry$getHolderByResourceLocation(FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_PATTERN), KeyUtils.toResourceLocation(pattern)) :
|
||||
FastNMS.INSTANCE.method$TrimPatterns$getFromTemplate(template.getLiteralObject());
|
||||
if (optionalMaterial.isPresent() && optionalPattern.isPresent()) {
|
||||
Object armorTrim = FastNMS.INSTANCE.constructor$ArmorTrim(optionalMaterial.get(), optionalPattern.get());
|
||||
Object previousTrim;
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
previousTrim = base.getExactComponent(ComponentKeys.TRIM);
|
||||
} else {
|
||||
try {
|
||||
previousTrim = VersionHelper.isOrAbove1_20_2() ?
|
||||
((Optional<?>) CoreReflections.method$ArmorTrim$getTrim.invoke(null, FastNMS.INSTANCE.registryAccess(), base.getLiteralObject(), true)).orElse(null) :
|
||||
((Optional<?>) CoreReflections.method$ArmorTrim$getTrim.invoke(null, FastNMS.INSTANCE.registryAccess(), base.getLiteralObject())).orElse(null);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get armor trim", e);
|
||||
return this.emptyItem;
|
||||
}
|
||||
}
|
||||
if (armorTrim.equals(previousTrim)) {
|
||||
return this.emptyItem;
|
||||
}
|
||||
Item<ItemStack> newItem = base.copyWithCount(1);
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
newItem.setExactComponent(ComponentKeys.TRIM, armorTrim);
|
||||
} else {
|
||||
try {
|
||||
CoreReflections.method$ArmorTrim$setTrim.invoke(null, FastNMS.INSTANCE.registryAccess(), newItem.getLiteralObject(), armorTrim);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to set armor trim", e);
|
||||
return this.emptyItem;
|
||||
}
|
||||
}
|
||||
return newItem;
|
||||
}
|
||||
return this.emptyItem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -72,8 +72,18 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
|
||||
return getComponentInternal(type, MRegistryOps.NBT);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public Optional<Tag> getSparrowNBTComponent(Object type) {
|
||||
return getComponentInternal(type, MRegistryOps.SPARROW_NBT);
|
||||
Object componentType = ensureDataComponentType(type);
|
||||
Codec codec = FastNMS.INSTANCE.method$DataComponentType$codec(componentType);
|
||||
try {
|
||||
Object componentData = FastNMS.INSTANCE.method$ItemStack$getComponent(getLiteralObject(), componentType);
|
||||
if (componentData == null) return Optional.empty();
|
||||
DataResult<Tag> result = codec.encodeStart(MRegistryOps.SPARROW_NBT, componentData);
|
||||
return result.result().map(Tag::copy);
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Cannot read component " + type.toString(), t);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ public class LegacyItemWrapper implements ItemWrapper<ItemStack> {
|
||||
getItem().setAmount(amount);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public Object getExactTag(Object... path) {
|
||||
Object compoundTag = FastNMS.INSTANCE.method$ItemStack$getTag(this.nmsStack);
|
||||
if (compoundTag == null) return null;
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
||||
public final class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
||||
|
||||
@Override
|
||||
public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
|
||||
@@ -45,7 +45,7 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
||||
return Optional.of(wrapped);
|
||||
}
|
||||
}
|
||||
CompoundTag networkData = (CompoundTag) wrapped.getNBTTag(NETWORK_ITEM_TAG);
|
||||
CompoundTag networkData = (CompoundTag) wrapped.getTag(NETWORK_ITEM_TAG);
|
||||
if (networkData == null) return Optional.empty();
|
||||
wrapped.removeTag(NETWORK_ITEM_TAG);
|
||||
for (Map.Entry<String, Tag> entry : networkData.entrySet()) {
|
||||
@@ -74,7 +74,7 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
||||
return new OtherItem(wrapped, hasDifferentMaterial).process();
|
||||
} else {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
Tag argumentTag = wrapped.getNBTTag(ArgumentModifier.ARGUMENTS_TAG);
|
||||
Tag argumentTag = wrapped.getTag(ArgumentModifier.ARGUMENTS_TAG);
|
||||
ItemBuildContext context;
|
||||
if (argumentTag instanceof CompoundTag arguments) {
|
||||
ContextHolder.Builder builder = ContextHolder.builder();
|
||||
@@ -87,6 +87,8 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler<ItemStack> {
|
||||
}
|
||||
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
|
||||
modifier.prepareNetworkItem(wrapped, context, tag);
|
||||
}
|
||||
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
|
||||
modifier.apply(wrapped, context);
|
||||
}
|
||||
if (Config.interceptItem()) {
|
||||
|
||||
@@ -29,7 +29,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
|
||||
@Override
|
||||
public Optional<Item<ItemStack>> c2s(Item<ItemStack> wrapped) {
|
||||
Tag customData = wrapped.getNBTComponent(ComponentTypes.CUSTOM_DATA);
|
||||
Tag customData = wrapped.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA);
|
||||
if (!(customData instanceof CompoundTag compoundTag)) return Optional.empty();
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||
boolean hasDifferentMaterial = false;
|
||||
@@ -75,7 +75,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
if (!Config.interceptItem() && !hasDifferentMaterial) return Optional.empty();
|
||||
return new OtherItem(wrapped, hasDifferentMaterial).process();
|
||||
} else {
|
||||
CompoundTag customData = Optional.ofNullable(wrapped.getNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag());
|
||||
CompoundTag customData = Optional.ofNullable(wrapped.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag());
|
||||
CompoundTag arguments = customData.getCompound(ArgumentModifier.ARGUMENTS_TAG);
|
||||
ItemBuildContext context;
|
||||
if (arguments == null) {
|
||||
@@ -90,6 +90,8 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
CompoundTag tag = new CompoundTag();
|
||||
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
|
||||
modifier.prepareNetworkItem(wrapped, context, tag);
|
||||
}
|
||||
for (ItemDataModifier<ItemStack> modifier : customItem.clientBoundDataModifiers()) {
|
||||
modifier.apply(wrapped, context);
|
||||
}
|
||||
if (Config.interceptItem()) {
|
||||
@@ -174,7 +176,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
}
|
||||
|
||||
public static boolean processModernItemName(Item<ItemStack> item, Supplier<CompoundTag> tag) {
|
||||
Tag nameTag = item.getNBTComponent(ComponentTypes.ITEM_NAME);
|
||||
Tag nameTag = item.getSparrowNBTComponent(ComponentTypes.ITEM_NAME);
|
||||
if (nameTag == null) return false;
|
||||
String tagStr = nameTag.getAsString();
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(tagStr);
|
||||
@@ -187,7 +189,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
}
|
||||
|
||||
public static boolean processModernCustomName(Item<ItemStack> item, Supplier<CompoundTag> tag) {
|
||||
Tag nameTag = item.getNBTComponent(ComponentTypes.CUSTOM_NAME);
|
||||
Tag nameTag = item.getSparrowNBTComponent(ComponentTypes.CUSTOM_NAME);
|
||||
if (nameTag == null) return false;
|
||||
String tagStr = nameTag.getAsString();
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(tagStr);
|
||||
@@ -200,7 +202,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
}
|
||||
|
||||
public static boolean processModernLore(Item<ItemStack> item, Supplier<CompoundTag> tagSupplier) {
|
||||
Tag loreTag = item.getNBTComponent(ComponentTypes.LORE);
|
||||
Tag loreTag = item.getSparrowNBTComponent(ComponentTypes.LORE);
|
||||
boolean changed = false;
|
||||
if (!(loreTag instanceof ListTag listTag)) {
|
||||
return false;
|
||||
@@ -252,7 +254,7 @@ public final class ModernNetworkItemHandler implements NetworkItemHandler<ItemSt
|
||||
this.globalChanged = true;
|
||||
}
|
||||
if (this.globalChanged) {
|
||||
CompoundTag customData = Optional.ofNullable(this.item.getNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag());
|
||||
CompoundTag customData = Optional.ofNullable(this.item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA)).map(CompoundTag.class::cast).orElse(new CompoundTag());
|
||||
customData.put(NETWORK_ITEM_TAG, getOrCreateTag());
|
||||
this.item.setNBTComponent(ComponentKeys.CUSTOM_DATA, customData);
|
||||
return Optional.of(this.item);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -61,7 +61,7 @@ public class CompostableItemBehavior extends ItemBehavior {
|
||||
context.getLevel().levelEvent(WorldEvents.COMPOSTER_COMPOSTS, context.getClickedPos(), willRaise ? 1 : 0);
|
||||
((World) context.getLevel().platformWorld()).sendGameEvent((Entity) context.getPlayer().platformPlayer(), GameEvent.BLOCK_CHANGE, new Vector(block.x() + 0.5, block.y() + 0.5, block.z() + 0.5));
|
||||
if (currentLevel + 1 == 7) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), blockOwner, 20);
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), blockOwner, 20);
|
||||
}
|
||||
if (!context.getPlayer().canInstabuild()) {
|
||||
context.getItem().shrink(1);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
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;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.UniqueKey;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -40,7 +45,7 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
case "1.21.4" -> {
|
||||
return new ComponentItemFactory1_21_4(plugin);
|
||||
}
|
||||
case "1.21.5", "1.21.6", "1.22", "1.22.1" -> {
|
||||
case "1.21.5", "1.21.6", "1.21.7", "1.22", "1.22.1" -> {
|
||||
return new ComponentItemFactory1_21_5(plugin);
|
||||
}
|
||||
default -> throw new IllegalStateException("Unsupported server version: " + plugin.serverVersion());
|
||||
@@ -55,13 +60,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
|
||||
@@ -74,6 +80,11 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
return item.getItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UniqueKey recipeIngredientID(W item) {
|
||||
return UniqueKey.create(id(item));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean is(W item, Key itemTag) {
|
||||
Object literalObject = item.getLiteralObject();
|
||||
@@ -111,7 +122,12 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tag getNBTComponent(W item, Object type) {
|
||||
public Object getNBTComponent(W item, Object type) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tag getSparrowNBTComponent(W item, Object type) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@@ -130,6 +146,11 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setExactComponent(W item, Object type, Object value) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasComponent(W item, Object type) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
|
||||
@@ -20,7 +20,10 @@ import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemWrapper> {
|
||||
|
||||
@@ -28,6 +31,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());
|
||||
@@ -64,8 +72,29 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
return currentObj;
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Override
|
||||
protected Tag getNBTTag(ComponentItemWrapper item, Object... path) {
|
||||
protected Object getExactTag(ComponentItemWrapper item, Object... path) {
|
||||
Object customData = getExactComponent(item, ComponentTypes.CUSTOM_DATA);
|
||||
if (customData == null) return null;
|
||||
Object currentTag = FastNMS.INSTANCE.method$CustomData$getUnsafe(customData);
|
||||
for (int i = 0; i < path.length; i++) {
|
||||
Object pathSegment = path[i];
|
||||
if (pathSegment == null) return null;
|
||||
currentTag = FastNMS.INSTANCE.method$CompoundTag$get(currentTag, path[i].toString());
|
||||
if (currentTag == null) return null;
|
||||
if (i == path.length - 1) {
|
||||
return currentTag;
|
||||
}
|
||||
if (!CoreReflections.clazz$CompoundTag.isInstance(currentTag)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tag getTag(ComponentItemWrapper item, Object... path) {
|
||||
CompoundTag rootTag = (CompoundTag) item.getSparrowNBTComponent(ComponentTypes.CUSTOM_DATA).orElse(null);
|
||||
if (rootTag == null) return null;
|
||||
Tag currentTag = rootTag;
|
||||
@@ -132,7 +161,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
|
||||
@Override
|
||||
protected boolean hasTag(ComponentItemWrapper item, Object... path) {
|
||||
return getNBTTag(item, path) != null;
|
||||
return getTag(item, path) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,6 +242,11 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
return item.getComponentExact(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setExactComponent(ComponentItemWrapper item, Object type, Object value) {
|
||||
item.setComponentExact(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getJavaComponent(ComponentItemWrapper item, Object type) {
|
||||
return item.getJavaComponent(type).orElse(null);
|
||||
@@ -224,7 +258,12 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tag getNBTComponent(ComponentItemWrapper item, Object type) {
|
||||
public Object getNBTComponent(ComponentItemWrapper item, Object type) {
|
||||
return item.getNBTComponent(type).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tag getSparrowNBTComponent(ComponentItemWrapper item, Object type) {
|
||||
return item.getSparrowNBTComponent(type).orElse(null);
|
||||
}
|
||||
|
||||
@@ -462,8 +501,8 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
item.resetComponent(ComponentTypes.TRIM);
|
||||
} else {
|
||||
item.setJavaComponent(ComponentTypes.TRIM, Map.of(
|
||||
"pattern", trim.pattern(),
|
||||
"material", trim.material()
|
||||
"pattern", trim.pattern().asString(),
|
||||
"material", trim.material().asString()
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -476,7 +515,7 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> trimMap = (Map<String, String>) trim.get();
|
||||
return Optional.of(new Trim(trimMap.get("pattern"), trimMap.get("material")));
|
||||
return Optional.of(new Trim(Key.of(trimMap.get("pattern")), Key.of(trimMap.get("material"))));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -2,9 +2,14 @@ package net.momirealms.craftengine.bukkit.item.factory;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
|
||||
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||
import net.momirealms.craftengine.core.entity.EquipmentSlot;
|
||||
import net.momirealms.craftengine.core.item.setting.EquipmentData;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ComponentItemFactory1_21_2 extends ComponentItemFactory1_21 {
|
||||
@@ -52,6 +57,18 @@ public class ComponentItemFactory1_21_2 extends ComponentItemFactory1_21 {
|
||||
|
||||
@Override
|
||||
protected Optional<EquipmentData> equippable(ComponentItemWrapper item) {
|
||||
throw new UnsupportedOperationException("Not implemented yet.");
|
||||
Optional<Object> optionalData = item.getJavaComponent(ComponentTypes.EQUIPPABLE);
|
||||
if (optionalData.isEmpty()) return Optional.empty();
|
||||
Map<String, Object> data = MiscUtils.castToMap(optionalData.get(), false);
|
||||
String slot = data.get("slot").toString();
|
||||
return Optional.of(new EquipmentData(
|
||||
EquipmentSlot.valueOf(slot.toUpperCase(Locale.ENGLISH)),
|
||||
data.containsKey("asset_id") ? Key.of((String) data.get("asset_id")) : null,
|
||||
(boolean) data.getOrDefault("dispensable", true),
|
||||
(boolean) data.getOrDefault("swappable", true),
|
||||
(boolean) data.getOrDefault("damage_on_hurt", true),
|
||||
(boolean) data.getOrDefault("equip_on_interact", false),
|
||||
data.containsKey("camera_overlay") ? Key.of((String) data.get("camera_overlay")) : null
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,15 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Tag getNBTTag(LegacyItemWrapper item, Object... path) {
|
||||
protected Tag getTag(LegacyItemWrapper item, Object... path) {
|
||||
return item.getNBTTag(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getExactTag(LegacyItemWrapper item, Object... path) {
|
||||
return item.getExactTag(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasTag(LegacyItemWrapper item, Object... path) {
|
||||
return item.hasTag(path);
|
||||
@@ -57,6 +62,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);
|
||||
@@ -258,8 +268,8 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
|
||||
item.remove("Trim");
|
||||
return;
|
||||
}
|
||||
item.setTag(trim.material(), "Trim", "material");
|
||||
item.setTag(trim.pattern(), "Trim", "pattern");
|
||||
item.setTag(trim.material().asString(), "Trim", "material");
|
||||
item.setTag(trim.pattern().asString(), "Trim", "pattern");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -299,7 +309,7 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
|
||||
String material = item.getJavaTag("Trim", "material");
|
||||
String pattern = item.getJavaTag("Trim", "pattern");
|
||||
if (material == null || pattern == null) return Optional.empty();
|
||||
return Optional.of(new Trim(material, pattern));
|
||||
return Optional.of(new Trim(Key.of(material), Key.of(pattern)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -2,6 +2,9 @@ package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.papermc.paper.potion.PotionMix;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.CloneableConstantItem;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
@@ -13,18 +16,14 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOp
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.MaterialUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.RecipeUtils;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.*;
|
||||
import net.momirealms.craftengine.core.item.recipe.*;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.vanilla.*;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.HeptaFunction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
@@ -135,11 +134,34 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
Object finalNmsRecipe = nmsRecipe;
|
||||
return () -> registerNMSSmithingRecipe(finalNmsRecipe);
|
||||
} catch (InvalidRecipeIngredientException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to convert smithing transform recipe", e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
MIXED_RECIPE_CONVERTORS.put(RecipeTypes.SMITHING_TRIM, (BukkitRecipeConvertor<CustomSmithingTrimRecipe<ItemStack>>) (id, recipe) -> {
|
||||
try {
|
||||
Object nmsRecipe = createMinecraftSmithingTrimRecipe(recipe);
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
nmsRecipe = CoreReflections.constructor$RecipeHolder.newInstance(
|
||||
CraftBukkitReflections.method$CraftRecipe$toMinecraft.invoke(null, new NamespacedKey(id.namespace(), id.value())), nmsRecipe);
|
||||
} else if (VersionHelper.isOrAbove1_20_2()) {
|
||||
nmsRecipe = CoreReflections.constructor$RecipeHolder.newInstance(KeyUtils.toResourceLocation(id), nmsRecipe);
|
||||
} else {
|
||||
Object finalNmsRecipe0 = nmsRecipe;
|
||||
return () -> registerNMSSmithingRecipe(finalNmsRecipe0);
|
||||
}
|
||||
Object finalNmsRecipe = nmsRecipe;
|
||||
return () -> registerNMSSmithingRecipe(finalNmsRecipe);
|
||||
} catch (InvalidRecipeIngredientException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to convert smithing trim recipe", e);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// TODO DO NOT USE BUKKIT RECIPE AS BRIDGE IN FUTURE VERSIONS, WE SHOULD DIRECTLY CONSTRUCT THOSE NMS RECIPES
|
||||
MIXED_RECIPE_CONVERTORS.put(RecipeTypes.SHAPED, (BukkitRecipeConvertor<CustomShapedRecipe<ItemStack>>) (id, recipe) -> {
|
||||
ShapedRecipe shapedRecipe = new ShapedRecipe(new NamespacedKey(id.namespace(), id.value()), recipe.result(ItemBuildContext.EMPTY));
|
||||
@@ -220,8 +242,8 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
});
|
||||
MIXED_RECIPE_CONVERTORS.put(RecipeTypes.STONECUTTING, (BukkitRecipeConvertor<CustomStoneCuttingRecipe<ItemStack>>) (id, recipe) -> {
|
||||
List<ItemStack> itemStacks = new ArrayList<>();
|
||||
for (Holder<Key> item : recipe.ingredient().items()) {
|
||||
itemStacks.add(BukkitItemManager.instance().buildItemStack(item.value(), null));
|
||||
for (UniqueKey item : recipe.ingredient().items()) {
|
||||
itemStacks.add(BukkitItemManager.instance().buildItemStack(item.key(), null));
|
||||
}
|
||||
StonecuttingRecipe stonecuttingRecipe = new StonecuttingRecipe(
|
||||
new NamespacedKey(id.namespace(), id.value()), recipe.result(ItemBuildContext.EMPTY),
|
||||
@@ -252,6 +274,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
private Object stolenFeatureFlagSet;
|
||||
// Some delayed tasks on main thread
|
||||
private final List<Runnable> delayedTasksOnMainThread = new ArrayList<>();
|
||||
private final Map<Key, PotionMix> brewingRecipes = new HashMap<>();
|
||||
|
||||
public BukkitRecipeManager(BukkitCraftEngine plugin) {
|
||||
instance = this;
|
||||
@@ -303,16 +326,16 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
@Override
|
||||
public void unload() {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
super.unload();
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
this.plugin.scheduler().executeSync(() -> {
|
||||
try {
|
||||
CoreReflections.method$RecipeManager$finalizeRecipeLoading.invoke(nmsRecipeManager);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to unregister recipes", e);
|
||||
}
|
||||
});
|
||||
// 安排卸载任务,这些任务会在load后执行。如果没有load说明服务器已经关闭了,那就不需要管卸载了。
|
||||
if (!Bukkit.isStopping()) {
|
||||
for (Map.Entry<Key, Recipe<ItemStack>> entry : this.byId.entrySet()) {
|
||||
Key id = entry.getKey();
|
||||
if (isDataPackRecipe(id)) continue;
|
||||
boolean isBrewingRecipe = entry.getValue() instanceof CustomBrewingRecipe<ItemStack>;
|
||||
this.delayedTasksOnMainThread.add(() -> this.unregisterPlatformRecipe(id, isBrewingRecipe));
|
||||
}
|
||||
}
|
||||
super.unload();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -325,6 +348,12 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
public void disable() {
|
||||
unload();
|
||||
CE_RECIPE_2_NMS_HOLDER.clear();
|
||||
// 不是服务器关闭造成disable,那么需要把配方卸载干净
|
||||
if (!Bukkit.isStopping()) {
|
||||
for (Runnable task : this.delayedTasksOnMainThread) {
|
||||
task.run();
|
||||
}
|
||||
}
|
||||
HandlerList.unregisterAll(this.recipeEventListener);
|
||||
if (this.crafterEventListener != null) {
|
||||
HandlerList.unregisterAll(this.crafterEventListener);
|
||||
@@ -332,19 +361,42 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unregisterPlatformRecipe(Key key) {
|
||||
unregisterNMSRecipe(new NamespacedKey(key.namespace(), key.value()));
|
||||
protected void unregisterPlatformRecipe(Key key, boolean isBrewingRecipe) {
|
||||
if (isBrewingRecipe) {
|
||||
Bukkit.getPotionBrewer().removePotionMix(new NamespacedKey(key.namespace(), key.value()));
|
||||
} else {
|
||||
unregisterNMSRecipe(new NamespacedKey(key.namespace(), key.value()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPlatformRecipe(Key id, Recipe<ItemStack> recipe) {
|
||||
try {
|
||||
Runnable converted = findNMSRecipeConvertor(recipe).convert(id, recipe);
|
||||
if (converted != null) {
|
||||
this.delayedTasksOnMainThread.add(converted);
|
||||
if (recipe instanceof CustomBrewingRecipe<ItemStack> brewingRecipe) {
|
||||
PotionMix potionMix = new PotionMix(new NamespacedKey(id.namespace(), id.value()),
|
||||
brewingRecipe.result(ItemBuildContext.EMPTY),
|
||||
PotionMix.createPredicateChoice(container -> {
|
||||
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(container);
|
||||
return brewingRecipe.container().test(new UniqueIdItem<>(wrapped.recipeIngredientId(), wrapped));
|
||||
}),
|
||||
PotionMix.createPredicateChoice(ingredient -> {
|
||||
Item<ItemStack> wrapped = this.plugin.itemManager().wrap(ingredient);
|
||||
return brewingRecipe.ingredient().test(new UniqueIdItem<>(wrapped.recipeIngredientId(), wrapped));
|
||||
})
|
||||
);
|
||||
this.delayedTasksOnMainThread.add(() -> {
|
||||
Bukkit.getPotionBrewer().addPotionMix(potionMix);
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
Runnable converted = findNMSRecipeConvertor(recipe).convert(id, recipe);
|
||||
if (converted != null) {
|
||||
this.delayedTasksOnMainThread.add(converted);
|
||||
}
|
||||
} catch (InvalidRecipeIngredientException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.recipe.invalid_ingredient", e.ingredient());
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to convert recipe " + id, e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to convert recipe " + id, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,11 +441,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
// continue;
|
||||
// }
|
||||
if (Config.disableAllVanillaRecipes()) {
|
||||
this.delayedTasksOnMainThread.add(() -> unregisterPlatformRecipe(id));
|
||||
this.delayedTasksOnMainThread.add(() -> unregisterPlatformRecipe(id, false));
|
||||
continue;
|
||||
}
|
||||
if (hasDisabledAny && Config.disabledVanillaRecipes().contains(id)) {
|
||||
this.delayedTasksOnMainThread.add(() -> unregisterPlatformRecipe(id));
|
||||
this.delayedTasksOnMainThread.add(() -> unregisterPlatformRecipe(id, false));
|
||||
continue;
|
||||
}
|
||||
markAsDataPackRecipe(id);
|
||||
@@ -429,6 +481,10 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
VanillaSmithingTransformRecipe recipe = this.recipeReader.readSmithingTransform(jsonObject);
|
||||
handleDataPackSmithingTransform(id, recipe, (this.delayedTasksOnMainThread::add));
|
||||
}
|
||||
case "minecraft:smithing_trim" -> {
|
||||
VanillaSmithingTrimRecipe recipe = this.recipeReader.readSmithingTrim(jsonObject);
|
||||
handleDataPackSmithingTrim(id, recipe, (this.delayedTasksOnMainThread::add));
|
||||
}
|
||||
case "minecraft:stonecutting" -> {
|
||||
VanillaStoneCuttingRecipe recipe = this.recipeReader.readStoneCutting(jsonObject);
|
||||
handleDataPackStoneCuttingRecipe(id, recipe);
|
||||
@@ -494,13 +550,13 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
|
||||
private void handleDataPackStoneCuttingRecipe(Key id, VanillaStoneCuttingRecipe recipe) {
|
||||
ItemStack result = createDataPackResultStack(recipe.result());
|
||||
Set<Holder<Key>> holders = new HashSet<>();
|
||||
Set<UniqueKey> holders = new HashSet<>();
|
||||
for (String item : recipe.ingredient()) {
|
||||
if (item.charAt(0) == '#') {
|
||||
Key tag = Key.from(item.substring(1));
|
||||
holders.addAll(this.plugin.itemManager().tagToItems(tag));
|
||||
} else {
|
||||
holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow());
|
||||
holders.add(UniqueKey.create(Key.from(item)));
|
||||
}
|
||||
}
|
||||
CustomStoneCuttingRecipe<ItemStack> ceRecipe = new CustomStoneCuttingRecipe<>(
|
||||
@@ -516,7 +572,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
boolean hasCustomItemInTag = false;
|
||||
List<Ingredient<ItemStack>> ingredientList = new ArrayList<>();
|
||||
for (List<String> list : recipe.ingredients()) {
|
||||
Set<Holder<Key>> holders = new HashSet<>();
|
||||
Set<UniqueKey> holders = new HashSet<>();
|
||||
for (String item : list) {
|
||||
if (item.charAt(0) == '#') {
|
||||
Key tag = Key.of(item.substring(1));
|
||||
@@ -527,7 +583,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
holders.addAll(plugin.itemManager().tagToItems(tag));
|
||||
} else {
|
||||
holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow());
|
||||
holders.add(UniqueKey.create(Key.from(item)));
|
||||
}
|
||||
}
|
||||
ingredientList.add(Ingredient.of(holders));
|
||||
@@ -552,7 +608,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
boolean hasCustomItemInTag = false;
|
||||
Map<Character, Ingredient<ItemStack>> ingredients = new HashMap<>();
|
||||
for (Map.Entry<Character, List<String>> entry : recipe.ingredients().entrySet()) {
|
||||
Set<Holder<Key>> holders = new HashSet<>();
|
||||
Set<UniqueKey> holders = new HashSet<>();
|
||||
for (String item : entry.getValue()) {
|
||||
if (item.charAt(0) == '#') {
|
||||
Key tag = Key.from(item.substring(1));
|
||||
@@ -563,7 +619,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
}
|
||||
holders.addAll(plugin.itemManager().tagToItems(tag));
|
||||
} else {
|
||||
holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow());
|
||||
holders.add(UniqueKey.create(Key.from(item)));
|
||||
}
|
||||
}
|
||||
ingredients.put(entry.getKey(), Ingredient.of(holders));
|
||||
@@ -589,7 +645,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
Consumer<Runnable> callback) {
|
||||
NamespacedKey key = new NamespacedKey(id.namespace(), id.value());
|
||||
ItemStack result = createDataPackResultStack(recipe.result());
|
||||
Set<Holder<Key>> holders = new HashSet<>();
|
||||
Set<UniqueKey> holders = new HashSet<>();
|
||||
boolean hasCustomItemInTag = readVanillaIngredients(false, recipe.ingredient(), holders::add);
|
||||
CustomCookingRecipe<ItemStack> ceRecipe = constructor2.apply(
|
||||
id, recipe.category(), recipe.group(),
|
||||
@@ -612,11 +668,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
ItemStack result = createDataPackResultStack(recipe.result());
|
||||
boolean hasCustomItemInTag;
|
||||
|
||||
Set<Holder<Key>> additionHolders = new HashSet<>();
|
||||
Set<UniqueKey> additionHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(false, recipe.addition(), additionHolders::add);
|
||||
Set<Holder<Key>> templateHolders = new HashSet<>();
|
||||
Set<UniqueKey> templateHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.template(), templateHolders::add);
|
||||
Set<Holder<Key>> baseHolders = new HashSet<>();
|
||||
Set<UniqueKey> baseHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.base(), baseHolders::add);
|
||||
|
||||
CustomSmithingTransformRecipe<ItemStack> ceRecipe = new CustomSmithingTransformRecipe<>(
|
||||
@@ -639,7 +695,36 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
this.registerInternalRecipe(id, ceRecipe);
|
||||
}
|
||||
|
||||
private boolean readVanillaIngredients(boolean hasCustomItemInTag, List<String> ingredients, Consumer<Holder<Key>> holderConsumer) {
|
||||
private void handleDataPackSmithingTrim(Key id, VanillaSmithingTrimRecipe recipe, Consumer<Runnable> callback) {
|
||||
NamespacedKey key = new NamespacedKey(id.namespace(), id.value());
|
||||
|
||||
boolean hasCustomItemInTag;
|
||||
Set<UniqueKey> additionHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(false, recipe.addition(), additionHolders::add);
|
||||
Set<UniqueKey> templateHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.template(), templateHolders::add);
|
||||
Set<UniqueKey> baseHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.base(), baseHolders::add);
|
||||
|
||||
CustomSmithingTrimRecipe<ItemStack> ceRecipe = new CustomSmithingTrimRecipe<>(
|
||||
id,
|
||||
Ingredient.of(baseHolders),
|
||||
Ingredient.of(templateHolders),
|
||||
Ingredient.of(additionHolders),
|
||||
Optional.ofNullable(recipe.pattern()).map(Key::of).orElse(null)
|
||||
);
|
||||
|
||||
if (hasCustomItemInTag) {
|
||||
Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe);
|
||||
callback.accept(() -> {
|
||||
unregisterNMSRecipe(key);
|
||||
converted.run();
|
||||
});
|
||||
}
|
||||
this.registerInternalRecipe(id, ceRecipe);
|
||||
}
|
||||
|
||||
private boolean readVanillaIngredients(boolean hasCustomItemInTag, List<String> ingredients, Consumer<UniqueKey> holderConsumer) {
|
||||
for (String item : ingredients) {
|
||||
if (item.charAt(0) == '#') {
|
||||
Key tag = Key.from(item.substring(1));
|
||||
@@ -648,11 +733,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
hasCustomItemInTag = true;
|
||||
}
|
||||
}
|
||||
for (Holder<Key> holder : this.plugin.itemManager().tagToItems(tag)) {
|
||||
for (UniqueKey holder : this.plugin.itemManager().tagToItems(tag)) {
|
||||
holderConsumer.accept(holder);
|
||||
}
|
||||
} else {
|
||||
holderConsumer.accept(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow());
|
||||
holderConsumer.accept(UniqueKey.create(Key.from(item)));
|
||||
}
|
||||
}
|
||||
return hasCustomItemInTag;
|
||||
@@ -695,8 +780,8 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
|
||||
private static RecipeChoice ingredientToBukkitRecipeChoice(Ingredient<ItemStack> ingredient) {
|
||||
Set<Material> materials = new HashSet<>();
|
||||
for (Holder<Key> holder : ingredient.items()) {
|
||||
materials.add(getMaterialById(holder.value()));
|
||||
for (UniqueKey holder : ingredient.items()) {
|
||||
materials.add(getMaterialById(holder.key()));
|
||||
}
|
||||
return new RecipeChoice.MaterialChoice(new ArrayList<>(materials));
|
||||
}
|
||||
@@ -707,15 +792,21 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
return material;
|
||||
}
|
||||
Optional<CustomItem<ItemStack>> optionalItem = BukkitItemManager.instance().getCustomItem(key);
|
||||
return optionalItem.map(itemStackCustomItem -> MaterialUtils.getMaterial(itemStackCustomItem.material())).orElse(null);
|
||||
return optionalItem.map(itemStackCustomItem -> MaterialUtils.getMaterial(itemStackCustomItem.material())).orElseThrow(() -> new InvalidRecipeIngredientException(key.asString()));
|
||||
}
|
||||
|
||||
private static List<Object> getIngredientLooks(List<Holder<Key>> holders) {
|
||||
private static List<Object> getIngredientLooks(List<UniqueKey> holders) {
|
||||
List<Object> itemStacks = new ArrayList<>();
|
||||
for (Holder<Key> holder : holders) {
|
||||
ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1);
|
||||
Object nmsStack = FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack);
|
||||
itemStacks.add(nmsStack);
|
||||
for (UniqueKey holder : holders) {
|
||||
Optional<? extends BuildableItem<ItemStack>> buildableItem = BukkitItemManager.instance().getBuildableItem(holder.key());
|
||||
if (buildableItem.isPresent()) {
|
||||
ItemStack itemStack = buildableItem.get().buildItemStack(ItemBuildContext.EMPTY, 1);
|
||||
Object nmsStack = FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack);
|
||||
itemStacks.add(nmsStack);
|
||||
} else {
|
||||
Item<ItemStack> barrier = BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, null);
|
||||
barrier.customNameJson(AdventureHelper.componentToJson(Component.text(holder.key().asString()).color(NamedTextColor.RED)));
|
||||
}
|
||||
}
|
||||
return itemStacks;
|
||||
}
|
||||
@@ -887,4 +978,35 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object createMinecraftSmithingTrimRecipe(CustomSmithingTrimRecipe<ItemStack> recipe) throws ReflectiveOperationException {
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_PATTERN);
|
||||
return CoreReflections.constructor$SmithingTrimRecipe.newInstance(
|
||||
toMinecraftIngredient(recipe.template()),
|
||||
toMinecraftIngredient(recipe.base()),
|
||||
toMinecraftIngredient(recipe.addition()),
|
||||
FastNMS.INSTANCE.method$Registry$getHolderByResourceLocation(registry, KeyUtils.toResourceLocation(recipe.pattern())).orElseThrow(() -> new RuntimeException("Pattern " + recipe.pattern() + " doesn't exist."))
|
||||
);
|
||||
} else if (VersionHelper.isOrAbove1_21_2()) {
|
||||
return CoreReflections.constructor$SmithingTrimRecipe.newInstance(
|
||||
toOptionalMinecraftIngredient(recipe.template()),
|
||||
toOptionalMinecraftIngredient(recipe.base()),
|
||||
toOptionalMinecraftIngredient(recipe.addition())
|
||||
);
|
||||
} else if (VersionHelper.isOrAbove1_20_2()) {
|
||||
return CoreReflections.constructor$SmithingTrimRecipe.newInstance(
|
||||
toMinecraftIngredient(recipe.template()),
|
||||
toMinecraftIngredient(recipe.base()),
|
||||
toMinecraftIngredient(recipe.addition())
|
||||
);
|
||||
} else {
|
||||
return CoreReflections.constructor$SmithingTrimRecipe.newInstance(
|
||||
KeyUtils.toResourceLocation(recipe.id()),
|
||||
toMinecraftIngredient(recipe.template()),
|
||||
toMinecraftIngredient(recipe.base()),
|
||||
toMinecraftIngredient(recipe.addition())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
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;
|
||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.block.Crafter;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -23,10 +21,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CrafterEventListener implements Listener {
|
||||
private static final OptimizedIDItem<ItemStack> EMPTY = new OptimizedIDItem<>(null, null);
|
||||
private final ItemManager<ItemStack> itemManager;
|
||||
private final BukkitRecipeManager recipeManager;
|
||||
private final BukkitCraftEngine plugin;
|
||||
@@ -56,40 +52,33 @@ public class CrafterEventListener implements Listener {
|
||||
Inventory inventory = crafter.getInventory();
|
||||
ItemStack[] ingredients = inventory.getStorageContents();
|
||||
|
||||
List<OptimizedIDItem<ItemStack>> optimizedIDItems = new ArrayList<>();
|
||||
List<UniqueIdItem<ItemStack>> uniqueIdItems = new ArrayList<>();
|
||||
for (ItemStack itemStack : ingredients) {
|
||||
if (ItemUtils.isEmpty(itemStack)) {
|
||||
optimizedIDItems.add(EMPTY);
|
||||
if (ItemStackUtils.isEmpty(itemStack)) {
|
||||
uniqueIdItems.add(this.itemManager.uniqueEmptyItem());
|
||||
} else {
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
// an invalid item is used in recipe, we disallow it
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
} else {
|
||||
optimizedIDItems.add(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
}
|
||||
uniqueIdItems.add(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
}
|
||||
}
|
||||
|
||||
CraftingInput<ItemStack> input;
|
||||
if (ingredients.length == 9) {
|
||||
input = CraftingInput.of(3, 3, optimizedIDItems);
|
||||
input = CraftingInput.of(3, 3, uniqueIdItems);
|
||||
} else if (ingredients.length == 4) {
|
||||
input = CraftingInput.of(2, 2, optimizedIDItems);
|
||||
input = CraftingInput.of(2, 2, uniqueIdItems);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPELESS, input);
|
||||
if (ceRecipe != null) {
|
||||
event.setResult(ceRecipe.result(ItemBuildContext.EMPTY));
|
||||
event.setResult(ceRecipe.assemble(input, ItemBuildContext.EMPTY));
|
||||
return;
|
||||
}
|
||||
ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input);
|
||||
if (ceRecipe != null) {
|
||||
event.setResult(ceRecipe.result(ItemBuildContext.EMPTY));
|
||||
event.setResult(ceRecipe.assemble(input, ItemBuildContext.EMPTY));
|
||||
return;
|
||||
}
|
||||
// clear result if not met
|
||||
|
||||
@@ -12,23 +12,21 @@ 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.InventoryUtils;
|
||||
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;
|
||||
import net.momirealms.craftengine.core.item.recipe.*;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
||||
import net.momirealms.craftengine.core.item.setting.AnvilRepairItem;
|
||||
import net.momirealms.craftengine.core.item.setting.ItemEquipment;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Campfire;
|
||||
@@ -40,6 +38,7 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
import org.bukkit.inventory.view.AnvilView;
|
||||
@@ -51,7 +50,6 @@ import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class RecipeEventListener implements Listener {
|
||||
private static final OptimizedIDItem<ItemStack> EMPTY = new OptimizedIDItem<>(null, null);
|
||||
private final ItemManager<ItemStack> itemManager;
|
||||
private final BukkitRecipeManager recipeManager;
|
||||
private final BukkitCraftEngine plugin;
|
||||
@@ -74,13 +72,9 @@ 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) {
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(item);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) return;
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), item));
|
||||
if (ItemStackUtils.isEmpty(item)) return;
|
||||
if (ItemStackUtils.isEmpty(fuelStack)) {
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(item));
|
||||
Key recipeType;
|
||||
if (furnaceInventory.getType() == InventoryType.FURNACE) {
|
||||
recipeType = RecipeTypes.SMELTING;
|
||||
@@ -90,16 +84,16 @@ public class RecipeEventListener implements Listener {
|
||||
recipeType = RecipeTypes.SMOKING;
|
||||
}
|
||||
|
||||
Recipe<ItemStack> ceRecipe = recipeManager.recipeByInput(recipeType, input);
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(recipeType, input);
|
||||
// The item is an ingredient, we should never consider it as fuel firstly
|
||||
if (ceRecipe != null) return;
|
||||
|
||||
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)) {
|
||||
@@ -160,11 +154,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;
|
||||
@@ -187,11 +181,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;
|
||||
@@ -344,7 +338,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(
|
||||
@@ -357,12 +351,7 @@ public class RecipeEventListener implements Listener {
|
||||
if (optionalMCRecipe.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(itemStack));
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setCancelled(true);
|
||||
@@ -387,14 +376,7 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getSource();
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(itemStack));
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
@@ -422,14 +404,7 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getSource();
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(itemStack));
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setCancelled(true);
|
||||
@@ -444,87 +419,109 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onAnvilCombineItems(PrepareAnvilEvent event) {
|
||||
public void onAnvilEvent(PrepareAnvilEvent event) {
|
||||
preProcess(event);
|
||||
processRepairable(event);
|
||||
processRename(event);
|
||||
}
|
||||
|
||||
/*
|
||||
预处理会阻止一些不合理的原版材质造成的合并问题
|
||||
*/
|
||||
private void preProcess(PrepareAnvilEvent event) {
|
||||
AnvilInventory inventory = event.getInventory();
|
||||
ItemStack first = inventory.getFirstItem();
|
||||
ItemStack second = inventory.getSecondItem();
|
||||
if (first == null || second == null) return;
|
||||
Item<ItemStack> wrappedFirst = BukkitItemManager.instance().wrap(first);
|
||||
boolean firstCustom = wrappedFirst.isCustomItem();
|
||||
Optional<CustomItem<ItemStack>> firstCustom = wrappedFirst.getCustomItem();
|
||||
Item<ItemStack> wrappedSecond = BukkitItemManager.instance().wrap(second);
|
||||
boolean secondCustom = wrappedSecond.isCustomItem();
|
||||
// both are vanilla items
|
||||
if (!firstCustom && !secondCustom) {
|
||||
Optional<CustomItem<ItemStack>> secondCustom = wrappedFirst.getCustomItem();
|
||||
// 两个都是原版物品
|
||||
if (firstCustom.isEmpty() && secondCustom.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// both of them are custom items
|
||||
// if the second is an enchanted book, then apply it
|
||||
// 如果第二个物品是附魔书,那么忽略
|
||||
if (wrappedSecond.vanillaId().equals(ItemKeys.ENCHANTED_BOOK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// one of them is vanilla item
|
||||
if (!firstCustom || !secondCustom) {
|
||||
if (second.canRepair(first)) return; // 这里需要考虑原版逻辑
|
||||
// block "vanilla + custom" recipes
|
||||
event.setResult(null);
|
||||
return;
|
||||
// 被修的是自定义,材料不是自定义
|
||||
if (firstCustom.isPresent() && secondCustom.isEmpty()) {
|
||||
if (firstCustom.get().settings().respectRepairableComponent()) {
|
||||
if (second.canRepair(first)) return; // 尊重原版的repairable
|
||||
} else {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// not the same item
|
||||
// 被修的是原版,材料是自定义
|
||||
if (firstCustom.isEmpty() && secondCustom.isPresent()) {
|
||||
if (secondCustom.get().settings().respectRepairableComponent()) {
|
||||
if (second.canRepair(first)) return;
|
||||
} else {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果两个物品id不同,不能合并
|
||||
if (!wrappedFirst.customId().equals(wrappedSecond.customId())) {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// can not repair
|
||||
wrappedFirst.getCustomItem().ifPresent(it -> {
|
||||
// 如果禁止在铁砧使用两个相同物品修复
|
||||
firstCustom.ifPresent(it -> {
|
||||
if (!it.settings().canRepair()) {
|
||||
event.setResult(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
处理item settings中repair item属性。如果修补材料不是自定义物品,则不会参与后续逻辑。
|
||||
这会忽略preprocess里event.setResult(null);
|
||||
*/
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onAnvilRepairItems(PrepareAnvilEvent event) {
|
||||
private void processRepairable(PrepareAnvilEvent event) {
|
||||
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);
|
||||
// if the second slot is not a custom item, ignore it
|
||||
Optional<CustomItem<ItemStack>> customItemOptional = plugin.itemManager().getCustomItem(wrappedSecond.id());
|
||||
// 如果材料不是自定义的,那么忽略
|
||||
Optional<CustomItem<ItemStack>> customItemOptional = this.plugin.itemManager().getCustomItem(wrappedSecond.id());
|
||||
if (customItemOptional.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomItem<ItemStack> customItem = customItemOptional.get();
|
||||
List<AnvilRepairItem> repairItems = customItem.settings().repairItems();
|
||||
// if the second slot is not a repair item, ignore it
|
||||
// 如果材料不支持修复物品,则忽略
|
||||
if (repairItems.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 后续均为修复逻辑
|
||||
Item<ItemStack> wrappedFirst = BukkitItemManager.instance().wrap(first.clone());
|
||||
|
||||
int maxDamage = wrappedFirst.maxDamage();
|
||||
int damage = wrappedFirst.damage().orElse(0);
|
||||
// not a repairable item
|
||||
// 物品无damage属性
|
||||
if (damage == 0 || maxDamage == 0) return;
|
||||
|
||||
Key firstId = wrappedFirst.id();
|
||||
Optional<CustomItem<ItemStack>> optionalCustomTool = wrappedFirst.getCustomItem();
|
||||
// can not repair
|
||||
// 物品无法被修复
|
||||
if (optionalCustomTool.isPresent() && !optionalCustomTool.get().settings().canRepair()) {
|
||||
return;
|
||||
}
|
||||
@@ -549,7 +546,7 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// no repair item matching
|
||||
// 找不到匹配的修复
|
||||
if (repairItem == null) {
|
||||
return;
|
||||
}
|
||||
@@ -566,7 +563,7 @@ public class RecipeEventListener implements Listener {
|
||||
String renameText;
|
||||
int maxRepairCost;
|
||||
//int previousCost;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
renameText = anvilView.getRenameText();
|
||||
maxRepairCost = anvilView.getMaximumRepairCost();
|
||||
@@ -623,13 +620,7 @@ public class RecipeEventListener implements Listener {
|
||||
LegacyInventoryUtils.setRepairCostAmount(inventory, actualConsumedAmount);
|
||||
}
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
|
||||
if (finalCost >= maxRepairCost && !plugin.adapt(player).canInstabuild()) {
|
||||
hasResult = false;
|
||||
@@ -647,12 +638,14 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
如果物品不可被重命名,则在最后处理。
|
||||
*/
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
|
||||
public void onAnvilRenameItem(PrepareAnvilEvent event) {
|
||||
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) {
|
||||
@@ -662,7 +655,7 @@ public class RecipeEventListener implements Listener {
|
||||
wrappedFirst.getCustomItem().ifPresent(item -> {
|
||||
if (!item.settings().renameable()) {
|
||||
String renameText;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
AnvilView anvilView = event.getView();
|
||||
renameText = anvilView.getRenameText();
|
||||
} else {
|
||||
@@ -695,7 +688,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;
|
||||
}
|
||||
@@ -733,13 +726,7 @@ public class RecipeEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
|
||||
Optional<CustomItem<ItemStack>> customItemOptional = plugin.itemManager().getCustomItem(left.id());
|
||||
if (customItemOptional.isEmpty()) {
|
||||
@@ -809,10 +796,10 @@ 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;
|
||||
if (ItemUtils.isEmpty(wrapped)) continue;
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||
if (optionalCustomItem.isPresent()) {
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
@@ -861,46 +848,28 @@ public class RecipeEventListener implements Listener {
|
||||
CraftingInventory inventory = event.getInventory();
|
||||
ItemStack[] ingredients = inventory.getMatrix();
|
||||
|
||||
List<OptimizedIDItem<ItemStack>> optimizedIDItems = new ArrayList<>();
|
||||
List<UniqueIdItem<ItemStack>> uniqueIdItems = new ArrayList<>();
|
||||
for (ItemStack itemStack : ingredients) {
|
||||
if (ItemUtils.isEmpty(itemStack)) {
|
||||
optimizedIDItems.add(EMPTY);
|
||||
} else {
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
// an invalid item is used in recipe, we disallow it
|
||||
inventory.setResult(null);
|
||||
return;
|
||||
} else {
|
||||
optimizedIDItems.add(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
}
|
||||
}
|
||||
uniqueIdItems.add(getUniqueIdItem(itemStack));
|
||||
}
|
||||
|
||||
CraftingInput<ItemStack> input;
|
||||
if (ingredients.length == 9) {
|
||||
input = CraftingInput.of(3, 3, optimizedIDItems);
|
||||
input = CraftingInput.of(3, 3, uniqueIdItems);
|
||||
} else if (ingredients.length == 4) {
|
||||
input = CraftingInput.of(2, 2, optimizedIDItems);
|
||||
input = CraftingInput.of(2, 2, uniqueIdItems);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
Key lastRecipe = serverPlayer.lastUsedRecipe();
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPELESS, input, lastRecipe);
|
||||
if (ceRecipe != null) {
|
||||
inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
inventory.setResult(ceRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||
@@ -909,7 +878,7 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input, lastRecipe);
|
||||
if (ceRecipe != null) {
|
||||
inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
inventory.setResult(ceRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||
@@ -933,6 +902,54 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSmithingTrim(PrepareSmithingEvent event) {
|
||||
SmithingInventory inventory = event.getInventory();
|
||||
if (!(inventory.getRecipe() instanceof SmithingTrimRecipe recipe)) return;
|
||||
|
||||
ItemStack equipment = inventory.getInputEquipment();
|
||||
if (!ItemStackUtils.isEmpty(equipment)) {
|
||||
Item<ItemStack> wrappedEquipment = this.itemManager.wrap(equipment);
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrappedEquipment.getCustomItem();
|
||||
if (optionalCustomItem.isPresent()) {
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
ItemEquipment itemEquipmentSettings = customItem.settings().equipment();
|
||||
if (itemEquipmentSettings != null && itemEquipmentSettings.equipment() instanceof TrimBasedEquipment) {
|
||||
// 不允许trim类型的盔甲再次被使用trim
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
SmithingInput<ItemStack> input = new SmithingInput<>(
|
||||
getUniqueIdItem(inventory.getInputEquipment()),
|
||||
getUniqueIdItem(inventory.getInputTemplate()),
|
||||
getUniqueIdItem(inventory.getInputMineral())
|
||||
);
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SMITHING_TRIM, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
CustomSmithingTrimRecipe<ItemStack> trimRecipe = (CustomSmithingTrimRecipe<ItemStack>) ceRecipe;
|
||||
ItemStack result = trimRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
event.setResult(result);
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSmithingTransform(PrepareSmithingEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
@@ -951,9 +968,9 @@ public class RecipeEventListener implements Listener {
|
||||
ItemStack addition = inventory.getInputMineral();
|
||||
|
||||
SmithingInput<ItemStack> input = new SmithingInput<>(
|
||||
getOptimizedIDItem(base),
|
||||
getOptimizedIDItem(template),
|
||||
getOptimizedIDItem(addition)
|
||||
getUniqueIdItem(base),
|
||||
getUniqueIdItem(template),
|
||||
getUniqueIdItem(addition)
|
||||
);
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SMITHING_TRANSFORM, input);
|
||||
@@ -962,16 +979,10 @@ public class RecipeEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
|
||||
CustomSmithingTransformRecipe<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) ceRecipe;
|
||||
ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base));
|
||||
ItemStack processed = transformRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
event.setResult(processed);
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||
@@ -991,13 +1002,12 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private OptimizedIDItem<ItemStack> getOptimizedIDItem(@Nullable ItemStack itemStack) {
|
||||
if (ItemUtils.isEmpty(itemStack)) {
|
||||
return EMPTY;
|
||||
private UniqueIdItem<ItemStack> getUniqueIdItem(@Nullable ItemStack itemStack) {
|
||||
if (ItemStackUtils.isEmpty(itemStack)) {
|
||||
return this.itemManager.uniqueEmptyItem();
|
||||
} else {
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
return idHolder.map(keyReference -> new OptimizedIDItem<>(keyReference, itemStack)).orElse(EMPTY);
|
||||
return new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -90,7 +91,7 @@ public class BukkitVanillaLootManager extends AbstractVanillaLootManager impleme
|
||||
}
|
||||
|
||||
public class VanillaLootParser implements ConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[] {"vanilla-loots", "vanilla-loot", "loots", "loot"};
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[] {"vanilla-loots", "vanilla-loot", "vanilla_loots", "vanilla_loot"};
|
||||
|
||||
@Override
|
||||
public int loadingSequence() {
|
||||
|
||||
@@ -5,13 +5,11 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.feature.ReloadCommand;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ResourcePackUtils;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.pack.AbstractPackManager;
|
||||
import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData;
|
||||
import net.momirealms.craftengine.core.pack.host.impl.NoneHost;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -25,11 +23,9 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
public static final String FAKE_URL = "https://127.0.0.1:65536";
|
||||
private final BukkitCraftEngine plugin;
|
||||
|
||||
public BukkitPackManager(BukkitCraftEngine plugin) {
|
||||
@@ -58,25 +54,6 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
public void load() {
|
||||
if (ReloadCommand.RELOAD_PACK_FLAG || CraftEngine.instance().isInitializing()) {
|
||||
super.load();
|
||||
if (Config.sendPackOnJoin() && VersionHelper.isOrAbove1_20_2() && !(resourcePackHost() instanceof NoneHost)) {
|
||||
this.modifyServerSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void modifyServerSettings() {
|
||||
try {
|
||||
Object settings = CoreReflections.field$DedicatedServer$settings.get(CoreReflections.method$MinecraftServer$getServer.invoke(null));
|
||||
Object properties = CoreReflections.field$DedicatedServerSettings$properties.get(settings);
|
||||
Object info;
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
info = CoreReflections.constructor$ServerResourcePackInfo.newInstance(new UUID(0, 0), FAKE_URL, "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
} else {
|
||||
info = CoreReflections.constructor$ServerResourcePackInfo.newInstance(FAKE_URL, "", Config.kickOnDeclined(), ComponentUtils.adventureToMinecraft(Config.resourcePackPrompt()));
|
||||
}
|
||||
CoreReflections.field$DedicatedServerProperties$serverResourcePackInfo.set(properties, Optional.of(info));
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to update resource pack settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
super.onPluginLoad();
|
||||
super.blockManager.init();
|
||||
super.networkManager = new BukkitNetworkManager(this);
|
||||
super.itemManager = new BukkitItemManager(this);
|
||||
this.successfullyLoaded = true;
|
||||
super.compatibilityManager().onLoad();
|
||||
}
|
||||
@@ -182,7 +183,6 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
PacketConsumers.initEntities(RegistryUtils.currentEntityTypeRegistrySize());
|
||||
super.packManager = new BukkitPackManager(this);
|
||||
super.senderFactory = new BukkitSenderFactory(this);
|
||||
super.itemManager = new BukkitItemManager(this);
|
||||
super.recipeManager = new BukkitRecipeManager(this);
|
||||
super.commandManager = new BukkitCommandManager(this);
|
||||
super.itemBrowserManager = new ItemBrowserManagerImpl(this);
|
||||
@@ -270,7 +270,7 @@ public class BukkitCraftEngine extends CraftEngine {
|
||||
|
||||
@Override
|
||||
public String serverVersion() {
|
||||
return Bukkit.getServer().getBukkitVersion().split("-")[0];
|
||||
return VersionHelper.MINECRAFT_VERSION.version();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.google.gson.JsonElement;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.Platform;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
@@ -28,7 +27,6 @@ public class BukkitPlatform implements Platform {
|
||||
Map<String, Object> map = (Map<String, Object>) MRegistryOps.NBT.convertTo(MRegistryOps.JAVA, tag);
|
||||
return map.get("root");
|
||||
} catch (CommandSyntaxException e) {
|
||||
CraftEngine.instance().debug(e::getMessage);
|
||||
throw new LocalizedResourceConfigException("warning.config.type.snbt.invalid_syntax", e, nbt);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +43,6 @@ public class BukkitPlatform implements Platform {
|
||||
CompoundTag map = (CompoundTag) MRegistryOps.NBT.convertTo(MRegistryOps.SPARROW_NBT, tag);
|
||||
return map.get("root");
|
||||
} catch (CommandSyntaxException e) {
|
||||
CraftEngine.instance().debug(e::getMessage);
|
||||
throw new LocalizedResourceConfigException("warning.config.type.snbt.invalid_syntax", e, nbt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
|
||||
new DebugGetBlockInternalIdCommand(this, plugin),
|
||||
new DebugAppearanceStateUsageCommand(this, plugin),
|
||||
new DebugClearCooldownCommand(this, plugin),
|
||||
new DebugEntityIdCommand(this, plugin),
|
||||
new DebugRealStateUsageCommand(this, plugin),
|
||||
new DebugItemDataCommand(this, plugin),
|
||||
new DebugSetBlockCommand(this, plugin),
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
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.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.bukkit.parser.WorldParser;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
|
||||
public class DebugEntityIdCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public DebugEntityIdCommand(CraftEngineCommandManager<CommandSender> commandManager, CraftEngine plugin) {
|
||||
super(commandManager, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.required("world", WorldParser.worldParser())
|
||||
.required("entityId", IntegerParser.integerParser())
|
||||
.handler(context -> {
|
||||
World world = context.get("world");
|
||||
int entityId = context.get("entityId");
|
||||
Object entityLookup = FastNMS.INSTANCE.method$ServerLevel$getEntityLookup(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world));
|
||||
Object entity = FastNMS.INSTANCE.method$EntityLookup$get(entityLookup, entityId);
|
||||
if (entity == null) {
|
||||
context.sender().sendMessage("entity not found");
|
||||
return;
|
||||
}
|
||||
context.sender().sendMessage(entity.toString());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "debug_entity_id";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ public final class BlockGenerator {
|
||||
// onExplosionHit 1.21+
|
||||
.method(ElementMatchers.returns(void.class)
|
||||
.and(ElementMatchers.takesArgument(0, CoreReflections.clazz$BlockState))
|
||||
.and(ElementMatchers.takesArgument(1, CoreReflections.clazz$ServerLevel))
|
||||
.and(ElementMatchers.takesArgument(1, VersionHelper.isOrAbove1_21_2() ? CoreReflections.clazz$ServerLevel : CoreReflections.clazz$Level))
|
||||
.and(ElementMatchers.takesArgument(2, CoreReflections.clazz$BlockPos))
|
||||
.and(ElementMatchers.takesArgument(3, CoreReflections.clazz$Explosion))
|
||||
.and(ElementMatchers.takesArgument(4, BiConsumer.class))
|
||||
@@ -177,11 +177,21 @@ public final class BlockGenerator {
|
||||
.intercept(MethodDelegation.to(GetDirectSignalInterceptor.INSTANCE))
|
||||
// isSignalSource
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$isSignalSource))
|
||||
.intercept(MethodDelegation.to(IsSignalSourceInterceptor.INSTANCE));
|
||||
.intercept(MethodDelegation.to(IsSignalSourceInterceptor.INSTANCE))
|
||||
// playerWillDestroy
|
||||
.method(ElementMatchers.is(CoreReflections.method$Block$playerWillDestroy))
|
||||
.intercept(MethodDelegation.to(PlayerWillDestroyInterceptor.INSTANCE))
|
||||
// spawnAfterBreak
|
||||
.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$spawnAfterBreak))
|
||||
.intercept(MethodDelegation.to(SpawnAfterBreakInterceptor.INSTANCE));
|
||||
if (CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval != null) {
|
||||
builder.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval))
|
||||
.intercept(MethodDelegation.to(AffectNeighborsAfterRemovalInterceptor.INSTANCE));
|
||||
}
|
||||
if (CoreReflections.method$BlockBehaviour$onRemove != null) {
|
||||
builder.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$onRemove))
|
||||
.intercept(MethodDelegation.to(OnRemoveInterceptor.INSTANCE));
|
||||
}
|
||||
|
||||
Class<?> clazz$CraftEngineBlock = builder.make().load(BlockGenerator.class.getClassLoader()).getLoaded();
|
||||
constructor$CraftEngineBlock = MethodHandles.publicLookup().in(clazz$CraftEngineBlock)
|
||||
@@ -225,15 +235,9 @@ public final class BlockGenerator {
|
||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
DelegatingBlock indicator = (DelegatingBlock) thisObj;
|
||||
// todo chain updater
|
||||
if (indicator.isNoteBlock()) {
|
||||
if (CoreReflections.clazz$ServerLevel.isInstance(args[levelIndex])) {
|
||||
startNoteBlockChain(args);
|
||||
}
|
||||
} else if (indicator.isTripwire()) {
|
||||
if (CoreReflections.clazz$ServerLevel.isInstance(args[posIndex])) {
|
||||
|
||||
}
|
||||
// todo better chain updater
|
||||
if (indicator.isNoteBlock() && CoreReflections.clazz$ServerLevel.isInstance(args[levelIndex])) {
|
||||
startNoteBlockChain(args);
|
||||
}
|
||||
try {
|
||||
return holder.value().updateShape(thisObj, args, superMethod);
|
||||
@@ -501,6 +505,7 @@ public final class BlockGenerator {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
holder.value().onExplosionHit(thisObj, args, superMethod);
|
||||
superMethod.call();
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run onExplosionHit", e);
|
||||
}
|
||||
@@ -611,6 +616,20 @@ public final class BlockGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnRemoveInterceptor {
|
||||
public static final OnRemoveInterceptor INSTANCE = new OnRemoveInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
holder.value().onRemove(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run onRemove", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntityInsideInterceptor {
|
||||
public static final EntityInsideInterceptor INSTANCE = new EntityInsideInterceptor();
|
||||
|
||||
@@ -624,4 +643,33 @@ public final class BlockGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlayerWillDestroyInterceptor {
|
||||
public static final PlayerWillDestroyInterceptor INSTANCE = new PlayerWillDestroyInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) throws Exception {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
return holder.value().playerWillDestroy(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run playerWillDestroy", e);
|
||||
return superMethod.call();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SpawnAfterBreakInterceptor {
|
||||
public static final SpawnAfterBreakInterceptor INSTANCE = new SpawnAfterBreakInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((DelegatingBlock) thisObj).behaviorDelegate();
|
||||
try {
|
||||
holder.value().spawnAfterBreak(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run spawnAfterBreak", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,9 @@ public final class BlockStateGenerator {
|
||||
Object tool = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.TOOL);
|
||||
Item<ItemStack> item = BukkitItemManager.instance().wrap(tool == null || FastNMS.INSTANCE.method$ItemStack$isEmpty(tool) ? null : FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(tool));
|
||||
Object optionalPlayer = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.THIS_ENTITY);
|
||||
if (!CoreReflections.clazz$Player.isInstance(optionalPlayer)) {
|
||||
optionalPlayer = null;
|
||||
}
|
||||
|
||||
// do not drop if it's not the correct tool
|
||||
BlockSettings settings = state.settings();
|
||||
@@ -115,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,9 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomCookingRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -135,12 +133,7 @@ public class RecipeInjector {
|
||||
);
|
||||
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
@@ -186,12 +179,7 @@ public class RecipeInjector {
|
||||
}
|
||||
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
@@ -232,12 +220,7 @@ public class RecipeInjector {
|
||||
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0]));
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
@@ -282,12 +265,7 @@ public class RecipeInjector {
|
||||
// 获取唯一内存地址id
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0]));
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe());
|
||||
// 这个ce配方并不存在,那么应该返回空
|
||||
if (ceRecipe == null) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
@@ -19,6 +18,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.CooldownData;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.plugin.network.*;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -43,8 +43,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
private static BukkitNetworkManager instance;
|
||||
private static final Map<Class<?>, TriConsumer<NetWorkUser, NMSPacketEvent, Object>> NMS_PACKET_HANDLERS = new HashMap<>();
|
||||
// only for game stage for the moment
|
||||
private static BiConsumer<NetWorkUser, ByteBufPacketEvent>[] S2C_BYTE_BUFFER_PACKET_HANDLERS;
|
||||
private static BiConsumer<NetWorkUser, ByteBufPacketEvent>[] C2S_BYTE_BUFFER_PACKET_HANDLERS;
|
||||
private static BiConsumer<NetWorkUser, ByteBufPacketEvent>[] S2C_GAME_BYTE_BUFFER_PACKET_HANDLERS;
|
||||
private static BiConsumer<NetWorkUser, ByteBufPacketEvent>[] C2S_GAME_BYTE_BUFFER_PACKET_HANDLERS;
|
||||
|
||||
private static void registerNMSPacketConsumer(final TriConsumer<NetWorkUser, NMSPacketEvent, Object> function, @Nullable Class<?> packet) {
|
||||
if (packet == null) return;
|
||||
@@ -53,18 +53,18 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
|
||||
private static void registerS2CByteBufPacketConsumer(final BiConsumer<NetWorkUser, ByteBufPacketEvent> function, int id) {
|
||||
if (id == -1) return;
|
||||
if (id < 0 || id >= S2C_BYTE_BUFFER_PACKET_HANDLERS.length) {
|
||||
if (id < 0 || id >= S2C_GAME_BYTE_BUFFER_PACKET_HANDLERS.length) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
S2C_BYTE_BUFFER_PACKET_HANDLERS[id] = function;
|
||||
S2C_GAME_BYTE_BUFFER_PACKET_HANDLERS[id] = function;
|
||||
}
|
||||
|
||||
private static void registerC2SByteBufPacketConsumer(final BiConsumer<NetWorkUser, ByteBufPacketEvent> function, int id) {
|
||||
if (id == -1) return;
|
||||
if (id < 0 || id >= C2S_BYTE_BUFFER_PACKET_HANDLERS.length) {
|
||||
if (id < 0 || id >= C2S_GAME_BYTE_BUFFER_PACKET_HANDLERS.length) {
|
||||
throw new IllegalArgumentException("Invalid packet id: " + id);
|
||||
}
|
||||
C2S_BYTE_BUFFER_PACKET_HANDLERS[id] = function;
|
||||
C2S_GAME_BYTE_BUFFER_PACKET_HANDLERS[id] = function;
|
||||
}
|
||||
|
||||
private final BiConsumer<ChannelHandler, Object> packetConsumer;
|
||||
@@ -92,10 +92,10 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
@SuppressWarnings("unchecked")
|
||||
public BukkitNetworkManager(BukkitCraftEngine plugin) {
|
||||
instance = this;
|
||||
S2C_BYTE_BUFFER_PACKET_HANDLERS = new BiConsumer[PacketIdFinder.maxS2CPacketId()];
|
||||
C2S_BYTE_BUFFER_PACKET_HANDLERS = new BiConsumer[PacketIdFinder.maxC2SPacketId()];
|
||||
Arrays.fill(S2C_BYTE_BUFFER_PACKET_HANDLERS, Handlers.DO_NOTHING);
|
||||
Arrays.fill(C2S_BYTE_BUFFER_PACKET_HANDLERS, Handlers.DO_NOTHING);
|
||||
S2C_GAME_BYTE_BUFFER_PACKET_HANDLERS = new BiConsumer[PacketIdFinder.s2cGamePackets()];
|
||||
C2S_GAME_BYTE_BUFFER_PACKET_HANDLERS = new BiConsumer[PacketIdFinder.c2sGamePackets()];
|
||||
Arrays.fill(S2C_GAME_BYTE_BUFFER_PACKET_HANDLERS, Handlers.DO_NOTHING);
|
||||
Arrays.fill(C2S_GAME_BYTE_BUFFER_PACKET_HANDLERS, Handlers.DO_NOTHING);
|
||||
hasModelEngine = Bukkit.getPluginManager().getPlugin("ModelEngine") != null;
|
||||
hasViaVersion = Bukkit.getPluginManager().getPlugin("ViaVersion") != null;
|
||||
this.plugin = plugin;
|
||||
@@ -117,8 +117,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
// set up mod channel
|
||||
this.plugin.javaPlugin().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.javaPlugin(), MOD_CHANNEL, this);
|
||||
this.plugin.javaPlugin().getServer().getMessenger().registerOutgoingPluginChannel(this.plugin.javaPlugin(), MOD_CHANNEL);
|
||||
// 配置via频道
|
||||
this.plugin.javaPlugin().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.javaPlugin(), VIA_CHANNEL, this);
|
||||
// Inject server channel
|
||||
try {
|
||||
Object server = CoreReflections.method$MinecraftServer$getServer.invoke(null);
|
||||
@@ -152,15 +150,15 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, NetworkReflections.clazz$ServerboundSignUpdatePacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.EDIT_BOOK, NetworkReflections.clazz$ServerboundEditBookPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.CUSTOM_PAYLOAD, NetworkReflections.clazz$ServerboundCustomPayloadPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_PUSH, NetworkReflections.clazz$ClientboundResourcePackPushPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.HANDSHAKE_C2S, NetworkReflections.clazz$ClientIntentionPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, NetworkReflections.clazz$ServerboundLoginAcknowledgedPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, NetworkReflections.clazz$ServerboundResourcePackPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, NetworkReflections.clazz$ClientboundEntityEventPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_AND_ROTATE_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$PosRot);
|
||||
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$Pos);
|
||||
registerNMSPacketConsumer(PacketConsumers.ROTATE_HEAD, NetworkReflections.clazz$ClientboundRotateHeadPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_MOTION, NetworkReflections.clazz$ClientboundSetEntityMotionPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.FINISH_CONFIGURATION, NetworkReflections.clazz$ClientboundFinishConfigurationPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.LOGIN_FINISHED, NetworkReflections.clazz$ClientboundLoginFinishedPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.UPDATE_TAGS, NetworkReflections.clazz$ClientboundUpdateTagsPacket);
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
@@ -176,6 +174,10 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerS2CByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.TEAM_1_20_3 : PacketConsumers.TEAM_1_20, this.packetIds.clientboundSetPlayerTeamPacket());
|
||||
registerS2CByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket());
|
||||
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.UPDATE_ADVANCEMENTS, this.packetIds.clientboundUpdateAdvancementsPacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY, this.packetIds.clientboundAddEntityPacket());
|
||||
registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());
|
||||
@@ -204,7 +206,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
this.resetUserArray();
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.getScheduler().runAtFixedRate(plugin.javaPlugin(), (t) -> user.tick(),
|
||||
() -> plugin.debug(() -> "Player " + player.getName() + "'s entity scheduler is retired"), 1, 1);
|
||||
() -> {}, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,14 +244,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte @NotNull [] message) {
|
||||
if (channel.equals(VIA_CHANNEL)) {
|
||||
BukkitServerPlayer user = this.plugin.adapt(player);
|
||||
if (user != null) {
|
||||
JsonObject payload = GsonHelper.get().fromJson(new String(message), JsonObject.class);
|
||||
int version = payload.get("version").getAsInt();
|
||||
user.setProtocolVersion(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -653,6 +647,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
}
|
||||
|
||||
private void onNMSPacketReceive(NetWorkUser user, NMSPacketEvent event, Object packet) {
|
||||
Debugger.PACKET.debug(() -> "[C->S]" + packet.getClass());
|
||||
handleNMSPacket(user, event, packet);
|
||||
}
|
||||
|
||||
@@ -663,6 +658,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
onNMSPacketSend(player, event, p);
|
||||
}
|
||||
} else {
|
||||
Debugger.PACKET.debug(() -> "[S->C]" + packet.getClass());
|
||||
handleNMSPacket(player, event, packet);
|
||||
}
|
||||
}
|
||||
@@ -674,13 +670,13 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
|
||||
protected void handleS2CByteBufPacket(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
int packetID = event.packetID();
|
||||
Optional.ofNullable(S2C_BYTE_BUFFER_PACKET_HANDLERS[packetID])
|
||||
Optional.ofNullable(S2C_GAME_BYTE_BUFFER_PACKET_HANDLERS[packetID])
|
||||
.ifPresent(function -> function.accept(user, event));
|
||||
}
|
||||
|
||||
protected void handleC2SByteBufPacket(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
int packetID = event.packetID();
|
||||
Optional.ofNullable(C2S_BYTE_BUFFER_PACKET_HANDLERS[packetID])
|
||||
Optional.ofNullable(C2S_GAME_BYTE_BUFFER_PACKET_HANDLERS[packetID])
|
||||
.ifPresent(function -> function.accept(user, event));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -21,7 +23,6 @@ import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManag
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FurnitureItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.pack.BukkitPackManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.ProtectedFieldVisitor;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.handler.*;
|
||||
@@ -34,6 +35,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityType
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.advancement.network.AdvancementHolder;
|
||||
import net.momirealms.craftengine.core.advancement.network.AdvancementProgress;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.font.FontManager;
|
||||
@@ -42,6 +45,9 @@ 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.legacy.LegacyRecipeHolder;
|
||||
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;
|
||||
@@ -50,6 +56,7 @@ import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
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.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.plugin.network.*;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
@@ -64,7 +71,6 @@ import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import net.momirealms.sparrow.nbt.Tag;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
@@ -127,8 +133,8 @@ public class PacketConsumers {
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.TEXT_DISPLAY$registryId] = simpleAddEntityHandler(TextDisplayPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ARMOR_STAND$registryId] = simpleAddEntityHandler(ArmorStandPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM_FRAME$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.GLOW_ITEM_FRAME$registryId] = simpleAddEntityHandler(CommonItemPacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.ITEM_FRAME$registryId] = simpleAddEntityHandler(ItemFramePacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.GLOW_ITEM_FRAME$registryId] = simpleAddEntityHandler(ItemFramePacketHandler.INSTANCE);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.FIREBALL$registryId] = createOptionalCustomProjectileEntityHandler(true);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.EYE_OF_ENDER$registryId] = createOptionalCustomProjectileEntityHandler(true);
|
||||
ADD_ENTITY_HANDLERS[MEntityTypes.FIREWORK_ROCKET$registryId] = createOptionalCustomProjectileEntityHandler(true);
|
||||
@@ -1254,9 +1260,6 @@ public class PacketConsumers {
|
||||
player.setConnectionState(ConnectionState.PLAY);
|
||||
Object dimensionKey;
|
||||
if (!VersionHelper.isOrAbove1_20_2()) {
|
||||
if (BukkitNetworkManager.hasViaVersion()) {
|
||||
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(player.uuid()));
|
||||
}
|
||||
dimensionKey = NetworkReflections.methodHandle$ClientboundLoginPacket$dimensionGetter.invokeExact(packet);
|
||||
} else {
|
||||
Object commonInfo = NetworkReflections.methodHandle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter.invokeExact(packet);
|
||||
@@ -1281,7 +1284,7 @@ public class PacketConsumers {
|
||||
// When the hotbar is full, the latest creative mode inventory can only be accessed when the player opens the inventory screen. Currently, it is not worth further handling this issue.
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SET_CREATIVE_SLOT = (user, event, packet) -> {
|
||||
try {
|
||||
if (user.protocolVersion().isVersionNewerThan(ProtocolVersion.V1_21_4)) return;
|
||||
if (VersionHelper.isOrAbove1_21_4()) return;
|
||||
if (!user.isOnline()) return;
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
if (VersionHelper.isFolia()) {
|
||||
@@ -1307,7 +1310,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;
|
||||
}
|
||||
@@ -1323,11 +1326,14 @@ public class PacketConsumers {
|
||||
Key itemId = state.settings().itemId();
|
||||
// no item available
|
||||
if (itemId == null) return;
|
||||
BlockData data = BlockStateUtils.fromBlockData(state.vanillaBlockState().handle());
|
||||
// compare item
|
||||
if (data == null || !data.getMaterial().equals(item.getType())) return;
|
||||
Object vanillaBlock = FastNMS.INSTANCE.method$BlockState$getBlock(state.vanillaBlockState().handle());
|
||||
Object vanillaBlockItem = FastNMS.INSTANCE.method$Block$asItem(vanillaBlock);
|
||||
if (vanillaBlockItem == null) return;
|
||||
Key addItemId = KeyUtils.namespacedKey2Key(item.getType().getKey());
|
||||
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;
|
||||
}
|
||||
@@ -1336,7 +1342,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;
|
||||
}
|
||||
@@ -1359,7 +1365,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;
|
||||
}
|
||||
@@ -1929,24 +1935,21 @@ public class PacketConsumers {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isPresent()) {
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (!tokens.isEmpty()) {
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))));
|
||||
isChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entityDataId != EntityDataUtils.CUSTOM_NAME_DATA_ID) continue;
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))));
|
||||
isChanged = true;
|
||||
break;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
@@ -2093,7 +2096,13 @@ public class PacketConsumers {
|
||||
int stateId = buf.readVarInt();
|
||||
int slot = buf.readShort();
|
||||
Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf);
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
|
||||
ItemStack itemStack;
|
||||
try {
|
||||
itemStack = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf);
|
||||
} catch (Exception e) {
|
||||
// 其他插件干的,比如某ty*****er,不要赖到ce头上
|
||||
return;
|
||||
}
|
||||
BukkitItemManager.instance().s2c(itemStack, serverPlayer).ifPresent((newItemStack) -> {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
@@ -2117,11 +2126,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());
|
||||
@@ -2280,73 +2289,55 @@ public class PacketConsumers {
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_PUSH = (user, event, packet) -> {
|
||||
try {
|
||||
if (!VersionHelper.isOrAbove1_20_2()) return;
|
||||
// we should only handle fake urls
|
||||
String url = FastNMS.INSTANCE.field$ClientboundResourcePackPushPacket$url(packet);
|
||||
if (!url.equals(BukkitPackManager.FAKE_URL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
UUID packUUID = FastNMS.INSTANCE.field$ClientboundResourcePackPushPacket$uuid(packet);
|
||||
ResourcePackHost host = CraftEngine.instance().packManager().resourcePackHost();
|
||||
host.requestResourcePackDownloadLink(user.uuid()).thenAccept(dataList -> {
|
||||
if (dataList.isEmpty()) {
|
||||
user.simulatePacket(FastNMS.INSTANCE.constructor$ServerboundResourcePackPacket$SUCCESSFULLY_LOADED(packUUID));
|
||||
return;
|
||||
}
|
||||
for (ResourcePackDownloadData data : dataList) {
|
||||
Object newPacket = ResourcePackUtils.createPacket(data.uuid(), data.url(), data.sha1());
|
||||
user.sendPacket(newPacket, true);
|
||||
user.addResourcePackUUID(data.uuid());
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundResourcePackPushPacket", throwable);
|
||||
user.simulatePacket(FastNMS.INSTANCE.constructor$ServerboundResourcePackPacket$SUCCESSFULLY_LOADED(packUUID));
|
||||
return null;
|
||||
});
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundResourcePackPushPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HANDSHAKE_C2S = (user, event, packet) -> {
|
||||
try {
|
||||
if (BukkitNetworkManager.hasViaVersion()) return;
|
||||
int protocolVersion = (int) NetworkReflections.methodHandle$ClientIntentionPacket$protocolVersionGetter.invokeExact(packet);
|
||||
user.setProtocolVersion(protocolVersion);
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientIntentionPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> LOGIN_ACKNOWLEDGED = (user, event, packet) -> {
|
||||
try {
|
||||
if (BukkitNetworkManager.hasViaVersion()) {
|
||||
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(user.uuid()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundLoginAcknowledgedPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_RESPONSE = (user, event, packet) -> {
|
||||
try {
|
||||
if (user.sentResourcePack() || !Config.sendPackOnJoin() || !Config.kickOnDeclined()) return;
|
||||
Object action = NetworkReflections.methodHandle$ServerboundResourcePackPacket$actionGetter.invokeExact(packet);
|
||||
if (action == null) return;
|
||||
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DECLINED
|
||||
|| action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD) {
|
||||
Object kickPacket = NetworkReflections.constructor$ClientboundDisconnectPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")));
|
||||
user.sendPacket(kickPacket, true);
|
||||
user.nettyChannel().disconnect();
|
||||
Object action = FastNMS.INSTANCE.field$ServerboundResourcePackPacket$action(packet);
|
||||
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
UUID uuid = FastNMS.INSTANCE.field$ServerboundResourcePackPacket$id(packet);
|
||||
if (!user.isResourcePackLoading(uuid)) {
|
||||
// 不是CraftEngine发送的资源包,不管
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == null) {
|
||||
user.kick(Component.text("Corrupted ResourcePackResponse Packet"));
|
||||
return;
|
||||
}
|
||||
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$SUCCESSFULLY_LOADED) {
|
||||
user.setSentResourcePack(true);
|
||||
|
||||
// 检查是否是拒绝
|
||||
if (Config.kickOnDeclined()) {
|
||||
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DECLINED || action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DISCARDED) {
|
||||
user.kick(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否失败
|
||||
if (Config.kickOnFailedApply()) {
|
||||
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD
|
||||
|| (VersionHelper.isOrAbove1_20_3() && action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$INVALID_URL)) {
|
||||
user.kick(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTerminal = action != NetworkReflections.instance$ServerboundResourcePackPacket$Action$ACCEPTED && action != NetworkReflections.instance$ServerboundResourcePackPacket$Action$DOWNLOADED;
|
||||
if (isTerminal && VersionHelper.isOrAbove1_20_2()) {
|
||||
event.setCancelled(true);
|
||||
Object packetListener = FastNMS.INSTANCE.method$Connection$getPacketListener(user.connection());
|
||||
if (!CoreReflections.clazz$ServerConfigurationPacketListenerImpl.isInstance(packetListener)) return;
|
||||
// 主线程上处理这个包
|
||||
CraftEngine.instance().scheduler().executeSync(() -> {
|
||||
try {
|
||||
// 当客户端发出多次成功包的时候,finish会报错,我们忽略他
|
||||
NetworkReflections.methodHandle$ServerCommonPacketListener$handleResourcePackResponse.invokeExact(packetListener, packet);
|
||||
CoreReflections.methodHandle$ServerConfigurationPacketListenerImpl$finishCurrentTask.invokeExact(packetListener, CoreReflections.instance$ServerResourcePackConfigurationTask$TYPE);
|
||||
} catch (Throwable e) {
|
||||
Debugger.RESOURCE_PACK.warn(() -> "Cannot finish current task", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundResourcePackPacket", e);
|
||||
@@ -2417,4 +2408,176 @@ public class PacketConsumers {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityMotionPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
// 这个包是由 JoinWorldTask 发出的,客户端收到后会返回 ServerboundFinishConfigurationPacket
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> FINISH_CONFIGURATION = (user, event, packet) -> {
|
||||
try {
|
||||
if (!VersionHelper.isOrAbove1_20_2() || !Config.sendPackOnJoin()) {
|
||||
// 防止后期调试进配置阶段造成问题
|
||||
user.setShouldProcessFinishConfiguration(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user.shouldProcessFinishConfiguration()) return;
|
||||
Object packetListener = FastNMS.INSTANCE.method$Connection$getPacketListener(user.connection());
|
||||
if (!CoreReflections.clazz$ServerConfigurationPacketListenerImpl.isInstance(packetListener)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 防止后续加入的JoinWorldTask再次处理
|
||||
user.setShouldProcessFinishConfiguration(false);
|
||||
|
||||
// 取消 ClientboundFinishConfigurationPacket,让客户端发呆,并结束掉当前的进入世界任务
|
||||
event.setCancelled(true);
|
||||
try {
|
||||
CoreReflections.methodHandle$ServerConfigurationPacketListenerImpl$finishCurrentTask.invokeExact(packetListener, CoreReflections.instance$JoinWorldTask$TYPE);
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to finish current task for " + user.name(), e);
|
||||
}
|
||||
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
// 1.20.5+开始会检查是否结束需要重新设置回去,不然不会发keepAlive包
|
||||
CoreReflections.methodHandle$ServerCommonPacketListenerImpl$closedSetter.invokeExact(packetListener, false);
|
||||
}
|
||||
|
||||
// 请求资源包
|
||||
ResourcePackHost host = CraftEngine.instance().packManager().resourcePackHost();
|
||||
host.requestResourcePackDownloadLink(user.uuid()).whenComplete((dataList, t) -> {
|
||||
if (t != null) {
|
||||
CraftEngine.instance().logger().warn("Failed to get pack data for player " + user.name(), t);
|
||||
FastNMS.INSTANCE.method$ServerConfigurationPacketListenerImpl$returnToWorld(packetListener);
|
||||
return;
|
||||
}
|
||||
if (dataList.isEmpty()) {
|
||||
FastNMS.INSTANCE.method$ServerConfigurationPacketListenerImpl$returnToWorld(packetListener);
|
||||
return;
|
||||
}
|
||||
Queue<Object> configurationTasks;
|
||||
try {
|
||||
configurationTasks = (Queue<Object>) CoreReflections.methodHandle$ServerConfigurationPacketListenerImpl$configurationTasksGetter.invokeExact(packetListener);
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to get configuration tasks for player " + user.name(), e);
|
||||
FastNMS.INSTANCE.method$ServerConfigurationPacketListenerImpl$returnToWorld(packetListener);
|
||||
return;
|
||||
}
|
||||
// 向配置阶段连接的任务重加入资源包的任务
|
||||
for (ResourcePackDownloadData data : dataList) {
|
||||
configurationTasks.add(FastNMS.INSTANCE.constructor$ServerResourcePackConfigurationTask(ResourcePackUtils.createServerResourcePackInfo(data.uuid(), data.url(), data.sha1())));
|
||||
user.addResourcePackUUID(data.uuid());
|
||||
}
|
||||
// 最后再加入一个 JoinWorldTask 并开始资源包任务
|
||||
FastNMS.INSTANCE.method$ServerConfigurationPacketListenerImpl$returnToWorld(packetListener);
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundFinishConfigurationPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> LOGIN_FINISHED = (user, event, packet) -> {
|
||||
try {
|
||||
GameProfile gameProfile = FastNMS.INSTANCE.field$ClientboundLoginFinishedPacket$gameProfile(packet);
|
||||
user.setName(gameProfile.getName());
|
||||
user.setUUID(gameProfile.getId());
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginFinishedPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> ADD_RECIPE_BOOK = (user, event) -> {
|
||||
try {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
List<RecipeBookEntry> entries = buf.readCollection(ArrayList::new, byteBuf -> {
|
||||
RecipeBookEntry entry = RecipeBookEntry.read(byteBuf);
|
||||
entry.applyClientboundData((BukkitServerPlayer) user);
|
||||
return entry;
|
||||
});
|
||||
boolean replace = buf.readBoolean();
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeCollection(entries, ((byteBuf, recipeBookEntry) -> recipeBookEntry.write(byteBuf)));
|
||||
buf.writeBoolean(replace);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundRecipeBookAddPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> PLACE_GHOST_RECIPE = (user, event) -> {
|
||||
try {
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int containerId = buf.readContainerId();
|
||||
RecipeDisplay display = RecipeDisplay.read(buf);
|
||||
display.applyClientboundData((BukkitServerPlayer) user);
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeContainerId(containerId);
|
||||
display.write(buf);
|
||||
} catch (Exception e) {
|
||||
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();
|
||||
List<LegacyRecipeHolder> holders = buf.readCollection(ArrayList::new, byteBuf -> {
|
||||
LegacyRecipeHolder holder = LegacyRecipeHolder.read(byteBuf);
|
||||
holder.recipe().applyClientboundData((BukkitServerPlayer) user);
|
||||
return holder;
|
||||
});
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeCollection(holders, ((byteBuf, recipeHolder) -> recipeHolder.write(byteBuf)));
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundUpdateRecipesPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> UPDATE_ADVANCEMENTS = (user, event) -> {
|
||||
try {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
boolean reset = buf.readBoolean();
|
||||
List<AdvancementHolder> added = buf.readCollection(ArrayList::new, byteBuf -> {
|
||||
AdvancementHolder holder = AdvancementHolder.read(byteBuf);
|
||||
holder.applyClientboundData((BukkitServerPlayer) user);
|
||||
return holder;
|
||||
});
|
||||
Set<Key> removed = buf.readCollection(Sets::newLinkedHashSetWithExpectedSize, FriendlyByteBuf::readKey);
|
||||
Map<Key, AdvancementProgress> progress = buf.readMap(FriendlyByteBuf::readKey, AdvancementProgress::read);
|
||||
|
||||
boolean showAdvancement = false;
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
showAdvancement = buf.readBoolean();
|
||||
}
|
||||
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
|
||||
buf.writeBoolean(reset);
|
||||
buf.writeCollection(added, (byteBuf, advancementHolder) -> advancementHolder.write(byteBuf));
|
||||
buf.writeCollection(removed, FriendlyByteBuf::writeKey);
|
||||
buf.writeMap(progress, FriendlyByteBuf::writeKey, (byteBuf, advancementProgress) -> advancementProgress.write(byteBuf));
|
||||
if (VersionHelper.isOrAbove1_21_5()) {
|
||||
buf.writeBoolean(showAdvancement);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundUpdateAdvancementsPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> UPDATE_TAGS = (user, event, packet) -> {
|
||||
try {
|
||||
Object modifiedPacket = BukkitBlockManager.instance().cachedUpdateTagsPacket();
|
||||
if (packet.equals(modifiedPacket) || modifiedPacket == null) return;
|
||||
event.replacePacket(modifiedPacket);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundUpdateTagsPacket", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -54,9 +54,17 @@ public interface PacketIds {
|
||||
|
||||
int clientboundBlockEventPacket();
|
||||
|
||||
int clientboundRecipeBookAddPacket();
|
||||
|
||||
int clientboundPlaceGhostRecipePacket();
|
||||
|
||||
int clientboundUpdateAdvancementsPacket();
|
||||
|
||||
int serverboundContainerClickPacket();
|
||||
|
||||
int serverboundSetCreativeModeSlotPacket();
|
||||
|
||||
int serverboundInteractPacket();
|
||||
|
||||
int clientboundUpdateRecipesPacket();
|
||||
}
|
||||
|
||||
@@ -32,25 +32,22 @@ public class ArmorStandPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isPresent()) {
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (!tokens.isEmpty()) {
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))));
|
||||
isChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entityDataId != EntityDataUtils.CUSTOM_NAME_DATA_ID) continue;
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))));
|
||||
isChanged = true;
|
||||
break;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
|
||||
@@ -47,22 +47,20 @@ public class BlockDisplayPacketHandler implements EntityPacketHandler {
|
||||
} else if (Config.interceptEntityName() && entityDataId == EntityDataUtils.CUSTOM_NAME_DATA_ID) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalTextComponent = (Optional<Object>) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (optionalTextComponent.isPresent()) {
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (!tokens.isEmpty()) {
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
|
||||
));
|
||||
isChanged = true;
|
||||
}
|
||||
if (optionalTextComponent.isEmpty()) continue;
|
||||
Object textComponent = optionalTextComponent.get();
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(
|
||||
entityDataId, serializer, Optional.of(ComponentUtils.adventureToMinecraft(component))
|
||||
));
|
||||
isChanged = true;
|
||||
}
|
||||
}
|
||||
if (isChanged) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.util.Optional;
|
||||
|
||||
public class CommonItemPacketHandler implements EntityPacketHandler {
|
||||
public static final CommonItemPacketHandler INSTANCE = new CommonItemPacketHandler();
|
||||
private static long lastWarningTime = 0;
|
||||
|
||||
@Override
|
||||
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
@@ -27,25 +28,28 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EntityDataUtils.ITEM_DATA_ID) {
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
// TODO 检查为什么会导致问题,难道是其他插件乱发entity id?
|
||||
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
|
||||
CraftEngine.instance().logger().warn("Invalid item data for entity " + id);
|
||||
continue;
|
||||
}
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||
if (optional.isPresent()) {
|
||||
isChanged = true;
|
||||
itemStack = optional.get();
|
||||
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)
|
||||
));
|
||||
break;
|
||||
if (entityDataId != EntityDataUtils.ITEM_DATA_ID) continue;
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
|
||||
long time = System.currentTimeMillis();
|
||||
if (time - lastWarningTime > 5000) {
|
||||
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
|
||||
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.");
|
||||
lastWarningTime = time;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||
if (optional.isEmpty()) continue;
|
||||
isChanged = true;
|
||||
itemStack = optional.get();
|
||||
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)
|
||||
));
|
||||
break;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
|
||||
@@ -25,20 +25,18 @@ public class ItemDisplayPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EntityDataUtils.DISPLAYED_ITEM_DATA_ID) {
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||
if (optional.isPresent()) {
|
||||
isChanged = true;
|
||||
itemStack = optional.get();
|
||||
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)
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entityDataId != EntityDataUtils.DISPLAYED_ITEM_DATA_ID) continue;
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||
if (optional.isEmpty()) continue;
|
||||
isChanged = true;
|
||||
itemStack = optional.get();
|
||||
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)
|
||||
));
|
||||
break;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.network.handler;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityDataUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ItemFramePacketHandler implements EntityPacketHandler {
|
||||
public static final ItemFramePacketHandler INSTANCE = new ItemFramePacketHandler();
|
||||
private static long lastWarningTime = 0;
|
||||
|
||||
@Override
|
||||
public void handleSetEntityData(NetWorkUser user, ByteBufPacketEvent event) {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
boolean isChanged = false;
|
||||
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId != EntityDataUtils.ITEM_FRAME_DATA_ID) continue;
|
||||
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
|
||||
long time = System.currentTimeMillis();
|
||||
if (time - lastWarningTime > 5000) {
|
||||
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
|
||||
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.");
|
||||
lastWarningTime = time;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
|
||||
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
|
||||
if (optional.isEmpty()) continue;
|
||||
isChanged = true;
|
||||
itemStack = optional.get();
|
||||
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)
|
||||
));
|
||||
break;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(id);
|
||||
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(packedItems, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,22 +31,20 @@ public class TextDisplayPacketHandler implements EntityPacketHandler {
|
||||
for (int i = 0; i < packedItems.size(); i++) {
|
||||
Object packedItem = packedItems.get(i);
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId == EntityDataUtils.TEXT_DATA_ID) {
|
||||
Object textComponent = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (textComponent == CoreReflections.instance$Component$empty) break;
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (!tokens.isEmpty()) {
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, ComponentUtils.adventureToMinecraft(component)));
|
||||
isChanged = true;
|
||||
break;
|
||||
}
|
||||
if (entityDataId != EntityDataUtils.TEXT_DATA_ID) continue;
|
||||
Object textComponent = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
|
||||
if (textComponent == CoreReflections.instance$Component$empty) break;
|
||||
String json = ComponentUtils.minecraftToJson(textComponent);
|
||||
Map<String, Component> tokens = CraftEngine.instance().fontManager().matchTags(json);
|
||||
if (tokens.isEmpty()) continue;
|
||||
Component component = AdventureHelper.jsonToComponent(json);
|
||||
for (Map.Entry<String, Component> token : tokens.entrySet()) {
|
||||
component = component.replaceText(b -> b.matchLiteral(token.getKey()).replacement(token.getValue()));
|
||||
}
|
||||
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem);
|
||||
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, ComponentUtils.adventureToMinecraft(component)));
|
||||
isChanged = true;
|
||||
break;
|
||||
}
|
||||
if (isChanged) {
|
||||
event.setChanged(true);
|
||||
|
||||
@@ -21,8 +21,8 @@ public class PacketIdFinder {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
Object packetReport = CoreReflections.constructor$PacketReport.newInstance((Object) null);
|
||||
JsonElement jsonElement = (JsonElement) CoreReflections.method$PacketReport$serializePackets.invoke(packetReport);
|
||||
var play = jsonElement.getAsJsonObject().get("play");
|
||||
for (var entry : play.getAsJsonObject().entrySet()) {
|
||||
JsonElement play = jsonElement.getAsJsonObject().get("play");
|
||||
for (Map.Entry<String, JsonElement> entry : play.getAsJsonObject().entrySet()) {
|
||||
Map<String, Integer> ids = new HashMap<>();
|
||||
gamePacketIdsByName.put(entry.getKey(), ids);
|
||||
for (var entry2 : entry.getValue().getAsJsonObject().entrySet()) {
|
||||
@@ -40,6 +40,7 @@ public class PacketIdFinder {
|
||||
maxS2CPacketId = calculateMaxId("clientbound");
|
||||
maxC2SPacketId = calculateMaxId("serverbound");
|
||||
}
|
||||
|
||||
private static int calculateMaxId(String direction) {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
return gamePacketIdsByName.getOrDefault(direction, Collections.emptyMap()).size();
|
||||
@@ -48,11 +49,11 @@ public class PacketIdFinder {
|
||||
}
|
||||
}
|
||||
|
||||
public static int maxC2SPacketId() {
|
||||
public static int c2sGamePackets() {
|
||||
return maxC2SPacketId;
|
||||
}
|
||||
|
||||
public static int maxS2CPacketId() {
|
||||
public static int s2cGamePackets() {
|
||||
return maxS2CPacketId;
|
||||
}
|
||||
|
||||
|
||||
@@ -149,4 +149,24 @@ public class PacketIds1_20 implements PacketIds {
|
||||
public int serverboundInteractPacket() {
|
||||
return PacketIdFinder.serverboundByClazz(NetworkReflections.clazz$ServerboundInteractPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundRecipeBookAddPacket() {
|
||||
return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundRecipeBookAddPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundPlaceGhostRecipePacket() {
|
||||
return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundPlaceGhostRecipePacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundUpdateRecipesPacket() {
|
||||
return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundUpdateRecipesPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundUpdateAdvancementsPacket() {
|
||||
return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundUpdateAdvancementsPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,26 @@ public class PacketIds1_20_5 implements PacketIds {
|
||||
return PacketIdFinder.clientboundByName("minecraft:block_event");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundRecipeBookAddPacket() {
|
||||
return PacketIdFinder.clientboundByName("minecraft:recipe_book_add");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundPlaceGhostRecipePacket() {
|
||||
return PacketIdFinder.clientboundByName("minecraft:place_ghost_recipe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundUpdateRecipesPacket() {
|
||||
return PacketIdFinder.clientboundByName("minecraft:update_recipes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientboundUpdateAdvancementsPacket() {
|
||||
return PacketIdFinder.clientboundByName("minecraft:update_advancements");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int serverboundContainerClickPacket() {
|
||||
return PacketIdFinder.serverboundByName("minecraft:container_click");
|
||||
|
||||
@@ -262,7 +262,7 @@ public final class CraftBukkitReflections {
|
||||
);
|
||||
|
||||
public static final Field field$CraftBlockEntityState$tileEntity = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$CraftBlockEntityState, 0)
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$CraftBlockEntityState, 0)
|
||||
);
|
||||
|
||||
public static final Method method$CraftInventory$getInventory = requireNonNull(
|
||||
|
||||
@@ -9,6 +9,7 @@ import io.netty.channel.ChannelFuture;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
@@ -289,11 +290,11 @@ public final class CoreReflections {
|
||||
)).getInterfaces()[0]
|
||||
);
|
||||
|
||||
public static final Method method$RegistryAccess$registryOrThrow = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$RegistryAccess, clazz$Registry, clazz$ResourceKey
|
||||
)
|
||||
);
|
||||
// public static final Method method$RegistryAccess$registryOrThrow = requireNonNull(
|
||||
// ReflectionUtils.getMethod(
|
||||
// clazz$RegistryAccess, clazz$Registry, clazz$ResourceKey
|
||||
// )
|
||||
// );
|
||||
|
||||
public static final Method method$Registry$register = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
@@ -328,58 +329,52 @@ public final class CoreReflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Registry$getKey = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$Registry, clazz$ResourceLocation, Object.class)
|
||||
);
|
||||
// public static final Method method$Registry$getKey = requireNonNull(
|
||||
// ReflectionUtils.getMethod(clazz$Registry, clazz$ResourceLocation, Object.class)
|
||||
// );
|
||||
|
||||
public static final Method method$Registry$get = requireNonNull(
|
||||
ReflectionUtils.getMethods(
|
||||
clazz$Registry, Object.class, clazz$ResourceLocation
|
||||
).stream().filter(m -> m.getReturnType() != Optional.class).findAny().orElse(null)
|
||||
);
|
||||
|
||||
// use ResourceLocation
|
||||
public static final Method method$Registry$getHolder0;
|
||||
// use ResourceKey
|
||||
public static final Method method$Registry$getHolder1;
|
||||
|
||||
static {
|
||||
List<Method> methods = ReflectionUtils.getMethods(clazz$Registry, Optional.class, clazz$ResourceLocation);
|
||||
Method theMethod1 = null;
|
||||
for (Method method : methods) {
|
||||
Type returnType = method.getGenericReturnType();
|
||||
if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == clazz$ResourceLocation) {
|
||||
if (returnType instanceof ParameterizedType parameterizedType) {
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArguments.length == 1) {
|
||||
if (actualTypeArguments[0] instanceof ParameterizedType) {
|
||||
theMethod1 = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
method$Registry$getHolder0 = theMethod1;
|
||||
}
|
||||
|
||||
static {
|
||||
List<Method> methods = ReflectionUtils.getMethods(clazz$Registry, Optional.class, clazz$ResourceKey);
|
||||
Method theMethod1 = null;
|
||||
for (Method method : methods) {
|
||||
Type returnType = method.getGenericReturnType();
|
||||
if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == clazz$ResourceKey) {
|
||||
if (returnType instanceof ParameterizedType parameterizedType) {
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArguments.length == 1) {
|
||||
if (actualTypeArguments[0] instanceof ParameterizedType) {
|
||||
theMethod1 = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
method$Registry$getHolder1 = theMethod1;
|
||||
}
|
||||
// // use ResourceLocation
|
||||
// public static final Method method$Registry$getHolder0;
|
||||
// // use ResourceKey
|
||||
// public static final Method method$Registry$getHolder1;
|
||||
//
|
||||
// static {
|
||||
// List<Method> methods = ReflectionUtils.getMethods(clazz$Registry, Optional.class, clazz$ResourceLocation);
|
||||
// Method theMethod1 = null;
|
||||
// for (Method method : methods) {
|
||||
// Type returnType = method.getGenericReturnType();
|
||||
// if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == clazz$ResourceLocation) {
|
||||
// if (returnType instanceof ParameterizedType parameterizedType) {
|
||||
// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
// if (actualTypeArguments.length == 1) {
|
||||
// if (actualTypeArguments[0] instanceof ParameterizedType) {
|
||||
// theMethod1 = method;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// method$Registry$getHolder0 = theMethod1;
|
||||
// }
|
||||
//
|
||||
// static {
|
||||
// List<Method> methods = ReflectionUtils.getMethods(clazz$Registry, Optional.class, clazz$ResourceKey);
|
||||
// Method theMethod1 = null;
|
||||
// for (Method method : methods) {
|
||||
// Type returnType = method.getGenericReturnType();
|
||||
// if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == clazz$ResourceKey) {
|
||||
// if (returnType instanceof ParameterizedType parameterizedType) {
|
||||
// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
// if (actualTypeArguments.length == 1) {
|
||||
// if (actualTypeArguments[0] instanceof ParameterizedType) {
|
||||
// theMethod1 = method;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// method$Registry$getHolder1 = theMethod1;
|
||||
// }
|
||||
|
||||
public static final Class<?> clazz$BlockPos = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
@@ -1328,6 +1323,10 @@ public final class CoreReflections {
|
||||
public static final Field field$BlockStateBase$lightBlock =
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$BlockStateBase, int.class, 1);
|
||||
|
||||
// 1.20-1.21.1
|
||||
public static final Field field$BlockStateBase$opacityIfCached =
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$BlockStateBase, int.class, 1);
|
||||
|
||||
public static final Class<?> clazz$AABB = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.phys.AxisAlignedBB",
|
||||
@@ -1825,18 +1824,10 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$Abilities, boolean.class, 2)
|
||||
);
|
||||
|
||||
public static final Field field$Abilities$instabuild = requireNonNull(
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$Abilities, boolean.class, 3)
|
||||
);
|
||||
|
||||
public static final Field field$Abilities$mayBuild = requireNonNull(
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$Abilities, boolean.class, 4)
|
||||
);
|
||||
|
||||
public static final Field field$Player$abilities = requireNonNull(
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$Player, clazz$Abilities, 0)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$FlowingFluid = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.material.FluidTypeFlowing",
|
||||
@@ -2299,12 +2290,26 @@ public final class CoreReflections {
|
||||
|
||||
public static final Constructor<?> constructor$SmithingTransformRecipe = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_5()
|
||||
? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, clazz$Ingredient, Optional.class, clazz$TransmuteResult)
|
||||
: VersionHelper.isOrAbove1_21_2()
|
||||
? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack)
|
||||
: VersionHelper.isOrAbove1_20_2()
|
||||
? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack)
|
||||
: ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack)
|
||||
? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, clazz$Ingredient, Optional.class, clazz$TransmuteResult)
|
||||
: VersionHelper.isOrAbove1_21_2()
|
||||
? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack)
|
||||
: VersionHelper.isOrAbove1_20_2()
|
||||
? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack)
|
||||
: ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$SmithingTrimRecipe = requireNonNull(
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("world.item.crafting.SmithingTrimRecipe"))
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$SmithingTrimRecipe = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_5() ?
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$Holder) :
|
||||
VersionHelper.isOrAbove1_21_2() ?
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, Optional.class, Optional.class, Optional.class) :
|
||||
VersionHelper.isOrAbove1_20_2() ?
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient) :
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient)
|
||||
);
|
||||
|
||||
public static final Method method$RecipeManager$addRecipe = requireNonNull(
|
||||
@@ -3588,4 +3593,241 @@ public final class CoreReflections {
|
||||
"nbt.CompoundTag"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$TrimPattern = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_2() ?
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.equipment.trim.TrimPattern",
|
||||
"world.item.equipment.trim.TrimPattern"
|
||||
) :
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.armortrim.TrimPattern",
|
||||
"world.item.armortrim.TrimPattern"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$TrimMaterial = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_2() ?
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.equipment.trim.TrimMaterial",
|
||||
"world.item.equipment.trim.TrimMaterial"
|
||||
) :
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.armortrim.TrimMaterial",
|
||||
"world.item.armortrim.TrimMaterial"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$MaterialAssetGroup = BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.equipment.trim.MaterialAssetGroup",
|
||||
"world.item.equipment.trim.MaterialAssetGroup"
|
||||
);
|
||||
|
||||
public static final Method method$MaterialAssetGroup$create = Optional.ofNullable(clazz$MaterialAssetGroup)
|
||||
.map(it -> ReflectionUtils.getStaticMethod(it, it, String.class)).orElse(null);
|
||||
|
||||
public static final Constructor<?> constructor$TrimPattern = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_5() ?
|
||||
ReflectionUtils.getConstructor(clazz$TrimPattern, clazz$ResourceLocation, clazz$Component, boolean.class) :
|
||||
VersionHelper.isOrAbove1_20_2() ?
|
||||
ReflectionUtils.getConstructor(clazz$TrimPattern, clazz$ResourceLocation, clazz$Holder, clazz$Component, boolean.class) :
|
||||
ReflectionUtils.getConstructor(clazz$TrimPattern, clazz$ResourceLocation, clazz$Holder, clazz$Component)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$TrimMaterial = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_5() ?
|
||||
ReflectionUtils.getConstructor(clazz$TrimMaterial, clazz$MaterialAssetGroup, clazz$Component) :
|
||||
VersionHelper.isOrAbove1_21_4() ?
|
||||
ReflectionUtils.getConstructor(clazz$TrimMaterial, String.class, clazz$Holder, Map.class, clazz$Component) :
|
||||
ReflectionUtils.getConstructor(clazz$TrimMaterial, String.class, clazz$Holder, float.class, Map.class, clazz$Component)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerConfigurationPacketListenerImpl = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("server.network.ServerConfigurationPacketListenerImpl")
|
||||
),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Field field$ServerConfigurationPacketListenerImpl$configurationTasks = Optional.ofNullable(clazz$ServerConfigurationPacketListenerImpl)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, Queue.class, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final MethodHandle methodHandle$ServerConfigurationPacketListenerImpl$configurationTasksGetter;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
methodHandle$ServerConfigurationPacketListenerImpl$configurationTasksGetter =
|
||||
ReflectionUtils.unreflectGetter(field$ServerConfigurationPacketListenerImpl$configurationTasks)
|
||||
.asType(MethodType.methodType(Queue.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ServerConfigurationPacketListenerImpl$configurationTasksGetter = null;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ReflectionInitException("Failed to initialize reflection", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$JoinWorldTask = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("server.network.config.JoinWorldTask")
|
||||
),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Constructor<?> constructor$JoinWorldTask = Optional.ofNullable(clazz$JoinWorldTask)
|
||||
.map(ReflectionUtils::getTheOnlyConstructor)
|
||||
.orElse(null);
|
||||
|
||||
public static final Class<?> clazz$ConfigurationTask$Type = MiscUtils.requireNonNullIf(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"server.network.ConfigurationTask$a",
|
||||
"server.network.ConfigurationTask$Type"
|
||||
),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Field field$JoinWorldTask$TYPE = Optional.ofNullable(clazz$JoinWorldTask)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, clazz$ConfigurationTask$Type, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Class<?> clazz$ServerResourcePackConfigurationTask = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("server.network.config.ServerResourcePackConfigurationTask")
|
||||
),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Field field$ServerResourcePackConfigurationTask$TYPE = Optional.ofNullable(clazz$ServerResourcePackConfigurationTask)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, clazz$ConfigurationTask$Type, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Object instance$JoinWorldTask;
|
||||
public static final Object instance$JoinWorldTask$TYPE;
|
||||
public static final Object instance$ServerResourcePackConfigurationTask$TYPE;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
instance$JoinWorldTask = constructor$JoinWorldTask.newInstance();
|
||||
instance$JoinWorldTask$TYPE = field$JoinWorldTask$TYPE.get(null);
|
||||
instance$ServerResourcePackConfigurationTask$TYPE = field$ServerResourcePackConfigurationTask$TYPE.get(null);
|
||||
} else {
|
||||
instance$JoinWorldTask = null;
|
||||
instance$JoinWorldTask$TYPE = null;
|
||||
instance$ServerResourcePackConfigurationTask$TYPE = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize reflection", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 注释的这些说不定以后调试有用
|
||||
// public static final Class<?> clazz$ConfigurationTask = MiscUtils.requireNonNullIf(
|
||||
// ReflectionUtils.getClazz(
|
||||
// BukkitReflectionUtils.assembleMCClass("server.network.ConfigurationTask")
|
||||
// ),
|
||||
// VersionHelper.isOrAbove1_20_2()
|
||||
// );
|
||||
//
|
||||
// public static final Field field$ServerConfigurationPacketListenerImpl$currentTask = MiscUtils.requireNonNullIf(
|
||||
// ReflectionUtils.getDeclaredField(clazz$ServerConfigurationPacketListenerImpl, clazz$ConfigurationTask, 0),
|
||||
// VersionHelper.isOrAbove1_20_2()
|
||||
// );
|
||||
|
||||
// 1.20.2+
|
||||
public static final Method method$ServerConfigurationPacketListenerImpl$finishCurrentTask = Optional.ofNullable(clazz$ServerConfigurationPacketListenerImpl)
|
||||
.map(it -> ReflectionUtils.getDeclaredMethod(it, void.class, clazz$ConfigurationTask$Type))
|
||||
.orElse( null);
|
||||
|
||||
public static final Field field$ServerCommonPacketListenerImpl$closed = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getDeclaredField(clazz$ServerCommonPacketListenerImpl, boolean.class, VersionHelper.isOrAbove1_21_6() ? 1 : 2),
|
||||
VersionHelper.isOrAbove1_20_5()
|
||||
);
|
||||
|
||||
public static final MethodHandle methodHandle$ServerConfigurationPacketListenerImpl$finishCurrentTask;
|
||||
public static final MethodHandle methodHandle$ServerCommonPacketListenerImpl$closedSetter;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
methodHandle$ServerConfigurationPacketListenerImpl$finishCurrentTask =
|
||||
ReflectionUtils.unreflectMethod(method$ServerConfigurationPacketListenerImpl$finishCurrentTask)
|
||||
.asType(MethodType.methodType(void.class, Object.class, Object.class));
|
||||
methodHandle$ServerCommonPacketListenerImpl$closedSetter =
|
||||
ReflectionUtils.unreflectSetter(field$ServerCommonPacketListenerImpl$closed)
|
||||
.asType(MethodType.methodType(void.class, Object.class, boolean.class));
|
||||
} else {
|
||||
methodHandle$ServerConfigurationPacketListenerImpl$finishCurrentTask = null;
|
||||
methodHandle$ServerCommonPacketListenerImpl$closedSetter = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize reflection", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Block$playerWillDestroy = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$Block,
|
||||
VersionHelper.isOrAbove1_20_3() ? clazz$BlockState : void.class,
|
||||
clazz$Level, clazz$BlockPos, clazz$BlockState, clazz$Player
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$BlockItem = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.item.ItemBlock",
|
||||
"world.item.BlockItem"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ArmorTrim = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
VersionHelper.isOrAbove1_21_2() ?
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.equipment.trim.ArmorTrim") :
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.armortrim.ArmorTrim")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ArmorTrim$CODEC = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$ArmorTrim, Codec.class, 0)
|
||||
);
|
||||
|
||||
public static final Codec<?> instance$ArmorTrim$CODEC;
|
||||
|
||||
static {
|
||||
try {
|
||||
instance$ArmorTrim$CODEC = (Codec<?>) field$ArmorTrim$CODEC.get(null);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize ArmorTrim CODEC", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$ArmorTrim$setTrim = ReflectionUtils.getStaticMethod(
|
||||
clazz$ArmorTrim, boolean.class, clazz$RegistryAccess, clazz$ItemStack, clazz$ArmorTrim
|
||||
);
|
||||
|
||||
public static final Method method$ArmorTrim$getTrim =
|
||||
VersionHelper.isOrAbove1_20_2() ?
|
||||
ReflectionUtils.getStaticMethod(clazz$ArmorTrim, Optional.class, clazz$RegistryAccess, clazz$ItemStack, boolean.class) :
|
||||
ReflectionUtils.getStaticMethod(clazz$ArmorTrim, Optional.class, clazz$RegistryAccess, clazz$ItemStack);
|
||||
|
||||
public static final Method method$BlockBehaviour$spawnAfterBreak = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$ServerLevel, clazz$BlockPos, clazz$ItemStack, boolean.class
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20~1.21.4
|
||||
public static final Method method$BlockBehaviour$onRemove = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$Level, clazz$BlockPos, clazz$BlockState, boolean.class
|
||||
),
|
||||
!VersionHelper.isOrAbove1_21_5()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class MAttributeHolders {
|
||||
private MAttributeHolders() {}
|
||||
|
||||
@@ -12,26 +10,20 @@ public final class MAttributeHolders {
|
||||
public static final Object BLOCK_INTERACTION_RANGE;
|
||||
public static final Object SCALE;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
Optional<Object> optionalHolder = (Optional<Object>) CoreReflections.method$Registry$getHolder0.invoke(MBuiltInRegistries.ATTRIBUTE, rl);
|
||||
return optionalHolder.orElse(null);
|
||||
return FastNMS.INSTANCE.method$Registry$getHolderByResourceLocation(MBuiltInRegistries.ATTRIBUTE, rl).get();
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
BLOCK_BREAK_SPEED = getById(VersionHelper.isOrAbove1_21_2() ? "block_break_speed" : "player.block_break_speed");
|
||||
BLOCK_INTERACTION_RANGE = getById(VersionHelper.isOrAbove1_21_2() ? "block_interaction_range" : "player.block_interaction_range");
|
||||
SCALE = getById(VersionHelper.isOrAbove1_21_2() ? "scale" : "generic.scale");
|
||||
} else {
|
||||
BLOCK_BREAK_SPEED = null;
|
||||
BLOCK_INTERACTION_RANGE = null;
|
||||
SCALE = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
if (VersionHelper.isOrAbove1_20_5()) {
|
||||
BLOCK_BREAK_SPEED = getById(VersionHelper.isOrAbove1_21_2() ? "block_break_speed" : "player.block_break_speed");
|
||||
BLOCK_INTERACTION_RANGE = getById(VersionHelper.isOrAbove1_21_2() ? "block_interaction_range" : "player.block_interaction_range");
|
||||
SCALE = getById(VersionHelper.isOrAbove1_21_2() ? "scale" : "generic.scale");
|
||||
} else {
|
||||
BLOCK_BREAK_SPEED = null;
|
||||
BLOCK_INTERACTION_RANGE = null;
|
||||
SCALE = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
public final class MBlocks {
|
||||
@@ -19,26 +18,22 @@ public final class MBlocks {
|
||||
public static final Object SHULKER_BOX;
|
||||
public static final Object COMPOSTER;
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.BLOCK, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.BLOCK, rl);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
AIR = getById("air");
|
||||
AIR$defaultState = FastNMS.INSTANCE.method$Block$defaultState(AIR);
|
||||
FIRE = getById("fire");
|
||||
SOUL_FIRE = getById("soul_fire");
|
||||
STONE = getById("stone");
|
||||
STONE$defaultState = FastNMS.INSTANCE.method$Block$defaultState(STONE);
|
||||
ICE = getById("ice");
|
||||
SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||
SHORT_GRASS$defaultState = FastNMS.INSTANCE.method$Block$defaultState(SHORT_GRASS);
|
||||
SHULKER_BOX = getById("shulker_box");
|
||||
COMPOSTER = getById("composter");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init Blocks", e);
|
||||
}
|
||||
AIR = getById("air");
|
||||
AIR$defaultState = FastNMS.INSTANCE.method$Block$defaultState(AIR);
|
||||
FIRE = getById("fire");
|
||||
SOUL_FIRE = getById("soul_fire");
|
||||
STONE = getById("stone");
|
||||
STONE$defaultState = FastNMS.INSTANCE.method$Block$defaultState(STONE);
|
||||
ICE = getById("ice");
|
||||
SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||
SHORT_GRASS$defaultState = FastNMS.INSTANCE.method$Block$defaultState(SHORT_GRASS);
|
||||
SHULKER_BOX = getById("shulker_box");
|
||||
COMPOSTER = getById("composter");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
public final class MEntityTypes {
|
||||
@@ -60,72 +59,68 @@ public final class MEntityTypes {
|
||||
public static final Object PLAYER;
|
||||
public static final int PLAYER$registryId;
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.ENTITY_TYPE, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ENTITY_TYPE, rl);
|
||||
}
|
||||
|
||||
private static int getRegistryId(Object type) throws ReflectiveOperationException {
|
||||
private static int getRegistryId(Object type) {
|
||||
if (type == null) return -1;
|
||||
return (int) CoreReflections.method$Registry$getId.invoke(MBuiltInRegistries.ENTITY_TYPE, type);
|
||||
return FastNMS.INSTANCE.method$Registry$getId(MBuiltInRegistries.ENTITY_TYPE, type);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
TEXT_DISPLAY = getById("text_display");
|
||||
TEXT_DISPLAY$registryId = getRegistryId(TEXT_DISPLAY);
|
||||
ITEM_DISPLAY = getById("item_display");
|
||||
ITEM_DISPLAY$registryId = getRegistryId(ITEM_DISPLAY);
|
||||
BLOCK_DISPLAY = getById("block_display");
|
||||
BLOCK_DISPLAY$registryId = getRegistryId(BLOCK_DISPLAY);
|
||||
FALLING_BLOCK = getById("falling_block");
|
||||
FALLING_BLOCK$registryId = getRegistryId(FALLING_BLOCK);
|
||||
INTERACTION = getById("interaction");
|
||||
INTERACTION$registryId = getRegistryId(INTERACTION);
|
||||
SHULKER = getById("shulker");
|
||||
SHULKER$registryId = getRegistryId(SHULKER);
|
||||
ARMOR_STAND = getById("armor_stand");
|
||||
ARMOR_STAND$registryId = getRegistryId(ARMOR_STAND);
|
||||
OAK_BOAT = getById(VersionHelper.isOrAbove1_21_2() ? "oak_boat" : "boat");
|
||||
OAK_BOAT$registryId = getRegistryId(OAK_BOAT);
|
||||
TRIDENT = getById("trident");
|
||||
TRIDENT$registryId = getRegistryId(TRIDENT);
|
||||
SNOWBALL = getById("snowball");
|
||||
SNOWBALL$registryId = getRegistryId(SNOWBALL);
|
||||
FIREBALL = getById("fireball");
|
||||
FIREBALL$registryId = getRegistryId(FIREBALL);
|
||||
EYE_OF_ENDER = getById("eye_of_ender");
|
||||
EYE_OF_ENDER$registryId = getRegistryId(EYE_OF_ENDER);
|
||||
FIREWORK_ROCKET = getById("firework_rocket");
|
||||
FIREWORK_ROCKET$registryId = getRegistryId(FIREWORK_ROCKET);
|
||||
ITEM = getById("item");
|
||||
ITEM$registryId = getRegistryId(ITEM);
|
||||
ITEM_FRAME = getById("item_frame");
|
||||
ITEM_FRAME$registryId = getRegistryId(ITEM_FRAME);
|
||||
GLOW_ITEM_FRAME = getById("glow_item_frame");
|
||||
GLOW_ITEM_FRAME$registryId = getRegistryId(GLOW_ITEM_FRAME);
|
||||
SMALL_FIREBALL = getById("small_fireball");
|
||||
SMALL_FIREBALL$registryId = getRegistryId(SMALL_FIREBALL);
|
||||
EGG = getById("egg");
|
||||
EGG$registryId = getRegistryId(EGG);
|
||||
ENDER_PEARL = getById("ender_pearl");
|
||||
ENDER_PEARL$registryId = getRegistryId(ENDER_PEARL);
|
||||
EXPERIENCE_BOTTLE = getById("experience_bottle");
|
||||
EXPERIENCE_BOTTLE$registryId = getRegistryId(EXPERIENCE_BOTTLE);
|
||||
POTION = getById("potion");
|
||||
POTION$registryId = getRegistryId(POTION);
|
||||
OMINOUS_ITEM_SPAWNER = VersionHelper.isOrAbove1_20_5() ? getById("ominous_item_spawner") : null;
|
||||
OMINOUS_ITEM_SPAWNER$registryId = getRegistryId(OMINOUS_ITEM_SPAWNER);
|
||||
HAPPY_GHAST = VersionHelper.isOrAbove1_21_6() ? getById("happy_ghast") : null;
|
||||
HAPPY_GHAST$registryId = getRegistryId(HAPPY_GHAST);
|
||||
PLAYER = getById("player");
|
||||
PLAYER$registryId = getRegistryId(PLAYER);
|
||||
ARROW = getById("arrow");
|
||||
ARROW$registryId = getRegistryId(ARROW);
|
||||
SPECTRAL_ARROW = getById("spectral_arrow");
|
||||
SPECTRAL_ARROW$registryId = getRegistryId(SPECTRAL_ARROW);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init EntityTypes", e);
|
||||
}
|
||||
TEXT_DISPLAY = getById("text_display");
|
||||
TEXT_DISPLAY$registryId = getRegistryId(TEXT_DISPLAY);
|
||||
ITEM_DISPLAY = getById("item_display");
|
||||
ITEM_DISPLAY$registryId = getRegistryId(ITEM_DISPLAY);
|
||||
BLOCK_DISPLAY = getById("block_display");
|
||||
BLOCK_DISPLAY$registryId = getRegistryId(BLOCK_DISPLAY);
|
||||
FALLING_BLOCK = getById("falling_block");
|
||||
FALLING_BLOCK$registryId = getRegistryId(FALLING_BLOCK);
|
||||
INTERACTION = getById("interaction");
|
||||
INTERACTION$registryId = getRegistryId(INTERACTION);
|
||||
SHULKER = getById("shulker");
|
||||
SHULKER$registryId = getRegistryId(SHULKER);
|
||||
ARMOR_STAND = getById("armor_stand");
|
||||
ARMOR_STAND$registryId = getRegistryId(ARMOR_STAND);
|
||||
OAK_BOAT = getById(VersionHelper.isOrAbove1_21_2() ? "oak_boat" : "boat");
|
||||
OAK_BOAT$registryId = getRegistryId(OAK_BOAT);
|
||||
TRIDENT = getById("trident");
|
||||
TRIDENT$registryId = getRegistryId(TRIDENT);
|
||||
SNOWBALL = getById("snowball");
|
||||
SNOWBALL$registryId = getRegistryId(SNOWBALL);
|
||||
FIREBALL = getById("fireball");
|
||||
FIREBALL$registryId = getRegistryId(FIREBALL);
|
||||
EYE_OF_ENDER = getById("eye_of_ender");
|
||||
EYE_OF_ENDER$registryId = getRegistryId(EYE_OF_ENDER);
|
||||
FIREWORK_ROCKET = getById("firework_rocket");
|
||||
FIREWORK_ROCKET$registryId = getRegistryId(FIREWORK_ROCKET);
|
||||
ITEM = getById("item");
|
||||
ITEM$registryId = getRegistryId(ITEM);
|
||||
ITEM_FRAME = getById("item_frame");
|
||||
ITEM_FRAME$registryId = getRegistryId(ITEM_FRAME);
|
||||
GLOW_ITEM_FRAME = getById("glow_item_frame");
|
||||
GLOW_ITEM_FRAME$registryId = getRegistryId(GLOW_ITEM_FRAME);
|
||||
SMALL_FIREBALL = getById("small_fireball");
|
||||
SMALL_FIREBALL$registryId = getRegistryId(SMALL_FIREBALL);
|
||||
EGG = getById("egg");
|
||||
EGG$registryId = getRegistryId(EGG);
|
||||
ENDER_PEARL = getById("ender_pearl");
|
||||
ENDER_PEARL$registryId = getRegistryId(ENDER_PEARL);
|
||||
EXPERIENCE_BOTTLE = getById("experience_bottle");
|
||||
EXPERIENCE_BOTTLE$registryId = getRegistryId(EXPERIENCE_BOTTLE);
|
||||
POTION = getById("potion");
|
||||
POTION$registryId = getRegistryId(POTION);
|
||||
OMINOUS_ITEM_SPAWNER = VersionHelper.isOrAbove1_20_5() ? getById("ominous_item_spawner") : null;
|
||||
OMINOUS_ITEM_SPAWNER$registryId = getRegistryId(OMINOUS_ITEM_SPAWNER);
|
||||
HAPPY_GHAST = VersionHelper.isOrAbove1_21_6() ? getById("happy_ghast") : null;
|
||||
HAPPY_GHAST$registryId = getRegistryId(HAPPY_GHAST);
|
||||
PLAYER = getById("player");
|
||||
PLAYER$registryId = getRegistryId(PLAYER);
|
||||
ARROW = getById("arrow");
|
||||
ARROW$registryId = getRegistryId(ARROW);
|
||||
SPECTRAL_ARROW = getById("spectral_arrow");
|
||||
SPECTRAL_ARROW$registryId = getRegistryId(SPECTRAL_ARROW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class MFluids {
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.FLUID, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.FLUID, rl);
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
|
||||
public final class MItems {
|
||||
private MItems() {}
|
||||
|
||||
public static final Object AIR;
|
||||
public static final Object WATER_BUCKET;
|
||||
public static final Object BARRIER;
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.ITEM, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, rl);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
AIR = getById("air");
|
||||
WATER_BUCKET = getById("water_bucket");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init Items", e);
|
||||
}
|
||||
AIR = getById("air");
|
||||
WATER_BUCKET = getById("water_bucket");
|
||||
BARRIER = getById("barrier");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
|
||||
public final class MMobEffects {
|
||||
private MMobEffects() {}
|
||||
@@ -10,19 +9,15 @@ public final class MMobEffects {
|
||||
public static final Object HASTE;
|
||||
public static final Object INVISIBILITY;
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.MOB_EFFECT, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.MOB_EFFECT, rl);
|
||||
}
|
||||
|
||||
// for 1.20.1-1.20.4
|
||||
static {
|
||||
try {
|
||||
MINING_FATIGUE = getById("mining_fatigue");
|
||||
HASTE = getById("haste");
|
||||
INVISIBILITY = getById("invisibility");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init MobEffects", e);
|
||||
}
|
||||
MINING_FATIGUE = getById("mining_fatigue");
|
||||
HASTE = getById("haste");
|
||||
INVISIBILITY = getById("invisibility");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
|
||||
public final class MRecipeTypes {
|
||||
private MRecipeTypes() {}
|
||||
@@ -14,22 +13,18 @@ public final class MRecipeTypes {
|
||||
public static final Object STONECUTTING;
|
||||
public static final Object SMITHING;
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.RECIPE_TYPE, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.RECIPE_TYPE, rl);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
CRAFTING = getById("crafting");
|
||||
SMELTING = getById("smelting");
|
||||
BLASTING = getById("blasting");
|
||||
SMOKING = getById("smoking");
|
||||
CAMPFIRE_COOKING = getById("campfire_cooking");
|
||||
STONECUTTING = getById("stonecutting");
|
||||
SMITHING = getById("smithing");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init RecipeTypes", e);
|
||||
}
|
||||
CRAFTING = getById("crafting");
|
||||
SMELTING = getById("smelting");
|
||||
BLASTING = getById("blasting");
|
||||
SMOKING = getById("smoking");
|
||||
CAMPFIRE_COOKING = getById("campfire_cooking");
|
||||
STONECUTTING = getById("stonecutting");
|
||||
SMITHING = getById("smithing");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ public final class MRegistries {
|
||||
public static final Object DIMENSION_TYPE;
|
||||
public static final Object CONFIGURED_FEATURE;
|
||||
public static final Object PLACED_FEATURE;
|
||||
public static final Object TRIM_PATTERN;
|
||||
public static final Object TRIM_MATERIAL;
|
||||
@Nullable // 1.21+
|
||||
public static final Object JUKEBOX_SONG;
|
||||
@Nullable // 1.21+
|
||||
@@ -46,6 +48,8 @@ public final class MRegistries {
|
||||
Object registries$PlacedFeature = null;
|
||||
Object registries$JukeboxSong = null;
|
||||
Object registries$Recipe = null;
|
||||
Object registries$TrimPattern = null;
|
||||
Object registries$TrimMaterial = null;
|
||||
for (Field field : fields) {
|
||||
Type fieldType = field.getGenericType();
|
||||
if (fieldType instanceof ParameterizedType paramType) {
|
||||
@@ -87,6 +91,10 @@ public final class MRegistries {
|
||||
registries$JukeboxSong = field.get(null);
|
||||
} else if (type == CoreReflections.clazz$PlacedFeature) {
|
||||
registries$PlacedFeature = field.get(null);
|
||||
} else if (type == CoreReflections.clazz$TrimPattern) {
|
||||
registries$TrimPattern = field.get(null);
|
||||
} else if (type == CoreReflections.clazz$TrimMaterial) {
|
||||
registries$TrimMaterial = field.get(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,6 +114,8 @@ public final class MRegistries {
|
||||
RECIPE_TYPE = requireNonNull(registries$RecipeType);
|
||||
CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature);
|
||||
PLACED_FEATURE = requireNonNull(registries$PlacedFeature);
|
||||
TRIM_PATTERN = requireNonNull(registries$TrimPattern);
|
||||
TRIM_MATERIAL = requireNonNull(registries$TrimMaterial);
|
||||
JUKEBOX_SONG = registries$JukeboxSong;
|
||||
RECIPE = registries$Recipe;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
|
||||
public final class MSoundEvents {
|
||||
private MSoundEvents() {}
|
||||
@@ -12,20 +11,16 @@ public final class MSoundEvents {
|
||||
public static final Object TRIDENT_RIPTIDE_3;
|
||||
public static final Object TRIDENT_THROW;
|
||||
|
||||
private static Object getById(String id) throws ReflectiveOperationException {
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
return CoreReflections.method$Registry$get.invoke(MBuiltInRegistries.SOUND_EVENT, rl);
|
||||
return FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.SOUND_EVENT, rl);
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
EMPTY = getById("intentionally_empty");
|
||||
TRIDENT_RIPTIDE_1 = getById("item.trident_riptide_1");
|
||||
TRIDENT_RIPTIDE_2 = getById("item.trident_riptide_2");
|
||||
TRIDENT_RIPTIDE_3 = getById("item.trident.riptide_3");
|
||||
TRIDENT_THROW = getById("item.trident.throw");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init SoundEvents", e);
|
||||
}
|
||||
EMPTY = getById("intentionally_empty");
|
||||
TRIDENT_RIPTIDE_1 = getById("item.trident_riptide_1");
|
||||
TRIDENT_RIPTIDE_2 = getById("item.trident_riptide_2");
|
||||
TRIDENT_RIPTIDE_3 = getById("item.trident.riptide_3");
|
||||
TRIDENT_THROW = getById("item.trident.throw");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
@@ -1315,7 +1316,6 @@ public final class NetworkReflections {
|
||||
public static final MethodHandle methodHandle$ServerboundEditBookPacket$pagesGetter;
|
||||
public static final MethodHandle methodHandle$ServerboundEditBookPacket$titleGetter;
|
||||
public static final MethodHandle methodHandle$ServerboundEditBookPacket$slotGetter;
|
||||
public static final MethodHandle methodHandle$ServerboundResourcePackPacket$actionGetter;
|
||||
public static final MethodHandle methodHandle$ClientboundEntityEventPacket$entityIdGetter;
|
||||
public static final MethodHandle methodHandle$ClientboundEntityEventPacket$eventIdGetter;
|
||||
public static final MethodHandle methodHandle$ClientIntentionPacket$protocolVersionGetter;
|
||||
@@ -1385,10 +1385,6 @@ public final class NetworkReflections {
|
||||
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$slot)
|
||||
.asType(MethodType.methodType(int.class, Object.class))
|
||||
);
|
||||
methodHandle$ServerboundResourcePackPacket$actionGetter = requireNonNull(
|
||||
ReflectionUtils.unreflectGetter(field$ServerboundResourcePackPacket$action)
|
||||
.asType(MethodType.methodType(Object.class, Object.class))
|
||||
);
|
||||
methodHandle$ClientboundEntityEventPacket$entityIdGetter = requireNonNull(
|
||||
ReflectionUtils.unreflectGetter(field$ClientboundEntityEventPacket$entityId)
|
||||
.asType(MethodType.methodType(int.class, Object.class))
|
||||
@@ -1497,4 +1493,105 @@ public final class NetworkReflections {
|
||||
throw new ReflectionInitException("Failed to initialize ParticleTypes$STREAM_CODEC", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$ClientboundFinishConfigurationPacket = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.configuration.ClientboundFinishConfigurationPacket")
|
||||
),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Constructor<?> constructor$ClientboundFinishConfigurationPacket = Optional.ofNullable(clazz$ClientboundFinishConfigurationPacket)
|
||||
.map(ReflectionUtils::getConstructor)
|
||||
.orElse(null);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Field field$ClientboundFinishConfigurationPacket$INSTANCE = Optional.ofNullable(clazz$ClientboundFinishConfigurationPacket)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, it, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Object instance$ClientboundFinishConfigurationPacket$INSTANCE;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
instance$ClientboundFinishConfigurationPacket$INSTANCE = VersionHelper.isOrAbove1_20_5()
|
||||
? field$ClientboundFinishConfigurationPacket$INSTANCE.get(null)
|
||||
: constructor$ClientboundFinishConfigurationPacket.newInstance();
|
||||
} else {
|
||||
instance$ClientboundFinishConfigurationPacket$INSTANCE = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize ClientboundFinishConfigurationPacket$INSTANCE", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$ServerCommonPacketListener = MiscUtils.requireNonNullIf(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.common.ServerCommonPacketListener")
|
||||
),
|
||||
VersionHelper.isOrAbove1_20_2()
|
||||
);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Method method$ServerCommonPacketListener$handleResourcePackResponse = Optional.ofNullable(clazz$ServerCommonPacketListener)
|
||||
.map(it -> ReflectionUtils.getMethod(it, void.class, clazz$ServerboundResourcePackPacket))
|
||||
.orElse(null);
|
||||
|
||||
public static final MethodHandle methodHandle$ServerCommonPacketListener$handleResourcePackResponse;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
methodHandle$ServerCommonPacketListener$handleResourcePackResponse =
|
||||
ReflectionUtils.unreflectMethod(method$ServerCommonPacketListener$handleResourcePackResponse)
|
||||
.asType(MethodType.methodType(void.class, Object.class, Object.class));
|
||||
} else {
|
||||
methodHandle$ServerCommonPacketListener$handleResourcePackResponse = null;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to initialize ServerCommonPacketListener$handleResourcePackResponse", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$ClientboundLoginFinishedPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.login.PacketLoginOutSuccess",
|
||||
List.of("network.protocol.login.ClientboundLoginFinishedPacket", "network.protocol.login.ClientboundGameProfilePacket")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundRecipeBookAddPacket = MiscUtils.requireNonNullIf(BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.ClientboundRecipeBookAddPacket",
|
||||
"network.protocol.game.ClientboundRecipeBookAddPacket"
|
||||
), VersionHelper.isOrAbove1_21_2());
|
||||
|
||||
public static final Class<?> clazz$ClientboundPlaceGhostRecipePacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.PacketPlayOutAutoRecipe",
|
||||
"network.protocol.game.ClientboundPlaceGhostRecipePacket"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundUpdateRecipesPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.PacketPlayOutRecipeUpdate",
|
||||
"network.protocol.game.ClientboundUpdateRecipesPacket"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundUpdateAdvancementsPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"network.protocol.game.PacketPlayOutAdvancements",
|
||||
"network.protocol.game.ClientboundUpdateAdvancementsPacket"
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClientboundUpdateTagsPacket = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
List.of("network.protocol.common.ClientboundUpdateTagsPacket", "network.protocol.game.PacketPlayOutTags"),
|
||||
List.of("network.protocol.common.ClientboundUpdateTagsPacket", "network.protocol.game.ClientboundUpdateTagsPacket")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.CooldownData;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
|
||||
import net.momirealms.craftengine.core.plugin.network.ProtocolVersion;
|
||||
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
@@ -48,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;
|
||||
@@ -58,8 +58,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BukkitServerPlayer extends Player {
|
||||
private final BukkitCraftEngine plugin;
|
||||
// handshake
|
||||
private ProtocolVersion protocolVersion = ProtocolVersion.UNKNOWN;
|
||||
|
||||
// connection state
|
||||
private final Channel channel;
|
||||
private ChannelHandler connection;
|
||||
@@ -67,8 +66,8 @@ public class BukkitServerPlayer extends Player {
|
||||
private UUID uuid;
|
||||
private ConnectionState decoderState;
|
||||
private ConnectionState encoderState;
|
||||
private boolean shouldProcessFinishConfiguration = true;
|
||||
private final Set<UUID> resourcePackUUID = Collections.synchronizedSet(new HashSet<>());
|
||||
private boolean sentResourcePack = !Config.sendPackOnJoin();
|
||||
// some references
|
||||
private Reference<org.bukkit.entity.Player> playerRef;
|
||||
private Reference<Object> serverPlayerRef;
|
||||
@@ -252,13 +251,8 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
@Override
|
||||
public boolean canInstabuild() {
|
||||
try {
|
||||
Object abilities = CoreReflections.field$Player$abilities.get(serverPlayer());
|
||||
return (boolean) CoreReflections.field$Abilities$instabuild.get(abilities);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to get canInstabuild for " + name(), e);
|
||||
return false;
|
||||
}
|
||||
Object abilities = FastNMS.INSTANCE.field$Player$abilities(serverPlayer());
|
||||
return FastNMS.INSTANCE.field$Abilities$instabuild(abilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -600,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
|
||||
@@ -618,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
|
||||
@@ -770,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();
|
||||
@@ -874,23 +868,18 @@ public class BukkitServerPlayer extends Player {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolVersion protocolVersion() {
|
||||
return this.protocolVersion;
|
||||
public boolean isResourcePackLoading(UUID uuid) {
|
||||
return this.resourcePackUUID.contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProtocolVersion(int protocolVersion) {
|
||||
this.protocolVersion = ProtocolVersion.getById(protocolVersion);
|
||||
public void setShouldProcessFinishConfiguration(boolean shouldProcess) {
|
||||
this.shouldProcessFinishConfiguration = shouldProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sentResourcePack() {
|
||||
return this.sentResourcePack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSentResourcePack(boolean sentResourcePack) {
|
||||
this.sentResourcePack = sentResourcePack;
|
||||
public boolean shouldProcessFinishConfiguration() {
|
||||
return this.shouldProcessFinishConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user