9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-20 15:39:22 +00:00

Merge pull request #212 from jhqwqmc/dev

perf(entity): 优化网络包处理
This commit is contained in:
XiaoMoMi
2025-06-09 02:28:26 +08:00
committed by GitHub
24 changed files with 439 additions and 113 deletions

View File

@@ -7,20 +7,21 @@ public interface EntityData<T> {
Object serializer(); Object serializer();
int id(); int id();
T defaultValue(); T defaultValue();
Object entityDataAccessor();
default Object createEntityDataIfNotDefaultValue(T value) { default Object createEntityDataIfNotDefaultValue(T value) {
if (defaultValue().equals(value)) return null; if (defaultValue().equals(value)) return null;
return EntityDataValue.create(id(), serializer(), value); return EntityDataValue.create(id(), serializer(), entityDataAccessor(), value);
} }
default void addEntityDataIfNotDefaultValue(T value, List<Object> list) { default void addEntityDataIfNotDefaultValue(T value, List<Object> list) {
if (!defaultValue().equals(value)) { if (!defaultValue().equals(value)) {
list.add(EntityDataValue.create(id(), serializer(), value)); list.add(EntityDataValue.create(id(), serializer(), entityDataAccessor(), value));
} }
} }
default void addEntityData(T value, List<Object> list) { default void addEntityData(T value, List<Object> list) {
list.add(EntityDataValue.create(id(), serializer(), value)); list.add(EntityDataValue.create(id(), serializer(), entityDataAccessor(), value));
} }
static <T> EntityData<T> of(int id, Object serializer, T defaultValue) { static <T> EntityData<T> of(int id, Object serializer, T defaultValue) {

View File

@@ -98,8 +98,7 @@ public class EntityDataValue {
throw new IllegalAccessError("Utility class"); throw new IllegalAccessError("Utility class");
} }
public static Object create(int id, Object serializer, Object value) { public static Object create(int id, Object serializer, Object entityDataAccessor, Object value) {
Object entityDataAccessor = FastNMS.INSTANCE.constructor$EntityDataAccessor(id, serializer);
return FastNMS.INSTANCE.method$SynchedEntityData$DataValue$create(entityDataAccessor, value); return FastNMS.INSTANCE.method$SynchedEntityData$DataValue$create(entityDataAccessor, value);
} }
} }

View File

@@ -1,14 +1,18 @@
package net.momirealms.craftengine.bukkit.entity.data; package net.momirealms.craftengine.bukkit.entity.data;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
public class SimpleEntityData<T> implements EntityData<T> { public class SimpleEntityData<T> implements EntityData<T> {
private final int id; private final int id;
private final Object serializer; private final Object serializer;
private final T defaultValue; private final T defaultValue;
private final Object entityDataAccessor;
public SimpleEntityData(int id, Object serializer, T defaultValue) { public SimpleEntityData(int id, Object serializer, T defaultValue) {
this.id = id; this.id = id;
this.serializer = serializer; this.serializer = serializer;
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
this.entityDataAccessor = FastNMS.INSTANCE.constructor$EntityDataAccessor(id, serializer);
} }
@Override @Override
@@ -25,4 +29,9 @@ public class SimpleEntityData<T> implements EntityData<T> {
public T defaultValue() { public T defaultValue() {
return defaultValue; return defaultValue;
} }
@Override
public Object entityDataAccessor() {
return entityDataAccessor;
}
} }

View File

@@ -28,6 +28,7 @@ import org.joml.Vector3f;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.*; import java.util.*;
import java.util.function.Consumer;
public class BukkitFurniture implements Furniture { public class BukkitFurniture implements Furniture {
private final Key id; private final Key id;
@@ -130,6 +131,7 @@ public class BukkitFurniture implements Furniture {
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld()); Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld());
for (Collider entity : this.colliderEntities) { for (Collider entity : this.colliderEntities) {
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle()); FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle());
injectFurnitureEntity(entity.handle());
Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity.handle()); Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity.handle());
bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1); bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1);
} }
@@ -359,4 +361,24 @@ public class BukkitFurniture implements Furniture {
newLocation.add(offset.x, offset.y + 0.6, -offset.z); newLocation.add(offset.x, offset.y + 0.6, -offset.z);
return newLocation; return newLocation;
} }
public static void injectFurnitureEntity(Object nmsEntity) {
try {
Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity);
Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity);
CoreReflections.handle$ServerEntity$broadcastSetter.invokeExact(serverEntity, Handlers.DO_NOTHING);
CoreReflections.handle$ServerEntity$updateIntervalSetter.invokeExact(serverEntity, Integer.MAX_VALUE);
} catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to inject collider", e);
}
}
@FunctionalInterface
public interface Handlers extends Consumer<Object> {
Consumer<Object> DO_NOTHING = doNothing();
static Handlers doNothing() {
return (packet) -> {};
}
}
} }

View File

