mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 12:29:15 +00:00
优化
This commit is contained in:
@@ -1,14 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.advancement;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.core.advancement.AbstractAdvancementManager;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -11,7 +11,6 @@ import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
@@ -24,7 +23,6 @@ import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextPar
|
||||
import net.momirealms.craftengine.core.util.Cancellable;
|
||||
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.WorldPosition;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -34,16 +32,13 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.world.GenericGameEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockEventListener implements Listener {
|
||||
@@ -179,36 +174,8 @@ public class BlockEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
// handle waterlogged blocks
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Boolean> waterloggedProperty = (Property<Boolean>) state.owner().value().getProperty("waterlogged");
|
||||
if (waterloggedProperty != null) {
|
||||
boolean waterlogged = state.get(waterloggedProperty);
|
||||
if (waterlogged) {
|
||||
location.getWorld().setBlockData(location, Material.WATER.createBlockData());
|
||||
}
|
||||
}
|
||||
|
||||
// play sound
|
||||
world.playBlockSound(position, state.sounds().breakSound());
|
||||
if (player.getGameMode() == GameMode.CREATIVE || !customBreakEvent.dropItems()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do not drop if it's not the correct tool
|
||||
if (!BlockStateUtils.isCorrectTool(state, itemInHand)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// drop items
|
||||
ContextHolder.Builder lootContext = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position)
|
||||
.withParameter(DirectContextParameters.PLAYER, serverPlayer)
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
|
||||
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand);
|
||||
for (Item<Object> item : state.getDrops(lootContext, world, serverPlayer)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// override vanilla block loots
|
||||
@@ -254,19 +221,6 @@ public class BlockEventListener implements Listener {
|
||||
Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData());
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
if (!BlockStateUtils.isVanillaBlock(stateId)) {
|
||||
// custom blocks
|
||||
ImmutableBlockState immutableBlockState = this.manager.getImmutableBlockStateUnsafe(stateId);
|
||||
if (!immutableBlockState.isEmpty()) {
|
||||
Location location = block.getLocation();
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(block.getWorld());
|
||||
WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5);
|
||||
for (Item<?> item : immutableBlockState.getDrops(ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position)
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)), world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// override vanilla block loots
|
||||
this.plugin.vanillaLootManager().getBlockLoot(stateId).ifPresent(it -> {
|
||||
if (it.override()) {
|
||||
@@ -326,44 +280,6 @@ public class BlockEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onEntityExplode(EntityExplodeEvent event) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
if (!ExplosionUtils.isDroppingItems(event)) return;
|
||||
}
|
||||
handleExplodeEvent(event.blockList(), new BukkitWorld(event.getEntity().getWorld()), event.getYield());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBlockExplode(BlockExplodeEvent event) {
|
||||
if (VersionHelper.isOrAbove1_21()) {
|
||||
if (!ExplosionUtils.isDroppingItems(event)) return;
|
||||
}
|
||||
handleExplodeEvent(event.blockList(), new BukkitWorld(event.getBlock().getWorld()), event.getYield());
|
||||
}
|
||||
|
||||
private void handleExplodeEvent(List<org.bukkit.block.Block> blocks, net.momirealms.craftengine.core.world.World world, float yield) {
|
||||
for (int i = blocks.size() - 1; i >= 0; i--) {
|
||||
Block block = blocks.get(i);
|
||||
Location location = block.getLocation();
|
||||
BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
ImmutableBlockState state = this.manager.getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData()));
|
||||
if (state != null && !state.isEmpty()) {
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(blockPos));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position)
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block));
|
||||
if (yield < 1f) {
|
||||
builder.withParameter(DirectContextParameters.EXPLOSION_RADIUS, 1.0f / yield);
|
||||
}
|
||||
for (Item<Object> item : state.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
world.playBlockSound(position, state.sounds().breakSound());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBlockPhysics(BlockPhysicsEvent event) {
|
||||
if (!this.enableNoteBlockCheck) return;
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
public class BukkitCustomBlock extends AbstractCustomBlock {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
@@ -8,15 +7,12 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
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.WorldEvents;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavior {
|
||||
@@ -34,21 +30,15 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
if (!canSurvive(thisBlock, args, () -> true)) {
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (currentState != null && !currentState.isEmpty() && currentState.owner().value() == this.customBlock) {
|
||||
// break the crop
|
||||
FastNMS.INSTANCE.method$Level$removeBlock(level, blockPos, false);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(LocationUtils.fromBlockPos(blockPos)));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position);
|
||||
for (Item<Object> item : currentState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> {
|
||||
if (!customState.isEmpty() && customState.owner().value() == this.customBlock) {
|
||||
FastNMS.INSTANCE.method$Level$removeBlock(level, blockPos, false);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(LocationUtils.fromBlockPos(blockPos)));
|
||||
world.playBlockSound(position, customState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
}
|
||||
world.playBlockSound(position, currentState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,19 +59,11 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level;
|
||||
Object blockPos;
|
||||
Object level = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
Object state = args[0];
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
level = args[3];
|
||||
blockPos = args[4];
|
||||
}
|
||||
int stateId = BlockStateUtils.blockStateToId(state);
|
||||
ImmutableBlockState previousState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (previousState == null || previousState.isEmpty()) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
return state;
|
||||
}
|
||||
if (this.delay != 0) {
|
||||
@@ -90,15 +72,11 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio
|
||||
}
|
||||
if (!canSurvive(thisBlock, new Object[] {state, level, blockPos}, () -> true)) {
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position);
|
||||
for (Item<Object> item : previousState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
world.playBlockSound(position, previousState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId);
|
||||
world.playBlockSound(position, customState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return state;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
|
||||
@@ -96,9 +95,9 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
@Override
|
||||
public Object mirror(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
if (this.mirrorFunction != null) {
|
||||
int id = BlockStateUtils.blockStateToId(args[0]);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
return this.mirrorFunction.mirror(thisBlock, state, MirrorUtils.fromNMSMirror(args[1]));
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
|
||||
if (optionalCustomState.isEmpty()) return args[0];
|
||||
return this.mirrorFunction.mirror(thisBlock, optionalCustomState.get(), MirrorUtils.fromNMSMirror(args[1]));
|
||||
}
|
||||
return super.mirror(thisBlock, args, superMethod);
|
||||
}
|
||||
@@ -106,9 +105,9 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
@Override
|
||||
public Object rotate(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
if (this.rotateFunction != null) {
|
||||
int id = BlockStateUtils.blockStateToId(args[0]);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
return this.rotateFunction.rotate(thisBlock, state, RotationUtils.fromNMSRotation(args[1]));
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
|
||||
if (optionalCustomState.isEmpty()) return args[0];
|
||||
return this.rotateFunction.rotate(thisBlock, optionalCustomState.get(), RotationUtils.fromNMSRotation(args[1]));
|
||||
}
|
||||
return super.rotate(thisBlock, args, superMethod);
|
||||
}
|
||||
@@ -135,12 +134,12 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
Object blockState = args[pickupBlock$blockState];
|
||||
Object world = args[pickupBlock$world];
|
||||
Object pos = args[pickupBlock$pos];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState != null) {
|
||||
if (immutableBlockState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, pos, immutableBlockState.with(this.waterloggedProperty, false).customBlockState().handle(), 3);
|
||||
return FastNMS.INSTANCE.constructor$ItemStack(MItems.WATER_BUCKET, 1);
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return CoreReflections.instance$ItemStack$EMPTY;
|
||||
ImmutableBlockState immutableBlockState = optionalCustomState.get();
|
||||
if (immutableBlockState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, pos, immutableBlockState.with(this.waterloggedProperty, false).customBlockState().handle(), 3);
|
||||
return FastNMS.INSTANCE.constructor$ItemStack(MItems.WATER_BUCKET, 1);
|
||||
}
|
||||
return CoreReflections.instance$ItemStack$EMPTY;
|
||||
}
|
||||
@@ -149,14 +148,14 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
public boolean placeLiquid(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
if (this.waterloggedProperty == null) return false;
|
||||
Object blockState = args[2];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState != null) {
|
||||
Object fluidType = FastNMS.INSTANCE.method$FluidState$getType(args[3]);
|
||||
if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == MFluids.WATER) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3);
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[0], args[1], fluidType, 5);
|
||||
return true;
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return false;
|
||||
ImmutableBlockState immutableBlockState = optionalCustomState.get();
|
||||
Object fluidType = FastNMS.INSTANCE.method$FluidState$getType(args[3]);
|
||||
if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == MFluids.WATER) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3);
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[0], args[1], fluidType, 5);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -168,4 +167,9 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior {
|
||||
if (this.waterloggedProperty == null) return false;
|
||||
return args[canPlaceLiquid$liquid] == MFluids.WATER;
|
||||
}
|
||||
|
||||
protected static final int updateShape$level = VersionHelper.isOrAbove1_21_2() ? 1 : 3;
|
||||
protected static final int updateShape$blockPos = VersionHelper.isOrAbove1_21_2() ? 3 : 4;
|
||||
protected static final int updateShape$neighborState = VersionHelper.isOrAbove1_21_2() ? 6 : 2;
|
||||
protected static final int updateShape$direction = VersionHelper.isOrAbove1_21_2() ? 4 : 1;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockTags;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
@@ -85,29 +83,27 @@ public class BushBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
return mayPlaceOn(belowState, world, belowPos);
|
||||
}
|
||||
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) throws ReflectiveOperationException {
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) {
|
||||
for (Object tag : this.tagsCanSurviveOn) {
|
||||
if ((boolean) CoreReflections.method$BlockStateBase$hasTag.invoke(belowState, tag)) {
|
||||
if (FastNMS.INSTANCE.method$BlockStateBase$is(belowState, tag)) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
}
|
||||
int id = BlockStateUtils.blockStateToId(belowState);
|
||||
if (BlockStateUtils.isVanillaBlock(id)) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
if (!this.blockStatesCanSurviveOn.isEmpty() && this.blockStatesCanSurviveOn.contains(belowState)) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
} else {
|
||||
ImmutableBlockState belowCustomState = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
if (belowCustomState != null && !belowCustomState.isEmpty()) {
|
||||
if (belowCustomState.owner().value() == super.customBlock) {
|
||||
return this.stackable;
|
||||
}
|
||||
if (this.customBlocksCansSurviveOn.contains(belowCustomState.owner().value().id().toString())) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
if (this.customBlocksCansSurviveOn.contains(belowCustomState.toString())) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
ImmutableBlockState belowCustomState = optionalCustomState.get();
|
||||
if (belowCustomState.owner().value() == super.customBlock) {
|
||||
return this.stackable;
|
||||
}
|
||||
if (this.customBlocksCansSurviveOn.contains(belowCustomState.owner().value().id().toString())) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
if (this.customBlocksCansSurviveOn.contains(belowCustomState.toString())) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
}
|
||||
return this.blacklistMode;
|
||||
|
||||
@@ -16,7 +16,6 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.event.block.BlockFormEvent;
|
||||
|
||||
@@ -94,17 +93,11 @@ public class ConcretePowderBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level;
|
||||
Object pos;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
pos = args[3];
|
||||
} else {
|
||||
level = args[3];
|
||||
pos = args[4];
|
||||
}
|
||||
Object level = args[updateShape$level];
|
||||
Object pos = args[updateShape$blockPos];
|
||||
if (touchesLiquid(level, pos)) {
|
||||
if (!CoreReflections.clazz$Level.isInstance(level)) {
|
||||
return getDefaultBlockState();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
@@ -18,7 +17,6 @@ import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.SimpleContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
@@ -33,6 +31,7 @@ import org.bukkit.World;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
@@ -90,13 +89,12 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
Object level = args[1];
|
||||
Object pos = args[2];
|
||||
if (getRawBrightness(level, pos) >= this.minGrowLight) {
|
||||
ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (currentState != null && !currentState.isEmpty()) {
|
||||
int age = this.getAge(currentState);
|
||||
BlockStateUtils.getOptionalCustomBlockState(state).ifPresent(customState -> {
|
||||
int age = this.getAge(customState);
|
||||
if (age < this.ageProperty.max && RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, customState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,12 +114,8 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
public boolean isValidBoneMealTarget(Object thisBlock, Object[] args) {
|
||||
if (!this.isBoneMealTarget) return false;
|
||||
Object state = args[2];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (immutableBlockState != null && !immutableBlockState.isEmpty()) {
|
||||
return getAge(immutableBlockState) != this.ageProperty.max;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
return optionalState.filter(immutableBlockState -> getAge(immutableBlockState) != this.ageProperty.max).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,20 +131,15 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
if (isMaxAge(state))
|
||||
return InteractionResult.PASS;
|
||||
boolean sendSwing = false;
|
||||
try {
|
||||
Object visualState = state.vanillaBlockState().handle();
|
||||
Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState);
|
||||
if (!is) {
|
||||
sendSwing = true;
|
||||
}
|
||||
} else {
|
||||
Object visualState = state.vanillaBlockState().handle();
|
||||
Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState);
|
||||
if (!is) {
|
||||
sendSwing = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to check visual state bone meal state", e);
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
sendSwing = true;
|
||||
}
|
||||
if (sendSwing) {
|
||||
context.getPlayer().swingHand(context.getHand());
|
||||
@@ -158,14 +147,15 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
private void performBoneMeal(Object level, Object pos, Object state) throws InvocationTargetException, IllegalAccessException {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) {
|
||||
private void performBoneMeal(Object level, Object pos, Object state) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
boolean sendParticles = false;
|
||||
Object visualState = immutableBlockState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
Object visualState = customState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, pos, visualState);
|
||||
if (!is) {
|
||||
@@ -174,24 +164,21 @@ public class CropBlockBehavior extends BukkitBlockBehavior {
|
||||
} else {
|
||||
sendParticles = true;
|
||||
}
|
||||
|
||||
World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
int x = FastNMS.INSTANCE.field$Vec3i$x(pos);
|
||||
int y = FastNMS.INSTANCE.field$Vec3i$y(pos);
|
||||
int z = FastNMS.INSTANCE.field$Vec3i$z(pos);
|
||||
int i = this.getAge(immutableBlockState) + this.boneMealBonus.getInt(
|
||||
SimpleContext.of(
|
||||
ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, immutableBlockState)
|
||||
int i = this.getAge(customState) + this.boneMealBonus.getInt(
|
||||
SimpleContext.of(ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, customState)
|
||||
.withParameter(DirectContextParameters.POSITION, new WorldPosition(new BukkitWorld(world), Vec3d.atCenterOf(new Vec3i(x, y, z))))
|
||||
.build()
|
||||
)
|
||||
.build())
|
||||
);
|
||||
int maxAge = this.ageProperty.max;
|
||||
if (i > maxAge) {
|
||||
i = maxAge;
|
||||
}
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, customState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
if (sendParticles) {
|
||||
world.spawnParticle(ParticleUtils.HAPPY_VILLAGER, x + 0.5, y + 0.5, z + 0.5, 15, 0.25, 0.25, 0.25);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,8 @@ import net.momirealms.craftengine.core.block.state.properties.DoorHinge;
|
||||
import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
@@ -83,20 +80,15 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level;
|
||||
Object blockPos;
|
||||
Object level = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
Object blockState = args[0];
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
level = args[3];
|
||||
blockPos = args[4];
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
return blockState;
|
||||
}
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState;
|
||||
DoubleBlockHalf half = immutableBlockState.get(this.halfProperty);
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
DoubleBlockHalf half = customState.get(this.halfProperty);
|
||||
Object direction = VersionHelper.isOrAbove1_21_2() ? args[4] : args[1];
|
||||
if (DirectionUtils.isYAxis(direction) && half == DoubleBlockHalf.LOWER == (direction == CoreReflections.instance$Direction$UP)) {
|
||||
ImmutableBlockState neighborState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(VersionHelper.isOrAbove1_21_2() ? args[6] : args[2]));
|
||||
@@ -117,13 +109,8 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
world.playBlockSound(position, immutableBlockState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId);
|
||||
world.playBlockSound(position, customState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return blockState;
|
||||
@@ -234,7 +221,7 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
|
||||
public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) {
|
||||
if (!this.canOpenWithHand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
@@ -260,18 +247,19 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
Object blockPos = args[2];
|
||||
Object level = args[1];
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
Object anotherHalfPos = immutableBlockState.get(this.halfProperty) == DoubleBlockHalf.LOWER ? LocationUtils.above(blockPos) : LocationUtils.below(blockPos);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
Object anotherHalfPos = customState.get(this.halfProperty) == DoubleBlockHalf.LOWER ? LocationUtils.above(blockPos) : LocationUtils.below(blockPos);
|
||||
Block bukkitBlock = FastNMS.INSTANCE.method$CraftBlock$at(level, blockPos);
|
||||
Block anotherBukkitBlock = FastNMS.INSTANCE.method$CraftBlock$at(level, anotherHalfPos);
|
||||
int power = Math.max(bukkitBlock.getBlockPower(), anotherBukkitBlock.getBlockPower());
|
||||
int oldPower = immutableBlockState.get(this.poweredProperty) ? 15 : 0;
|
||||
int oldPower = customState.get(this.poweredProperty) ? 15 : 0;
|
||||
if (oldPower == 0 ^ power == 0) {
|
||||
BlockRedstoneEvent event = new BlockRedstoneEvent(bukkitBlock, oldPower, power);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
boolean flag = event.getNewCurrent() > 0;
|
||||
if (flag != immutableBlockState.get(this.openProperty)) {
|
||||
if (flag != customState.get(this.openProperty)) {
|
||||
org.bukkit.World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
world.sendGameEvent(null, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ()));
|
||||
SoundData soundData = flag ? this.openSound : this.closeSound;
|
||||
@@ -282,25 +270,24 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
);
|
||||
}
|
||||
}
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, flag).with(this.openProperty, flag).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, flag).with(this.openProperty, flag).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws Exception {
|
||||
ImmutableBlockState customBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (customBlockState == null || customBlockState.isEmpty()) return false;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
if (optionalCustomState.isEmpty()) return false;
|
||||
int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos);
|
||||
int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos) - 1;
|
||||
int z = FastNMS.INSTANCE.field$Vec3i$z(blockPos);
|
||||
Object belowPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z);
|
||||
Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, belowPos);
|
||||
if (customBlockState.get(this.halfProperty) == DoubleBlockHalf.UPPER) {
|
||||
ImmutableBlockState belowCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(belowState));
|
||||
if (belowCustomState == null || belowCustomState.isEmpty()) return false;
|
||||
return belowCustomState.owner().value() == super.customBlock;
|
||||
if (optionalCustomState.get().get(this.halfProperty) == DoubleBlockHalf.UPPER) {
|
||||
Optional<ImmutableBlockState> belowCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState);
|
||||
return belowCustomState.filter(immutableBlockState -> immutableBlockState.owner().value() == super.customBlock).isPresent();
|
||||
} else {
|
||||
return (boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke(
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(
|
||||
belowState, world, belowPos, CoreReflections.instance$Direction$UP,
|
||||
CoreReflections.instance$SupportType$FULL
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
@@ -41,15 +42,8 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object world;
|
||||
Object blockPos;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
world = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
world = args[3];
|
||||
blockPos = args[4];
|
||||
}
|
||||
Object world = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 2);
|
||||
return args[0];
|
||||
}
|
||||
@@ -88,21 +82,21 @@ public class FallingBlockBehavior extends BukkitBlockBehavior {
|
||||
boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity);
|
||||
if (cancelDrop) return;
|
||||
Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity);
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.FALLING_BLOCK, true)
|
||||
.withParameter(DirectContextParameters.POSITION, position);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
for (Item<Object> item : customState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity);
|
||||
boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT);
|
||||
if (!isSilent) {
|
||||
world.playBlockSound(position, immutableBlockState.sounds().destroySound());
|
||||
world.playBlockSound(position, customState.sounds().destroySound());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
@@ -93,14 +92,15 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object blockState = args[0];
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null || state.isEmpty()) return blockState;
|
||||
if (state.get(this.facingProperty).toDirection().clockWise().axis() != direction.axis()) {
|
||||
Direction direction = DirectionUtils.fromNMSDirection(args[updateShape$direction]);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return blockState;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
if (customState.get(this.facingProperty).toDirection().clockWise().axis() != direction.axis()) {
|
||||
return superMethod.call();
|
||||
}
|
||||
Object neighborState = VersionHelper.isOrAbove1_21_2() ? args[6] : args[2];
|
||||
Object level = VersionHelper.isOrAbove1_21_2() ? args[1] : args[3];
|
||||
Object neighborState = args[updateShape$neighborState];
|
||||
Object level = args[updateShape$level];
|
||||
BlockPos blockPos = LocationUtils.fromBlockPos(VersionHelper.isOrAbove1_21_2() ? args[3] : args[4]);
|
||||
Object relativeState = getBlockState(level, blockPos.relative(direction.opposite()));
|
||||
boolean neighborStateIsWall = this.isWall(neighborState);
|
||||
@@ -112,7 +112,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
if (relativeStateIsWall) {
|
||||
// TODO: 连接原版方块
|
||||
}
|
||||
return state.with(this.inWallProperty, flag).customBlockState().handle();
|
||||
return customState.with(this.inWallProperty, flag).customBlockState().handle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,19 +135,12 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) {
|
||||
public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) {
|
||||
if (!this.canOpenWithHand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
if (context.getItem() == null) {
|
||||
playerToggle(context, state);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!context.getPlayer().isSecondaryUseActive()) {
|
||||
playerToggle(context, state);
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
playerToggle(context, state);
|
||||
return InteractionResult.SUCCESS_AND_CANCEL;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -163,10 +156,10 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3];
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null || state.isEmpty()) return false;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return false;
|
||||
if (type == CoreReflections.instance$PathComputationType$LAND || type == CoreReflections.instance$PathComputationType$AIR) {
|
||||
return isOpen(state);
|
||||
return isOpen(optionalCustomState.get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -174,9 +167,9 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public void onExplosionHit(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
if (this.canOpenByWindCharge && FastNMS.INSTANCE.method$Explosion$canTriggerBlocks(args[3])) {
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0]));
|
||||
if (state == null || state.isEmpty()) return;
|
||||
this.toggle(state, new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
this.toggle(optionalCustomState.get(), new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,16 +177,17 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public void neighborChanged(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
boolean hasSignal = FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, blockPos);
|
||||
if (hasSignal == immutableBlockState.get(this.poweredProperty)) return;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
if (hasSignal == customState.get(this.poweredProperty)) return;
|
||||
|
||||
Block bblock = FastNMS.INSTANCE.method$CraftBlock$at(level, blockPos);
|
||||
int power = bblock.getBlockPower();
|
||||
int oldPower = isOpen(immutableBlockState) ? 15 : 0;
|
||||
int oldPower = isOpen(customState) ? 15 : 0;
|
||||
Object neighborBlock = args[3];
|
||||
|
||||
if (oldPower == 0 ^ power == 0 || FastNMS.INSTANCE.method$BlockStateBase$isSignalSource(FastNMS.INSTANCE.method$Block$defaultState(neighborBlock))) {
|
||||
@@ -203,7 +197,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
boolean changed = isOpen(immutableBlockState) != hasSignal;
|
||||
boolean changed = isOpen(customState) != hasSignal;
|
||||
if (hasSignal && changed) {
|
||||
Object abovePos = LocationUtils.above(blockPos);
|
||||
Object aboveBlockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, abovePos);
|
||||
@@ -220,7 +214,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
immutableBlockState = immutableBlockState.with(this.openProperty, hasSignal);
|
||||
customState = customState.with(this.openProperty, hasSignal);
|
||||
FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(null,
|
||||
hasSignal ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE,
|
||||
new Vector(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos), FastNMS.INSTANCE.field$Vec3i$z(blockPos))
|
||||
@@ -228,8 +222,9 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
this.playSound(LocationUtils.fromBlockPos(blockPos), world, hasSignal);
|
||||
}
|
||||
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
}
|
||||
|
||||
private void toggle(ImmutableBlockState state, World world, BlockPos pos, @Nullable Player player) {
|
||||
ImmutableBlockState newState;
|
||||
if (state.get(this.openProperty)) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
@@ -15,13 +14,13 @@ import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GrassBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
@@ -38,18 +37,19 @@ public class GrassBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) throws Exception {
|
||||
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) {
|
||||
if (!VersionHelper.isOrAbove1_20_2()) return true;
|
||||
Object level = args[0];
|
||||
Object blockPos = args[2];
|
||||
Object blockState = args[3];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
boolean sendParticles = false;
|
||||
Object visualState = immutableBlockState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
Object visualState = customState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, blockPos, visualState);
|
||||
if (!is) {
|
||||
@@ -80,20 +80,15 @@ public class GrassBlockBehavior extends BukkitBlockBehavior {
|
||||
if (!block.isEmpty())
|
||||
return InteractionResult.PASS;
|
||||
boolean sendSwing = false;
|
||||
try {
|
||||
Object visualState = state.vanillaBlockState().handle();
|
||||
Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState);
|
||||
if (!is) {
|
||||
sendSwing = true;
|
||||
}
|
||||
} else {
|
||||
Object visualState = state.vanillaBlockState().handle();
|
||||
Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState);
|
||||
if (!is) {
|
||||
sendSwing = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to check visual state bone meal state", e);
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
sendSwing = true;
|
||||
}
|
||||
if (sendSwing) {
|
||||
context.getPlayer().swingHand(context.getHand());
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class LampBlockBehavior extends BukkitBlockBehavior {
|
||||
@@ -34,20 +35,16 @@ public class LampBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public void tick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null || state.isEmpty()) return;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
Object world = args[1];
|
||||
Object blockPos = args[2];
|
||||
if (state.get(this.litProperty)) {
|
||||
if (!FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||
// TODO Call Event
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||
}
|
||||
} else {
|
||||
if (FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||
// TODO Call Event
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
if (customState.get(this.litProperty) && !FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||
if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) {
|
||||
return;
|
||||
}
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +60,9 @@ public class LampBlockBehavior extends BukkitBlockBehavior {
|
||||
if (lit) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 4);
|
||||
} else {
|
||||
// TODO Call Event
|
||||
if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) {
|
||||
return;
|
||||
}
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,18 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockTags;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
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.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
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.WorldPosition;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.block.LeavesDecayEvent;
|
||||
|
||||
@@ -113,16 +106,18 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Override
|
||||
public void randomTick(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = args[0];
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0]));
|
||||
if (immutableBlockState != null) {
|
||||
Optional<LeavesBlockBehavior> optionalBehavior = immutableBlockState.behavior().getAs(LeavesBlockBehavior.class);
|
||||
BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> {
|
||||
// 可能是另一种树叶
|
||||
Optional<LeavesBlockBehavior> optionalBehavior = customState.behavior().getAs(LeavesBlockBehavior.class);
|
||||
if (optionalBehavior.isPresent()) {
|
||||
LeavesBlockBehavior behavior = optionalBehavior.get();
|
||||
if (behavior.isDecaying(immutableBlockState)) {
|
||||
if (behavior.isDecaying(customState)) {
|
||||
World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
// call bukkit event
|
||||
@@ -132,19 +127,10 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
|
||||
return;
|
||||
}
|
||||
FastNMS.INSTANCE.method$Level$removeBlock(level, blockPos, false);
|
||||
if (isWaterLogged(immutableBlockState)) {
|
||||
bukkitWorld.setBlockData(pos.x(), pos.y(), pos.z(), Material.WATER.createBlockData());
|
||||
}
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(bukkitWorld);
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position);
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
FastNMS.INSTANCE.method$Block$dropResources(blockState, level, blockPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isDecaying(ImmutableBlockState blockState) {
|
||||
@@ -168,7 +154,7 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
private int getDistanceAt(Object blockState) throws ReflectiveOperationException {
|
||||
boolean isLog = (boolean) CoreReflections.method$BlockStateBase$hasTag.invoke(blockState, LOG_TAG);
|
||||
boolean isLog = FastNMS.INSTANCE.method$BlockStateBase$is(blockState, LOG_TAG);
|
||||
if (isLog) return 0;
|
||||
int id = BlockStateUtils.blockStateToId(blockState);
|
||||
if (BlockStateUtils.isVanillaBlock(id)) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
|
||||
@@ -16,6 +15,7 @@ import net.momirealms.craftengine.core.world.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
private static final List<Object> WATER = List.of(MFluids.WATER, MFluids.FLOWING_WATER);
|
||||
@@ -70,12 +70,9 @@ public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
if (this.stackable) {
|
||||
Object belowPos = FastNMS.INSTANCE.constructor$BlockPos(x, y - 1, z);
|
||||
Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, belowPos);
|
||||
int id = BlockStateUtils.blockStateToId(belowState);
|
||||
if (!BlockStateUtils.isVanillaBlock(id)) {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id);
|
||||
if (immutableBlockState.owner().value() == super.customBlock) {
|
||||
return true;
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalBelowCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState);
|
||||
if (optionalBelowCustomState.isPresent() && optionalBelowCustomState.get().owner().value() == super.customBlock) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (BlockPos pos : positions) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
|
||||
@@ -15,6 +14,7 @@ import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
@@ -59,12 +59,9 @@ public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) {
|
||||
if (this.stackable) {
|
||||
int id = BlockStateUtils.blockStateToId(belowState);
|
||||
if (!BlockStateUtils.isVanillaBlock(id)) {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id);
|
||||
if (immutableBlockState.owner().value() == super.customBlock) {
|
||||
return true;
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState);
|
||||
if (optionalCustomState.isPresent() && optionalCustomState.get().owner().value() == super.customBlock) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(world, belowPos);
|
||||
|
||||
@@ -16,9 +16,6 @@ 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.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.PressurePlateSensitivity;
|
||||
@@ -60,30 +57,20 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object level;
|
||||
Object blockPos;
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
level = args[3];
|
||||
blockPos = args[4];
|
||||
}
|
||||
Object level = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
if (direction == Direction.DOWN && !FastNMS.INSTANCE.method$BlockStateBase$canSurvive(state, level, blockPos)) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
ContextHolder.Builder builder = ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.POSITION, position);
|
||||
int stateId = BlockStateUtils.blockStateToId(state);
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return MBlocks.AIR$defaultState;
|
||||
for (Item<Object> item : immutableBlockState.getDrops(builder, world, null)) {
|
||||
world.dropItemNaturally(position, item);
|
||||
}
|
||||
world.playBlockSound(position, immutableBlockState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId);
|
||||
world.playBlockSound(position, customState.sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return state;
|
||||
@@ -205,9 +192,8 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
private int getSignalForState(Object state) {
|
||||
ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (blockState == null || blockState.isEmpty()) return 0;
|
||||
return blockState.get(this.poweredProperty) ? 15 : 0;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
return optionalCustomState.filter(immutableBlockState -> immutableBlockState.get(this.poweredProperty)).map(immutableBlockState -> 15).orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
@@ -14,6 +13,7 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
@@ -33,11 +33,11 @@ import java.util.concurrent.Callable;
|
||||
public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Key feature;
|
||||
private final Property<Integer> stageProperty;
|
||||
private final IntegerProperty stageProperty;
|
||||
private final double boneMealSuccessChance;
|
||||
private final float growSpeed;
|
||||
|
||||
public SaplingBlockBehavior(CustomBlock block, Key feature, Property<Integer> stageProperty, double boneMealSuccessChance, float growSpeed) {
|
||||
public SaplingBlockBehavior(CustomBlock block, Key feature, IntegerProperty stageProperty, double boneMealSuccessChance, float growSpeed) {
|
||||
super(block);
|
||||
this.feature = feature;
|
||||
this.stageProperty = stageProperty;
|
||||
@@ -55,17 +55,18 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
||||
Object blockPos = args[2];
|
||||
Object blockState = args[0];
|
||||
Object aboveBlockPos = LocationUtils.above(blockPos);
|
||||
if ((int) CoreReflections.method$LevelReader$getMaxLocalRawBrightness.invoke(world, aboveBlockPos) >= 9 && RandomUtils.generateRandomFloat(0, 1) < growSpeed) {
|
||||
if ((int) CoreReflections.method$LevelReader$getMaxLocalRawBrightness.invoke(world, aboveBlockPos) >= 9 && RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
increaseStage(world, blockPos, blockState, args[3]);
|
||||
}
|
||||
}
|
||||
|
||||
private void increaseStage(Object world, Object blockPos, Object blockState, Object randomSource) throws Exception {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
int currentStage = immutableBlockState.get(this.stageProperty);
|
||||
if (currentStage != this.stageProperty.possibleValues().get(this.stageProperty.possibleValues().size() - 1)) {
|
||||
ImmutableBlockState nextStage = immutableBlockState.cycle(this.stageProperty);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
int currentStage = customState.get(this.stageProperty);
|
||||
if (currentStage != this.stageProperty.max) {
|
||||
ImmutableBlockState nextStage = customState.cycle(this.stageProperty);
|
||||
World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(world);
|
||||
int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos);
|
||||
int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos);
|
||||
@@ -101,18 +102,19 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) throws Exception {
|
||||
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) {
|
||||
boolean success = RandomUtils.generateRandomDouble(0d, 1d) < this.boneMealSuccessChance;
|
||||
Object level = args[0];
|
||||
Object blockPos = args[2];
|
||||
Object blockState = args[3];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
boolean sendParticles = false;
|
||||
Object visualState = immutableBlockState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
Object visualState = customState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, blockPos, visualState);
|
||||
if (!is) {
|
||||
@@ -148,20 +150,15 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
||||
if (item == null || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode())
|
||||
return InteractionResult.PASS;
|
||||
boolean sendSwing = false;
|
||||
try {
|
||||
Object visualState = state.vanillaBlockState().handle();
|
||||
Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState);
|
||||
if (!is) {
|
||||
sendSwing = true;
|
||||
}
|
||||
} else {
|
||||
Object visualState = state.vanillaBlockState().handle();
|
||||
Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState);
|
||||
if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState);
|
||||
if (!is) {
|
||||
sendSwing = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to check visual state bone meal state", e);
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
sendSwing = true;
|
||||
}
|
||||
if (sendSwing) {
|
||||
context.getPlayer().swingHand(context.getHand());
|
||||
@@ -177,7 +174,7 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior {
|
||||
String feature = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("feature"), "warning.config.block.behavior.sapling.missing_feature");
|
||||
Property<Integer> stageProperty = (Property<Integer>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("stage"), "warning.config.block.behavior.sapling.missing_stage");
|
||||
double boneMealSuccessChance = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("bone-meal-success-chance", 0.45), "bone-meal-success-chance");
|
||||
return new SaplingBlockBehavior(block, Key.of(feature), stageProperty, boneMealSuccessChance,
|
||||
return new SaplingBlockBehavior(block, Key.of(feature), (IntegerProperty) stageProperty, boneMealSuccessChance,
|
||||
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("grow-speed", 1.0 / 7.0), "grow-speed"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
|
||||
@@ -81,26 +80,24 @@ public class SlabBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public boolean placeLiquid(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = args[2];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return false;
|
||||
return immutableBlockState.get(this.typeProperty) != SlabType.DOUBLE && super.placeLiquid(thisBlock, args, superMethod);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
return optionalCustomState.filter(state -> state.get(this.typeProperty) != SlabType.DOUBLE && super.placeLiquid(thisBlock, args, superMethod)).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = VersionHelper.isOrAbove1_20_2() ? args[3] : args[2];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return false;
|
||||
return immutableBlockState.get(this.typeProperty) != SlabType.DOUBLE && super.canPlaceLiquid(thisBlock, args, superMethod);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
return optionalCustomState.filter(state -> state.get(this.typeProperty) != SlabType.DOUBLE && super.canPlaceLiquid(thisBlock, args, superMethod)).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object blockState = args[0];
|
||||
if (super.waterloggedProperty == null) return blockState;
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState;
|
||||
if (immutableBlockState.get(super.waterloggedProperty)) {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return blockState;
|
||||
if (optionalCustomState.get().get(super.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5);
|
||||
}
|
||||
return blockState;
|
||||
@@ -110,10 +107,10 @@ public class SlabBlockBehavior extends BukkitBlockBehavior {
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3];
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null || state.isEmpty()) return false;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return false;
|
||||
if (type == CoreReflections.instance$PathComputationType$WATER) {
|
||||
return super.waterloggedProperty != null && state.get(this.typeProperty) != SlabType.DOUBLE && state.get(super.waterloggedProperty);
|
||||
return super.waterloggedProperty != null && optionalCustomState.get().get(this.typeProperty) != SlabType.DOUBLE && optionalCustomState.get().get(super.waterloggedProperty);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
@@ -54,127 +52,76 @@ public class StairsBlockBehavior extends BukkitBlockBehavior {
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object level;
|
||||
Object blockPos;
|
||||
Object level = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
Object blockState = args[0];
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
level = args[1];
|
||||
blockPos = args[3];
|
||||
} else {
|
||||
level = args[3];
|
||||
blockPos = args[4];
|
||||
}
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState;
|
||||
if (super.waterloggedProperty != null && immutableBlockState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return blockState;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
if (super.waterloggedProperty != null && customState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
}
|
||||
Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]);
|
||||
StairsShape stairsShape = getStairsShape(immutableBlockState, level, LocationUtils.fromBlockPos(blockPos));
|
||||
StairsShape stairsShape = getStairsShape(customState, level, LocationUtils.fromBlockPos(blockPos));
|
||||
return direction.axis().isHorizontal()
|
||||
? immutableBlockState.with(this.shapeProperty, stairsShape).customBlockState().handle()
|
||||
? customState.with(this.shapeProperty, stairsShape).customBlockState().handle()
|
||||
: superMethod.call();
|
||||
}
|
||||
|
||||
private StairsShape getStairsShape(ImmutableBlockState state, Object level, BlockPos pos) {
|
||||
Direction direction = state.get(this.facingProperty).toDirection();
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction)));
|
||||
int stateId = BlockStateUtils.blockStateToId(blockState);
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId);
|
||||
if (immutableBlockState != null && !immutableBlockState.isEmpty()) {
|
||||
if (isStairs(blockState) && state.get(this.halfProperty) == immutableBlockState.get(this.halfProperty)) {
|
||||
Direction direction1 = immutableBlockState.get(this.facingProperty).toDirection();
|
||||
if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1.opposite())) {
|
||||
if (direction1 == direction.counterClockWise()) {
|
||||
return StairsShape.OUTER_LEFT;
|
||||
Object relativeBlockState1 = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction)));
|
||||
Optional<ImmutableBlockState> optionalCustomState1 = BlockStateUtils.getOptionalCustomBlockState(relativeBlockState1);
|
||||
if (optionalCustomState1.isPresent()) {
|
||||
ImmutableBlockState customState1 = optionalCustomState1.get();
|
||||
Optional<StairsBlockBehavior> optionalStairsBlockBehavior = customState1.behavior().getAs(StairsBlockBehavior.class);
|
||||
if (optionalStairsBlockBehavior.isPresent()) {
|
||||
StairsBlockBehavior stairsBlockBehavior = optionalStairsBlockBehavior.get();
|
||||
if (state.get(this.halfProperty) == customState1.get(stairsBlockBehavior.halfProperty)) {
|
||||
Direction direction1 = customState1.get(stairsBlockBehavior.facingProperty).toDirection();
|
||||
if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1.opposite())) {
|
||||
if (direction1 == direction.counterClockWise()) {
|
||||
return StairsShape.OUTER_LEFT;
|
||||
}
|
||||
return StairsShape.OUTER_RIGHT;
|
||||
}
|
||||
return StairsShape.OUTER_RIGHT;
|
||||
}
|
||||
}
|
||||
} else if (isStairs(blockState)) {
|
||||
// 处理可能是原版楼梯
|
||||
// try {
|
||||
// Object nmsHalf = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$HALF);
|
||||
// SingleBlockHalf half = SingleBlockHalf.valueOf(nmsHalf.toString().toUpperCase(Locale.ROOT));
|
||||
// if (state.get(this.halfProperty).equals(half)) {
|
||||
// Object nmsFacing = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$FACING);
|
||||
// Direction direction1 = DirectionUtils.fromNMSDirection(nmsFacing);
|
||||
// if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1.opposite())) {
|
||||
// if (direction1 == direction.counterClockWise()) {
|
||||
// return StairsShape.OUTER_LEFT;
|
||||
// }
|
||||
// return StairsShape.OUTER_RIGHT;
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// CraftEngine.instance().logger().warn("Failed to get facing from blockState", e);
|
||||
// }
|
||||
}
|
||||
|
||||
Object blockState1 = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction.opposite())));
|
||||
int stateId1 = BlockStateUtils.blockStateToId(blockState1);
|
||||
ImmutableBlockState immutableBlockState1 = BukkitBlockManager.instance().getImmutableBlockState(stateId1);
|
||||
if (immutableBlockState1 != null && !immutableBlockState1.isEmpty()) {
|
||||
if (isStairs(blockState1) && state.get(this.halfProperty) == immutableBlockState1.get(this.halfProperty)) {
|
||||
Direction direction2 = immutableBlockState1.get(this.facingProperty).toDirection();
|
||||
if (direction2.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction2)) {
|
||||
if (direction2 == direction.counterClockWise()) {
|
||||
return StairsShape.INNER_LEFT;
|
||||
Object relativeBlockState2 = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction.opposite())));
|
||||
Optional<ImmutableBlockState> optionalCustomState2 = BlockStateUtils.getOptionalCustomBlockState(relativeBlockState2);
|
||||
if (optionalCustomState2.isPresent()) {
|
||||
ImmutableBlockState customState2 = optionalCustomState2.get();
|
||||
Optional<StairsBlockBehavior> optionalStairsBlockBehavior = customState2.behavior().getAs(StairsBlockBehavior.class);
|
||||
if (optionalStairsBlockBehavior.isPresent()) {
|
||||
StairsBlockBehavior stairsBlockBehavior = optionalStairsBlockBehavior.get();
|
||||
if (state.get(this.halfProperty) == customState2.get(stairsBlockBehavior.halfProperty)) {
|
||||
Direction direction2 = customState2.get(stairsBlockBehavior.facingProperty).toDirection();
|
||||
if (direction2.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction2)) {
|
||||
if (direction2 == direction.counterClockWise()) {
|
||||
return StairsShape.INNER_LEFT;
|
||||
}
|
||||
return StairsShape.INNER_RIGHT;
|
||||
}
|
||||
return StairsShape.INNER_RIGHT;
|
||||
}
|
||||
}
|
||||
} else if (isStairs(blockState1)) {
|
||||
// 处理可能是原版楼梯
|
||||
// try {
|
||||
// Object nmsHalf = CoreReflections.method$StateHolder$getValue.invoke(blockState1, CoreReflections.instance$StairBlock$HALF);
|
||||
// SingleBlockHalf half = SingleBlockHalf.valueOf(nmsHalf.toString().toUpperCase(Locale.ROOT));
|
||||
// if (state.get(this.halfProperty).equals(half)) {
|
||||
// Object nmsFacing = CoreReflections.method$StateHolder$getValue.invoke(blockState1, CoreReflections.instance$StairBlock$FACING);
|
||||
// Direction direction1 = DirectionUtils.fromNMSDirection(nmsFacing);
|
||||
// if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1)) {
|
||||
// if (direction1 == direction.counterClockWise()) {
|
||||
// return StairsShape.INNER_LEFT;
|
||||
// }
|
||||
// return StairsShape.INNER_RIGHT;
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// CraftEngine.instance().logger().warn("Failed to get facing from blockState", e);
|
||||
// }
|
||||
}
|
||||
|
||||
return StairsShape.STRAIGHT;
|
||||
}
|
||||
|
||||
private boolean isStairs(Object state) {
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) {
|
||||
return FastNMS.INSTANCE.method$BlockState$getBlock(state).equals(CoreReflections.clazz$StairBlock);
|
||||
}
|
||||
Optional<StairsBlockBehavior> optionalBehavior = immutableBlockState.behavior().getAs(StairsBlockBehavior.class);
|
||||
return optionalBehavior.isPresent();
|
||||
}
|
||||
|
||||
private boolean canTakeShape(ImmutableBlockState state, Object level, BlockPos pos, Direction face) {
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(face)));
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) {
|
||||
// 处理可能是原版楼梯
|
||||
// try {
|
||||
// Object nmsFacing = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$FACING);
|
||||
// Direction direction = DirectionUtils.fromNMSDirection(nmsFacing);
|
||||
// if (direction != state.get(this.facingProperty).toDirection()) return true;
|
||||
// Object nmsHalf = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$HALF);
|
||||
// SingleBlockHalf half = SingleBlockHalf.valueOf(nmsHalf.toString().toUpperCase(Locale.ROOT));
|
||||
// if (half != state.get(this.halfProperty)) return true;
|
||||
// } catch (Exception e) {
|
||||
// CraftEngine.instance().logger().warn("Failed to handle canTakeShape", e);
|
||||
// }
|
||||
return !isStairs(blockState);
|
||||
Optional<ImmutableBlockState> optionalAnotherState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalAnotherState.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return !isStairs(blockState) || immutableBlockState.get(this.facingProperty) != state.get(this.facingProperty) || immutableBlockState.get(this.halfProperty) != state.get(this.halfProperty);
|
||||
ImmutableBlockState anotherState = optionalAnotherState.get();
|
||||
Optional<StairsBlockBehavior> optionalBehavior = anotherState.behavior().getAs(StairsBlockBehavior.class);
|
||||
if (optionalBehavior.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
StairsBlockBehavior anotherBehavior = optionalBehavior.get();
|
||||
return anotherState.get(anotherBehavior.facingProperty) != state.get(this.facingProperty) || anotherState.get(anotherBehavior.halfProperty) != state.get(this.halfProperty);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
@@ -16,6 +15,7 @@ import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
@@ -56,9 +56,8 @@ public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
if (!this.stackable) {
|
||||
return false;
|
||||
}
|
||||
ImmutableBlockState targetCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (targetCustomState == null || targetCustomState.isEmpty()) return false;
|
||||
return targetCustomState.owner().value() == super.customBlock;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
return optionalCustomState.filter(immutableBlockState -> immutableBlockState.owner().value() == super.customBlock).isPresent();
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
@@ -75,10 +74,11 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = args[0];
|
||||
if (super.waterloggedProperty != null) {
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state != null && !state.isEmpty() && state.get(super.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5);
|
||||
}
|
||||
BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> {
|
||||
if (customState.get(super.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
}
|
||||
});
|
||||
}
|
||||
return blockState;
|
||||
}
|
||||
@@ -126,12 +126,12 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3];
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (state == null || state.isEmpty()) return false;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return false;
|
||||
if (type == CoreReflections.instance$PathComputationType$LAND || type == CoreReflections.instance$PathComputationType$AIR) {
|
||||
return state.get(this.openProperty);
|
||||
return optionalCustomState.get().get(this.openProperty);
|
||||
} else if (type == CoreReflections.instance$PathComputationType$WATER) {
|
||||
return state.get(super.waterloggedProperty);
|
||||
return optionalCustomState.get().get(super.waterloggedProperty);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -139,9 +139,9 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public void onExplosionHit(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
if (this.canOpenByWindCharge && FastNMS.INSTANCE.method$Explosion$canTriggerBlocks(args[3])) {
|
||||
ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0]));
|
||||
if (state == null || state.isEmpty()) return;
|
||||
this.toggle(state, new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null);
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
this.toggle(optionalCustomState.get(), new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,16 +149,17 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
@Override
|
||||
public void neighborChanged(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (immutableBlockState == null || immutableBlockState.isEmpty()) return;
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCustomState.isEmpty()) return;
|
||||
ImmutableBlockState customState = optionalCustomState.get();
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
boolean hasSignal = FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, blockPos);
|
||||
if (hasSignal == immutableBlockState.get(this.poweredProperty)) return;
|
||||
if (hasSignal == customState.get(this.poweredProperty)) return;
|
||||
|
||||
Block bblock = FastNMS.INSTANCE.method$CraftBlock$at(level, blockPos);
|
||||
int power = bblock.getBlockPower();
|
||||
int oldPower = immutableBlockState.get(this.openProperty) ? 15 : 0;
|
||||
int oldPower = customState.get(this.openProperty) ? 15 : 0;
|
||||
Object neighborBlock = args[3];
|
||||
|
||||
if (oldPower == 0 ^ power == 0 || FastNMS.INSTANCE.method$BlockStateBase$isSignalSource(FastNMS.INSTANCE.method$Block$defaultState(neighborBlock))) {
|
||||
@@ -168,7 +169,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
boolean changed = immutableBlockState.get(this.openProperty) != hasSignal;
|
||||
boolean changed = customState.get(this.openProperty) != hasSignal;
|
||||
if (hasSignal && changed) {
|
||||
Object abovePos = LocationUtils.above(blockPos);
|
||||
Object aboveBlockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, abovePos);
|
||||
@@ -185,7 +186,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
immutableBlockState = immutableBlockState.with(this.openProperty, hasSignal);
|
||||
customState = customState.with(this.openProperty, hasSignal);
|
||||
FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(null,
|
||||
hasSignal ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE,
|
||||
new Vector(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos), FastNMS.INSTANCE.field$Vec3i$z(blockPos))
|
||||
@@ -193,8 +194,8 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior {
|
||||
this.playSound(LocationUtils.fromBlockPos(blockPos), world, hasSignal);
|
||||
}
|
||||
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
if (this.waterloggedProperty != null && immutableBlockState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS);
|
||||
if (this.waterloggedProperty != null && customState.get(this.waterloggedProperty)) {
|
||||
FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(level, blockPos, MFluids.WATER, 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
@@ -19,6 +18,7 @@ import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class VerticalCropBlockBehavior extends BukkitBlockBehavior {
|
||||
@@ -42,26 +42,25 @@ public class VerticalCropBlockBehavior extends BukkitBlockBehavior {
|
||||
Object blockState = args[0];
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
Optional<ImmutableBlockState> optionalCurrentState = BlockStateUtils.getOptionalCustomBlockState(blockState);
|
||||
if (optionalCurrentState.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ImmutableBlockState currentState = optionalCurrentState.get();
|
||||
// above block is empty
|
||||
if (FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, (this.direction ? LocationUtils.above(blockPos) : LocationUtils.below(blockPos))) == MBlocks.AIR$defaultState) {
|
||||
int currentHeight = 1;
|
||||
BlockPos currentPos = LocationUtils.fromBlockPos(blockPos);
|
||||
ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (currentState != null && !currentState.isEmpty()) {
|
||||
while (true) {
|
||||
Object nextPos = LocationUtils.toBlockPos(currentPos.x(), this.direction ? currentPos.y() - currentHeight : currentPos.y() + currentHeight, currentPos.z());
|
||||
Object nextState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, nextPos);
|
||||
ImmutableBlockState belowImmutableState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(nextState));
|
||||
if (belowImmutableState != null && !belowImmutableState.isEmpty() && belowImmutableState.owner() == currentState.owner()) {
|
||||
currentHeight++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
while (true) {
|
||||
Object nextPos = LocationUtils.toBlockPos(currentPos.x(), this.direction ? currentPos.y() - currentHeight : currentPos.y() + currentHeight, currentPos.z());
|
||||
Object nextState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, nextPos);
|
||||
Optional<ImmutableBlockState> optionalBelowCustomState = BlockStateUtils.getOptionalCustomBlockState(nextState);
|
||||
if (optionalBelowCustomState.isPresent() && optionalBelowCustomState.get().owner().value() == super.customBlock) {
|
||||
currentHeight++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentHeight < this.maxHeight) {
|
||||
int age = currentState.get(ageProperty);
|
||||
if (age >= this.ageProperty.max || RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) {
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -2,8 +2,6 @@ package net.momirealms.craftengine.bukkit.entity.projectile;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||
import io.papermc.paper.event.player.PlayerStopUsingItemEvent;
|
||||
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.reflection.minecraft.CoreReflections;
|
||||
@@ -11,25 +9,24 @@ import net.momirealms.craftengine.bukkit.plugin.scheduler.impl.FoliaTask;
|
||||
import net.momirealms.craftengine.bukkit.util.ParticleUtils;
|
||||
import net.momirealms.craftengine.core.entity.projectile.ProjectileManager;
|
||||
import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta;
|
||||
import net.momirealms.craftengine.core.entity.projectile.ProjectileType;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.ThrowableProjectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.command.feature;
|
||||
|
||||
import com.saicone.rtag.RtagMirror;
|
||||
import com.saicone.rtag.item.ItemTagStream;
|
||||
import com.saicone.rtag.tag.TagCompound;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
|
||||
@@ -13,12 +13,23 @@ import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
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.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MItems;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MLootContextParams;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.BlockSettings;
|
||||
import net.momirealms.craftengine.core.block.CustomBlockStateHolder;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@@ -69,7 +80,37 @@ public final class BlockStateGenerator {
|
||||
ImmutableBlockState state = ((CustomBlockStateHolder) thisObj).customBlockState();
|
||||
if (state == null) return List.of();
|
||||
Object builder = args[0];
|
||||
return List.of(FastNMS.INSTANCE.constructor$ItemStack(MItems.WATER_BUCKET, 1));
|
||||
Object vec3 = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.ORIGIN);
|
||||
if (vec3 == null) return List.of();
|
||||
|
||||
Object tool = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.TOOL);
|
||||
|
||||
Item<ItemStack> item = BukkitItemManager.instance().wrap(tool == null || FastNMS.INSTANCE.method$ItemStack$isEmpty(tool) ? null : FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(tool));
|
||||
|
||||
// do not drop if it's not the correct tool
|
||||
BlockSettings settings = state.settings();
|
||||
if (settings.requireCorrectTool()) {
|
||||
if (tool == null) return List.of();
|
||||
if (!settings.isCorrectTool(item.id()) &&
|
||||
(!settings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(tool, state.customBlockState().handle()))) {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
Object serverLevel = FastNMS.INSTANCE.method$LootParams$Builder$getLevel(builder);
|
||||
World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(serverLevel));
|
||||
ContextHolder.Builder lootBuilder = new ContextHolder.Builder()
|
||||
.withParameter(DirectContextParameters.POSITION, new WorldPosition(world, FastNMS.INSTANCE.field$Vec3$x(vec3), FastNMS.INSTANCE.field$Vec3$y(vec3), FastNMS.INSTANCE.field$Vec3$z(vec3)));
|
||||
if (item != null) {
|
||||
lootBuilder.withParameter(DirectContextParameters.ITEM_IN_HAND, item);
|
||||
}
|
||||
Object optionalPlayer = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.THIS_ENTITY);
|
||||
BukkitServerPlayer player = optionalPlayer != null ? BukkitCraftEngine.instance().adapt(FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(optionalPlayer)) : null;
|
||||
Float radius = (Float) FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.EXPLOSION_RADIUS);
|
||||
if (radius != null) {
|
||||
lootBuilder.withParameter(DirectContextParameters.EXPLOSION_RADIUS, radius);
|
||||
}
|
||||
return state.getDrops(lootBuilder, world, player).stream().map(Item::getLiteralObject).toList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1691,10 +1691,6 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getInstanceDeclaredField(clazz$Entity, double.class, 2)
|
||||
);
|
||||
|
||||
public static final Method method$BlockStateBase$hasTag = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$BlockStateBase, boolean.class, clazz$TagKey)
|
||||
);
|
||||
|
||||
public static final Method method$Level$removeBlock = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$Level, boolean.class, clazz$BlockPos, boolean.class)
|
||||
);
|
||||
@@ -2492,10 +2488,6 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getDeclaredField(clazz$BlockInWorld, clazz$BlockState, 0)
|
||||
);
|
||||
|
||||
public static final Method method$BlockStateBase$getBlock = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$BlockStateBase, clazz$Block)
|
||||
);
|
||||
|
||||
public static final Method method$BlockBehaviour$getDescriptionId = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_2()
|
||||
? ReflectionUtils.getMethod(clazz$BlockBehaviour, String.class)
|
||||
@@ -3545,5 +3537,10 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getMethod(clazz$BlockStateBase, List.class, clazz$LootParams$Builder)
|
||||
);
|
||||
|
||||
|
||||
public static final Class<?> clazz$LootContextParams = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.storage.loot.parameters.LootContextParameters",
|
||||
"world.level.storage.loot.parameters.LootContextParams"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class MLootContextParams {
|
||||
public static final Object THIS_ENTITY;
|
||||
public static final Object ORIGIN;
|
||||
public static final Object TOOL;
|
||||
public static final Object EXPLOSION_RADIUS;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object params$THIS_ENTITY = null;
|
||||
Object params$ORIGIN = null;
|
||||
Object params$TOOL = null;
|
||||
Object params$EXPLOSION_RADIUS = null;
|
||||
Field[] fields = CoreReflections.clazz$LootContextParams.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
Type fieldType = field.getGenericType();
|
||||
if (fieldType instanceof ParameterizedType paramType) {
|
||||
Type type = paramType.getActualTypeArguments()[0];
|
||||
if (type == CoreReflections.clazz$Entity && params$THIS_ENTITY == null) {
|
||||
params$THIS_ENTITY = field.get(null);
|
||||
} else if (type == CoreReflections.clazz$ItemStack) {
|
||||
params$TOOL = field.get(null);
|
||||
} else if (type == CoreReflections.clazz$Vec3) {
|
||||
params$ORIGIN = field.get(null);
|
||||
} else if (type == Float.class) {
|
||||
params$EXPLOSION_RADIUS = field.get(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
THIS_ENTITY = requireNonNull(params$THIS_ENTITY);
|
||||
TOOL = requireNonNull(params$TOOL);
|
||||
ORIGIN = requireNonNull(params$ORIGIN);
|
||||
EXPLOSION_RADIUS = requireNonNull(params$EXPLOSION_RADIUS);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ReflectionInitException("Failed to init LootContextParams", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ 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.network.BukkitNetworkManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.payload.DiscardedPayload;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders;
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.BlockSettings;
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.block.CustomBlockStateHolder;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Instrument;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MapColor;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -138,6 +132,14 @@ public class BlockStateUtils {
|
||||
return vanillaStateSize;
|
||||
}
|
||||
|
||||
public static Optional<ImmutableBlockState> getOptionalCustomBlockState(Object state) {
|
||||
if (state instanceof CustomBlockStateHolder holder) {
|
||||
return Optional.ofNullable(holder.customBlockState());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBurnable(Object state) {
|
||||
Object blockOwner = getBlockOwner(state);
|
||||
return IGNITE_ODDS.getOrDefault(blockOwner, 0) > 0;
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
Reference in New Issue
Block a user