mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 12:29:15 +00:00
feat(entity): 添加自定义三叉戟
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.data;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
|
||||
public class ThrowableItemProjectileData<T> extends BaseEntityData<T> {
|
||||
public static final ThrowableItemProjectileData<Object> ItemStack = new ThrowableItemProjectileData<>(8, EntityDataValue.Serializers$ITEM_STACK, Reflections.instance$ItemStack$Air);
|
||||
|
||||
|
||||
public ThrowableItemProjectileData(int id, Object serializer, T defaultValue) {
|
||||
super(id, serializer, defaultValue);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,25 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
@@ -19,9 +31,26 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() {
|
||||
@Override
|
||||
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
|
||||
return CompletableFuture.completedFuture(plugin().itemManager().cachedSuggestions());
|
||||
}
|
||||
}))
|
||||
.required("interpolationDelay", IntegerParser.integerParser())
|
||||
.required("transformationInterpolationDuration", IntegerParser.integerParser())
|
||||
.required("positionRotationInterpolationDuration", IntegerParser.integerParser())
|
||||
.handler(context -> {
|
||||
Player player = context.sender();
|
||||
player.getInventory().addItem(BukkitItemManager.instance().createWrappedItem(Key.from("default:topaz"), null).getItem());
|
||||
NamespacedKey namespacedKey = context.get("id");
|
||||
var item = ItemStack.of(Material.TRIDENT);
|
||||
item.editPersistentDataContainer(container -> {
|
||||
container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")), PersistentDataType.STRING, namespacedKey.asString());
|
||||
container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")), PersistentDataType.INTEGER, context.get("interpolationDelay"));
|
||||
container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")), PersistentDataType.INTEGER, context.get("transformationInterpolationDuration"));
|
||||
container.set(Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")), PersistentDataType.INTEGER, context.get("positionRotationInterpolationDuration"));
|
||||
});
|
||||
player.getInventory().addItem(item);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerNMSPacketConsumer(PacketConsumers.LOGIN_ACKNOWLEDGED, Reflections.clazz$ServerboundLoginAcknowledgedPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RESOURCE_PACK_RESPONSE, Reflections.clazz$ServerboundResourcePackPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.ENTITY_EVENT, Reflections.clazz$ClientboundEntityEventPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SET_ENTITY_DATA, Reflections.clazz$ClientboundSetEntityDataPacket);
|
||||
registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
@@ -170,7 +171,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
registerByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA_BYTEBUFFER, this.packetIds.clientboundSetEntityDataPacket());
|
||||
}
|
||||
|
||||
public static BukkitNetworkManager instance() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.papermc.paper.persistence.PersistentDataContainerView;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslationArgument;
|
||||
@@ -9,8 +10,10 @@ import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
|
||||
import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture;
|
||||
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;
|
||||
@@ -48,8 +51,10 @@ import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Trident;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@@ -1590,6 +1595,32 @@ public class PacketConsumers {
|
||||
if (furniture != null) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} else if (entityType == Reflections.instance$EntityType$TRIDENT) {
|
||||
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
|
||||
Player player = (Player) user.platformPlayer();
|
||||
Trident trident = (Trident) FastNMS.INSTANCE.getBukkitEntityById(player.getWorld(), entityId);
|
||||
PersistentDataContainerView container = trident.getItemStack().getPersistentDataContainer();
|
||||
if (container == null) return;
|
||||
String customTrident = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:custom_trident")), PersistentDataType.STRING);
|
||||
int interpolationDelay = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:interpolation_delay")), PersistentDataType.INTEGER);
|
||||
int transformationInterpolationDuration = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:transformation_interpolation_duration")), PersistentDataType.INTEGER);
|
||||
int positionRotationInterpolationDuration = container.get(Objects.requireNonNull(NamespacedKey.fromString("craftengine:position_rotation_interpolation_duration")), PersistentDataType.INTEGER);
|
||||
if (customTrident == null) return;
|
||||
Reflections.field$ClientboundAddEntityPacket$type.set(packet, Reflections.instance$EntityType$ITEM_DISPLAY);
|
||||
List<Object> itemDisplayValues = new ArrayList<>();
|
||||
Item<ItemStack> item = BukkitItemManager.instance().createWrappedItem(Key.of(customTrident), null);
|
||||
ItemDisplayEntityData.InterpolationDelay.addEntityDataIfNotDefaultValue(interpolationDelay, itemDisplayValues);
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
ItemDisplayEntityData.TransformationInterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues);
|
||||
ItemDisplayEntityData.PositionRotationInterpolationDuration.addEntityDataIfNotDefaultValue(positionRotationInterpolationDuration, itemDisplayValues);
|
||||
} else {
|
||||
ItemDisplayEntityData.InterpolationDuration.addEntityDataIfNotDefaultValue(transformationInterpolationDuration, itemDisplayValues);
|
||||
}
|
||||
ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), itemDisplayValues);
|
||||
user.tridentView().put(entityId, itemDisplayValues);
|
||||
event.addDelayedTask(() -> {
|
||||
user.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, itemDisplayValues), true);
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundAddEntityPacket", e);
|
||||
@@ -1600,6 +1631,12 @@ public class PacketConsumers {
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SYNC_ENTITY_POSITION = (user, event, packet) -> {
|
||||
try {
|
||||
int entityId = FastNMS.INSTANCE.method$ClientboundEntityPositionSyncPacket$id(packet);
|
||||
// if (user.tridentView().contains(entityId)) {
|
||||
// if (!VersionHelper.isOrAbove1_21_3()) return;
|
||||
// Object values = Reflections.field$ClientboundEntityPositionSyncPacket$values.get(packet);
|
||||
// user.sendPacket(Reflections.constructor$ClientboundTeleportEntityPacket.newInstance(entityId, values, Set.of(), false), true);
|
||||
// Bukkit.getOnlinePlayers().forEach(player -> player.sendMessage("Sync entity position: " + values));
|
||||
// }
|
||||
if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
@@ -1628,6 +1665,7 @@ public class PacketConsumers {
|
||||
int entityId = intList.getInt(i);
|
||||
user.entityView().remove(entityId);
|
||||
List<Integer> entities = user.furnitureView().remove(entityId);
|
||||
user.tridentView().remove(entityId);
|
||||
if (entities == null) continue;
|
||||
for (int subEntityId : entities) {
|
||||
isChange = true;
|
||||
@@ -1979,7 +2017,7 @@ public class PacketConsumers {
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> SET_ENTITY_DATA = (user, event) -> {
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> SET_ENTITY_DATA_BYTEBUFFER = (user, event) -> {
|
||||
try {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
@@ -2301,4 +2339,15 @@ public class PacketConsumers {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SET_ENTITY_DATA = (user, event, packet) -> {
|
||||
try {
|
||||
int entityId = Reflections.field$clazz$ClientboundSetEntityDataPacket$id.getInt(packet);
|
||||
if (user.tridentView().containsKey(entityId)) {
|
||||
event.replacePacket(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, user.tridentView().get(entityId)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ public class BukkitServerPlayer extends Player {
|
||||
// for better fake furniture visual sync
|
||||
private final Map<Integer, List<Integer>> furnitureView = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, Object> entityTypeView = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, List<Object>> tridentView = new ConcurrentHashMap<>();
|
||||
|
||||
public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) {
|
||||
this.channel = channel;
|
||||
@@ -723,6 +724,11 @@ public class BukkitServerPlayer extends Player {
|
||||
return this.entityTypeView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, List<Object>> tridentView() {
|
||||
return this.tridentView;
|
||||
}
|
||||
|
||||
public void setResendSound() {
|
||||
resentSoundTick = gameTicks();
|
||||
}
|
||||
|
||||
@@ -558,7 +558,6 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
@Deprecated
|
||||
public static final Field field$ClientboundAddEntityPacket$type = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundAddEntityPacket, clazz$EntityType, 0
|
||||
@@ -3811,6 +3810,8 @@ public class Reflections {
|
||||
public static final Object instance$EntityType$INTERACTION;
|
||||
public static final Object instance$EntityType$SHULKER;
|
||||
public static final Object instance$EntityType$OAK_BOAT;
|
||||
public static final Object instance$EntityType$TRIDENT;
|
||||
public static final Object instance$EntityType$SNOWBALL;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -3830,6 +3831,10 @@ public class Reflections {
|
||||
instance$EntityType$ARMOR_STAND = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, armorStand);
|
||||
Object oakBoat = VersionHelper.isOrAbove1_21_2() ? FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "oak_boat") : FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "boat");
|
||||
instance$EntityType$OAK_BOAT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, oakBoat);
|
||||
Object trident = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "trident");
|
||||
instance$EntityType$TRIDENT = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, trident);
|
||||
Object snowball = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "snowball");
|
||||
instance$EntityType$SNOWBALL = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$ENTITY_TYPE, snowball);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -6615,4 +6620,56 @@ public class Reflections {
|
||||
BukkitReflectionUtils.assembleCBClass("block.CraftBlockStates$BlockEntityStateFactory")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$clazz$ClientboundSetEntityDataPacket$id = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundSetEntityDataPacket, int.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
// public static final Class<?> clazz$PositionMoveRotation =
|
||||
// ReflectionUtils.getClazz(
|
||||
// BukkitReflectionUtils.assembleMCClass("world.entity.PositionMoveRotation")
|
||||
// );
|
||||
//
|
||||
// public static final Field field$ClientboundEntityPositionSyncPacket$values = Optional.ofNullable(clazz$ClientboundEntityPositionSyncPacket)
|
||||
// .map(it -> ReflectionUtils.getInstanceDeclaredField(it, clazz$PositionMoveRotation, 0))
|
||||
// .orElse(null);
|
||||
//
|
||||
// public static final Class<?> clazz$ClientboundTeleportEntityPacket = requireNonNull(
|
||||
// BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
// "network.protocol.game.PacketPlayOutEntityTeleport",
|
||||
// "network.protocol.game.ClientboundTeleportEntityPacket"
|
||||
// )
|
||||
// );
|
||||
//
|
||||
// /**
|
||||
// * 实体移动数据包
|
||||
// *
|
||||
// * <p><b>1.20 ~ 1.21.1 版本传入参数:</b></p>
|
||||
// * <ul>
|
||||
// * <li>{@code FriendlyByteBuf} 需要按顺序写入:
|
||||
// * <ul>
|
||||
// * <li>{@code id} - VarInt 实体ID</li>
|
||||
// * <li>{@code x} - Double X坐标</li>
|
||||
// * <li>{@code y} - Double Y坐标</li>
|
||||
// * <li>{@code z} - Double Z坐标</li>
|
||||
// * <li>{@code yRot} - Byte 垂直旋转角度</li>
|
||||
// * <li>{@code xRot} - Byte 水平旋转角度</li>
|
||||
// * <li>{@code onGround} - Boolean 着地状态</li>
|
||||
// * </ul>
|
||||
// * </li>
|
||||
// * </ul>
|
||||
// *
|
||||
// * <p><b>1.21.2+ 版本传入参数:</b></p>
|
||||
// * <ul>
|
||||
// * <li>{@code id} - int 实体ID</li>
|
||||
// * <li>{@code PositionMoveRotation change} - 位置和移动向量和旋转</li>
|
||||
// * <li>{@code Set<Relative> relatives} - 相对坐标标记集合</li>
|
||||
// * <li>{@code onGround} - boolean 着地状态</li>
|
||||
// * </ul>
|
||||
// */
|
||||
// public static final Constructor<?> constructor$ClientboundTeleportEntityPacket = requireNonNull(
|
||||
// ReflectionUtils.getConstructor(clazz$ClientboundTeleportEntityPacket, VersionHelper.isOrAbove1_21_2() ? 0 : 1)
|
||||
// );
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ public interface NetWorkUser {
|
||||
|
||||
Map<Integer, Object> entityView();
|
||||
|
||||
Map<Integer, List<Object>> tridentView();
|
||||
|
||||
boolean clientModEnabled();
|
||||
|
||||
void setClientModState(boolean enable);
|
||||
|
||||
Reference in New Issue
Block a user