@@ -86,6 +86,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
SoundData data = furniture.settings().sounds().placeSound(); SoundData data = furniture.settings().sounds().placeSound();
location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume(), data.pitch()); location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume(), data.pitch());
} }
BukkitFurniture.injectFurnitureEntity(FastNMS.INSTANCE.method$CraftEntity$getHandle(furnitureEntity));
return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId()); return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId());
} }
@@ -101,6 +102,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
for (Entity entity : entities) { for (Entity entity : entities) {
if (entity instanceof ItemDisplay display) { if (entity instanceof ItemDisplay display) {
handleBaseEntityLoadEarly(display); handleBaseEntityLoadEarly(display);
BukkitFurniture.injectFurnitureEntity(FastNMS.INSTANCE.method$CraftEntity$getHandle(display));
} else if (entity instanceof Interaction interaction) { } else if (entity instanceof Interaction interaction) {
handleCollisionEntityLoadOnEntitiesLoad(interaction); handleCollisionEntityLoadOnEntitiesLoad(interaction);
} else if (entity instanceof Boat boat) { } else if (entity instanceof Boat boat) {
@@ -208,6 +210,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
furniture.initializeColliders(); furniture.initializeColliders();
} }
} }
BukkitFurniture.injectFurnitureEntity(FastNMS.INSTANCE.method$CraftEntity$getHandle(display));
if (depth > 2) return; if (depth > 2) return;
this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
} }

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.entity.furniture;
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.ItemDisplay;
@@ -36,6 +37,7 @@ public class FurnitureEventListener implements Listener {
for (Entity entity : entities) { for (Entity entity : entities) {
if (entity instanceof ItemDisplay itemDisplay) { if (entity instanceof ItemDisplay itemDisplay) {
this.manager.handleBaseEntityLoadEarly(itemDisplay); this.manager.handleBaseEntityLoadEarly(itemDisplay);
BukkitFurniture.injectFurnitureEntity(FastNMS.INSTANCE.method$CraftEntity$getHandle(itemDisplay));
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity); this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
} }
@@ -48,6 +50,7 @@ public class FurnitureEventListener implements Listener {
for (Entity entity : entities) { for (Entity entity : entities) {
if (entity instanceof ItemDisplay itemDisplay) { if (entity instanceof ItemDisplay itemDisplay) {
this.manager.handleBaseEntityLoadEarly(itemDisplay); this.manager.handleBaseEntityLoadEarly(itemDisplay);
BukkitFurniture.injectFurnitureEntity(FastNMS.INSTANCE.method$CraftEntity$getHandle(itemDisplay));
} else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) {
this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity); this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity);
} }

View File

@@ -161,7 +161,10 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
public class ProjectileInjectTask implements Runnable { public class ProjectileInjectTask implements Runnable {
private final Projectile projectile; private final Projectile projectile;
private final SchedulerTask task; private final SchedulerTask task;
private Object cachedServerEntity;
private boolean injected; private boolean injected;
private int lastInjectedInterval = -1;
private boolean wasInGround;
public ProjectileInjectTask(Projectile projectile) { public ProjectileInjectTask(Projectile projectile) {
this.projectile = projectile; this.projectile = projectile;
@@ -180,30 +183,49 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
} }
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(this.projectile); Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(this.projectile);
if (!this.injected) { if (!this.injected) {
Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(nmsEntity); injectProjectile(nmsEntity, 1);
if (trackedEntity == null) { this.injected = true;
return; this.lastInjectedInterval = 1;
} }
boolean inGround = FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity);
if (canSpawnParticle(nmsEntity, inGround)) {
this.projectile.getWorld().spawnParticle(ParticleUtils.BUBBLE, this.projectile.getLocation(), 3, 0.1, 0.1, 0.1, 0);
}
projectileByEntityId(this.projectile.getEntityId()).ifPresent(customProjectile -> {
customProjectile.setInGroundTime(inGround ? customProjectile.inGroundTime() + 1 : 0);
if (customProjectile.inGroundTime() > 5) {
if (lastInjectedInterval != Integer.MAX_VALUE) {
injectProjectile(nmsEntity, Integer.MAX_VALUE);
}
} else if (!inGround && wasInGround) {
if (lastInjectedInterval != 1) {
injectProjectile(nmsEntity, 1);
}
}
this.wasInGround = inGround;
});
}
private void injectProjectile(Object entity, int updateInterval) {
if (this.cachedServerEntity == null) {
Object trackedEntity = FastNMS.INSTANCE.field$Entity$trackedEntity(entity);
if (trackedEntity == null) return;
Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity); Object serverEntity = FastNMS.INSTANCE.filed$ChunkMap$TrackedEntity$serverEntity(trackedEntity);
if (serverEntity == null) { if (serverEntity == null) return;
return; this.cachedServerEntity = serverEntity;
} }
try { try {
CoreReflections.field$ServerEntity$updateInterval.set(serverEntity, 1); CoreReflections.handle$ServerEntity$updateIntervalSetter.invokeExact(this.cachedServerEntity, updateInterval);
this.injected = true; this.lastInjectedInterval = updateInterval;
} catch (ReflectiveOperationException e) { } catch (Throwable e) {
plugin.logger().warn("Failed to update server entity tracking interval", e); plugin.logger().warn("Failed to update server entity tracking interval", e);
} }
} }
if (canSpawnParticle(nmsEntity)) {
this.projectile.getWorld().spawnParticle(ParticleUtils.BUBBLE, this.projectile.getLocation(), 3, 0.1, 0.1, 0.1, 0);
}
}
private static boolean canSpawnParticle(Object nmsEntity) { private static boolean canSpawnParticle(Object nmsEntity, boolean inGround) {
if (!FastNMS.INSTANCE.field$Entity$wasTouchingWater(nmsEntity)) return false; if (!FastNMS.INSTANCE.field$Entity$wasTouchingWater(nmsEntity)) return false;
if (CoreReflections.clazz$AbstractArrow.isInstance(nmsEntity)) { if (CoreReflections.clazz$AbstractArrow.isInstance(nmsEntity)) {
return !FastNMS.INSTANCE.method$AbstractArrow$isInGround(nmsEntity); return !inGround;
} }
return true; return true;
} }

View File

@@ -8,6 +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.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps;
import net.momirealms.craftengine.core.item.ItemWrapper; import net.momirealms.craftengine.core.item.ItemWrapper;
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.sparrow.nbt.Tag; import net.momirealms.sparrow.nbt.Tag;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -111,6 +112,10 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
private void setComponentInternal(Object type, DynamicOps ops, Object value) { private void setComponentInternal(Object type, DynamicOps ops, Object value) {
if (value == null) return; if (value == null) return;
Object componentType = ensureDataComponentType(type); Object componentType = ensureDataComponentType(type);
if (componentType == null) {
TranslationManager.instance().log("warning.config.item.component_notfound", type.toString());
return;
}
Codec codec = FastNMS.INSTANCE.method$DataComponentType$codec(componentType); Codec codec = FastNMS.INSTANCE.method$DataComponentType$codec(componentType);
try { try {
DataResult<Object> result = codec.parse(ops, value); DataResult<Object> result = codec.parse(ops, value);

View File

@@ -48,6 +48,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new DebugSpawnFurnitureCommand(this, plugin), new DebugSpawnFurnitureCommand(this, plugin),
new DebugTargetBlockCommand(this, plugin), new DebugTargetBlockCommand(this, plugin),
new DebugIsSectionInjectedCommand(this, plugin), new DebugIsSectionInjectedCommand(this, plugin),
new DebugEntityId2UUIDCommand(this, plugin),
new TotemAnimationCommand(this, plugin), new TotemAnimationCommand(this, plugin),
new EnableResourceCommand(this, plugin), new EnableResourceCommand(this, plugin),
new DisableResourceCommand(this, plugin), new DisableResourceCommand(this, plugin),

View File

@@ -0,0 +1,59 @@
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.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
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 DebugEntityId2UUIDCommand extends BukkitCommandFeature<CommandSender> {
public DebugEntityId2UUIDCommand(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");
Entity entity = FastNMS.INSTANCE.getBukkitEntityById(world, entityId);
if (entity == null) {
context.sender().sendMessage("entity not found");
return;
}
Location location = entity.getLocation();
context.sender().sendMessage(
String.format(
"""
===========================
uuid: %s
name: %s
location: %s,%s,%s
type: %s
===========================
""",
entity.getUniqueId(),
entity.getName(),
location.x(), location.y(), location.z(),
entity.getType()
)
);
});
}
@Override
public String getFeatureID() {
return "debug_entity_id_to_uuid";
}
}

View File

@@ -148,7 +148,6 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
registerNMSPacketConsumer(PacketConsumers.LOGIN, NetworkReflections.clazz$ClientboundLoginPacket); registerNMSPacketConsumer(PacketConsumers.LOGIN, NetworkReflections.clazz$ClientboundLoginPacket);
registerNMSPacketConsumer(PacketConsumers.RESPAWN, NetworkReflections.clazz$ClientboundRespawnPacket); registerNMSPacketConsumer(PacketConsumers.RESPAWN, NetworkReflections.clazz$ClientboundRespawnPacket);
registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, NetworkReflections.clazz$ClientboundEntityPositionSyncPacket); registerNMSPacketConsumer(PacketConsumers.SYNC_ENTITY_POSITION, NetworkReflections.clazz$ClientboundEntityPositionSyncPacket);
registerNMSPacketConsumer(PacketConsumers.MOVE_POS_ENTITY, NetworkReflections.clazz$ClientboundMoveEntityPacket$Pos);
registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, NetworkReflections.clazz$ServerboundPickItemFromEntityPacket); registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, NetworkReflections.clazz$ServerboundPickItemFromEntityPacket);
registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, NetworkReflections.clazz$ServerboundRenameItemPacket); registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, NetworkReflections.clazz$ServerboundRenameItemPacket);
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, NetworkReflections.clazz$ServerboundSignUpdatePacket); registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, NetworkReflections.clazz$ServerboundSignUpdatePacket);
@@ -176,7 +175,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
registerS2CByteBufPacketConsumer(VersionHelper.isOrAbove1_20_3() ? PacketConsumers.SET_OBJECTIVE_1_20_3 : PacketConsumers.SET_OBJECTIVE_1_20, this.packetIds.clientboundSetObjectivePacket()); 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.SET_SCORE_1_20_3, VersionHelper.isOrAbove1_20_3() ? this.packetIds.clientboundSetScorePacket() : -1);
registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY_BYTEBUFFER, this.packetIds.clientboundAddEntityPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY, this.packetIds.clientboundAddEntityPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.SET_ENTITY_DATA, this.packetIds.clientboundSetEntityDataPacket());
registerS2CByteBufPacketConsumer(PacketConsumers.CONTAINER_SET_CONTENT, this.packetIds.clientboundContainerSetContentPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.CONTAINER_SET_CONTENT, this.packetIds.clientboundContainerSetContentPacket());

