mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-29 11:59:11 +00:00
refactor(bukkit): 添加水下气泡
- 准备设计配置格式
This commit is contained in:
@@ -42,7 +42,6 @@ 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("forceUpdate", BooleanParser.booleanParser())
|
||||
.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) {
|
||||
@@ -55,18 +54,6 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
|
||||
.required("rotationLeft", StringParser.stringParser())
|
||||
.handler(context -> {
|
||||
Player player = context.sender();
|
||||
if (context.get("forceUpdate")) {
|
||||
net.momirealms.craftengine.core.entity.player.Player cePlayer = plugin().adapt(player);
|
||||
Collection<Trident> tridents = player.getWorld().getEntitiesByClass(Trident.class);
|
||||
List<Object> packets = new ArrayList<>();
|
||||
for (Trident trident : tridents) {
|
||||
int entityId = FastNMS.INSTANCE.method$Entity$getId(FastNMS.INSTANCE.method$CraftEntity$getHandle(trident));
|
||||
player.sendMessage("COMMAND entityId: " + entityId);
|
||||
packets.add(CustomTridentUtils.buildCustomTridentSetEntityDataPacket(cePlayer, entityId));
|
||||
}
|
||||
cePlayer.sendPackets(packets, true);
|
||||
return;
|
||||
}
|
||||
NamespacedKey namespacedKey = context.get("id");
|
||||
ItemStack item = new ItemStack(Material.TRIDENT);
|
||||
item.editMeta((meta) -> {
|
||||
|
||||
@@ -152,7 +152,6 @@ 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);
|
||||
registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY_ALL, Reflections.clazz$ClientboundMoveEntityPacket$PosRot);
|
||||
registerByteBufPacketConsumer(PacketConsumers.LEVEL_CHUNK_WITH_LIGHT, this.packetIds.clientboundLevelChunkWithLightPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
@@ -172,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_BYTEBUFFER, this.packetIds.clientboundSetEntityDataPacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket());
|
||||
}
|
||||
|
||||
public static BukkitNetworkManager instance() {
|
||||
|
||||
@@ -2008,10 +2008,20 @@ public class PacketConsumers {
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> SET_ENTITY_DATA_BYTEBUFFER = (user, event) -> {
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> SET_ENTITY_DATA = (user, event) -> {
|
||||
try {
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
int id = buf.readVarInt();
|
||||
if (user.tridentView().containsKey(id)) {
|
||||
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
|
||||
List<Object> newPackedItems = CustomTridentUtils.buildCustomTridentSetEntityDataPacket(user, packedItems, id);
|
||||
event.setChanged(true);
|
||||
buf.clear();
|
||||
buf.writeVarInt(event.packetID());
|
||||
buf.writeVarInt(id);
|
||||
FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$pack(newPackedItems, buf);
|
||||
return;
|
||||
}
|
||||
Object entityType = user.entityView().get(id);
|
||||
if (entityType == Reflections.instance$EntityType$BLOCK_DISPLAY) {
|
||||
boolean isChanged = false;
|
||||
@@ -2331,17 +2341,6 @@ public class PacketConsumers {
|
||||
}
|
||||
};
|
||||
|
||||
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)) {
|
||||
CustomTridentUtils.modifyCustomTridentSetEntityData(user, event, entityId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSetEntityDataPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_ENTITY_ALL = (user, event, packet) -> {
|
||||
try {
|
||||
int entityId = BukkitInjector.internalFieldAccessor().field$ClientboundMoveEntityPacket$entityId(packet);
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Trident;
|
||||
@@ -39,6 +40,8 @@ public class CustomTridentUtils {
|
||||
public static void handleCustomTrident(NetWorkUser user, NMSPacketEvent event, Object packet) throws IllegalAccessException {
|
||||
int entityId = FastNMS.INSTANCE.field$ClientboundAddEntityPacket$entityId(packet);
|
||||
Trident trident = getTridentById(user, entityId);
|
||||
if (trident == null) return;
|
||||
World world = trident.getWorld();
|
||||
Object serverEntity;
|
||||
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(trident);
|
||||
Object tracker = Reflections.field$Entity$trackedEntity.get(nmsEntity);
|
||||
@@ -59,14 +62,26 @@ public class CustomTridentUtils {
|
||||
SchedulerTask task = CraftEngine.instance().scheduler().asyncRepeating(() -> {
|
||||
try {
|
||||
Reflections.method$ServerEntity$sendChanges.invoke(serverEntity);
|
||||
if (!isInGround(nmsEntity)) {
|
||||
world.spawnParticle(ParticleUtils.getParticle("BUBBLE"), trident.getLocation(), 1, 0, 0, 0, 0);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to send entity data packet", e);
|
||||
}
|
||||
}, 5, 5, TimeUnit.MILLISECONDS);
|
||||
}, 0, 5, TimeUnit.MILLISECONDS);
|
||||
user.tridentTaskView().put(entityId, task);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInGround(Object nmsEntity) throws IllegalAccessException, InvocationTargetException {
|
||||
if (!Reflections.field$Entity$wasTouchingWater.getBoolean(nmsEntity)) return true;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
return (boolean) Reflections.method$AbstractArrow$isInGround.invoke(nmsEntity);
|
||||
} else {
|
||||
return Reflections.field$AbstractArrow$inGround.getBoolean(nmsEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Trident getTridentById(NetWorkUser user, int entityId) {
|
||||
Player player = (Player) user.platformPlayer();
|
||||
@@ -135,20 +150,22 @@ public class CustomTridentUtils {
|
||||
Reflections.field$ClientboundMoveEntityPacket$yRot.setByte(packet, MCUtils.packDegrees(-yRot));
|
||||
}
|
||||
|
||||
public static Object buildCustomTridentSetEntityDataPacket(NetWorkUser user, int entityId) {
|
||||
public static List<Object> buildCustomTridentSetEntityDataPacket(NetWorkUser user, List<Object> packedItems, int entityId) {
|
||||
List<Object> newPackedItems = new ArrayList<>();
|
||||
for (Object packedItem : packedItems) {
|
||||
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
|
||||
if (entityDataId < 8) {
|
||||
newPackedItems.add(packedItem);
|
||||
}
|
||||
}
|
||||
List<Object> newData = user.tridentView().getOrDefault(entityId, List.of());
|
||||
if (newData.isEmpty()) {
|
||||
Trident trident = getTridentById(user, entityId);
|
||||
if (notCustomTrident(trident)) return null;
|
||||
if (notCustomTrident(trident)) return newPackedItems;
|
||||
newData = buildEntityDataValues(trident);
|
||||
user.tridentView().put(entityId, newData);
|
||||
}
|
||||
return FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, newData);
|
||||
}
|
||||
|
||||
public static void modifyCustomTridentSetEntityData(NetWorkUser user, NMSPacketEvent event, int entityId) {
|
||||
Object packet = buildCustomTridentSetEntityDataPacket(user, entityId);
|
||||
if (packet == null) return;
|
||||
event.replacePacket(packet);
|
||||
newPackedItems.addAll(newData);
|
||||
return newPackedItems;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public class ParticleUtils {
|
||||
return switch (particle) {
|
||||
case "REDSTONE" -> Particle.valueOf("DUST");
|
||||
case "VILLAGER_HAPPY", "HAPPY_VILLAGER" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "HAPPY_VILLAGER" : "VILLAGER_HAPPY");
|
||||
case "BUBBLE" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "BUBBLE" : "WATER_BUBBLE");
|
||||
default -> Particle.valueOf(particle);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6632,7 +6632,7 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$clazz$ClientboundSetEntityDataPacket$id = requireNonNull(
|
||||
public static final Field field$ClientboundSetEntityDataPacket$id = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundSetEntityDataPacket, int.class, 0
|
||||
)
|
||||
@@ -6730,4 +6730,32 @@ public class Reflections {
|
||||
clazz$ChunkMap$TrackedEntity, clazz$ServerEntity, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$Entity$wasTouchingWater = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$Entity, VersionHelper.isOrAbove1_21_2()
|
||||
? new String[]{ "wasTouchingWater", "ag" } : VersionHelper.isOrAbove1_20_5()
|
||||
? new String[]{ "wasTouchingWater", "aj" } : VersionHelper.isOrAbove1_20_2()
|
||||
? new String[]{ "wasTouchingWater", "ai" } : new String[]{ "wasTouchingWater", "ah" }
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$AbstractArrow = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.entity.projectile.EntityArrow",
|
||||
"world.entity.projectile.AbstractArrow"
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20~1.21.1
|
||||
public static final Field field$AbstractArrow$inGround =
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$AbstractArrow, boolean.class, 0
|
||||
);
|
||||
|
||||
// 1.21.2+
|
||||
public static final Method method$AbstractArrow$isInGround =
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$AbstractArrow, boolean.class, VersionHelper.isOrAbove1_21_5() ? new String[]{ "isInGround", "e" } : new String[]{ "isInGround", "l" }
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user