From 8931433bb1c4bfaa4d27b48586555516bcacff28 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 5 Sep 2025 07:06:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B9=E5=9D=97=E5=AE=9E=E4=BD=933?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BukkitBlockBehaviors.java | 2 + .../behavior/SimpleStorageBlockBehavior.java | 186 ++++++++++++++++ .../block/entity/BlockEntityHolder.java | 28 +++ .../block/entity/BukkitBlockEntityTypes.java | 9 + .../entity/SimpleStorageBlockEntity.java | 205 ++++++++++++++++++ .../bukkit/plugin/gui/BukkitGuiManager.java | 32 ++- ...yHolder.java => CraftEngineGUIHolder.java} | 4 +- .../plugin/injector/BlockGenerator.java | 1 - .../reflection/minecraft/CoreReflections.java | 4 +- .../plugin/user/BukkitServerPlayer.java | 28 ++- .../bukkit/util/EnchantmentUtils.java | 1 - .../craftengine/bukkit/world/BukkitWorld.java | 5 + .../default/configuration/blocks.yml | 69 +++++- .../block/custom/safe_block_front_open.png | Bin 0 -> 368 bytes .../block/behavior/EntityBlockBehavior.java | 2 + .../block/entity/BlockEntityTypeKeys.java | 9 + .../core/block/entity/BlockEntityTypes.java | 12 + .../core/pack/AbstractPackManager.java | 1 + .../core/plugin/dependency/Dependencies.java | 4 - .../craftengine/core/util/MCUtils.java | 5 + .../craftengine/core/world/World.java | 7 + .../craftengine/core/world/chunk/CEChunk.java | 14 +- .../core/world/collision/AABB.java | 13 ++ gradle.properties | 4 +- 24 files changed, 612 insertions(+), 33 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleStorageBlockBehavior.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BlockEntityHolder.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java rename bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/{CraftEngineInventoryHolder.java => CraftEngineGUIHolder.java} (86%) create mode 100644 common-files/src/main/resources/resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_front_open.png create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index d7b4b9b0d..0705b6c10 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -28,6 +28,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key PRESSURE_PLATE_BLOCK = Key.from("craftengine:pressure_plate_block"); public static final Key DOUBLE_HIGH_BLOCK = Key.from("craftengine:double_high_block"); public static final Key CHANGE_OVER_TIME_BLOCK = Key.from("craftengine:change_over_time_block"); + public static final Key SIMPLE_STORAGE_BLOCK = Key.from("craftengine:simple_storage_block"); public static void init() { register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE); @@ -54,5 +55,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(PRESSURE_PLATE_BLOCK, PressurePlateBlockBehavior.FACTORY); register(DOUBLE_HIGH_BLOCK, DoubleHighBlockBehavior.FACTORY); register(CHANGE_OVER_TIME_BLOCK, ChangeOverTimeBlockBehavior.FACTORY); + register(SIMPLE_STORAGE_BLOCK, SimpleStorageBlockBehavior.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleStorageBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleStorageBlockBehavior.java new file mode 100644 index 000000000..65ae93bad --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleStorageBlockBehavior.java @@ -0,0 +1,186 @@ +package net.momirealms.craftengine.bukkit.block.behavior; + +import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes; +import net.momirealms.craftengine.bukkit.block.entity.SimpleStorageBlockEntity; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.gui.BukkitInventory; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; +import net.momirealms.craftengine.core.block.BlockBehavior; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior; +import net.momirealms.craftengine.core.block.entity.BlockEntity; +import net.momirealms.craftengine.core.block.entity.BlockEntityType; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.entity.player.InteractionResult; +import net.momirealms.craftengine.core.item.context.UseOnContext; +import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; +import net.momirealms.craftengine.core.sound.SoundData; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.CEWorld; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Callable; + +public class SimpleStorageBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior { + public static final Factory FACTORY = new Factory(); + private final String containerTitle; + private final int rows; + private final SoundData openSound; + private final SoundData closeSound; + private final boolean hasAnalogOutputSignal; + @Nullable + private final Property openProperty; + + public SimpleStorageBlockBehavior(CustomBlock customBlock, + String containerTitle, + int rows, + SoundData openSound, + SoundData closeSound, + boolean hasAnalogOutputSignal, + Property openProperty) { + super(customBlock); + this.containerTitle = containerTitle; + this.rows = rows; + this.openSound = openSound; + this.closeSound = closeSound; + this.hasAnalogOutputSignal = hasAnalogOutputSignal; + this.openProperty = openProperty; + } + + @Override + public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { + CEWorld world = context.getLevel().storageWorld(); + net.momirealms.craftengine.core.entity.player.Player player = context.getPlayer(); + BlockEntity blockEntity = world.getBlockEntityAtIfLoaded(context.getClickedPos()); + if (player != null && blockEntity instanceof SimpleStorageBlockEntity entity) { + Player bukkitPlayer = (Player) player.platformPlayer(); + Optional.ofNullable(entity.inventory()).ifPresent(inventory -> { + entity.onPlayerOpen(player); + bukkitPlayer.openInventory(inventory); + new BukkitInventory(inventory).open(player, AdventureHelper.miniMessage().deserialize(this.containerTitle, PlayerOptionalContext.of(player).tagResolvers())); + }); + } + return InteractionResult.SUCCESS_AND_CANCEL; + } + + // 1.21.5+ + @Override + public void affectNeighborsAfterRemoval(Object thisBlock, Object[] args, Callable superMethod) { + Object level = args[1]; + Object pos = args[2]; + Object blockState = args[0]; + FastNMS.INSTANCE.method$Level$updateNeighbourForOutputSignal(level, pos, BlockStateUtils.getBlockOwner(blockState)); + } + + @Override + public void tick(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + Object world = args[1]; + Object blockPos = args[2]; + BlockPos pos = LocationUtils.fromBlockPos(blockPos); + World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(world); + CEWorld ceWorld = BukkitWorldManager.instance().getWorld(bukkitWorld.getUID()); + BlockEntity blockEntity = ceWorld.getBlockEntityAtIfLoaded(pos); + if (blockEntity instanceof SimpleStorageBlockEntity entity) { + entity.checkOpeners(world, blockPos, args[0]); + } + } + + @SuppressWarnings("unchecked") + @Override + public BlockEntityType blockEntityType() { + return (BlockEntityType) BukkitBlockEntityTypes.SIMPLE_STORAGE; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) { + return new SimpleStorageBlockEntity(pos, state); + } + + @NotNull + public String containerTitle() { + return this.containerTitle; + } + + @Nullable + public SoundData closeSound() { + return this.closeSound; + } + + @Nullable + public SoundData openSound() { + return this.openSound; + } + + public int rows() { + return this.rows; + } + + public @Nullable Property openProperty() { + return openProperty; + } + + @Override + public int getAnalogOutputSignal(Object thisBlock, Object[] args) { + if (!this.hasAnalogOutputSignal) return 0; + Object world = args[1]; + Object blockPos = args[2]; + BlockPos pos = LocationUtils.fromBlockPos(blockPos); + World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(world); + CEWorld ceWorld = BukkitWorldManager.instance().getWorld(bukkitWorld.getUID()); + BlockEntity blockEntity = ceWorld.getBlockEntityAtIfLoaded(pos); + if (blockEntity instanceof SimpleStorageBlockEntity entity) { + Inventory inventory = entity.inventory(); + if (inventory != null) { + float signal = 0.0F; + for (int i = 0; i < inventory.getSize(); i++) { + ItemStack item = inventory.getItem(i); + if (item != null) { + signal += (float) item.getAmount() / (float) (Math.min(inventory.getMaxStackSize(), item.getMaxStackSize())); + } + } + signal /= (float) inventory.getSize(); + return MCUtils.lerpDiscrete(signal, 0, 15); + } + } + return 0; + } + + @Override + public boolean hasAnalogOutputSignal(Object thisBlock, Object[] args) { + return this.hasAnalogOutputSignal; + } + + public static class Factory implements BlockBehaviorFactory { + + @SuppressWarnings("unchecked") + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + String title = arguments.getOrDefault("title", "").toString(); + int rows = MCUtils.clamp(ResourceConfigUtils.getAsInt(arguments.getOrDefault("rows", 1), "rows"), 1, 6); + Map sounds = (Map) arguments.get("sounds"); + boolean hasAnalogOutputSignal = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("has-signal", true), "has-signal"); + SoundData openSound = null; + SoundData closeSound = null; + if (sounds != null) { + openSound = Optional.ofNullable(sounds.get("open")).map(obj -> SoundData.create(obj, SoundData.SoundValue.FIXED_0_5, SoundData.SoundValue.ranged(0.9f, 1f))).orElse(null); + closeSound = Optional.ofNullable(sounds.get("close")).map(obj -> SoundData.create(obj, SoundData.SoundValue.FIXED_0_5, SoundData.SoundValue.ranged(0.9f, 1f))).orElse(null); + } + Property property = (Property) block.getProperty("open"); + return new SimpleStorageBlockBehavior(block, title, rows, openSound, closeSound, hasAnalogOutputSignal, property); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BlockEntityHolder.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BlockEntityHolder.java new file mode 100644 index 000000000..23ec8fb4c --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BlockEntityHolder.java @@ -0,0 +1,28 @@ +package net.momirealms.craftengine.bukkit.block.entity; + +import net.momirealms.craftengine.core.block.entity.BlockEntity; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.jetbrains.annotations.NotNull; + +public class BlockEntityHolder implements InventoryHolder { + private final BlockEntity blockEntity; + private Inventory inventory; + + public BlockEntityHolder(BlockEntity entity) { + this.blockEntity = entity; + } + + public BlockEntity blockEntity() { + return blockEntity; + } + + public void setInventory(Inventory inventory) { + this.inventory = inventory; + } + + @Override + public @NotNull Inventory getInventory() { + return this.inventory; + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java new file mode 100644 index 000000000..0385b0b32 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java @@ -0,0 +1,9 @@ +package net.momirealms.craftengine.bukkit.block.entity; + +import net.momirealms.craftengine.core.block.entity.BlockEntityType; +import net.momirealms.craftengine.core.block.entity.BlockEntityTypeKeys; +import net.momirealms.craftengine.core.block.entity.BlockEntityTypes; + +public class BukkitBlockEntityTypes extends BlockEntityTypes { + public static final BlockEntityType SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new); +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java new file mode 100644 index 000000000..b9ec60521 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleStorageBlockEntity.java @@ -0,0 +1,205 @@ +package net.momirealms.craftengine.bukkit.block.entity; + +import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; +import net.momirealms.craftengine.bukkit.block.behavior.SimpleStorageBlockBehavior; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistryOps; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.UpdateOption; +import net.momirealms.craftengine.core.block.entity.BlockEntity; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.sound.SoundData; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.ListTag; +import org.bukkit.Bukkit; +import org.bukkit.GameEvent; +import org.bukkit.GameMode; +import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +public class SimpleStorageBlockEntity extends BlockEntity { + private final SimpleStorageBlockBehavior behavior; + private final Inventory inventory; + private double maxInteractionDistance; + private boolean openState = false; + + public SimpleStorageBlockEntity(BlockPos pos, ImmutableBlockState blockState) { + super(BukkitBlockEntityTypes.SIMPLE_STORAGE, pos, blockState); + this.behavior = super.blockState.behavior().getAs(SimpleStorageBlockBehavior.class).orElseThrow(); + BlockEntityHolder holder = new BlockEntityHolder(this); + this.inventory = Bukkit.createInventory(holder, this.behavior.rows() * 9); + } + + @Override + protected void saveCustomData(CompoundTag tag) { + // 保存前先把所有打开此容器的玩家界面关闭 + this.inventory.close(); + ListTag itemsTag = new ListTag(); + @Nullable ItemStack[] storageContents = this.inventory.getStorageContents(); + for (int i = 0; i < storageContents.length; i++) { + if (storageContents[i] != null) { + int slot = i; + CoreReflections.instance$ItemStack$CODEC.encodeStart(MRegistryOps.SPARROW_NBT, FastNMS.INSTANCE.field$CraftItemStack$handle(storageContents[i])) + .ifSuccess(success -> { + CompoundTag itemTag = (CompoundTag) success; + itemTag.putInt("slot", slot); + itemsTag.add(itemTag); + }) + .ifError(error -> CraftEngine.instance().logger().severe("Error while saving storage item: " + error)); + } + } + tag.put("items", itemsTag); + } + + @Override + public void loadCustomData(CompoundTag tag) { + ListTag itemsTag = Optional.ofNullable(tag.getList("items")).orElseGet(ListTag::new); + for (int i = 0; i < itemsTag.size(); i++) { + CompoundTag itemTag = itemsTag.getCompound(i); + int slot = itemTag.getInt("slot"); + if (slot < 0 || slot >= this.behavior.rows() * 9) { + continue; + } + CoreReflections.instance$ItemStack$CODEC.parse(MRegistryOps.SPARROW_NBT, itemTag) + .resultOrPartial((s) -> CraftEngine.instance().logger().severe("Tried to load invalid item: '" + itemTag + "'. " + s)) + .ifPresent(nmsStack -> this.inventory.setItem(slot, FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsStack))); + } + } + + public Inventory inventory() { + if (!isValid()) return null; + return this.inventory; + } + + public void onPlayerOpen(Player player) { + if (!isValidContainer()) return; + if (!player.isSpectatorMode()) { + // 有非观察者的人,那么就不触发开启音效和事件 + if (!hasNoViewer(this.inventory.getViewers())) return; + this.maxInteractionDistance = Math.max(player.getCachedInteractionRange(), this.maxInteractionDistance); + this.setOpen(player); + FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(super.world.world().serverWorld(), LocationUtils.toBlockPos(this.pos), BlockStateUtils.getBlockOwner(this.blockState.customBlockState().literalObject()), 5); + } + } + + public void onPlayerClose(Player player) { + if (!isValidContainer()) return; + if (!player.isSpectatorMode()) { + // 有非观察者的人,那么就不触发关闭音效和事件 + for (HumanEntity viewer : this.inventory.getViewers()) { + if (viewer.getGameMode() == GameMode.SPECTATOR || viewer == player.platformPlayer()) { + continue; + } + return; + } + this.maxInteractionDistance = 0; + this.setClose(player); + } + } + + private void setOpen(@Nullable Player player) { + this.updateOpenBlockState(true); + org.bukkit.World bukkitWorld = (org.bukkit.World) super.world.world().platformWorld(); + if (player != null) { + bukkitWorld.sendGameEvent((org.bukkit.entity.Player) player.platformPlayer(), GameEvent.CONTAINER_OPEN, new Vector(this.pos.x(), this.pos.y(), this.pos.z())); + } else { + bukkitWorld.sendGameEvent(null, GameEvent.CONTAINER_OPEN, new Vector(this.pos.x(), this.pos.y(), this.pos.z())); + } + this.openState = true; + SoundData soundData = this.behavior.openSound(); + if (soundData != null) { + super.world.world().playBlockSound(Vec3d.atCenterOf(this.pos), soundData); + } + } + + private void setClose(@Nullable Player player) { + this.updateOpenBlockState(false); + org.bukkit.World bukkitWorld = (org.bukkit.World) super.world.world().platformWorld(); + if (player != null) { + bukkitWorld.sendGameEvent((org.bukkit.entity.Player) player.platformPlayer(), GameEvent.CONTAINER_CLOSE, new Vector(this.pos.x(), this.pos.y(), this.pos.z())); + } else { + bukkitWorld.sendGameEvent(null, GameEvent.CONTAINER_CLOSE, new Vector(this.pos.x(), this.pos.y(), this.pos.z())); + } + this.openState = false; + SoundData soundData = this.behavior.closeSound(); + if (soundData != null) { + super.world.world().playBlockSound(Vec3d.atCenterOf(this.pos), soundData); + } + } + + private boolean hasNoViewer(List viewers) { + for (HumanEntity viewer : viewers) { + if (viewer.getGameMode() != GameMode.SPECTATOR) { + return false; + } + } + return true; + } + + private boolean isValidContainer() { + return this.isValid() && this.inventory != null && this.behavior != null; + } + + public void updateOpenBlockState(boolean open) { + ImmutableBlockState state = super.world.getBlockStateAtIfLoaded(this.pos); + if (state == null || state.behavior() != this.behavior) return; + Property property = this.behavior.openProperty(); + if (property == null) return; + super.world.world().setBlockAt(this.pos.x(), this.pos.y(), this.pos.z(), state.with(property, open), UpdateOption.UPDATE_ALL.flags()); + } + + public void checkOpeners(Object level, Object pos, Object blockState) { + if (!this.isValidContainer()) return; + double maxInteractionDistance = 0d; + List viewers = this.inventory.getViewers(); + int validViewers = 0; + for (HumanEntity viewer : viewers) { + if (viewer instanceof org.bukkit.entity.Player player) { + maxInteractionDistance = Math.max(BukkitAdaptors.adapt(player).getCachedInteractionRange(), maxInteractionDistance); + if (player.getGameMode() != GameMode.SPECTATOR) { + validViewers++; + } + } + } + boolean shouldOpen = validViewers != 0; + if (shouldOpen && !this.openState) { + this.setOpen(null); + } else if (!shouldOpen && this.openState) { + this.setClose(null); + } + + this.maxInteractionDistance = maxInteractionDistance; + if (!viewers.isEmpty()) { + FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(level, pos, BlockStateUtils.getBlockOwner(blockState), 5); + } + } + + @Override + public void preRemove() { + this.inventory.close(); + Vec3d pos = Vec3d.atCenterOf(this.pos); + for (ItemStack stack : this.inventory.getContents()) { + if (stack != null) { + super.world.world().dropItemNaturally(pos, BukkitItemManager.instance().wrap(stack)); + } + } + this.inventory.clear(); + } + + +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java index 26b31cebc..afef50d62 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/BukkitGuiManager.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.bukkit.plugin.gui; import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.bukkit.block.entity.BlockEntityHolder; +import net.momirealms.craftengine.bukkit.block.entity.SimpleStorageBlockEntity; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; @@ -18,16 +20,19 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.MenuType; public class BukkitGuiManager implements GuiManager, Listener { private static final boolean useNewOpenInventory = ReflectionUtils.getDeclaredMethod(InventoryView.class, void.class, new String[]{"open"}) != null; + private static BukkitGuiManager instance; private final BukkitCraftEngine plugin; public BukkitGuiManager(BukkitCraftEngine plugin) { this.plugin = plugin; + instance = this; } @Override @@ -83,7 +88,7 @@ public class BukkitGuiManager implements GuiManager, Listener { @Override public Inventory createInventory(Gui gui, int size) { - CraftEngineInventoryHolder holder = new CraftEngineInventoryHolder(gui); + CraftEngineGUIHolder holder = new CraftEngineGUIHolder(gui); org.bukkit.inventory.Inventory inventory = Bukkit.createInventory(holder, size); holder.holder().bindValue(inventory); return new BukkitInventory(inventory); @@ -95,10 +100,10 @@ public class BukkitGuiManager implements GuiManager, Listener { if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(inventory))) { return; } - if (!(inventory.getHolder() instanceof CraftEngineInventoryHolder craftEngineInventoryHolder)) { + if (!(inventory.getHolder() instanceof CraftEngineGUIHolder craftEngineGUIHolder)) { return; } - AbstractGui gui = (AbstractGui) craftEngineInventoryHolder.gui(); + AbstractGui gui = (AbstractGui) craftEngineGUIHolder.gui(); Player player = (Player) event.getWhoClicked(); if (event.getClickedInventory() == player.getInventory()) { gui.handleInventoryClick(new BukkitClick(event, gui, new BukkitInventory(player.getInventory()))); @@ -113,7 +118,7 @@ public class BukkitGuiManager implements GuiManager, Listener { if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(inventory))) { return; } - if (!(inventory.getHolder() instanceof CraftEngineInventoryHolder)) { + if (!(inventory.getHolder() instanceof CraftEngineGUIHolder)) { return; } for (int raw : event.getRawSlots()) { @@ -123,4 +128,23 @@ public class BukkitGuiManager implements GuiManager, Listener { } } } + + // 处理自定义容器的关闭音效 + @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) + public void onInventoryClose(InventoryCloseEvent event) { + org.bukkit.inventory.Inventory inventory = event.getInventory(); + if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(inventory))) { + return; + } + if (!(inventory.getHolder() instanceof BlockEntityHolder holder)) { + return; + } + if (event.getPlayer() instanceof Player player && holder.blockEntity() instanceof SimpleStorageBlockEntity simpleStorageBlockEntity) { + simpleStorageBlockEntity.onPlayerClose(this.plugin.adapt(player)); + } + } + + public static BukkitGuiManager instance() { + return instance; + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/CraftEngineInventoryHolder.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/CraftEngineGUIHolder.java similarity index 86% rename from bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/CraftEngineInventoryHolder.java rename to bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/CraftEngineGUIHolder.java index 50938e21b..a35679a4b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/CraftEngineInventoryHolder.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/gui/CraftEngineGUIHolder.java @@ -6,11 +6,11 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.jetbrains.annotations.NotNull; -public class CraftEngineInventoryHolder implements InventoryHolder { +public class CraftEngineGUIHolder implements InventoryHolder { private final ObjectHolder inventory; private final Gui gui; - public CraftEngineInventoryHolder(Gui gui) { + public CraftEngineGUIHolder(Gui gui) { this.inventory = new ObjectHolder<>(); this.gui = gui; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java index 85ba77e5b..b4d14745b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java @@ -15,7 +15,6 @@ import net.bytebuddy.implementation.bind.annotation.This; import net.bytebuddy.matcher.ElementMatchers; import net.momirealms.craftengine.bukkit.block.BukkitBlockShape; import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.injector.BlockGenerator.*; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks; import net.momirealms.craftengine.bukkit.util.NoteBlockChainUpdateUtils; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index 600e1505b..dac330b75 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -3671,11 +3671,11 @@ public final class CoreReflections { // 1.20.5+ public static final Field field$ItemStack$CODEC = ReflectionUtils.getDeclaredField(clazz$ItemStack, "CODEC", "b"); - public static final Codec instance$ItemStack$CODEC; + public static final Codec instance$ItemStack$CODEC; static { try { - instance$ItemStack$CODEC = VersionHelper.isOrAbove1_20_5() ? (Codec) field$ItemStack$CODEC.get(null) : null; + instance$ItemStack$CODEC = VersionHelper.isOrAbove1_20_5() ? (Codec) field$ItemStack$CODEC.get(null) : null; } catch (ReflectiveOperationException e) { throw new ReflectionInitException("Failed to init ItemStack$CODEC", e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index c448b31cd..e62760b77 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -7,10 +7,12 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; +import net.momirealms.craftengine.bukkit.block.entity.BlockEntityHolder; +import net.momirealms.craftengine.bukkit.block.entity.SimpleStorageBlockEntity; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.plugin.gui.CraftEngineInventoryHolder; +import net.momirealms.craftengine.bukkit.plugin.gui.CraftEngineGUIHolder; import net.momirealms.craftengine.bukkit.plugin.network.payload.DiscardedPayload; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; @@ -21,6 +23,7 @@ import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.BlockStateWrapper; import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.entity.BlockEntity; import net.momirealms.craftengine.core.entity.player.GameMode; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.Player; @@ -36,13 +39,16 @@ import net.momirealms.craftengine.core.util.IntIdentityList; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldEvents; import net.momirealms.craftengine.core.world.chunk.ChunkStatus; +import net.momirealms.craftengine.core.world.collision.AABB; import org.bukkit.*; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.block.Block; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; @@ -467,7 +473,7 @@ public class BukkitServerPlayer extends Player { } else { this.gameTicks = FastNMS.INSTANCE.field$MinecraftServer$currentTick(); } - if (this.gameTicks % 30 == 0) { + if (this.gameTicks % 20 == 0) { this.updateGUI(); } if (this.isDestroyingBlock) { @@ -491,11 +497,27 @@ public class BukkitServerPlayer extends Player { if (!CraftBukkitReflections.clazz$MinecraftInventory.isInstance(FastNMS.INSTANCE.method$CraftInventory$getInventory(top))) { return; } - if (top.getHolder() instanceof CraftEngineInventoryHolder holder) { + if (top.getHolder() instanceof CraftEngineGUIHolder holder) { holder.gui().onTimer(); + } else if (top.getHolder() instanceof BlockEntityHolder holder) { + BlockEntity blockEntity = holder.blockEntity(); + BlockPos blockPos = blockEntity.pos(); + if (!canInteractWithBlock(blockPos, 4d)) { + platformPlayer().closeInventory(); + } } } + public boolean canInteractWithBlock(BlockPos pos, double distance) { + double d = this.getCachedInteractionRange() + distance; + return (new AABB(pos)).distanceToSqr(this.getEyePosition()) < d * d; + } + + public final Vec3d getEyePosition() { + Location eyeLocation = this.platformPlayer().getEyeLocation(); + return new Vec3d(eyeLocation.getX(), eyeLocation.getY(), eyeLocation.getZ()); + } + @Override public float getDestroyProgress(Object blockState, BlockPos pos) { Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EnchantmentUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EnchantmentUtils.java index 9bd42c689..2a6bd2117 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EnchantmentUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EnchantmentUtils.java @@ -4,7 +4,6 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import java.util.HashMap; import java.util.Map; -import java.util.Objects; public final class EnchantmentUtils { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java index bfb04f654..db9d707bf 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java @@ -123,4 +123,9 @@ public class BukkitWorld implements World { public void levelEvent(int id, BlockPos pos, int data) { FastNMS.INSTANCE.method$LevelAccessor$levelEvent(serverWorld(), id, LocationUtils.toBlockPos(pos), data); } + + @Override + public CEWorld storageWorld() { + return BukkitWorldManager.instance().getWorld(uuid()); + } } diff --git a/common-files/src/main/resources/resources/default/configuration/blocks.yml b/common-files/src/main/resources/resources/default/configuration/blocks.yml index 746bf00b4..573ed098d 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks.yml @@ -464,11 +464,21 @@ items#misc: hit: minecraft:block.stone.hit place: minecraft:block.stone.place step: minecraft:block.stone.step + behavior: + type: simple_storage_block + title: "" + rows: 1 + sounds: + open: minecraft:block.iron_trapdoor.open + close: minecraft:block.iron_trapdoor.close states: properties: facing: type: 4-direction default: north + open: + type: boolean + default: false appearances: east: state: note_block:22 @@ -481,33 +491,70 @@ items#misc: front: minecraft:block/custom/safe_block_front side: minecraft:block/custom/safe_block_side top: minecraft:block/custom/safe_block_top - north: + east_open: state: note_block:23 model: - path: minecraft:block/custom/safe_block - south: + path: minecraft:block/custom/safe_block_open + y: 90 + generation: + parent: minecraft:block/orientable + textures: + front: minecraft:block/custom/safe_block_front_open + side: minecraft:block/custom/safe_block_side + top: minecraft:block/custom/safe_block_top + north: state: note_block:24 model: path: minecraft:block/custom/safe_block + north_open: + state: note_block:25 + model: + path: minecraft:block/custom/safe_block_open + south: + state: note_block:26 + model: + path: minecraft:block/custom/safe_block + y: 180 + south_open: + state: note_block:27 + model: + path: minecraft:block/custom/safe_block_open y: 180 west: - state: note_block:25 + state: note_block:28 model: path: minecraft:block/custom/safe_block y: 270 + west_open: + state: note_block:29 + model: + path: minecraft:block/custom/safe_block_open + y: 270 variants: - facing=east: + facing=east,open=false: appearance: east id: 22 - facing=north: - appearance: north + facing=east,open=true: + appearance: east_open id: 23 - facing=south: - appearance: south + facing=north,open=false: + appearance: north id: 24 - facing=west: - appearance: west + facing=north,open=true: + appearance: north_open id: 25 + facing=south,open=false: + appearance: south + id: 26 + facing=south,open=true: + appearance: south_open + id: 27 + facing=west,open=false: + appearance: west + id: 28 + facing=west,open=true: + appearance: west_open + id: 29 recipes#misc: default:chinese_lantern: type: shaped diff --git a/common-files/src/main/resources/resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_front_open.png b/common-files/src/main/resources/resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_front_open.png new file mode 100644 index 0000000000000000000000000000000000000000..50cd8f450d7ee4bd1d966887dbccad282d55f1fd GIT binary patch literal 368 zcmV-$0gwKPP)Px$DoI2^R5*==l21!QK@`P*4i7OA=RI8p{n@sNmQhh5{h`)v>Wj2$(}$@|OWQ_) zri6qQ*cXr%f^TL-)LgZ=@sQN%uI`*U_nx_TPU`aN8USKr3sJ~_5df8^M>!0JqnV`a zLPnCEz5PHk9frAlw7ROyhDoU9WXmM#phuZTJXS$Lo;OzV&xi~yI z_0OPUW4oPBa=yF0@vviK6>wiJ14qXPf7E6x$P%1&(!j3(D4_!F_7||ZRr0W%bqZKp z-vDaW8c=_Jn8%i1QvIG855E)Cuh8!q1vFl&{hkr%v-LWUJsu5ytpPY|0Uc^drb9 BlockEntityType blockEntityType(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java new file mode 100644 index 000000000..5d969518d --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java @@ -0,0 +1,9 @@ +package net.momirealms.craftengine.core.block.entity; + +import net.momirealms.craftengine.core.util.Key; + +public final class BlockEntityTypeKeys { + private BlockEntityTypeKeys() {} + + public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage"); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java index 1f90b42c5..d3d0c0941 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java @@ -1,5 +1,17 @@ package net.momirealms.craftengine.core.block.entity; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceKey; + public class BlockEntityTypes { + public static BlockEntityType register(Key id, BlockEntity.Factory factory) { + BlockEntityType type = new BlockEntityType<>(id, factory); + ((WritableRegistry>) BuiltInRegistries.BLOCK_ENTITY_TYPE) + .register(ResourceKey.create(Registries.BLOCK_ENTITY_TYPE.location(), id), type); + return type; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 80831f27b..a080cae06 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -426,6 +426,7 @@ public abstract class AbstractPackManager implements PackManager { plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_bottom.png"); plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_side.png"); plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_front.png"); + plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/safe_block_front_open.png"); // items plugin.saveResource("resources/default/configuration/items.yml"); plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/item/custom/topaz_rod.png"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java index 5caddb618..5adccc541 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/dependency/Dependencies.java @@ -1,13 +1,9 @@ package net.momirealms.craftengine.core.plugin.dependency; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.dependency.relocation.Relocation; -import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; public class Dependencies { diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java index 95e1621f7..38cf3acdd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/MCUtils.java @@ -31,6 +31,11 @@ public class MCUtils { return value < (double) truncated ? truncated - 1 : truncated; } + public static int lerpDiscrete(float delta, int start, int end) { + int i = end - start; + return start + fastFloor(delta * (float) (i - 1)) + (delta > 0.0F ? 1 : 0); + } + public static int murmurHash3Mixer(int value) { value ^= value >>> 16; value *= -2048144789; diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/World.java b/core/src/main/java/net/momirealms/craftengine/core/world/World.java index a7d960454..287429f5a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/World.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/World.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.core.world; import net.momirealms.craftengine.core.block.BlockStateWrapper; +import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.sound.SoundData; @@ -15,6 +16,8 @@ import java.util.UUID; public interface World { + CEWorld storageWorld(); + Object platformWorld(); Object serverWorld(); @@ -29,6 +32,10 @@ public interface World { void setBlockAt(int x, int y, int z, BlockStateWrapper blockState, int flags); + default void setBlockAt(int x, int y, int z, ImmutableBlockState blockState, int flags) { + this.setBlockAt(x, y, z, blockState.customBlockState(), flags); + } + String name(); Path directory(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java index cce78f674..6b8acd1a7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java @@ -65,11 +65,18 @@ public class CEChunk { if (removedBlockEntity != null) { removedBlockEntity.setValid(false); } + this.removeBlockEntityTicker(blockPos); } - public void clearAllBlockEntities() { + public void activateAllBlockEntities() { + for (BlockEntity blockEntity : this.blockEntities.values()) { + blockEntity.setValid(true); + replaceOrCreateTickingBlockEntity(blockEntity); + } + } + + public void deactivateAllBlockEntities() { this.blockEntities.values().forEach(e -> e.setValid(false)); - this.blockEntities.clear(); this.tickingBlockEntitiesByPos.values().forEach((ticker) -> ticker.setTicker(DummyTickingBlockEntity.INSTANCE)); this.tickingBlockEntitiesByPos.clear(); } @@ -247,13 +254,14 @@ public class CEChunk { public void load() { if (this.loaded) return; this.world.addLoadedChunk(this); + this.activateAllBlockEntities(); this.loaded = true; } public void unload() { if (!this.loaded) return; this.world.removeLoadedChunk(this); - this.clearAllBlockEntities(); + this.deactivateAllBlockEntities(); this.loaded = false; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java b/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java index 931692fef..8121e3b64 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/collision/AABB.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.core.world.collision; import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.EntityHitResult; import net.momirealms.craftengine.core.world.Vec3d; import org.jetbrains.annotations.Nullable; @@ -34,6 +36,17 @@ public class AABB { this.maxZ = Math.max(pos1.z, pos2.z); } + public AABB(BlockPos pos) { + this(pos.x(), pos.y(), pos.z(), pos.x() + 1, pos.y() + 1, pos.z() + 1); + } + + public double distanceToSqr(Vec3d vec) { + double x = Math.max(Math.max(this.minX - vec.x, vec.x - this.maxX), 0.0F); + double y = Math.max(Math.max(this.minY - vec.y, vec.y - this.maxY), 0.0F); + double z = Math.max(Math.max(this.minZ - vec.z, vec.z - this.maxZ), 0.0F); + return x * x + y * y + z * z; + } + public static AABB fromInteraction(Vec3d pos, double width, double height) { return new AABB( pos.x - width / 2, diff --git a/gradle.properties b/gradle.properties index 09b0c867e..ffbcaf5cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.62.12 +project_version=0.0.62.13 config_version=45 lang_version=25 project_group=net.momirealms @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.20 -nms_helper_version=1.0.74 +nms_helper_version=1.0.75 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.33.1