View File

@@ -70,7 +70,6 @@ import org.bukkit.util.RayTraceResult;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@@ -163,7 +162,6 @@ public class PacketConsumers {
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(id); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(id);
if (furniture != null) { if (furniture != null) {
event.setCancelled(true); event.setCancelled(true);
user.entityPacketHandlers().put(id, FurnitureCollisionPacketHandler.INSTANCE);
} }
}; };
ADD_ENTITY_HANDLERS[MEntityTypes.OAK_BOAT$registryId] = (user, event) -> { ADD_ENTITY_HANDLERS[MEntityTypes.OAK_BOAT$registryId] = (user, event) -> {
@@ -174,7 +172,6 @@ public class PacketConsumers {
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(id); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(id);
if (furniture != null) { if (furniture != null) {
event.setCancelled(true); event.setCancelled(true);
user.entityPacketHandlers().put(id, FurnitureCollisionPacketHandler.INSTANCE);
} }
}; };
} }
@@ -1172,21 +1169,21 @@ public class PacketConsumers {
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HELLO_C2S = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HELLO_C2S = (user, event, packet) -> {
try { try {
BukkitServerPlayer player = (BukkitServerPlayer) user; BukkitServerPlayer player = (BukkitServerPlayer) user;
String name = (String) NetworkReflections.field$ServerboundHelloPacket$name.get(packet); String name = (String) NetworkReflections.handle$ServerboundHelloPacket$nameGetter.invokeExact(packet);
player.setName(name); player.setName(name);
if (VersionHelper.isOrAbove1_20_2()) { if (VersionHelper.isOrAbove1_20_2()) {
UUID uuid = (UUID) NetworkReflections.field$ServerboundHelloPacket$uuid.get(packet); UUID uuid = (UUID) NetworkReflections.handle$ServerboundHelloPacket$uuidGetter.invokeExact(packet);
player.setUUID(uuid); player.setUUID(uuid);
} else { } else {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Optional<UUID> uuid = (Optional<UUID>) NetworkReflections.field$ServerboundHelloPacket$uuid.get(packet); Optional<UUID> uuid = (Optional<UUID>) NetworkReflections.handle$ServerboundHelloPacket$uuidGetter.invokeExact(packet);
if (uuid.isPresent()) { if (uuid.isPresent()) {
player.setUUID(uuid.get()); player.setUUID(uuid.get());
} else { } else {
player.setUUID(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8))); player.setUUID(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)));
} }
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundHelloPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundHelloPacket", e);
} }
}; };
@@ -1223,10 +1220,10 @@ public class PacketConsumers {
player.clearView(); player.clearView();
Object dimensionKey; Object dimensionKey;
if (!VersionHelper.isOrAbove1_20_2()) { if (!VersionHelper.isOrAbove1_20_2()) {
dimensionKey = NetworkReflections.field$ClientboundRespawnPacket$dimension.get(packet); dimensionKey = NetworkReflections.handle$ClientboundRespawnPacket$dimensionGetter.invokeExact(packet);
} else { } else {
Object commonInfo = NetworkReflections.field$ClientboundRespawnPacket$commonPlayerSpawnInfo.get(packet); Object commonInfo = NetworkReflections.handle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter.invokeExact(packet);
dimensionKey = NetworkReflections.field$CommonPlayerSpawnInfo$dimension.get(commonInfo); dimensionKey = NetworkReflections.handle$CommonPlayerSpawnInfo$dimensionGetter.invokeExact(commonInfo);
} }
Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey); Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey);
World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString()))); World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString())));
@@ -1237,7 +1234,7 @@ public class PacketConsumers {
} else { } else {
CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket: World " + location + " does not exist"); CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket: World " + location + " does not exist");
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket", e); CraftEngine.instance().logger().warn("Failed to handle ClientboundRespawnPacket", e);
} }
}; };
@@ -1251,10 +1248,10 @@ public class PacketConsumers {
if (BukkitNetworkManager.hasViaVersion()) { if (BukkitNetworkManager.hasViaVersion()) {
user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(player.uuid())); user.setProtocolVersion(CraftEngine.instance().compatibilityManager().getPlayerProtocolVersion(player.uuid()));
} }
dimensionKey = NetworkReflections.field$ClientboundLoginPacket$dimension.get(packet); dimensionKey = NetworkReflections.handle$ClientboundLoginPacket$dimensionGetter.invokeExact(packet);
} else { } else {
Object commonInfo = NetworkReflections.field$ClientboundLoginPacket$commonPlayerSpawnInfo.get(packet); Object commonInfo = NetworkReflections.handle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter.invokeExact(packet);
dimensionKey = NetworkReflections.field$CommonPlayerSpawnInfo$dimension.get(commonInfo); dimensionKey = NetworkReflections.handle$CommonPlayerSpawnInfo$dimensionGetter.invokeExact(commonInfo);
} }
Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey); Object location = FastNMS.INSTANCE.field$ResourceKey$location(dimensionKey);
World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString()))); World world = Bukkit.getWorld(Objects.requireNonNull(NamespacedKey.fromString(location.toString())));
@@ -1265,7 +1262,7 @@ public class PacketConsumers {
} else { } else {
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket: World " + location + " does not exist"); CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket: World " + location + " does not exist");
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket", e); CraftEngine.instance().logger().warn("Failed to handle ClientboundLoginPacket", e);
} }
}; };
@@ -1282,25 +1279,25 @@ public class PacketConsumers {
player.platformPlayer().getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> { player.platformPlayer().getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
try { try {
handleSetCreativeSlotPacketOnMainThread(player, packet); handleSetCreativeSlotPacketOnMainThread(player, packet);
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
} }
}, () -> {}); }, () -> {});
} else { } else {
handleSetCreativeSlotPacketOnMainThread(player, packet); handleSetCreativeSlotPacketOnMainThread(player, packet);
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
} }
}; };
private static void handleSetCreativeSlotPacketOnMainThread(BukkitServerPlayer player, Object packet) throws Exception { private static void handleSetCreativeSlotPacketOnMainThread(BukkitServerPlayer player, Object packet) throws Throwable {
Player bukkitPlayer = player.platformPlayer(); Player bukkitPlayer = player.platformPlayer();
if (bukkitPlayer == null) return; if (bukkitPlayer == null) return;
if (bukkitPlayer.getGameMode() != GameMode.CREATIVE) return; if (bukkitPlayer.getGameMode() != GameMode.CREATIVE) return;
int slot = VersionHelper.isOrAbove1_20_5() ? NetworkReflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getShort(packet) : NetworkReflections.field$ServerboundSetCreativeModeSlotPacket$slotNum.getInt(packet); int slot = VersionHelper.isOrAbove1_20_5() ? (short) NetworkReflections.handle$ServerboundSetCreativeModeSlotPacket$slotNumGetter.invokeExact(packet) : (int) NetworkReflections.handle$ServerboundSetCreativeModeSlotPacket$slotNumGetter.invokeExact(packet);
if (slot < 36 || slot > 44) return; if (slot < 36 || slot > 44) return;
ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(NetworkReflections.field$ServerboundSetCreativeModeSlotPacket$itemStack.get(packet)); ItemStack item = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(NetworkReflections.handle$ServerboundSetCreativeModeSlotPacket$itemStackGetter.invokeExact(packet));
if (ItemUtils.isEmpty(item)) return; if (ItemUtils.isEmpty(item)) return;
if (slot - 36 != bukkitPlayer.getInventory().getHeldItemSlot()) { if (slot - 36 != bukkitPlayer.getInventory().getHeldItemSlot()) {
return; return;
@@ -1373,14 +1370,14 @@ public class PacketConsumers {
if (!user.isOnline()) return; if (!user.isOnline()) return;
Player player = (Player) user.platformPlayer(); Player player = (Player) user.platformPlayer();
if (player == null) return; if (player == null) return;
Object pos = NetworkReflections.field$ServerboundPickItemFromBlockPacket$pos.get(packet); Object pos = NetworkReflections.handle$ServerboundPickItemFromBlockPacket$posGetter.invokeExact(packet);
if (VersionHelper.isFolia()) { if (VersionHelper.isFolia()) {
int x = FastNMS.INSTANCE.field$Vec3i$x(pos); int x = FastNMS.INSTANCE.field$Vec3i$x(pos);
int z = FastNMS.INSTANCE.field$Vec3i$z(pos); int z = FastNMS.INSTANCE.field$Vec3i$z(pos);
BukkitCraftEngine.instance().scheduler().sync().run(() -> { BukkitCraftEngine.instance().scheduler().sync().run(() -> {
try { try {
handlePickItemFromBlockPacketOnMainThread(player, pos); handlePickItemFromBlockPacketOnMainThread(player, pos);
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
} }
}, player.getWorld(), x >> 4, z >> 4); }, player.getWorld(), x >> 4, z >> 4);
@@ -1388,17 +1385,17 @@ public class PacketConsumers {
BukkitCraftEngine.instance().scheduler().sync().run(() -> { BukkitCraftEngine.instance().scheduler().sync().run(() -> {
try { try {
handlePickItemFromBlockPacketOnMainThread(player, pos); handlePickItemFromBlockPacketOnMainThread(player, pos);
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
} }
}); });
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromBlockPacket", e);
} }
}; };
private static void handlePickItemFromBlockPacketOnMainThread(Player player, Object pos) throws Exception { private static void handlePickItemFromBlockPacketOnMainThread(Player player, Object pos) throws Throwable {
Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld()); Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld());
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, pos); Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, pos);
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
@@ -1411,7 +1408,7 @@ public class PacketConsumers {
// 1.21.4+ // 1.21.4+
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> {
try { try {
int entityId = (int) NetworkReflections.field$ServerboundPickItemFromEntityPacket$id.get(packet); int entityId = (int) NetworkReflections.handle$ServerboundPickItemFromEntityPacket$idGetter.invokeExact(packet);
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId); BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
if (furniture == null) return; if (furniture == null) return;
Player player = (Player) user.platformPlayer(); Player player = (Player) user.platformPlayer();
@@ -1420,7 +1417,7 @@ public class PacketConsumers {
player.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> { player.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> {
try { try {
handlePickItemFromEntityOnMainThread(player, furniture); handlePickItemFromEntityOnMainThread(player, furniture);
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
} }
}, () -> {}); }, () -> {});
@@ -1428,23 +1425,23 @@ public class PacketConsumers {
BukkitCraftEngine.instance().scheduler().sync().run(() -> { BukkitCraftEngine.instance().scheduler().sync().run(() -> {
try { try {
handlePickItemFromEntityOnMainThread(player, furniture); handlePickItemFromEntityOnMainThread(player, furniture);
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
} }
}); });
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundPickItemFromEntityPacket", e);
} }
}; };
private static void handlePickItemFromEntityOnMainThread(Player player, BukkitFurniture furniture) throws Exception { private static void handlePickItemFromEntityOnMainThread(Player player, BukkitFurniture furniture) throws Throwable {
Key itemId = furniture.config().settings().itemId(); Key itemId = furniture.config().settings().itemId();
if (itemId == null) return; if (itemId == null) return;
pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity())); pickItem(player, itemId, null, FastNMS.INSTANCE.method$CraftEntity$getHandle(furniture.baseEntity()));
} }
private static void pickItem(Player player, Key itemId, @Nullable Object blockPos, @Nullable Object entity) throws IllegalAccessException, InvocationTargetException { private static void pickItem(Player player, Key itemId, @Nullable Object blockPos, @Nullable Object entity) throws Throwable {
ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, BukkitCraftEngine.instance().adapt(player)); ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, BukkitCraftEngine.instance().adapt(player));
if (itemStack == null) { if (itemStack == null) {
CraftEngine.instance().logger().warn("Item: " + itemId + " is not a valid item"); CraftEngine.instance().logger().warn("Item: " + itemId + " is not a valid item");
@@ -1453,15 +1450,15 @@ public class PacketConsumers {
assert CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem != null; assert CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem != null;
if (VersionHelper.isOrAbove1_21_5()) { if (VersionHelper.isOrAbove1_21_5()) {
CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke( CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
CoreReflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), CoreReflections.handle$ServerPlayer$connectionGetter.invokeExact(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)),
FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack), blockPos, entity, true); FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack), blockPos, entity, true);
} else { } else {
CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke( CoreReflections.method$ServerGamePacketListenerImpl$tryPickItem.invoke(
CoreReflections.field$ServerPlayer$connection.get(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)); CoreReflections.handle$ServerPlayer$connectionGetter.invokeExact(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)), FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack));
} }
} }
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> ADD_ENTITY_BYTEBUFFER = (user, event) -> { public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> ADD_ENTITY = (user, event) -> {
try { try {
FriendlyByteBuf buf = event.getBuffer(); FriendlyByteBuf buf = event.getBuffer();
buf.readVarInt(); buf.readVarInt();
@@ -1665,7 +1662,7 @@ public class PacketConsumers {
} else { } else {
BukkitCraftEngine.instance().scheduler().executeSync(mainThreadTask); BukkitCraftEngine.instance().scheduler().executeSync(mainThreadTask);
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundInteractPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundInteractPacket", e);
} }
}; };
@@ -1750,20 +1747,20 @@ public class PacketConsumers {
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_ANVIL)) { if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_ANVIL)) {
return; return;
} }
String message = (String) NetworkReflections.field$ServerboundRenameItemPacket$name.get(packet); String message = (String) NetworkReflections.handle$ServerboundRenameItemPacket$nameGetter.invokeExact(packet);
if (message != null && !message.isEmpty()) { if (message != null && !message.isEmpty()) {
// check bypass // check bypass
FontManager manager = CraftEngine.instance().fontManager(); FontManager manager = CraftEngine.instance().fontManager();
IllegalCharacterProcessResult result = manager.processIllegalCharacters(message); IllegalCharacterProcessResult result = manager.processIllegalCharacters(message);
if (result.has()) { if (result.has()) {
try { try {
NetworkReflections.field$ServerboundRenameItemPacket$name.set(packet, result.text()); NetworkReflections.handle$ServerboundRenameItemPacket$nameSetter.invokeExact(packet, result.text());
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {
CraftEngine.instance().logger().warn("Failed to replace chat", e); CraftEngine.instance().logger().warn("Failed to replace chat", e);
} }
} }
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e);
} }
}; };
@@ -1776,7 +1773,7 @@ public class PacketConsumers {
if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_SIGN)) { if (((BukkitServerPlayer) user).hasPermission(FontManager.BYPASS_SIGN)) {
return; return;
} }
String[] lines = (String[]) NetworkReflections.field$ServerboundSignUpdatePacket$lines.get(packet); String[] lines = (String[]) NetworkReflections.handle$ServerboundSignUpdatePacket$linesGetter.invokeExact(packet);
FontManager manager = CraftEngine.instance().fontManager(); FontManager manager = CraftEngine.instance().fontManager();
if (!manager.isDefaultFontInUse()) return; if (!manager.isDefaultFontInUse()) return;
for (int i = 0; i < lines.length; i++) { for (int i = 0; i < lines.length; i++) {
@@ -1788,7 +1785,7 @@ public class PacketConsumers {
} }
} }
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundSignUpdatePacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundSignUpdatePacket", e);
} }
}; };
@@ -1807,9 +1804,9 @@ public class PacketConsumers {
boolean changed = false; boolean changed = false;
List<String> pages = (List<String>) NetworkReflections.field$ServerboundEditBookPacket$pages.get(packet); List<String> pages = (List<String>) NetworkReflections.handleServerboundEditBookPacket$pagesGetter.invokeExact(packet);
List<String> newPages = new ArrayList<>(pages.size()); List<String> newPages = new ArrayList<>(pages.size());
Optional<String> title = (Optional<String>) NetworkReflections.field$ServerboundEditBookPacket$title.get(packet); Optional<String> title = (Optional<String>) NetworkReflections.handle$ServerboundEditBookPacket$titleGetter.invokeExact(packet);
Optional<String> newTitle; Optional<String> newTitle;
if (title.isPresent()) { if (title.isPresent()) {
@@ -1833,13 +1830,13 @@ public class PacketConsumers {
if (changed) { if (changed) {
Object newPacket = NetworkReflections.constructor$ServerboundEditBookPacket.newInstance( Object newPacket = NetworkReflections.constructor$ServerboundEditBookPacket.newInstance(
NetworkReflections.field$ServerboundEditBookPacket$slot.get(packet), (int) NetworkReflections.handle$ServerboundEditBookPacket$slotGetter.invokeExact(packet),
newPages, newPages,
newTitle newTitle
); );
event.replacePacket(newPacket); event.replacePacket(newPacket);
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundEditBookPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundEditBookPacket", e);
} }
}; };
@@ -1866,7 +1863,7 @@ public class PacketConsumers {
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CUSTOM_PAYLOAD = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CUSTOM_PAYLOAD = (user, event, packet) -> {
try { try {
if (!VersionHelper.isOrAbove1_20_5()) return; if (!VersionHelper.isOrAbove1_20_5()) return;
Object payload = NetworkReflections.field$ServerboundCustomPayloadPacket$payload.get(packet); Object payload = NetworkReflections.handle$ServerboundCustomPayloadPacket$payloadGetter.invokeExact(packet);
if (NetworkReflections.clazz$DiscardedPayload.isInstance(payload)) { if (NetworkReflections.clazz$DiscardedPayload.isInstance(payload)) {
Payload discardedPayload = DiscardedPayload.from(payload); Payload discardedPayload = DiscardedPayload.from(payload);
if (discardedPayload == null || !discardedPayload.channel().equals(NetworkManager.MOD_CHANNEL_KEY)) if (discardedPayload == null || !discardedPayload.channel().equals(NetworkManager.MOD_CHANNEL_KEY))
@@ -1895,7 +1892,7 @@ public class PacketConsumers {
} }
} }
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundCustomPayloadPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundCustomPayloadPacket", e);
} }
}; };
@@ -2285,9 +2282,9 @@ public class PacketConsumers {
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HANDSHAKE_C2S = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> HANDSHAKE_C2S = (user, event, packet) -> {
try { try {
if (BukkitNetworkManager.hasViaVersion()) return; if (BukkitNetworkManager.hasViaVersion()) return;
int protocolVersion = NetworkReflections.field$ClientIntentionPacket$protocolVersion.getInt(packet); int protocolVersion = (int) NetworkReflections.handle$ClientIntentionPacket$protocolVersionGetter.invokeExact(packet);
user.setProtocolVersion(protocolVersion); user.setProtocolVersion(protocolVersion);
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ClientIntentionPacket", e); CraftEngine.instance().logger().warn("Failed to handle ClientIntentionPacket", e);
} }
}; };
@@ -2305,7 +2302,7 @@ public class PacketConsumers {
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_RESPONSE = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RESOURCE_PACK_RESPONSE = (user, event, packet) -> {
try { try {
if (user.sentResourcePack() || !Config.sendPackOnJoin() || !Config.kickOnDeclined()) return; if (user.sentResourcePack() || !Config.sendPackOnJoin() || !Config.kickOnDeclined()) return;
Object action = NetworkReflections.field$ServerboundResourcePackPacket$action.get(packet); Object action = NetworkReflections.handle$ServerboundResourcePackPacket$actionGetter.invokeExact(packet);
if (action == null) return; if (action == null) return;
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DECLINED if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$DECLINED
|| action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD) { || action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$FAILED_DOWNLOAD) {
@@ -2318,7 +2315,7 @@ public class PacketConsumers {
if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$SUCCESSFULLY_LOADED) { if (action == NetworkReflections.instance$ServerboundResourcePackPacket$Action$SUCCESSFULLY_LOADED) {
user.setSentResourcePack(true); user.setSentResourcePack(true);
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ServerboundResourcePackPacket", e); CraftEngine.instance().logger().warn("Failed to handle ServerboundResourcePackPacket", e);
} }
}; };
@@ -2327,28 +2324,17 @@ public class PacketConsumers {
try { try {
Object player = user.serverPlayer(); Object player = user.serverPlayer();
if (player == null) return; if (player == null) return;
int entityId = NetworkReflections.field$ClientboundEntityEventPacket$entityId.getInt(packet); int entityId = (int) NetworkReflections.handle$ClientboundEntityEventPacket$entityIdGetter.invokeExact(packet);
if (entityId != FastNMS.INSTANCE.method$Entity$getId(player)) return; if (entityId != FastNMS.INSTANCE.method$Entity$getId(player)) return;
byte eventId = NetworkReflections.field$ClientboundEntityEventPacket$eventId.getByte(packet); byte eventId = (byte) NetworkReflections.handle$ClientboundEntityEventPacket$eventIdGetter.invokeExact(packet);
if (eventId >= 24 && eventId <= 28) { if (eventId >= 24 && eventId <= 28) {
CraftEngine.instance().fontManager().refreshEmojiSuggestions(user.uuid()); CraftEngine.instance().fontManager().refreshEmojiSuggestions(user.uuid());
} }
} catch (Exception e) { } catch (Throwable e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e); CraftEngine.instance().logger().warn("Failed to handle ClientboundEntityEventPacket", e);
} }
}; };
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_ENTITY = (user, event, packet) -> {
try {
int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet);
if (BukkitFurnitureManager.instance().isFurnitureRealEntity(entityId)) {
event.setCancelled(true);
}
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundMoveEntityPacket", e);
}
};
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_AND_ROTATE_ENTITY = (user, event, packet) -> { public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> MOVE_POS_AND_ROTATE_ENTITY = (user, event, packet) -> {
try { try {
int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet); int entityId = ProtectedFieldVisitor.get().field$ClientboundMoveEntityPacket$entityId(packet);

View File

@@ -5,6 +5,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.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.EntityDataUtils; 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.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler; import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser; import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
@@ -26,9 +27,13 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
for (int i = 0; i < packedItems.size(); i++) { for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i); Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
// TODO 检查为什么会导致问题难道是其他插件乱发entity id if (entityDataId == EntityDataUtils.ITEM_DATA_ID) {
if (entityDataId == EntityDataUtils.ITEM_DATA_ID && CoreReflections.clazz$ItemStack.isInstance(packedItem)) {
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); 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); ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user); Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, (BukkitServerPlayer) user);
if (optional.isPresent()) { if (optional.isPresent()) {

View File

@@ -1,14 +0,0 @@
package net.momirealms.craftengine.bukkit.plugin.network.handler;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.NMSPacketEvent;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
public class FurnitureCollisionPacketHandler implements EntityPacketHandler {
public static final FurnitureCollisionPacketHandler INSTANCE = new FurnitureCollisionPacketHandler();
@Override
public void handleSyncEntityPosition(NetWorkUser user, NMSPacketEvent event, Object packet) {
event.setCancelled(true);
}
}

View File

@@ -2,8 +2,6 @@ package net.momirealms.craftengine.bukkit.plugin.network.handler;
import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntList;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler; import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.NMSPacketEvent;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import java.util.List; import java.util.List;
@@ -19,9 +17,4 @@ public class FurniturePacketHandler implements EntityPacketHandler {
entityIds.addAll(this.fakeEntities); entityIds.addAll(this.fakeEntities);
return true; return true;
} }
@Override
public void handleSyncEntityPosition(NetWorkUser user, NMSPacketEvent event, Object packet) {
event.setCancelled(true);
}
} }

