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

修复错误的id删除

This commit is contained in:
XiaoMoMi
2025-12-04 04:22:34 +08:00
parent a156942344
commit 14b0c71147
15 changed files with 128 additions and 47 deletions

View File

@@ -330,7 +330,7 @@ public final class CraftEngineFurniture {
public static BukkitFurniture getLoadedFurnitureByCollider(@NotNull Entity collider) {
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(collider);
if (nmsEntity instanceof CollisionEntity collisionEntity) {
return BukkitFurnitureManager.instance().loadedFurnitureByColliderEntityId(collisionEntity.getId());
return BukkitFurnitureManager.instance().loadedFurnitureByColliderEntityId(collisionEntity.getEntityId());
}
return null;
}

View File

@@ -21,7 +21,7 @@ public class BukkitCollider implements Collider {
@Override
public int entityId() {
return this.collisionEntity.getId();
return this.collisionEntity.getEntityId();
}
@Override

View File

@@ -31,10 +31,12 @@ public class BukkitFurniture extends Furniture {
public void addCollidersToWorld() {
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld());
for (Collider entity : super.colliders) {
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle());
Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity.handle());
bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1);
bukkitEntity.setPersistent(false);
if (!bukkitEntity.isValid()) {
FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle());
}
}
}

View File

@@ -1,15 +1,19 @@
package net.momirealms.craftengine.bukkit.entity.furniture;
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionFurnitureHitboxConfig;
import net.momirealms.craftengine.bukkit.nms.CollisionEntity;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.EntityUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.entity.furniture.*;
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.Key;
@@ -29,6 +33,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class BukkitFurnitureManager extends AbstractFurnitureManager {
public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY);
@@ -73,7 +78,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
} catch (IOException e) {
this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e);
}
handleMetaEntityAfterChunkLoad(display);
handleMetaEntityDuringChunkLoad(display);
});
if (playSound) {
SoundData sound = furniture.settings().sounds().placeSound();
@@ -228,6 +233,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
createFurnitureInstance(entity, customFurniture);
}
@SuppressWarnings("deprecation")
protected void handleMetaEntityAfterChunkLoad(ItemDisplay entity) {
// 实体可能不是持久的
if (!entity.isPersistent()) {
@@ -239,7 +245,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
if (id == null) return;
// 这个区块还处于加载实体中,这个时候不处理
if (!isEntitiesLoaded(entity.getLocation())) {
Location location = entity.getLocation();
if (!isEntitiesLoaded(location)) {
return;
}
@@ -254,13 +261,16 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
if (previous != null) return;
createFurnitureInstance(entity, customFurniture);
// 补发一次包
for (Player player : entity.getTrackedPlayers()) {
BukkitAdaptors.adapt(player).sendPacket(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
entity.getEntityId(), entity.getUniqueId(), location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw(),
MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
), false);
}
}
protected void handleCollisionEntityAfterChunkLoad(Entity entity) {
// 实体可能不是持久的
if (!entity.isPersistent()) {
return;
}
// 如果是碰撞实体,那么就忽略
if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) {
return;
@@ -271,11 +281,13 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
return;
}
// 实体未加载
if (!isEntitiesLoaded(entity.getLocation())) {
Location location = entity.getLocation();
if (!isEntitiesLoaded(location)) {
return;
}
// 移除被WorldEdit错误复制的碰撞实体
entity.remove();
runSafeEntityOperation(location, entity::remove);
}
public void handleCollisionEntityDuringChunkLoad(Entity collisionEntity) {
@@ -306,7 +318,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
}
// 创建家具实例,并初始化碰撞实体
private void createFurnitureInstance(ItemDisplay display, FurnitureConfig furniture) {
private BukkitFurniture createFurnitureInstance(ItemDisplay display, FurnitureConfig furniture) {
BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, getFurnitureDataAccessor(display));
this.byMetaEntityId.put(display.getEntityId(), bukkitFurniture);
for (int entityId : bukkitFurniture.virtualEntityIds()) {
@@ -315,7 +327,18 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
for (Collider collisionEntity : bukkitFurniture.colliders()) {
this.byColliderEntityId.put(collisionEntity.entityId(), bukkitFurniture);
}
bukkitFurniture.addCollidersToWorld();
Location location = display.getLocation();
runSafeEntityOperation(location, bukkitFurniture::addCollidersToWorld);
return bukkitFurniture;
}
private void runSafeEntityOperation(Location location, Runnable action) {
boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4);
if (preventChange) {
this.plugin.scheduler().sync().runLater(action, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
} else {
action.run();
}
}
@Override

View File

@@ -27,6 +27,7 @@ public class CustomFurnitureHitbox extends AbstractFurnitureHitBox {
private final Object spawnPacket;
private final Object despawnPacket;
private final FurnitureHitboxPart part;
private final int entityId;
public CustomFurnitureHitbox(Furniture furniture, CustomFurnitureHitboxConfig config) {
super(furniture, config);
@@ -54,6 +55,7 @@ public class CustomFurnitureHitbox extends AbstractFurnitureHitBox {
this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets);
this.part = new FurnitureHitboxPart(entityId, aabb, pos, false);
this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(entityId); }});
this.entityId = entityId;
}
@Override
@@ -76,6 +78,11 @@ public class CustomFurnitureHitbox extends AbstractFurnitureHitBox {
player.sendPacket(this.despawnPacket, false);
}
@Override
public void collectVirtualEntityId(Consumer<Integer> collector) {
collector.accept(this.entityId);
}
@Override
public CustomFurnitureHitboxConfig config() {
return this.config;

View File

@@ -83,6 +83,11 @@ public class HappyGhastFurnitureHitbox extends AbstractFurnitureHitBox {
player.sendPacket(this.despawnPacket, false);
}
@Override
public void collectVirtualEntityId(Consumer<Integer> collector) {
collector.accept(this.entityId);
}
@Override
public HappyGhastFurnitureHitboxConfig config() {
return this.config;

View File

@@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.world.collision.AABB;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox {
private final InteractionFurnitureHitboxConfig config;
@@ -21,6 +22,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox {
private final Object spawnPacket;
private final Object despawnPacket;
private final FurnitureHitboxPart part;
private final int entityId;
public InteractionFurnitureHitbox(Furniture furniture, InteractionFurnitureHitboxConfig config) {
super(furniture, config);
@@ -39,6 +41,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox {
));
this.part = new FurnitureHitboxPart(interactionId, aabb, pos, config.responsive());
this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(interactionId); }});
this.entityId = interactionId;
}
@Override
@@ -56,6 +59,11 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox {
return this.config;
}
@Override
public void collectVirtualEntityId(Consumer<Integer> collector) {
collector.accept(this.entityId);
}
@Override
public void show(Player player) {
player.sendPacket(this.spawnPacket, false);

View File

@@ -17,10 +17,7 @@ import net.momirealms.craftengine.core.world.WorldPosition;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -30,11 +27,12 @@ public class ShulkerFurnitureHitbox extends AbstractFurnitureHitBox {
private final List<Collider> colliders;
private final Object spawnPacket;
private final Object despawnPacket;
private final int[] entityIds;
public ShulkerFurnitureHitbox(Furniture furniture, ShulkerFurnitureHitboxConfig config) {
super(furniture, config);
this.config = config;
int[] entityIds = acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet);
this.entityIds = acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet);
WorldPosition position = furniture.position();
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0f, (float) Math.toRadians(180 - position.yRot()), 0f).conjugate();
Vector3f offset = conjugated.transform(new Vector3f(config.position()));
@@ -99,6 +97,13 @@ public class ShulkerFurnitureHitbox extends AbstractFurnitureHitBox {
return this.parts;
}
@Override
public void collectVirtualEntityId(Consumer<Integer> collector) {
for (int entityId : entityIds) {
collector.accept(entityId);
}
}
@Override
public void show(Player player) {
player.sendPacket(this.spawnPacket, false);

View File

@@ -80,11 +80,9 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
));
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)));
if (canUseItemOn) {
Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y, z - offset.z);
aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive));
}
}
};
this.aabbCreator = (x, y, z, yaw, offset) -> createAABB(Direction.UP, offset, x, y, z);
} else if (direction == Direction.DOWN) {
@@ -100,11 +98,9 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
));
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[2], List.copyOf(cachedInteractionValues)));
if (canUseItemOn) {
Vec3d vec3d = new Vec3d(x + offset.x, y + offset.y - shulkerHeight + scale, z - offset.z);
aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d, scale, shulkerHeight), vec3d, interactive));
}
}
};
this.aabbCreator = (x, y, z, yaw, offset) -> createAABB(Direction.DOWN, offset, x, y, z);
} else {
@@ -130,13 +126,11 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
));
packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityIds[3], List.copyOf(cachedInteractionValues)));
if (canUseItemOn) {
Vec3d vec3d1 = new Vec3d(x + offset.x, y + offset.y, z - offset.z);
Vec3d vec3d2 = new Vec3d(x + offset.x + shulkerDirection.stepX() * distance, y + offset.y, z - offset.z + shulkerDirection.stepZ() * distance);
aabb.accept(new FurnitureHitboxPart(entityIds[2], AABB.makeBoundingBox(vec3d1, scale, scale), vec3d1, interactive));
aabb.accept(new FurnitureHitboxPart(entityIds[3], AABB.makeBoundingBox(vec3d2, scale, scale), vec3d2, interactive));
}
}
};
this.aabbCreator = (x, y, z, yaw, offset) -> {
Direction shulkerAnchor = getOriginalDirection(direction, Direction.fromYaw(yaw));

View File

@@ -3954,14 +3954,16 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
BukkitFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByMetaEntityId(id);
if (furniture != null) {
serverPlayer.entityPacketHandlers().put(id, new FurniturePacketHandler(id, furniture.virtualEntityIds()));
EntityPacketHandler previous = serverPlayer.entityPacketHandlers().put(id, new FurniturePacketHandler(id, furniture.virtualEntityIds()));
if (Config.enableEntityCulling()) {
serverPlayer.addTrackedFurniture(id, furniture);
} else {
// 修复addEntityToWorld包比事件先发的问题 (WE)
if (previous == null || previous instanceof ItemDisplayPacketHandler) {
furniture.show(serverPlayer);
}
// fixme 外部模型
if (Config.hideBaseEntity() && true) {
}
if (Config.hideBaseEntity() && !furniture.hasExternalModel()) {
event.setCancelled(true);
}
} else {

View File

@@ -558,7 +558,7 @@ chunk-system:
client-optimization:
# Requires a restart to fully apply.
entity-culling:
enable: true
enable: false
# Using server-side ray tracing algorithms to hide block entities/furniture and reduce client-side rendering pressure.
ray-tracing: true
# Cull entities based on distance

View File

@@ -27,6 +27,7 @@ items:
billboard: FIXED
translation: 0,0.5,0
hitboxes:
$$>=1.20.5:
- position: 0,0,0
type: custom
entity-type: slime
@@ -35,6 +36,16 @@ items:
blocks-building: true
seats:
- 0,0,-0.1 0
$$fallback:
- position: 0,0,0
type: interaction
blocks-building: true
invisible: true
width: 0.7
height: 1.2
interactive: true
seats:
- 0,0,-0.1 0
loot:
template: default:loot_table/furniture
arguments:

View File

@@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.momirealms.craftengine.core.entity.AbstractEntity;
import net.momirealms.craftengine.core.entity.Entity;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
@@ -13,6 +14,7 @@ import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxCo
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitboxPart;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.entity.seat.Seat;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.QuaternionUtils;
@@ -25,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.Optional;
import java.util.UUID;
public abstract class Furniture implements Cullable {
@@ -41,6 +44,8 @@ public abstract class Furniture implements Cullable {
protected int[] virtualEntityIds;
protected int[] colliderEntityIds;
private boolean hasExternalModel;
protected Furniture(Entity metaDataEntity, FurnitureDataAccessor data, FurnitureConfig config) {
this.config = config;
this.dataAccessor = data;
@@ -77,8 +82,8 @@ public abstract class Furniture implements Cullable {
this.hitboxes[i] = hitbox;
for (FurnitureHitboxPart part : hitbox.parts()) {
this.hitboxMap.put(part.entityId(), hitbox);
virtualEntityIds.add(part.entityId());
}
hitbox.collectVirtualEntityId(virtualEntityIds::addLast);
colliders.addAll(hitbox.colliders());
}
// 虚拟碰撞箱的实体id
@@ -86,6 +91,18 @@ public abstract class Furniture implements Cullable {
this.colliders = colliders.toArray(new Collider[0]);
this.colliderEntityIds = colliders.stream().mapToInt(Collider::entityId).toArray();
this.cullingData = createCullingData(variant.cullingData());
// 外部模型
Optional<ExternalModel> externalModel = variant.externalModel();
if (externalModel.isPresent()) {
this.hasExternalModel = true;
try {
externalModel.get().bindModel((AbstractEntity) this.metaDataEntity);
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id(), e);
}
} else {
this.hasExternalModel = false;
}
}
private CullingData createCullingData(CullingData parent) {
@@ -181,6 +198,10 @@ public abstract class Furniture implements Cullable {
return this.metaDataEntity.entityID();
}
public boolean hasExternalModel() {
return hasExternalModel;
}
public Vec3d getRelativePosition(Vector3f position) {
return getRelativePosition(this.position(), position);
}

View File

@@ -9,6 +9,7 @@ import net.momirealms.craftengine.core.world.Vec3d;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public interface FurnitureHitBox extends SeatOwner {
@@ -24,6 +25,8 @@ public interface FurnitureHitBox extends SeatOwner {
FurnitureHitBoxConfig<?> config();
void collectVirtualEntityId(Consumer<Integer> collector);
default Optional<EntityHitResult> clip(Vec3d min, Vec3d max) {
for (FurnitureHitboxPart value : parts()) {
Optional<EntityHitResult> clip = value.aabb().clip(min, max);

View File

@@ -48,7 +48,7 @@ byte_buddy_version=1.18.1
ahocorasick_version=0.6.3
snake_yaml_version=2.5
anti_grief_version=1.0.5
nms_helper_version=1.0.138
nms_helper_version=1.0.140
evalex_version=3.5.0
reactive_streams_version=1.0.4
amazon_awssdk_version=2.38.7