mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
Merge remote-tracking branch 'upstream/dev' into feat/function-and-condition
# Conflicts: # core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java # core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java
This commit is contained in:
@@ -19,6 +19,7 @@ import net.momirealms.craftengine.bukkit.compatibility.quickshop.QuickShopItemEx
|
||||
import net.momirealms.craftengine.bukkit.compatibility.region.WorldGuardRegionCondition;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.slimeworld.SlimeFormatStorageAdaptor;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.tag.CustomNameplateHatSettings;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.tag.CustomNameplateProviders;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtils;
|
||||
import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister;
|
||||
@@ -97,6 +98,7 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
||||
registerTagResolverProvider(new CustomNameplateProviders.Background());
|
||||
registerTagResolverProvider(new CustomNameplateProviders.Nameplate());
|
||||
registerTagResolverProvider(new CustomNameplateProviders.Bubble());
|
||||
new CustomNameplateHatSettings().register();
|
||||
logHook("CustomNameplates");
|
||||
}
|
||||
Key worldGuardRegion = Key.of("worldguard:region");
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.tag;
|
||||
|
||||
import io.papermc.paper.event.entity.EntityEquipmentChangedEvent;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemSettings;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.CustomDataType;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.customnameplates.api.CNPlayer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplates;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesAPI;
|
||||
import net.momirealms.customnameplates.api.feature.tag.TagRenderer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class CustomNameplateHatSettings implements Listener {
|
||||
public static final CustomDataType<Double> HAT_HEIGHT = new CustomDataType<>();
|
||||
|
||||
public void register() {
|
||||
ItemSettings.Modifiers.registerFactory("hat-height", height -> {
|
||||
double heightD = ResourceConfigUtils.getAsDouble(height, "hat-height");
|
||||
return settings -> settings.addCustomData(HAT_HEIGHT, heightD);
|
||||
});
|
||||
Bukkit.getPluginManager().registerEvents(this, BukkitCraftEngine.instance().javaPlugin());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onEquipmentChange(EntityEquipmentChangedEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) return;
|
||||
Map<EquipmentSlot, EntityEquipmentChangedEvent.EquipmentChange> equipmentChanges = event.getEquipmentChanges();
|
||||
EntityEquipmentChangedEvent.EquipmentChange equipmentChange = equipmentChanges.get(EquipmentSlot.HEAD);
|
||||
if (equipmentChange == null) return;
|
||||
ItemStack newItem = equipmentChange.newItem();
|
||||
updateHatHeight(player, newItem);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
// 稍微延迟一下,可以等待背包同步插件的处理
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.getScheduler().runDelayed(BukkitCraftEngine.instance().javaPlugin(), t1 -> {
|
||||
if (player.isOnline()) {
|
||||
updateHatHeight(player, player.getInventory().getItem(EquipmentSlot.HEAD));
|
||||
}
|
||||
}, null, 10);
|
||||
} else {
|
||||
CraftEngine.instance().scheduler().sync().runLater(() -> {
|
||||
if (player.isOnline()) {
|
||||
updateHatHeight(player, player.getInventory().getItem(EquipmentSlot.HEAD));
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateHatHeight(Player player, ItemStack newItem) {
|
||||
CNPlayer cnPlayer = CustomNameplatesAPI.getInstance().getPlayer(player.getUniqueId());
|
||||
if (cnPlayer == null) return;
|
||||
TagRenderer tagRender = CustomNameplates.getInstance().getUnlimitedTagManager().getTagRender(cnPlayer);
|
||||
if (tagRender == null) return;
|
||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(newItem);
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||
if (optionalCustomItem.isEmpty()) {
|
||||
tagRender.hatOffset(0d);
|
||||
return;
|
||||
}
|
||||
Double customHeight = optionalCustomItem.get().settings().getCustomData(HAT_HEIGHT);
|
||||
tagRender.hatOffset(Objects.requireNonNullElse(customHeight, 0d));
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBloc
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
||||
return new SeatBlockEntity(pos, state, this.seats, this.directionProperty);
|
||||
return new SeatBlockEntity(pos, state, this.seats);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.SeatBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
@@ -13,14 +14,14 @@ import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class SeatBlockEntity extends BlockEntity implements SeatOwner {
|
||||
private final Seat<SeatBlockEntity>[] seats;
|
||||
private final Property<HorizontalDirection> facing;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState, SeatConfig[] seats, Property<HorizontalDirection> directionProperty) {
|
||||
public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState, SeatConfig[] seats) {
|
||||
super(BukkitBlockEntityTypes.SEAT, pos, blockState);
|
||||
this.facing = directionProperty;
|
||||
this.seats = new Seat[seats.length];
|
||||
for (int i = 0; i < seats.length; i++) {
|
||||
this.seats[i] = new BukkitSeat<>(this, seats[i]);
|
||||
@@ -41,7 +42,10 @@ public class SeatBlockEntity extends BlockEntity implements SeatOwner {
|
||||
|
||||
public boolean spawnSeat(Player player) {
|
||||
int yRot = 0;
|
||||
if (this.facing != null) {
|
||||
Optional<SeatBlockBehavior> behavior = super.blockState.behavior().getAs(SeatBlockBehavior.class);
|
||||
if (behavior.isEmpty()) return false;
|
||||
Property<HorizontalDirection> facing = behavior.get().directionProperty();
|
||||
if (facing != null) {
|
||||
HorizontalDirection direction = super.blockState.get(facing);
|
||||
yRot = switch (direction) {
|
||||
case NORTH -> 0;
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||
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.util.QuaternionUtils;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitFurniture extends Furniture {
|
||||
private final WeakReference<ItemDisplay> metaEntity;
|
||||
@@ -40,6 +49,76 @@ public class BukkitFurniture extends Furniture {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVariant(String variantName) {
|
||||
FurnitureVariant variant = this.config.getVariant(variantName);
|
||||
if (variant == null) return false;
|
||||
if (this.currentVariant == variant) return false;
|
||||
BukkitFurnitureManager.instance().invalidateFurniture(this);
|
||||
super.clearColliders();
|
||||
super.setVariantInternal(variant);
|
||||
BukkitFurnitureManager.instance().initFurniture(this);
|
||||
this.addCollidersToWorld();
|
||||
this.refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public CompletableFuture<Boolean> moveTo(WorldPosition position) {
|
||||
ItemDisplay itemDisplay = this.metaEntity.get();
|
||||
if (itemDisplay == null) return CompletableFuture.completedFuture(false);
|
||||
// 检查新位置是否可用
|
||||
List<AABB> aabbs = new ArrayList<>();
|
||||
for (FurnitureHitBoxConfig<?> hitBoxConfig : getCurrentVariant().hitBoxConfigs()) {
|
||||
hitBoxConfig.prepareBoundingBox(position, aabbs::add, false);
|
||||
}
|
||||
if (!aabbs.isEmpty()) {
|
||||
if (!FastNMS.INSTANCE.checkEntityCollision(position.world.serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) {
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}
|
||||
// 准备传送
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
BukkitFurnitureManager.instance().invalidateFurniture(this);
|
||||
super.clearColliders();
|
||||
this.location = LocationUtils.toLocation(position);
|
||||
Object removePacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(itemDisplay.getEntityId()); }});
|
||||
for (Player player : itemDisplay.getTrackedPlayers()) {
|
||||
BukkitAdaptors.adapt(player).sendPacket(removePacket, false);
|
||||
}
|
||||
itemDisplay.teleportAsync(this.location).thenAccept(result -> {
|
||||
if (result) {
|
||||
super.setVariantInternal(getCurrentVariant());
|
||||
BukkitFurnitureManager.instance().initFurniture(this);
|
||||
this.addCollidersToWorld();
|
||||
Object addPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(itemDisplay.getEntityId(), itemDisplay.getUniqueId(),
|
||||
itemDisplay.getX(), itemDisplay.getY(), itemDisplay.getZ(), itemDisplay.getPitch(), itemDisplay.getYaw(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0);
|
||||
for (Player player : itemDisplay.getTrackedPlayers()) {
|
||||
BukkitAdaptors.adapt(player).sendPacket(addPacket, false);
|
||||
}
|
||||
future.complete(true);
|
||||
} else {
|
||||
future.complete(false);
|
||||
}
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void refresh() {
|
||||
ItemDisplay itemDisplay = this.metaEntity.get();
|
||||
if (itemDisplay == null) return;
|
||||
Object removePacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(itemDisplay.getEntityId()); }});
|
||||
Object addPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(itemDisplay.getEntityId(), itemDisplay.getUniqueId(),
|
||||
itemDisplay.getX(), itemDisplay.getY(), itemDisplay.getZ(), itemDisplay.getPitch(), itemDisplay.getYaw(), MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0);
|
||||
for (Player player : itemDisplay.getTrackedPlayers()) {
|
||||
BukkitAdaptors.adapt(player).sendPacket(removePacket, false);
|
||||
BukkitAdaptors.adapt(player).sendPacket(addPacket, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Optional.ofNullable(this.metaEntity.get()).ifPresent(Entity::remove);
|
||||
|
||||
@@ -323,18 +323,32 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
// 创建家具实例,并初始化碰撞实体
|
||||
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()) {
|
||||
this.byVirtualEntityId.put(entityId, bukkitFurniture);
|
||||
}
|
||||
for (Collider collisionEntity : bukkitFurniture.colliders()) {
|
||||
this.byColliderEntityId.put(collisionEntity.entityId(), bukkitFurniture);
|
||||
}
|
||||
initFurniture(bukkitFurniture);
|
||||
Location location = display.getLocation();
|
||||
runSafeEntityOperation(location, bukkitFurniture::addCollidersToWorld);
|
||||
return bukkitFurniture;
|
||||
}
|
||||
|
||||
protected void initFurniture(BukkitFurniture furniture) {
|
||||
this.byMetaEntityId.put(furniture.entityId(), furniture);
|
||||
for (int entityId : furniture.virtualEntityIds()) {
|
||||
this.byVirtualEntityId.put(entityId, furniture);
|
||||
}
|
||||
for (Collider collisionEntity : furniture.colliders()) {
|
||||
this.byColliderEntityId.put(collisionEntity.entityId(), furniture);
|
||||
}
|
||||
}
|
||||
|
||||
protected void invalidateFurniture(BukkitFurniture furniture) {
|
||||
this.byMetaEntityId.remove(furniture.entityId());
|
||||
for (int entityId : furniture.virtualEntityIds()) {
|
||||
this.byVirtualEntityId.remove(entityId);
|
||||
}
|
||||
for (Collider collisionEntity : furniture.colliders()) {
|
||||
this.byColliderEntityId.remove(collisionEntity.entityId());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -2,11 +2,26 @@ package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemDisplay;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -14,8 +29,12 @@ import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FurnitureEventListener implements Listener {
|
||||
private final BukkitFurnitureManager manager;
|
||||
@@ -104,4 +123,44 @@ public class FurnitureEventListener implements Listener {
|
||||
this.manager.handleCollisionEntityUnload(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onInteractFurniture(FurnitureInteractEvent event) {
|
||||
Player bukkitPlayer = event.getPlayer();
|
||||
BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer);
|
||||
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
|
||||
return;
|
||||
}
|
||||
Item<ItemStack> itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
if (!itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) return;
|
||||
BukkitFurniture furniture = event.furniture();
|
||||
List<String> variants = new ArrayList<>(furniture.config.variants().keySet());
|
||||
if (variants.size() == 1) {
|
||||
try {
|
||||
Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(furniture.id().asString()))), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Could not create system chat packet", e);
|
||||
}
|
||||
} else {
|
||||
String variantName = furniture.getCurrentVariant().name();
|
||||
int index = variants.indexOf(variantName) + 1;
|
||||
if (index >= variants.size()) {
|
||||
index = 0;
|
||||
}
|
||||
furniture.setVariant(variants.get(index));
|
||||
try {
|
||||
Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update")
|
||||
.arguments(
|
||||
Component.text("variant"),
|
||||
Component.text(variants.get(index))
|
||||
)), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Could not create system chat packet", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ public class CustomFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<C
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, this.width, this.height));
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ public class HappyGhastFurnitureHitboxConfig extends AbstractFurnitureHitBoxConf
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, 4 * this.scale, 4 * this.scale));
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ public class InteractionFurnitureHitboxConfig extends AbstractFurnitureHitBoxCon
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, size.x, size.y));
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
||||
if (this.blocksBuilding) {
|
||||
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0f, (float) Math.toRadians(180 - targetPos.yRot()), 0f).conjugate();
|
||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||
aabbConsumer.accept(this.aabbCreator.create(targetPos.x, targetPos.y, targetPos.z, targetPos.yRot, offset));
|
||||
|
||||
@@ -114,7 +114,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
List<AABB> aabbs = new ArrayList<>();
|
||||
// 收集阻挡的碰撞箱
|
||||
for (FurnitureHitBoxConfig<?> hitBoxConfig : variant.hitBoxConfigs()) {
|
||||
hitBoxConfig.prepareForPlacement(furniturePos, aabbs::add);
|
||||
hitBoxConfig.prepareBoundingBox(furniturePos, aabbs::add, false);
|
||||
}
|
||||
// 检查方块、实体阻挡
|
||||
if (!aabbs.isEmpty()) {
|
||||
|
||||
@@ -16,7 +16,9 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -44,12 +46,10 @@ public class DebugStickListener implements Listener {
|
||||
public void onUseDebugStick(PlayerInteractEvent event) {
|
||||
Block clickedBlock = event.getClickedBlock();
|
||||
if (clickedBlock == null) return;
|
||||
ItemStack itemInHand = event.getItem();
|
||||
if (ItemStackUtils.isEmpty(itemInHand)) return;
|
||||
Material material = itemInHand.getType();
|
||||
if (material != Material.DEBUG_STICK) return;
|
||||
Player bukkitPlayer = event.getPlayer();
|
||||
BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer);
|
||||
Item<ItemStack> itemInHand = player.getItemInHand(event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND);
|
||||
if (!itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) return;
|
||||
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
|
||||
return;
|
||||
}
|
||||
@@ -73,8 +73,7 @@ public class DebugStickListener implements Listener {
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
||||
player.sendPacket(systemChatPacket, false);
|
||||
} else {
|
||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemInHand);
|
||||
Object storedData = wrapped.getJavaTag("craftengine:debug_stick_state");
|
||||
Object storedData = itemInHand.getJavaTag("craftengine:debug_stick_state");
|
||||
if (storedData == null) storedData = new HashMap<>();
|
||||
if (storedData instanceof Map<?,?> map) {
|
||||
Map<String, Object> data = new HashMap<>(MiscUtils.castToMap(map, false));
|
||||
@@ -96,7 +95,7 @@ public class DebugStickListener implements Listener {
|
||||
} else {
|
||||
currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive());
|
||||
data.put(blockId, currentProperty.name());
|
||||
wrapped.setTag(data, "craftengine:debug_stick_state");
|
||||
itemInHand.setTag(data, "craftengine:debug_stick_state");
|
||||
Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")
|
||||
.arguments(
|
||||
|
||||
@@ -67,6 +67,7 @@ import net.momirealms.craftengine.core.font.FontManager;
|
||||
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipeHolder;
|
||||
@@ -3804,6 +3805,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
return;
|
||||
}
|
||||
|
||||
// 不处理调试棒
|
||||
if (itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
||||
if (serverPlayer.isSecondaryUseActive() && !itemInHand.isEmpty() && hitBox.config().canUseItemOn()) {
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||
|
||||
@@ -567,7 +567,7 @@ public class BukkitServerPlayer extends Player {
|
||||
FurnitureVariant currentVariant = furniture.getCurrentVariant();
|
||||
List<AABB> aabbs = new ArrayList<>();
|
||||
for (FurnitureHitBoxConfig<?> config : currentVariant.hitBoxConfigs()) {
|
||||
config.prepareForPlacement(furniture.position(), aabbs::add);
|
||||
config.prepareBoundingBox(furniture.position(), aabbs::add, true);
|
||||
}
|
||||
Key endRod = Key.of("soul_fire_flame");
|
||||
for (AABB aabb : aabbs) {
|
||||
|
||||
@@ -53,6 +53,8 @@ items:
|
||||
behavior:
|
||||
type: block_item
|
||||
block:
|
||||
events:
|
||||
- template: default:rotatable_block
|
||||
loot:
|
||||
template: default:loot_table/self
|
||||
settings:
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
templates:
|
||||
default:rotatable_block:
|
||||
on: right_click
|
||||
conditions:
|
||||
- type: expression
|
||||
expression: <arg:player.is_sneaking>
|
||||
functions:
|
||||
- type: update_interaction_tick
|
||||
- type: play_sound
|
||||
sound: ${rotate_sound:-'minecraft:block.bamboo.place'}
|
||||
- type: swing_hand
|
||||
- type: cycle_block_property
|
||||
property: facing
|
||||
rules:
|
||||
north: east
|
||||
east: south
|
||||
south: west
|
||||
west: north
|
||||
default:rotatable_furniture:
|
||||
on: right_click
|
||||
conditions:
|
||||
- type: expression
|
||||
expression: <arg:player.is_sneaking>
|
||||
functions:
|
||||
- type: rotate_furniture
|
||||
degree: 90
|
||||
on-success:
|
||||
- type: swing_hand
|
||||
- type: play_sound
|
||||
sound: ${rotate_sound:-'minecraft:block.bamboo.place'}
|
||||
on-failure: []
|
||||
@@ -123,7 +123,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
||||
throw new LocalizedResourceConfigException("warning.config.furniture.missing_variants");
|
||||
}
|
||||
|
||||
Map<String, FurnitureVariant> variants = new HashMap<>();
|
||||
Map<String, FurnitureVariant> variants = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> e0 : variantsMap.entrySet()) {
|
||||
String variantName = e0.getKey();
|
||||
Map<String, Object> variantArguments = ResourceConfigUtils.getAsMap(e0.getValue(), variantName);
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class Furniture implements Cullable {
|
||||
public final FurnitureConfig config;
|
||||
@@ -53,7 +54,7 @@ public abstract class Furniture implements Cullable {
|
||||
this.config = config;
|
||||
this.dataAccessor = data;
|
||||
this.metaDataEntity = metaDataEntity;
|
||||
this.setVariant(config.getVariant(data));
|
||||
this.setVariantInternal(config.getVariant(data));
|
||||
}
|
||||
|
||||
public Entity metaDataEntity() {
|
||||
@@ -64,7 +65,21 @@ public abstract class Furniture implements Cullable {
|
||||
return this.currentVariant;
|
||||
}
|
||||
|
||||
public void setVariant(FurnitureVariant variant) {
|
||||
public abstract boolean setVariant(String variantName);
|
||||
|
||||
public abstract CompletableFuture<Boolean> moveTo(WorldPosition position);
|
||||
|
||||
protected abstract void refresh();
|
||||
|
||||
protected void clearColliders() {
|
||||
if (this.colliders != null) {
|
||||
for (Collider collider : this.colliders) {
|
||||
collider.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void setVariantInternal(FurnitureVariant variant) {
|
||||
this.currentVariant = variant;
|
||||
this.hitboxMap = new Int2ObjectOpenHashMap<>();
|
||||
// 初始化家具元素
|
||||
@@ -115,7 +130,7 @@ public abstract class Furniture implements Cullable {
|
||||
if (aabb == null) {
|
||||
List<AABB> aabbs = new ArrayList<>();
|
||||
for (FurnitureHitBoxConfig<?> hitBoxConfig : this.currentVariant.hitBoxConfigs()) {
|
||||
hitBoxConfig.prepareForPlacement(position, aabbs::add);
|
||||
hitBoxConfig.prepareBoundingBox(position, aabbs::add, true);
|
||||
}
|
||||
return new CullingData(getMaxAABB(aabbs), parent.maxDistance, parent.aabbExpansion, parent.rayTracing);
|
||||
} else {
|
||||
@@ -201,20 +216,28 @@ public abstract class Furniture implements Cullable {
|
||||
@Override
|
||||
public void show(Player player) {
|
||||
for (FurnitureElement element : this.elements) {
|
||||
element.show(player);
|
||||
if (element != null) {
|
||||
element.show(player);
|
||||
}
|
||||
}
|
||||
for (FurnitureHitBox hitbox : this.hitboxes) {
|
||||
hitbox.show(player);
|
||||
if (hitbox != null) {
|
||||
hitbox.show(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide(Player player) {
|
||||
for (FurnitureElement element : this.elements) {
|
||||
element.hide(player);
|
||||
if (element != null) {
|
||||
element.hide(player);
|
||||
}
|
||||
}
|
||||
for (FurnitureHitBox hitbox : this.hitboxes) {
|
||||
hitbox.hide(player);
|
||||
if (hitbox != null) {
|
||||
hitbox.hide(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import net.momirealms.craftengine.core.entity.furniture.behavior.EmptyFurnitureBehavior;
|
||||
import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
@@ -33,7 +34,7 @@ class FurnitureConfigImpl implements FurnitureConfig {
|
||||
@Nullable LootTable<?> lootTable) {
|
||||
this.id = id;
|
||||
this.settings = settings;
|
||||
this.variants = ImmutableMap.copyOf(variants);
|
||||
this.variants = ImmutableSortedMap.copyOf(variants);
|
||||
this.lootTable = lootTable;
|
||||
this.behavior = behavior;
|
||||
this.events = events;
|
||||
|
||||
@@ -22,6 +22,6 @@ public interface FurnitureHitBoxConfig<H extends FurnitureHitBox> {
|
||||
|
||||
boolean canUseItemOn();
|
||||
|
||||
void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer);
|
||||
void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding);
|
||||
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ public final class ItemKeys {
|
||||
public static final Key PURPLE_DYE = Key.of("minecraft:purple_dye");
|
||||
public static final Key MAGENTA_DYE = Key.of("minecraft:magenta_dye");
|
||||
public static final Key PINK_DYE = Key.of("minecraft:pink_dye");
|
||||
public static final Key DEBUG_STICK = Key.of("minecraft:debug_stick");
|
||||
|
||||
public static final Key CARROT = Key.of("minecraft:carrot");
|
||||
public static final Key POTATO = Key.of("minecraft:potato");
|
||||
|
||||
@@ -471,6 +471,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
plugin.saveResource("resources/default/configuration/templates/loot_tables.yml");
|
||||
plugin.saveResource("resources/default/configuration/templates/recipes.yml");
|
||||
plugin.saveResource("resources/default/configuration/templates/tool_levels.yml");
|
||||
plugin.saveResource("resources/default/configuration/templates/events.yml");
|
||||
plugin.saveResource("resources/default/configuration/categories.yml");
|
||||
plugin.saveResource("resources/default/configuration/emoji.yml");
|
||||
plugin.saveResource("resources/default/configuration/translations.yml");
|
||||
|
||||
@@ -58,6 +58,7 @@ public class EventFunctions {
|
||||
register(CommonFunctions.SET_EXP, new SetExpFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.SET_LEVEL, new SetLevelFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.PLAY_TOTEM_ANIMATION, new PlayTotemAnimationFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.CLOSE_INVENTORY, new CloseInventoryFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.CLEAR_ITEM, new ClearItemFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.function;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelector;
|
||||
import net.momirealms.craftengine.core.plugin.context.selector.PlayerSelectors;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CloseInventoryFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||
private final PlayerSelector<CTX> selector;
|
||||
|
||||
public CloseInventoryFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector) {
|
||||
super(predicates);
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runInternal(CTX ctx) {
|
||||
if (this.selector == null) {
|
||||
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(Player::closeInventory);
|
||||
} else {
|
||||
for (Player viewer : this.selector.get(ctx)) {
|
||||
viewer.closeInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return CommonFunctions.CLOSE_INVENTORY;
|
||||
}
|
||||
|
||||
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
|
||||
|
||||
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
return new CloseInventoryFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,5 +49,6 @@ public final class CommonFunctions {
|
||||
public static final Key SET_EXP = Key.of("craftengine:set_exp");
|
||||
public static final Key SET_LEVEL = Key.of("craftengine:set_level");
|
||||
public static final Key PLAY_TOTEM_ANIMATION = Key.of("craftengine:play_totem_animation");
|
||||
public static final Key CLOSE_INVENTORY = Key.of("craftengine:close_inventory");
|
||||
public static final Key CLEAR_ITEM = Key.of("craftengine:clear_item");
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -71,7 +72,7 @@ public class CycleBlockPropertyFunction<CTX extends Context> extends AbstractCon
|
||||
if (value == null) {
|
||||
return wrapper.cycleProperty(this.property, inverse);
|
||||
}
|
||||
String mapValue = this.rules.get(value.toString());
|
||||
String mapValue = this.rules.get(value.toString().toLowerCase(Locale.ROOT));
|
||||
if (mapValue == null) {
|
||||
return wrapper.cycleProperty(this.property, inverse);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.entityculling;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.craftengine.core.world.MutableVec3d;
|
||||
|
||||
Reference in New Issue
Block a user