View File

@@ -11,6 +11,8 @@ import net.momirealms.craftengine.core.util.ReflectionUtils;
import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.util.VersionHelper;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle; import java.lang.invoke.VarHandle;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
@@ -3265,4 +3267,33 @@ public final class CoreReflections {
public static final Method method$Registry$asLookup = ReflectionUtils.getMethod( public static final Method method$Registry$asLookup = ReflectionUtils.getMethod(
clazz$Registry, clazz$HolderLookup$RegistryLookup, new String[]{"asLookup", "p"} clazz$Registry, clazz$HolderLookup$RegistryLookup, new String[]{"asLookup", "p"}
); );
public static final Field field$ServerEntity$broadcast = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$ServerEntity, Consumer.class, 0
)
);
public static final MethodHandle handle$ServerEntity$broadcastSetter;
public static final MethodHandle handle$ServerEntity$updateIntervalSetter;
public static final MethodHandle handle$ServerPlayer$connectionGetter;
static {
try {
handle$ServerEntity$broadcastSetter = requireNonNull(
ReflectionUtils.unreflectSetter(field$ServerEntity$broadcast)
.asType(MethodType.methodType(void.class, Object.class, Consumer.class))
);
handle$ServerEntity$updateIntervalSetter = requireNonNull(
ReflectionUtils.unreflectSetter(field$ServerEntity$updateInterval)
.asType(MethodType.methodType(void.class, Object.class, int.class))
);
handle$ServerPlayer$connectionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerPlayer$connection)
.asType(MethodType.methodType(Object.class, Object.class))
);
} catch (IllegalAccessException e) {
throw new ReflectionInitException("Failed to initialize reflection", e);
}
}
} }

