From 61762e314d71974344326ffbe439f3885acbdd52 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Tue, 1 Apr 2025 02:25:21 +0800 Subject: [PATCH] add minimized option --- .../furniture/BukkitFurnitureManager.java | 2 +- .../entity/furniture/LoadedFurniture.java | 33 ++++++++++++++----- .../furniture/hitbox/HappyGhastHitBox.java | 3 +- .../furniture/hitbox/InteractionHitBox.java | 7 ++-- .../furniture/hitbox/ShulkerHitBox.java | 17 +++++----- .../plugin/network/PacketConsumers.java | 2 +- .../entity/furniture/FurnitureManager.java | 1 + .../entity/furniture/FurnitureSettings.java | 15 +++++++++ .../core/entity/furniture/HitBox.java | 3 +- 9 files changed, 60 insertions(+), 23 deletions(-) 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 9a685a32f..9a7a74142 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 @@ -285,7 +285,7 @@ public class BukkitFurnitureManager implements FurnitureManager { LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(entity, customFurniture)); for (Player player : display.getTrackedPlayers()) { this.plugin.adapt(player).furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.subEntityIds()); - this.plugin.networkManager().sendPacket(player, furniture.spawnPacket()); + this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player)); } } } 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 04c8255f7..cb2addc6b 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 @@ -13,10 +13,7 @@ import net.momirealms.craftengine.core.util.QuaternionUtils; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Location; import org.bukkit.attribute.Attribute; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.*; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; @@ -41,11 +38,13 @@ public class LoadedFurniture { private final List fakeEntityIds; private final List hitBoxEntityIds; private final Map hitBoxes; + private final boolean minimized; // seats private final Set occupiedSeats = Collections.synchronizedSet(new HashSet<>()); private final Vector seats = new Vector<>(); // cached spawn packet private Object cachedSpawnPacket; + private Object cachedMinimizedSpawnPacket; public LoadedFurniture(Entity baseEntity, CustomFurniture furniture, @@ -57,6 +56,7 @@ public class LoadedFurniture { this.baseEntity = new WeakReference<>(baseEntity); this.furniture = furniture; this.hitBoxes = new HashMap<>(); + this.minimized = furniture.settings().minimized(); List fakeEntityIds = new ArrayList<>(); List hitBoxEntityIds = new ArrayList<>(); CustomFurniture.Placement placement = furniture.getPlacement(anchorType); @@ -70,22 +70,34 @@ public class LoadedFurniture { float yaw = this.location.getYaw(); List packets = new ArrayList<>(); + List minimizedPackets = new ArrayList<>(); for (FurnitureElement element : placement.elements()) { int entityId = Reflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); fakeEntityIds.add(entityId); - element.addSpawnPackets(entityId, x, y, z, yaw, conjugated, packets::add); + element.addSpawnPackets(entityId, x, y, z, yaw, conjugated, packet -> { + packets.add(packet); + if (this.minimized) minimizedPackets.add(packet); + }); } for (HitBox hitBox : placement.hitBoxes()) { int[] ids = hitBox.acquireEntityIds(Reflections.instance$Entity$ENTITY_COUNTER::incrementAndGet); for (int entityId : ids) { fakeEntityIds.add(entityId); hitBoxEntityIds.add(entityId); - hitBox.addSpawnPackets(ids, x, y, z, yaw, conjugated, packets::add); + hitBox.addSpawnPackets(ids, x, y, z, yaw, conjugated, (packet, canBeMinimized) -> { + packets.add(packet); + if (this.minimized && !canBeMinimized) { + minimizedPackets.add(packet); + } + }); this.hitBoxes.put(entityId, hitBox); } } try { this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets); + if (this.minimized) { + this.cachedMinimizedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(minimizedPackets); + } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e); } @@ -114,8 +126,13 @@ public class LoadedFurniture { } @NotNull - public Object spawnPacket() { - return this.cachedSpawnPacket; + public Object spawnPacket(Player player) { + // TODO hasPermission might be slow, can we use a faster way in the future? + if (!this.minimized || player.hasPermission(FurnitureManager.FURNITURE_ADMIN_NODE)) { + return this.cachedSpawnPacket; + } else { + return this.cachedMinimizedSpawnPacket; + } } @NotNull diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBox.java index 98b4766bd..64883d486 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBox.java @@ -7,6 +7,7 @@ import org.joml.Quaternionf; import org.joml.Vector3f; import java.util.Map; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; @@ -29,7 +30,7 @@ public class HappyGhastHitBox extends AbstractHitBox { } @Override - public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer packets) { + public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer packets) { // todo 乐魂 } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBox.java index 047fc19c0..b14dc9816 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBox.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; @@ -46,14 +47,14 @@ public class InteractionHitBox extends AbstractHitBox { } @Override - public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer packets) { + public void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer packets) { Vector3f offset = conjugated.transform(new Vector3f(position())); try { packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance( entityId[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw, Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0 - )); - packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId[0], List.copyOf(this.cachedValues))); + ), true); + packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityId[0], List.copyOf(this.cachedValues)), true); } catch (ReflectiveOperationException e) { throw new RuntimeException("Failed to construct hitbox spawn packet", e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBox.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBox.java index 4eca2774b..a91c42b81 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBox.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBox.java @@ -14,6 +14,7 @@ import org.joml.Quaternionf; import org.joml.Vector3f; import java.util.*; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; @@ -90,30 +91,30 @@ public class ShulkerHitBox extends AbstractHitBox { } @Override - public void addSpawnPackets(int[] entityIds, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer packets) { + public void addSpawnPackets(int[] entityIds, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer packets) { Vector3f offset = conjugated.transform(new Vector3f(position())); try { packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance( entityIds[0], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw, Reflections.instance$EntityType$ITEM_DISPLAY, 0, Reflections.instance$Vec3$Zero, 0 - )); + ), false); packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance( entityIds[1], UUID.randomUUID(), x + offset.x, y + offset.y, z - offset.z, 0, yaw, Reflections.instance$EntityType$SHULKER, 0, Reflections.instance$Vec3$Zero, 0 - )); - packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityIds[1], List.copyOf(this.cachedShulkerValues))); - packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(entityIds[0], entityIds[1])); + ), false); + packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityIds[1], List.copyOf(this.cachedShulkerValues)), false); + packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(entityIds[0], entityIds[1]), false); if (VersionHelper.isVersionNewerThan1_20_5()) { Object attributeInstance = Reflections.constructor$AttributeInstance.newInstance(Reflections.instance$Holder$Attribute$scale, (Consumer) (o) -> {}); Reflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, scale); - packets.accept(Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[1], Collections.singletonList(attributeInstance))); + packets.accept(Reflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityIds[1], Collections.singletonList(attributeInstance)), false); } if (this.interactionEntity) { packets.accept(Reflections.constructor$ClientboundAddEntityPacket.newInstance( entityIds[2], UUID.randomUUID(), x + offset.x, y + offset.y - 0.0005f, z - offset.z, 0, yaw, Reflections.instance$EntityType$INTERACTION, 0, Reflections.instance$Vec3$Zero, 0 - )); - packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityIds[2], List.copyOf(this.cachedInteractionValues))); + ), true); + packets.accept(Reflections.constructor$ClientboundSetEntityDataPacket.newInstance(entityIds[2], List.copyOf(this.cachedInteractionValues)), true); } } catch (ReflectiveOperationException e) { throw new RuntimeException("Failed to construct shulker hitbox spawn packet", e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 2e7fa1d6d..469532c46 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -619,7 +619,7 @@ public class PacketConsumers { LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByBaseEntityId(entityId); if (furniture != null) { user.furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.subEntityIds()); - user.sendPacket(furniture.spawnPacket(), false); + user.sendPacket(furniture.spawnPacket((Player) user.platformPlayer()), false); if (ConfigManager.hideBaseEntity()) { event.setCancelled(true); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java index 5cb3f595d..100a41b5c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java @@ -11,6 +11,7 @@ import java.util.Optional; public interface FurnitureManager extends Reloadable, ConfigSectionParser { String CONFIG_SECTION_NAME = "furniture"; + String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin"; void delayedLoad(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java index e1cdc66fb..21401e2bd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.Map; public class FurnitureSettings { + boolean minimized; FurnitureSounds sounds = FurnitureSounds.EMPTY; @Nullable Key itemId; @@ -26,6 +27,7 @@ public class FurnitureSettings { FurnitureSettings newSettings = of(); newSettings.sounds = settings.sounds; newSettings.itemId = settings.itemId; + newSettings.minimized = settings.minimized; return newSettings; } @@ -45,6 +47,10 @@ public class FurnitureSettings { return sounds; } + public boolean minimized() { + return minimized; + } + @Nullable public Key itemId() { return itemId; @@ -60,6 +66,11 @@ public class FurnitureSettings { return this; } + public FurnitureSettings minimized(boolean minimized) { + this.minimized = minimized; + return this; + } + public interface Modifier { void apply(FurnitureSettings settings); @@ -82,6 +93,10 @@ public class FurnitureSettings { String item = value.toString(); return settings -> settings.itemId(Key.of(item)); })); + registerFactory("minimized", (value -> { + boolean bool = (boolean) value; + return settings -> settings.minimized(bool); + })); } private static void registerFactory(String id, FurnitureSettings.Modifier.Factory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java index 0eddfd069..2d91741fd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java @@ -5,6 +5,7 @@ import org.joml.Quaternionf; import org.joml.Vector3f; import java.util.Optional; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; @@ -12,7 +13,7 @@ public interface HitBox { Key type(); - void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, Consumer packets); + void addSpawnPackets(int[] entityId, double x, double y, double z, float yaw, Quaternionf conjugated, BiConsumer packets); int[] acquireEntityIds(Supplier entityIdSupplier);