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.region.WorldGuardRegionCondition;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook;
|
import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.slimeworld.SlimeFormatStorageAdaptor;
|
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.tag.CustomNameplateProviders;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtils;
|
import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtils;
|
||||||
import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister;
|
import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister;
|
||||||
@@ -97,6 +98,7 @@ public class BukkitCompatibilityManager implements CompatibilityManager {
|
|||||||
registerTagResolverProvider(new CustomNameplateProviders.Background());
|
registerTagResolverProvider(new CustomNameplateProviders.Background());
|
||||||
registerTagResolverProvider(new CustomNameplateProviders.Nameplate());
|
registerTagResolverProvider(new CustomNameplateProviders.Nameplate());
|
||||||
registerTagResolverProvider(new CustomNameplateProviders.Bubble());
|
registerTagResolverProvider(new CustomNameplateProviders.Bubble());
|
||||||
|
new CustomNameplateHatSettings().register();
|
||||||
logHook("CustomNameplates");
|
logHook("CustomNameplates");
|
||||||
}
|
}
|
||||||
Key worldGuardRegion = Key.of("worldguard:region");
|
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
|
@Override
|
||||||
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
||||||
return new SeatBlockEntity(pos, state, this.seats, this.directionProperty);
|
return new SeatBlockEntity(pos, state, this.seats);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.bukkit.block.entity;
|
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.bukkit.entity.seat.BukkitSeat;
|
||||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
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.craftengine.core.world.WorldPosition;
|
||||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class SeatBlockEntity extends BlockEntity implements SeatOwner {
|
public class SeatBlockEntity extends BlockEntity implements SeatOwner {
|
||||||
private final Seat<SeatBlockEntity>[] seats;
|
private final Seat<SeatBlockEntity>[] seats;
|
||||||
private final Property<HorizontalDirection> facing;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@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);
|
super(BukkitBlockEntityTypes.SEAT, pos, blockState);
|
||||||
this.facing = directionProperty;
|
|
||||||
this.seats = new Seat[seats.length];
|
this.seats = new Seat[seats.length];
|
||||||
for (int i = 0; i < seats.length; i++) {
|
for (int i = 0; i < seats.length; i++) {
|
||||||
this.seats[i] = new BukkitSeat<>(this, seats[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) {
|
public boolean spawnSeat(Player player) {
|
||||||
int yRot = 0;
|
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);
|
HorizontalDirection direction = super.blockState.get(facing);
|
||||||
yRot = switch (direction) {
|
yRot = switch (direction) {
|
||||||
case NORTH -> 0;
|
case NORTH -> 0;
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
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.entity.BukkitEntity;
|
||||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.Collider;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor;
|
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.util.QuaternionUtils;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.ItemDisplay;
|
import org.bukkit.entity.ItemDisplay;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
import org.joml.Quaternionf;
|
import org.joml.Quaternionf;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class BukkitFurniture extends Furniture {
|
public class BukkitFurniture extends Furniture {
|
||||||
private final WeakReference<ItemDisplay> metaEntity;
|
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
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
Optional.ofNullable(this.metaEntity.get()).ifPresent(Entity::remove);
|
Optional.ofNullable(this.metaEntity.get()).ifPresent(Entity::remove);
|
||||||
|
|||||||
@@ -323,18 +323,32 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
// 创建家具实例,并初始化碰撞实体
|
// 创建家具实例,并初始化碰撞实体
|
||||||
private BukkitFurniture createFurnitureInstance(ItemDisplay display, FurnitureConfig furniture) {
|
private BukkitFurniture createFurnitureInstance(ItemDisplay display, FurnitureConfig furniture) {
|
||||||
BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, getFurnitureDataAccessor(display));
|
BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, getFurnitureDataAccessor(display));
|
||||||
this.byMetaEntityId.put(display.getEntityId(), bukkitFurniture);
|
initFurniture(bukkitFurniture);
|
||||||
for (int entityId : bukkitFurniture.virtualEntityIds()) {
|
|
||||||
this.byVirtualEntityId.put(entityId, bukkitFurniture);
|
|
||||||
}
|
|
||||||
for (Collider collisionEntity : bukkitFurniture.colliders()) {
|
|
||||||
this.byColliderEntityId.put(collisionEntity.entityId(), bukkitFurniture);
|
|
||||||
}
|
|
||||||
Location location = display.getLocation();
|
Location location = display.getLocation();
|
||||||
runSafeEntityOperation(location, bukkitFurniture::addCollidersToWorld);
|
runSafeEntityOperation(location, bukkitFurniture::addCollidersToWorld);
|
||||||
return bukkitFurniture;
|
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) {
|
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);
|
boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||||
if (preventChange) {
|
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.EntityAddToWorldEvent;
|
||||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
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.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.CEWorld;
|
||||||
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.ItemDisplay;
|
import org.bukkit.entity.ItemDisplay;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
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.EntitiesLoadEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
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.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class FurnitureEventListener implements Listener {
|
public class FurnitureEventListener implements Listener {
|
||||||
private final BukkitFurnitureManager manager;
|
private final BukkitFurnitureManager manager;
|
||||||
@@ -104,4 +123,44 @@ public class FurnitureEventListener implements Listener {
|
|||||||
this.manager.handleCollisionEntityUnload(entity);
|
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
|
@Override
|
||||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||||
if (this.blocksBuilding) {
|
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, this.width, this.height));
|
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, this.width, this.height));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ public class HappyGhastFurnitureHitboxConfig extends AbstractFurnitureHitBoxConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||||
if (this.blocksBuilding) {
|
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, 4 * this.scale, 4 * this.scale));
|
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, 4 * this.scale, 4 * this.scale));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ public class InteractionFurnitureHitboxConfig extends AbstractFurnitureHitBoxCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||||
if (this.blocksBuilding) {
|
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||||
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
Vec3d relativePosition = Furniture.getRelativePosition(targetPos, this.position);
|
||||||
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, size.x, size.y));
|
aabbConsumer.accept(AABB.makeBoundingBox(relativePosition, size.x, size.y));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,8 +145,8 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareForPlacement(WorldPosition targetPos, Consumer<AABB> aabbConsumer) {
|
public void prepareBoundingBox(WorldPosition targetPos, Consumer<AABB> aabbConsumer, boolean ignoreBlocksBuilding) {
|
||||||
if (this.blocksBuilding) {
|
if (this.blocksBuilding || ignoreBlocksBuilding) {
|
||||||
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0f, (float) Math.toRadians(180 - targetPos.yRot()), 0f).conjugate();
|
Quaternionf conjugated = QuaternionUtils.toQuaternionf(0f, (float) Math.toRadians(180 - targetPos.yRot()), 0f).conjugate();
|
||||||
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
Vector3f offset = conjugated.transform(new Vector3f(position()));
|
||||||
aabbConsumer.accept(this.aabbCreator.create(targetPos.x, targetPos.y, targetPos.z, targetPos.yRot, offset));
|
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<>();
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
// 收集阻挡的碰撞箱
|
// 收集阻挡的碰撞箱
|
||||||
for (FurnitureHitBoxConfig<?> hitBoxConfig : variant.hitBoxConfigs()) {
|
for (FurnitureHitBoxConfig<?> hitBoxConfig : variant.hitBoxConfigs()) {
|
||||||
hitBoxConfig.prepareForPlacement(furniturePos, aabbs::add);
|
hitBoxConfig.prepareBoundingBox(furniturePos, aabbs::add, false);
|
||||||
}
|
}
|
||||||
// 检查方块、实体阻挡
|
// 检查方块、实体阻挡
|
||||||
if (!aabbs.isEmpty()) {
|
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.ImmutableBlockState;
|
||||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||||
import net.momirealms.craftengine.core.block.properties.Property;
|
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.Item;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@@ -44,12 +46,10 @@ public class DebugStickListener implements Listener {
|
|||||||
public void onUseDebugStick(PlayerInteractEvent event) {
|
public void onUseDebugStick(PlayerInteractEvent event) {
|
||||||
Block clickedBlock = event.getClickedBlock();
|
Block clickedBlock = event.getClickedBlock();
|
||||||
if (clickedBlock == null) return;
|
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();
|
Player bukkitPlayer = event.getPlayer();
|
||||||
BukkitServerPlayer player = BukkitAdaptors.adapt(bukkitPlayer);
|
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")) {
|
if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -73,8 +73,7 @@ public class DebugStickListener implements Listener {
|
|||||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
|
||||||
player.sendPacket(systemChatPacket, false);
|
player.sendPacket(systemChatPacket, false);
|
||||||
} else {
|
} else {
|
||||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemInHand);
|
Object storedData = itemInHand.getJavaTag("craftengine:debug_stick_state");
|
||||||
Object storedData = wrapped.getJavaTag("craftengine:debug_stick_state");
|
|
||||||
if (storedData == null) storedData = new HashMap<>();
|
if (storedData == null) storedData = new HashMap<>();
|
||||||
if (storedData instanceof Map<?,?> map) {
|
if (storedData instanceof Map<?,?> map) {
|
||||||
Map<String, Object> data = new HashMap<>(MiscUtils.castToMap(map, false));
|
Map<String, Object> data = new HashMap<>(MiscUtils.castToMap(map, false));
|
||||||
@@ -96,7 +95,7 @@ public class DebugStickListener implements Listener {
|
|||||||
} else {
|
} else {
|
||||||
currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive());
|
currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive());
|
||||||
data.put(blockId, currentProperty.name());
|
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(
|
Object systemChatPacket = NetworkReflections.constructor$ClientboundSystemChatPacket.newInstance(
|
||||||
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")
|
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")
|
||||||
.arguments(
|
.arguments(
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import net.momirealms.craftengine.core.font.FontManager;
|
|||||||
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult;
|
||||||
import net.momirealms.craftengine.core.item.CustomItem;
|
import net.momirealms.craftengine.core.item.CustomItem;
|
||||||
import net.momirealms.craftengine.core.item.Item;
|
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.behavior.ItemBehavior;
|
||||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||||
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipeHolder;
|
import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipeHolder;
|
||||||
@@ -3804,6 +3805,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 不处理调试棒
|
||||||
|
if (itemInHand.vanillaId().equals(ItemKeys.DEBUG_STICK)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
// 必须从网络包层面处理,否则无法获取交互的具体实体
|
||||||
if (serverPlayer.isSecondaryUseActive() && !itemInHand.isEmpty() && hitBox.config().canUseItemOn()) {
|
if (serverPlayer.isSecondaryUseActive() && !itemInHand.isEmpty() && hitBox.config().canUseItemOn()) {
|
||||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||||
|
|||||||
@@ -567,7 +567,7 @@ public class BukkitServerPlayer extends Player {
|
|||||||
FurnitureVariant currentVariant = furniture.getCurrentVariant();
|
FurnitureVariant currentVariant = furniture.getCurrentVariant();
|
||||||
List<AABB> aabbs = new ArrayList<>();
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
for (FurnitureHitBoxConfig<?> config : currentVariant.hitBoxConfigs()) {
|
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");
|
Key endRod = Key.of("soul_fire_flame");
|
||||||
for (AABB aabb : aabbs) {
|
for (AABB aabb : aabbs) {
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ items:
|
|||||||
behavior:
|
behavior:
|
||||||
type: block_item
|
type: block_item
|
||||||
block:
|
block:
|
||||||
|
events:
|
||||||
|
- template: default:rotatable_block
|
||||||
loot:
|
loot:
|
||||||
template: default:loot_table/self
|
template: default:loot_table/self
|
||||||
settings:
|
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");
|
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()) {
|
for (Map.Entry<String, Object> e0 : variantsMap.entrySet()) {
|
||||||
String variantName = e0.getKey();
|
String variantName = e0.getKey();
|
||||||
Map<String, Object> variantArguments = ResourceConfigUtils.getAsMap(e0.getValue(), variantName);
|
Map<String, Object> variantArguments = ResourceConfigUtils.getAsMap(e0.getValue(), variantName);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public abstract class Furniture implements Cullable {
|
public abstract class Furniture implements Cullable {
|
||||||
public final FurnitureConfig config;
|
public final FurnitureConfig config;
|
||||||
@@ -53,7 +54,7 @@ public abstract class Furniture implements Cullable {
|
|||||||
this.config = config;
|
this.config = config;
|
||||||
this.dataAccessor = data;
|
this.dataAccessor = data;
|
||||||
this.metaDataEntity = metaDataEntity;
|
this.metaDataEntity = metaDataEntity;
|
||||||
this.setVariant(config.getVariant(data));
|
this.setVariantInternal(config.getVariant(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity metaDataEntity() {
|
public Entity metaDataEntity() {
|
||||||
@@ -64,7 +65,21 @@ public abstract class Furniture implements Cullable {
|
|||||||
return this.currentVariant;
|
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.currentVariant = variant;
|
||||||
this.hitboxMap = new Int2ObjectOpenHashMap<>();
|
this.hitboxMap = new Int2ObjectOpenHashMap<>();
|
||||||
// 初始化家具元素
|
// 初始化家具元素
|
||||||
@@ -115,7 +130,7 @@ public abstract class Furniture implements Cullable {
|
|||||||
if (aabb == null) {
|
if (aabb == null) {
|
||||||
List<AABB> aabbs = new ArrayList<>();
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
for (FurnitureHitBoxConfig<?> hitBoxConfig : this.currentVariant.hitBoxConfigs()) {
|
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);
|
return new CullingData(getMaxAABB(aabbs), parent.maxDistance, parent.aabbExpansion, parent.rayTracing);
|
||||||
} else {
|
} else {
|
||||||
@@ -201,20 +216,28 @@ public abstract class Furniture implements Cullable {
|
|||||||
@Override
|
@Override
|
||||||
public void show(Player player) {
|
public void show(Player player) {
|
||||||
for (FurnitureElement element : this.elements) {
|
for (FurnitureElement element : this.elements) {
|
||||||
element.show(player);
|
if (element != null) {
|
||||||
|
element.show(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (FurnitureHitBox hitbox : this.hitboxes) {
|
for (FurnitureHitBox hitbox : this.hitboxes) {
|
||||||
hitbox.show(player);
|
if (hitbox != null) {
|
||||||
|
hitbox.show(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hide(Player player) {
|
public void hide(Player player) {
|
||||||
for (FurnitureElement element : this.elements) {
|
for (FurnitureElement element : this.elements) {
|
||||||
element.hide(player);
|
if (element != null) {
|
||||||
|
element.hide(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (FurnitureHitBox hitbox : this.hitboxes) {
|
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;
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
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.EmptyFurnitureBehavior;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior;
|
import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior;
|
||||||
import net.momirealms.craftengine.core.loot.LootTable;
|
import net.momirealms.craftengine.core.loot.LootTable;
|
||||||
@@ -33,7 +34,7 @@ class FurnitureConfigImpl implements FurnitureConfig {
|
|||||||
@Nullable LootTable<?> lootTable) {
|
@Nullable LootTable<?> lootTable) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.variants = ImmutableMap.copyOf(variants);
|
this.variants = ImmutableSortedMap.copyOf(variants);
|
||||||
this.lootTable = lootTable;
|
this.lootTable = lootTable;
|
||||||
this.behavior = behavior;
|
this.behavior = behavior;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ public interface FurnitureHitBoxConfig<H extends FurnitureHitBox> {
|
|||||||
|
|
||||||
boolean canUseItemOn();
|
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 PURPLE_DYE = Key.of("minecraft:purple_dye");
|
||||||
public static final Key MAGENTA_DYE = Key.of("minecraft:magenta_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 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 CARROT = Key.of("minecraft:carrot");
|
||||||
public static final Key POTATO = Key.of("minecraft:potato");
|
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/loot_tables.yml");
|
||||||
plugin.saveResource("resources/default/configuration/templates/recipes.yml");
|
plugin.saveResource("resources/default/configuration/templates/recipes.yml");
|
||||||
plugin.saveResource("resources/default/configuration/templates/tool_levels.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/categories.yml");
|
||||||
plugin.saveResource("resources/default/configuration/emoji.yml");
|
plugin.saveResource("resources/default/configuration/emoji.yml");
|
||||||
plugin.saveResource("resources/default/configuration/translations.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_EXP, new SetExpFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||||
register(CommonFunctions.SET_LEVEL, new SetLevelFunction.FactoryImpl<>(EventConditions::fromMap));
|
register(CommonFunctions.SET_LEVEL, new SetLevelFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||||
register(CommonFunctions.PLAY_TOTEM_ANIMATION, new PlayTotemAnimationFunction.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));
|
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_EXP = Key.of("craftengine:set_exp");
|
||||||
public static final Key SET_LEVEL = Key.of("craftengine:set_level");
|
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 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");
|
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 org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ public class CycleBlockPropertyFunction<CTX extends Context> extends AbstractCon
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
return wrapper.cycleProperty(this.property, inverse);
|
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) {
|
if (mapValue == null) {
|
||||||
return wrapper.cycleProperty(this.property, inverse);
|
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.entity.player.Player;
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
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.util.MiscUtils;
|
||||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||||
import net.momirealms.craftengine.core.world.MutableVec3d;
|
import net.momirealms.craftengine.core.world.MutableVec3d;
|
||||||
|
|||||||
Reference in New Issue
Block a user