View File

@@ -1,10 +1,13 @@
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft; package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils; import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils;
import net.momirealms.craftengine.core.util.ReflectionUtils; import net.momirealms.craftengine.core.util.ReflectionUtils;
import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.util.VersionHelper;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -968,7 +971,7 @@ public final class NetworkReflections {
); );
public static final Field field$ServerboundEditBookPacket$slot = requireNonNull( public static final Field field$ServerboundEditBookPacket$slot = requireNonNull(
ReflectionUtils.getDeclaredField(clazz$ServerboundEditBookPacket, int.class, 0) ReflectionUtils.getDeclaredField(clazz$ServerboundEditBookPacket, int.class, VersionHelper.isOrAbove1_20_5() ? 0 : 4)
); );
public static final Field field$ServerboundEditBookPacket$pages = requireNonNull( public static final Field field$ServerboundEditBookPacket$pages = requireNonNull(
@@ -1300,4 +1303,170 @@ public final class NetworkReflections {
"network.protocol.game.ClientboundBlockEventPacket" "network.protocol.game.ClientboundBlockEventPacket"
) )
); );
public static final MethodHandle handle$ServerboundRenameItemPacket$nameGetter;
public static final MethodHandle handle$ServerboundRenameItemPacket$nameSetter;
public static final MethodHandle handle$ServerboundHelloPacket$nameGetter;
public static final MethodHandle handle$ServerboundHelloPacket$uuidGetter;
public static final MethodHandle handle$ServerboundSetCreativeModeSlotPacket$itemStackGetter;
public static final MethodHandle handle$ServerboundSetCreativeModeSlotPacket$slotNumGetter;
public static final MethodHandle handle$ServerboundInteractPacket$actionGetter;
public static final MethodHandle handle$ServerboundInteractPacket$InteractionAtLocationAction$handGetter;
public static final MethodHandle handle$ServerboundInteractPacket$InteractionAtLocationAction$locationGetter;
public static final MethodHandle handle$ServerboundSignUpdatePacket$linesGetter;
public static final MethodHandle handleServerboundEditBookPacket$pagesGetter;
public static final MethodHandle handle$ServerboundEditBookPacket$titleGetter;
public static final MethodHandle handle$ServerboundEditBookPacket$slotGetter;
public static final MethodHandle handle$ServerboundResourcePackPacket$actionGetter;
public static final MethodHandle handle$ClientboundEntityEventPacket$entityIdGetter;
public static final MethodHandle handle$ClientboundEntityEventPacket$eventIdGetter;
public static final MethodHandle handle$ClientIntentionPacket$protocolVersionGetter;
public static final MethodHandle handle$ClientboundRespawnPacket$dimensionGetter;
public static final MethodHandle handle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter;
public static final MethodHandle handle$CommonPlayerSpawnInfo$dimensionGetter;
public static final MethodHandle handle$ClientboundLoginPacket$dimensionGetter;
public static final MethodHandle handle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter;
public static final MethodHandle handle$ServerboundPickItemFromBlockPacket$posGetter;
public static final MethodHandle handle$ServerboundPickItemFromEntityPacket$idGetter;
public static final MethodHandle handle$ServerboundCustomPayloadPacket$payloadGetter;
static {
try {
handle$ServerboundRenameItemPacket$nameGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundRenameItemPacket$name)
.asType(MethodType.methodType(String.class, Object.class))
);
handle$ServerboundRenameItemPacket$nameSetter = requireNonNull(
ReflectionUtils.unreflectSetter(field$ServerboundRenameItemPacket$name)
.asType(MethodType.methodType(void.class, Object.class, String.class))
);
handle$ServerboundHelloPacket$nameGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundHelloPacket$name)
.asType(MethodType.methodType(String.class, Object.class))
);
handle$ServerboundHelloPacket$uuidGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundHelloPacket$uuid)
.asType(MethodType.methodType(VersionHelper.isOrAbove1_20_2() ? UUID.class : Optional.class, Object.class))
);
handle$ServerboundSetCreativeModeSlotPacket$itemStackGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundSetCreativeModeSlotPacket$itemStack)
.asType(MethodType.methodType(Object.class, Object.class))
);
handle$ServerboundSetCreativeModeSlotPacket$slotNumGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundSetCreativeModeSlotPacket$slotNum)
.asType(MethodType.methodType(VersionHelper.isOrAbove1_20_5() ? short.class : int.class, Object.class))
);
handle$ServerboundInteractPacket$actionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundInteractPacket$action)
.asType(MethodType.methodType(Object.class, Object.class))
);
handle$ServerboundInteractPacket$InteractionAtLocationAction$handGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundInteractPacket$InteractionAtLocationAction$hand)
.asType(MethodType.methodType(Object.class, Object.class))
);
handle$ServerboundInteractPacket$InteractionAtLocationAction$locationGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundInteractPacket$InteractionAtLocationAction$location)
.asType(MethodType.methodType(Object.class, Object.class))
);
handle$ServerboundSignUpdatePacket$linesGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundSignUpdatePacket$lines)
.asType(MethodType.methodType(String[].class, Object.class))
);
handleServerboundEditBookPacket$pagesGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$pages)
.asType(MethodType.methodType(List.class, Object.class))
);
handle$ServerboundEditBookPacket$titleGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$title)
.asType(MethodType.methodType(Optional.class, Object.class))
);
handle$ServerboundEditBookPacket$slotGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundEditBookPacket$slot)
.asType(MethodType.methodType(int.class, Object.class))
);
handle$ServerboundResourcePackPacket$actionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundResourcePackPacket$action)
.asType(MethodType.methodType(Object.class, Object.class))
);
handle$ClientboundEntityEventPacket$entityIdGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientboundEntityEventPacket$entityId)
.asType(MethodType.methodType(int.class, Object.class))
);
handle$ClientboundEntityEventPacket$eventIdGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientboundEntityEventPacket$eventId)
.asType(MethodType.methodType(byte.class, Object.class))
);
handle$ClientIntentionPacket$protocolVersionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientIntentionPacket$protocolVersion)
.asType(MethodType.methodType(int.class, Object.class))
);
if (field$ServerboundCustomPayloadPacket$payload != null) {
handle$ServerboundCustomPayloadPacket$payloadGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundCustomPayloadPacket$payload)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$ServerboundCustomPayloadPacket$payloadGetter = null;
}
if (field$ServerboundPickItemFromEntityPacket$id != null) {
handle$ServerboundPickItemFromEntityPacket$idGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundPickItemFromEntityPacket$id)
.asType(MethodType.methodType(int.class, Object.class))
);
} else {
handle$ServerboundPickItemFromEntityPacket$idGetter = null;
}
if (field$ServerboundPickItemFromBlockPacket$pos != null) {
handle$ServerboundPickItemFromBlockPacket$posGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ServerboundPickItemFromBlockPacket$pos)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$ServerboundPickItemFromBlockPacket$posGetter = null;
}
if (field$ClientboundLoginPacket$commonPlayerSpawnInfo != null) {
handle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientboundLoginPacket$commonPlayerSpawnInfo)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$ClientboundLoginPacket$commonPlayerSpawnInfoGetter = null;
}
if (field$ClientboundLoginPacket$dimension != null) {
handle$ClientboundLoginPacket$dimensionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientboundLoginPacket$dimension)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$ClientboundLoginPacket$dimensionGetter = null;
}
if (field$CommonPlayerSpawnInfo$dimension != null) {
handle$CommonPlayerSpawnInfo$dimensionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$CommonPlayerSpawnInfo$dimension)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$CommonPlayerSpawnInfo$dimensionGetter = null;
}
if (field$ClientboundRespawnPacket$commonPlayerSpawnInfo != null) {
handle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientboundRespawnPacket$commonPlayerSpawnInfo)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$ClientboundRespawnPacket$commonPlayerSpawnInfoGetter = null;
}
if (field$ClientboundRespawnPacket$dimension != null) {
handle$ClientboundRespawnPacket$dimensionGetter = requireNonNull(
ReflectionUtils.unreflectGetter(field$ClientboundRespawnPacket$dimension)
.asType(MethodType.methodType(Object.class, Object.class))
);
} else {
handle$ClientboundRespawnPacket$dimensionGetter = null;
}
} catch (Throwable e) {
throw new ReflectionInitException("Failed to initialize reflection", e);
}
}
} }

