mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-31 04:46:37 +00:00
红石基础
This commit is contained in:
@@ -17,6 +17,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key SUGARCANE_BLOCK = Key.from("craftengine:sugar_cane_block");
|
||||
public static final Key CROP_BLOCK = Key.from("craftengine:crop_block");
|
||||
public static final Key GRASS_BLOCK = Key.from("craftengine:grass_block");
|
||||
public static final Key LAMP_BLOCK = Key.from("craftengine:lamp_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -32,5 +33,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(SUGARCANE_BLOCK, SugarCaneBlockBehavior.FACTORY);
|
||||
register(CROP_BLOCK, CropBlockBehavior.FACTORY);
|
||||
register(GRASS_BLOCK, GrassBlockBehavior.FACTORY);
|
||||
register(LAMP_BLOCK, LampBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
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.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
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.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class LampBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Property<Boolean> litProperty;
|
||||
|
||||
public LampBlockBehavior(CustomBlock block, Property<Boolean> litProperty) {
|
||||
super(block);
|
||||
this.litProperty = litProperty;
|
||||
}
|
||||
|
||||
@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;
|
||||
Object world = args[1];
|
||||
Object blockPos = args[2];
|
||||
if (state.get(this.litProperty) && !FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||
// TODO Call Event
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void neighborChanged(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;
|
||||
Object world = args[1];
|
||||
Object blockPos = args[2];
|
||||
boolean lit = state.get(this.litProperty);
|
||||
if (lit != FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) {
|
||||
if (lit) {
|
||||
Reflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 4);
|
||||
} else {
|
||||
// TODO Call Event
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Property<Boolean> lit = (Property<Boolean>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("lit"), "warning.config.block.behavior.lamp.missing_lit");
|
||||
return new LampBlockBehavior(block, lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import org.bukkit.event.block.LeavesDecayEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
@@ -78,10 +79,14 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
neighborState = args[2];
|
||||
}
|
||||
ImmutableBlockState thisState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (thisState != null && thisState.behavior() instanceof LeavesBlockBehavior behavior) {
|
||||
int distance = behavior.getDistanceAt(neighborState) + 1;
|
||||
if (distance != 1 || behavior.getDistance(thisState) != distance) {
|
||||
Reflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 1);
|
||||
if (thisState != null) {
|
||||
Optional<LeavesBlockBehavior> optionalBehavior = thisState.behavior().getAs(LeavesBlockBehavior.class);
|
||||
if (optionalBehavior.isPresent()) {
|
||||
LeavesBlockBehavior behavior = optionalBehavior.get();
|
||||
int distance = behavior.getDistanceAt(neighborState) + 1;
|
||||
if (distance != 1 || behavior.getDistance(thisState) != distance) {
|
||||
Reflections.method$LevelAccessor$scheduleTick.invoke(world, blockPos, thisBlock, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return blockState;
|
||||
@@ -93,13 +98,17 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
|
||||
if (currentState != null && !currentState.isEmpty() && currentState.behavior() instanceof LeavesBlockBehavior behavior) {
|
||||
ImmutableBlockState newState = behavior.updateDistance(currentState, level, blockPos);
|
||||
if (newState != currentState) {
|
||||
if (blockState == newState.customBlockState().handle()) {
|
||||
Reflections.method$BlockStateBase$updateNeighbourShapes.invoke(blockState, level, blockPos, UpdateOption.UPDATE_ALL.flags(), 512);
|
||||
} else {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, newState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
if (currentState != null && !currentState.isEmpty()) {
|
||||
Optional<LeavesBlockBehavior> optionalBehavior = currentState.behavior().getAs(LeavesBlockBehavior.class);
|
||||
if (optionalBehavior.isPresent()) {
|
||||
LeavesBlockBehavior behavior = optionalBehavior.get();
|
||||
ImmutableBlockState newState = behavior.updateDistance(currentState, level, blockPos);
|
||||
if (newState != currentState) {
|
||||
if (blockState == newState.customBlockState().handle()) {
|
||||
Reflections.method$BlockStateBase$updateNeighbourShapes.invoke(blockState, level, blockPos, UpdateOption.UPDATE_ALL.flags(), 512);
|
||||
} else {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, newState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,25 +119,31 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
Object level = args[1];
|
||||
Object blockPos = args[2];
|
||||
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0]));
|
||||
if (immutableBlockState != null && immutableBlockState.behavior() instanceof LeavesBlockBehavior behavior && behavior.isDecaying(immutableBlockState)) {
|
||||
World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
// call bukkit event
|
||||
LeavesDecayEvent event = new LeavesDecayEvent(bukkitWorld.getBlockAt(pos.x(), pos.y(), pos.z()));
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
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);
|
||||
if (immutableBlockState != null) {
|
||||
Optional<LeavesBlockBehavior> optionalBehavior = immutableBlockState.behavior().getAs(LeavesBlockBehavior.class);
|
||||
if (optionalBehavior.isPresent()) {
|
||||
LeavesBlockBehavior behavior = optionalBehavior.get();
|
||||
if (behavior.isDecaying(immutableBlockState)) {
|
||||
World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
// call bukkit event
|
||||
LeavesDecayEvent event = new LeavesDecayEvent(bukkitWorld.getBlockAt(pos.x(), pos.y(), pos.z()));
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,8 +179,8 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior {
|
||||
return (int) Reflections.method$StateHolder$getValue.invoke(blockState, distanceProperty);
|
||||
} else {
|
||||
ImmutableBlockState anotherBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id);
|
||||
if (!(anotherBlockState.behavior() instanceof LeavesBlockBehavior otherBehavior)) return this.maxDistance;
|
||||
return otherBehavior.getDistance(anotherBlockState);
|
||||
Optional<LeavesBlockBehavior> optionalAnotherBehavior = anotherBlockState.behavior().getAs(LeavesBlockBehavior.class);
|
||||
return optionalAnotherBehavior.map(leavesBlockBehavior -> leavesBlockBehavior.getDistance(anotherBlockState)).orElse(this.maxDistance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,6 +318,9 @@ public class BukkitInjector {
|
||||
.and(ElementMatchers.takesArgument(1, Reflections.clazz$LevelReader).or(ElementMatchers.takesArgument(1, Reflections.clazz$Direction)))
|
||||
.and(ElementMatchers.named("updateShape").or(ElementMatchers.named("a"))))
|
||||
.intercept(MethodDelegation.to(UpdateShapeInterceptor.INSTANCE))
|
||||
// neighborChanged
|
||||
.method(ElementMatchers.is(Reflections.method$BlockBehaviour$neighborChanged))
|
||||
.intercept(MethodDelegation.to(NeighborChangedInterceptor.INSTANCE))
|
||||
// // getFluidState
|
||||
// .method(ElementMatchers.returns(Reflections.clazz$FluidState)
|
||||
// .and(ElementMatchers.takesArgument(0, Reflections.clazz$BlockState)))
|
||||
@@ -1078,6 +1081,20 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class NeighborChangedInterceptor {
|
||||
public static final NeighborChangedInterceptor INSTANCE = new NeighborChangedInterceptor();
|
||||
|
||||
@RuntimeType
|
||||
public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable<Object> superMethod) {
|
||||
ObjectHolder<BlockBehavior> holder = ((BehaviorHolder) thisObj).getBehaviorHolder();
|
||||
try {
|
||||
holder.value().neighborChanged(thisObj, args, superMethod);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().severe("Failed to run neighborChanged", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// public static class PickUpBlockInterceptor {
|
||||
// public static final PickUpBlockInterceptor INSTANCE = new PickUpBlockInterceptor();
|
||||
|
||||
@@ -6791,4 +6791,16 @@ public class Reflections {
|
||||
}
|
||||
}
|
||||
|
||||
public static final Class<?> clazz$Orientation =
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.redstone.Orientation",
|
||||
"world.level.redstone.Orientation"
|
||||
);
|
||||
|
||||
public static final Method method$BlockBehaviour$neighborChanged = requireNonNull(
|
||||
VersionHelper.isOrAbove1_21_2() ?
|
||||
ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$Level, clazz$BlockPos, clazz$Block, clazz$Orientation, boolean.class) :
|
||||
Optional.ofNullable(ReflectionUtils.getDeclaredMethod(clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$Level, clazz$BlockPos, clazz$Block, clazz$BlockPos, boolean.class))
|
||||
.orElse(ReflectionUtils.getMethod(clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$Level, clazz$BlockPos, clazz$Block, clazz$BlockPos, boolean.class))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ParticleUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.SoundUtils;
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
@@ -15,7 +18,6 @@ import net.momirealms.craftengine.core.world.WorldHeight;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleData;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
|
||||
Reference in New Issue
Block a user