mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 01:49:30 +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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: "<i18n:item.safe_block>"
|
||||
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
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 368 B |
@@ -6,7 +6,9 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public interface EntityBlockBehavior {
|
||||
|
||||
<T extends BlockEntity> BlockEntityType<T> blockEntityType();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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 <T extends BlockEntity> BlockEntityType<T> register(Key id, BlockEntity.Factory<T> factory) {
|
||||
BlockEntityType<T> type = new BlockEntityType<>(id, factory);
|
||||
((WritableRegistry<BlockEntityType<?>>) BuiltInRegistries.BLOCK_ENTITY_TYPE)
|
||||
.register(ResourceKey.create(Registries.BLOCK_ENTITY_TYPE.location(), id), type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user