View File

@@ -182,6 +182,13 @@ debug_clear_cooldown:
- /craftengine debug clear-cooldown - /craftengine debug clear-cooldown
- /ce debug clear-cooldown - /ce debug clear-cooldown
debug_entity_id_to_uuid:
enable: true
permission: ce.command.debug.entity_id_to_uuid
usage:
- /craftengine debug entity-id-to-uuid
- /ce debug entity-id-to-uuid
debug_test: debug_test:
enable: true enable: true
permission: ce.command.debug.test permission: ce.command.debug.test

View File

@@ -156,6 +156,7 @@ warning.config.item.invalid_material: "<yellow>Issue found in file <arg:0> - The
warning.config.item.invalid_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a negative custom model data '<arg:2>' which is invalid.</yellow>" warning.config.item.invalid_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a negative custom model data '<arg:2>' which is invalid.</yellow>"
warning.config.item.bad_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that is too large. It's recommended to use a value lower than 16,777,216.</yellow>" warning.config.item.bad_custom_model_data: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that is too large. It's recommended to use a value lower than 16,777,216.</yellow>"
warning.config.item.custom_model_data_conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that has been occupied by item '<arg:3>'.</yellow>" warning.config.item.custom_model_data_conflict: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is using a custom model data '<arg:2>' that has been occupied by item '<arg:3>'.</yellow>"
warning.config.item.component_notfound: "<yellow>Issue found - Have item using a component '<arg:0>' that does not exist.</yellow>"
warning.config.item.missing_model_id: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'custom-model-data' or 'item-model' argument.</yellow>" warning.config.item.missing_model_id: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'custom-model-data' or 'item-model' argument.</yellow>"
warning.config.item.missing_model: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'model' section for 1.21.4+ resource pack support.</yellow>" warning.config.item.missing_model: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'model' section for 1.21.4+ resource pack support.</yellow>"
warning.config.item.behavior.missing_type: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'type' argument for its item behavior.</yellow>" warning.config.item.behavior.missing_type: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'type' argument for its item behavior.</yellow>"

