From e6a0430d65632ace6c2a09ca943c36bc74a0b25f Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Mon, 7 Apr 2025 04:17:16 +0800 Subject: [PATCH] 0.0.45 --- bukkit/loader/src/main/resources/config.yml | 2 +- .../furniture/BukkitFurnitureManager.java | 133 ++++++++++++------ .../furniture/FurnitureEventListener.java | 37 +++-- .../entity/furniture/LoadedFurniture.java | 4 +- .../plugin/command/feature/TestCommand.java | 14 +- gradle.properties | 6 +- 6 files changed, 135 insertions(+), 61 deletions(-) diff --git a/bukkit/loader/src/main/resources/config.yml b/bukkit/loader/src/main/resources/config.yml index e4a3c6378..c7a90b6a0 100644 --- a/bukkit/loader/src/main/resources/config.yml +++ b/bukkit/loader/src/main/resources/config.yml @@ -233,7 +233,7 @@ chunk-system: # 2 = DEFLATE | Medium-Slow Medium Moderate Low | # 3 = GZIP | Medium-Slow Medium Moderate Low | # 4 = LAZ4 | Blazing-Fast Blazing-Fast Low Low | - # 5 = ZSTD | Medium-Fast Fast High Medium | + # 5 = ZSTD | Medium-Fast Fast High Medium | compression-method: 4 # Disabling this option prevents the plugin from converting custom blocks to vanilla states when chunks are unloaded. # While this can improve performance, custom blocks will turn into air if the plugin is uninstalled. diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index f861fdc9d..fefc399c1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -32,12 +32,14 @@ import javax.annotation.Nullable; import java.nio.file.Path; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; public class BukkitFurnitureManager extends AbstractFurnitureManager { public static final NamespacedKey FURNITURE_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_id")); public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type")); public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity")); public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_vector")); + public static final NamespacedKey FURNITURE_COLLISION = Objects.requireNonNull(NamespacedKey.fromString("craftengine:collision")); private static BukkitFurnitureManager instance; private final BukkitCraftEngine plugin; private final FurnitureParser furnitureParser; @@ -57,6 +59,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { this.furnitureParser = new FurnitureParser(); this.furnitureEventListener = new FurnitureEventListener(this); this.dismountListener = VersionHelper.isVersionNewerThan1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount); + plugin.scheduler().asyncRepeating(() -> { + System.out.println("数量" + furnitureByRealEntityId.size()); + }, 3, 3, TimeUnit.SECONDS); } @Override @@ -73,7 +78,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { ItemDisplay display = (ItemDisplay) entity; display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_KEY, PersistentDataType.STRING, furniture.id().toString()); display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, finalAnchorType.name()); - handleEntityLoadEarly(display); + handleBaseEntityLoadEarly(display); }); if (playSound) { SoundData data = furniture.settings().sounds().placeSound(); @@ -214,7 +219,9 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { for (World world : Bukkit.getWorlds()) { List entities = world.getEntities(); for (Entity entity : entities) { - handleEntityLoadEarly(entity); + if (entity instanceof ItemDisplay display) { + handleBaseEntityLoadEarly(display); + } } } } @@ -249,7 +256,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { return this.furnitureByEntityId.get(entityId); } - protected void handleBaseFurnitureUnload(Entity entity, boolean unloadColliders) { + protected void handleBaseEntityUnload(Entity entity) { int id = entity.getEntityId(); LoadedFurniture furniture = this.furnitureByRealEntityId.remove(id); if (furniture != null) { @@ -261,57 +268,97 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { for (int sub : furniture.entityIds()) { this.furnitureByEntityId.remove(sub); } - for (CollisionEntity collision : furniture.collisionEntities()) { - if (unloadColliders) { - this.furnitureByRealEntityId.remove(FastNMS.INSTANCE.method$Entity$getId(collision)); - } - if (!isPreventing) collision.destroy(); - } +// for (CollisionEntity collision : furniture.collisionEntities()) { +// this.furnitureByRealEntityId.remove(FastNMS.INSTANCE.method$Entity$getId(collision)); +// if (!isPreventing) collision.destroy(); +// } } } + protected void handleCollisionEntityUnload(Entity entity) { + int id = entity.getEntityId(); + this.furnitureByRealEntityId.remove(id); + } + @SuppressWarnings("deprecation") // just a misleading name `getTrackedPlayers` - protected void handleEntityLoadLate(Entity entity) { - if (entity instanceof ItemDisplay display) { - String id = entity.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); - if (id == null) return; - Key key = Key.of(id); - Optional optionalFurniture = furnitureById(key); - if (optionalFurniture.isEmpty()) return; - CustomFurniture customFurniture = optionalFurniture.get(); - LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); - if (previous != null) return; - Location location = entity.getLocation(); - if (FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4)) { - return; - } - LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(entity, customFurniture)); + protected void handleBaseEntityLoadLate(ItemDisplay display, int depth) { + // must be a furniture item + String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); + if (id == null) return; + + Key key = Key.of(id); + Optional optionalFurniture = furnitureById(key); + if (optionalFurniture.isEmpty()) return; + + CustomFurniture customFurniture = optionalFurniture.get(); + LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); + if (previous != null) return; + + Location location = display.getLocation(); + if (!FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4)) { + LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture)); for (Player player : display.getTrackedPlayers()) { this.plugin.adapt(player).furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.fakeEntityIds()); this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player)); } + return; + } + + if (depth > 2) return; + this.plugin.scheduler().sync().runLater(() -> { + handleBaseEntityLoadLate(display, depth + 1); + }, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); + } + + protected void handleCollisionEntityLoadLate(Shulker shulker, int depth) { + // remove the shulker if it's not a collision entity, it might be wrongly copied by WorldEdit + if (FastNMS.INSTANCE.method$CraftEntity$getHandle(shulker) instanceof CollisionEntity) { + return; + } + Byte flag = shulker.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); + if (flag != null && flag == 1) { + return; + } + + Location location = shulker.getLocation(); + World world = location.getWorld(); + int chunkX = location.getBlockX() >> 4; + int chunkZ = location.getBlockZ() >> 4; + if (!FastNMS.INSTANCE.isPreventingStatusUpdates(world, chunkX, chunkZ)) { + shulker.remove(); + return; + } + + if (depth > 2) return; + plugin.scheduler().sync().runLater(() -> { + handleCollisionEntityLoadLate(shulker, depth + 1); + }, 1, world, chunkX, chunkZ); + } + + public void handleBaseEntityLoadEarly(ItemDisplay display) { + String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); + if (id == null) return; + Key key = Key.of(id); + Optional optionalFurniture = furnitureById(key); + if (optionalFurniture.isPresent()) { + CustomFurniture customFurniture = optionalFurniture.get(); + LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); + if (previous != null) return; + addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture)); + return; + } + // Remove the entity if it's not a valid furniture + if (Config.removeInvalidFurniture()) { + if (Config.furnitureToRemove().isEmpty() || Config.furnitureToRemove().contains(id)) { + display.remove(); + } } } - public void handleEntityLoadEarly(Entity entity) { - if (entity instanceof ItemDisplay display) { - String id = entity.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); - if (id == null) return; - Key key = Key.of(id); - Optional optionalFurniture = furnitureById(key); - if (optionalFurniture.isPresent()) { - CustomFurniture customFurniture = optionalFurniture.get(); - LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); - if (previous != null) return; - addNewFurniture(display, customFurniture, getAnchorType(entity, customFurniture)); - return; - } - // Remove the entity if it's not a valid furniture - if (Config.removeInvalidFurniture()) { - if (Config.furnitureToRemove().isEmpty() || Config.furnitureToRemove().contains(id)) { - entity.remove(); - } - } + public void handleCollisionEntityLoadOnEntitiesLoad(Shulker shulker) { + // remove the shulker if it's on chunk load stage + if (FastNMS.INSTANCE.method$CraftEntity$getHandle(shulker) instanceof CollisionEntity) { + shulker.remove(); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java index dadd87e7f..18bfa8e42 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java @@ -2,10 +2,7 @@ package net.momirealms.craftengine.bukkit.entity.furniture; import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.ItemDisplay; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -34,7 +31,11 @@ public class FurnitureEventListener implements Listener { public void onEntitiesLoadEarly(EntitiesLoadEvent event) { List entities = event.getEntities(); for (Entity entity : entities) { - this.manager.handleEntityLoadEarly(entity); + if (entity instanceof ItemDisplay itemDisplay) { + this.manager.handleBaseEntityLoadEarly(itemDisplay); + } else if (entity instanceof Shulker shulker) { + this.manager.handleCollisionEntityLoadOnEntitiesLoad(shulker); + } } } @@ -42,13 +43,20 @@ public class FurnitureEventListener implements Listener { public void onWorldLoad(WorldLoadEvent event) { List entities = event.getWorld().getEntities(); for (Entity entity : entities) { - this.manager.handleEntityLoadEarly(entity); + if (entity instanceof ItemDisplay itemDisplay) { + this.manager.handleBaseEntityLoadEarly(itemDisplay); + } } } @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onEntityLoad(EntityAddToWorldEvent event) { - this.manager.handleEntityLoadLate(event.getEntity()); + Entity entity = event.getEntity(); + if (entity instanceof ItemDisplay itemDisplay) { + this.manager.handleBaseEntityLoadLate(itemDisplay, 0); + } else if (entity instanceof Shulker shulker) { + this.manager.handleCollisionEntityLoadLate(shulker, 0); + } } /* @@ -59,7 +67,9 @@ public class FurnitureEventListener implements Listener { Entity[] entities = event.getChunk().getEntities(); for (Entity entity : entities) { if (entity instanceof ItemDisplay) { - this.manager.handleBaseFurnitureUnload(entity, true); + this.manager.handleBaseEntityUnload(entity); + } else if (entity instanceof Shulker) { + this.manager.handleCollisionEntityUnload(entity); } } } @@ -69,15 +79,20 @@ public class FurnitureEventListener implements Listener { List entities = event.getWorld().getEntities(); for (Entity entity : entities) { if (entity instanceof ItemDisplay) { - this.manager.handleBaseFurnitureUnload(entity, true); + this.manager.handleBaseEntityUnload(entity); + } else if (entity instanceof Shulker) { + this.manager.handleCollisionEntityUnload(entity); } } } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onEntityUnload(EntityRemoveFromWorldEvent event) { - if (event.getEntity() instanceof ItemDisplay itemDisplay) { - this.manager.handleBaseFurnitureUnload(itemDisplay, false); + Entity entity = event.getEntity(); + if (entity instanceof ItemDisplay) { + this.manager.handleBaseEntityUnload(entity); + } else if (entity instanceof Shulker) { + this.manager.handleCollisionEntityUnload(entity); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java index 74862a595..24c43664f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java @@ -44,7 +44,6 @@ public class LoadedFurniture implements Furniture { private final Map hitBoxes; private final boolean minimized; private final boolean hasExternalModel; - private final CustomFurniture.Placement placement; // seats private final Set occupiedSeats = Collections.synchronizedSet(new HashSet<>()); private final Vector seats = new Vector<>(); @@ -68,7 +67,6 @@ public class LoadedFurniture implements Furniture { mainEntityIds.add(this.baseEntityId); CustomFurniture.Placement placement = furniture.getPlacement(anchorType); - this.placement = placement; // bind external furniture Optional optionalExternal = placement.externalModel(); if (optionalExternal.isPresent()) { @@ -152,6 +150,8 @@ public class LoadedFurniture implements Furniture { Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld()); for (CollisionEntity entity : this.collisionEntities) { FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity); + Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity); + bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 688e8743b..d73c9aa4f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -1,13 +1,18 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; +import net.momirealms.craftengine.bukkit.nms.CollisionEntity; +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.command.CommandSender; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.incendo.cloud.Command; +import java.util.Collection; + public class TestCommand extends BukkitCommandFeature { public TestCommand(CraftEngineCommandManager commandManager, CraftEngine plugin) { @@ -22,7 +27,14 @@ public class TestCommand extends BukkitCommandFeature { Player player = context.sender(); Location location = player.getLocation(); try { - + Collection entities = player.getLocation().getNearbyEntities(2,2,2); + for (Entity entity : entities) { + System.out.println(entity.getType()); + if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) { + System.out.println(entity.getEntityId()); + System.out.println(entity.getUniqueId()); + } + } } catch (Exception e) { e.printStackTrace(); } diff --git a/gradle.properties b/gradle.properties index 739463b8a..a80c87bb7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,8 +2,8 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.44 -config_version=21 +project_version=0.0.45 +config_version=22 lang_version=4 project_group=net.momirealms latest_supported_version=1.21.5 @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.13 -nms_helper_version=0.42 +nms_helper_version=0.43 # Ignite Dependencies mixinextras_version=0.4.1 mixin_version=0.15.2+mixin.0.8.7