mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 12:29:15 +00:00
方块实体3
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Boolean> openProperty;
|
||||
|
||||
public SimpleStorageBlockBehavior(CustomBlock customBlock,
|
||||
String containerTitle,
|
||||
int rows,
|
||||
SoundData openSound,
|
||||
SoundData closeSound,
|
||||
boolean hasAnalogOutputSignal,
|
||||
Property<Boolean> 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<Object> 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<Object> 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 <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
||||
return (BlockEntityType<T>) 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<Boolean> 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<String, Object> arguments) {
|
||||
String title = arguments.getOrDefault("title", "").toString();
|
||||
int rows = MCUtils.clamp(ResourceConfigUtils.getAsInt(arguments.getOrDefault("rows", 1), "rows"), 1, 6);
|
||||
Map<String, Object> sounds = (Map<String, Object>) 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<Boolean> property = (Property<Boolean>) block.getProperty("open");
|
||||
return new SimpleStorageBlockBehavior(block, title, rows, openSound, closeSound, hasAnalogOutputSignal, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<SimpleStorageBlockEntity> SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new);
|
||||
}
|
||||
@@ -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<HumanEntity> 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<Boolean> 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<HumanEntity> 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> inventory;
|
||||
private final Gui gui;
|
||||
|
||||
public CraftEngineInventoryHolder(Gui gui) {
|
||||
public CraftEngineGUIHolder(Gui gui) {
|
||||
this.inventory = new ObjectHolder<>();
|
||||
this.gui = gui;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Object> 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<Object>) field$ItemStack$CODEC.get(null) : null;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init ItemStack$CODEC", e);
|
||||
}
|
||||
|
||||
@@ -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<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user