View File

@@ -156,6 +156,7 @@ warning.config.item.invalid_material: "<yellow>在文件 <arg:0> 发现问题 -
warning.config.item.invalid_custom_model_data: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用了无效的负数模型值 '<arg:2>'.</yellow>" warning.config.item.invalid_custom_model_data: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用了无效的负数模型值 '<arg:2>'.</yellow>"
warning.config.item.bad_custom_model_data: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 数值过大 建议使用小于 16,777,216 的值</yellow>" warning.config.item.bad_custom_model_data: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 数值过大 建议使用小于 16,777,216 的值</yellow>"
warning.config.item.custom_model_data_conflict: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 已被物品 '<arg:3>' 占用</yellow>" warning.config.item.custom_model_data_conflict: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 使用的自定义模型数据 '<arg:2>' 已被物品 '<arg:3>' 占用</yellow>"
warning.config.item.component_notfound: "<yellow>发现问题 - 有物品使用了未知的组件 '<arg:0>'</yellow>"
warning.config.item.missing_model_id: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 缺少必需的 'custom-model-data' 或 'item-model' 参数</yellow>" warning.config.item.missing_model_id: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 缺少必需的 'custom-model-data' 或 'item-model' 参数</yellow>"
warning.config.item.missing_model: "<yellow>在文件 <arg:0> 中发现问题 - 物品 '<arg:1>' 缺少支持 1.21.4+ 资源包必需的 'model' 配置项</yellow>" warning.config.item.missing_model: "<yellow>在文件 <arg:0> 中发现问题 - 物品 '<arg:1>' 缺少支持 1.21.4+ 资源包必需的 'model' 配置项</yellow>"
warning.config.item.behavior.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的行为配置缺少必需的 'type' 参数</yellow>" warning.config.item.behavior.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的行为配置缺少必需的 'type' 参数</yellow>"

View File

@@ -6,6 +6,7 @@ public abstract class AbstractCustomProjectile implements CustomProjectile {
protected final ProjectileMeta meta; protected final ProjectileMeta meta;
protected final Projectile projectile; protected final Projectile projectile;
protected final Item<?> item; protected final Item<?> item;
private int inGroundTime;
protected AbstractCustomProjectile(ProjectileMeta meta, Projectile projectile, Item<?> item) { protected AbstractCustomProjectile(ProjectileMeta meta, Projectile projectile, Item<?> item) {
this.meta = meta; this.meta = meta;
@@ -27,4 +28,14 @@ public abstract class AbstractCustomProjectile implements CustomProjectile {
public Item<?> item() { public Item<?> item() {
return item; return item;
} }
@Override
public int inGroundTime() {
return inGroundTime;
}
@Override
public void setInGroundTime(int inGroundTime) {
this.inGroundTime = inGroundTime;
}
} }

View File

@@ -9,4 +9,8 @@ public interface CustomProjectile {
Projectile projectile(); Projectile projectile();
Item<?> item(); Item<?> item();
int inGroundTime();
void setInGroundTime(int inGroundTime);
} }

View File

@@ -494,6 +494,15 @@ public class ReflectionUtils {
} }
} }
public static MethodHandle unreflectSetter(Field field) throws IllegalAccessException {
try {
return LOOKUP.unreflectSetter(field);
} catch (IllegalAccessException e) {
field.setAccessible(true);
return LOOKUP.unreflectSetter(field);
}
}
public static MethodHandle unreflectMethod(Method method) throws IllegalAccessException { public static MethodHandle unreflectMethod(Method method) throws IllegalAccessException {
try { try {
return LOOKUP.unreflect(method); return LOOKUP.unreflect(method);

View File

@@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
# Project settings # Project settings
# Rule: [major update].[feature update].[bug fix] # Rule: [major update].[feature update].[bug fix]
project_version=0.0.56.3 project_version=0.0.56.3
config_version=34 config_version=35
lang_version=15 lang_version=15
project_group=net.momirealms project_group=net.momirealms
latest_supported_version=1.21.5 latest_supported_version=1.21.5