mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-23 17:09:19 +00:00
feat(block): 添加草方块行为
This commit is contained in:
@@ -16,6 +16,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key CONCRETE_POWDER_BLOCK = Key.from("craftengine:concrete_powder_block");
|
||||
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 void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -30,5 +31,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(CONCRETE_POWDER_BLOCK, ConcretePowderBlockBehavior.FACTORY);
|
||||
register(SUGARCANE_BLOCK, SugarCaneBlockBehavior.FACTORY);
|
||||
register(CROP_BLOCK, CropBlockBehavior.FACTORY);
|
||||
register(GRASS_BLOCK, GrassBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
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.ParticleUtils;
|
||||
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.util.VersionHelper;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GrassBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public GrassBlockBehavior(CustomBlock block) {
|
||||
super(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidBoneMealTarget(Object thisBlock, Object[] args) {
|
||||
return FastNMS.INSTANCE.method$GrassBlock$isValidBonemealTarget(args[0], args[1], args[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoneMealSuccess(Object thisBlock, Object[] args) throws Exception {
|
||||
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()) {
|
||||
return false;
|
||||
}
|
||||
boolean sendParticles = false;
|
||||
Object visualState = immutableBlockState.vanillaBlockState().handle();
|
||||
Object visualStateBlock = Reflections.method$BlockStateBase$getBlock.invoke(visualState);
|
||||
if (Reflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) {
|
||||
boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, blockPos, visualState);
|
||||
if (!is) {
|
||||
sendParticles = true;
|
||||
}
|
||||
} else {
|
||||
sendParticles = true;
|
||||
}
|
||||
if (sendParticles) {
|
||||
World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level);
|
||||
int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos);
|
||||
int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos);
|
||||
int z = FastNMS.INSTANCE.field$Vec3i$z(blockPos);
|
||||
world.spawnParticle(ParticleUtils.getParticle("HAPPY_VILLAGER"), x + 0.5, y + 1.5, z + 0.5, 20, 2, 0, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performBoneMeal(Object thisBlock, Object[] args) {
|
||||
FastNMS.INSTANCE.method$GrassBlock$performBoneMeal(args[0], args[1], args[2], args[3], thisBlock);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
return new GrassBlockBehavior(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.CropBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.GrassBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.SaplingBlockBehavior;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
@@ -43,6 +44,10 @@ public class BoneMealItemBehavior extends ItemBehavior {
|
||||
}
|
||||
} else if (state.behavior() instanceof SaplingBlockBehavior) {
|
||||
shouldHandle = true;
|
||||
} else if (state.behavior() instanceof GrassBlockBehavior) {
|
||||
if (block.getLocation().add(0, 1, 0).getBlock().isEmpty()) {
|
||||
shouldHandle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldHandle) return InteractionResult.PASS;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Particle;
|
||||
|
||||
public class ParticleUtils {
|
||||
@@ -10,7 +11,7 @@ public class ParticleUtils {
|
||||
} catch (IllegalArgumentException e) {
|
||||
return switch (particle) {
|
||||
case "REDSTONE" -> Particle.valueOf("DUST");
|
||||
case "VILLAGER_HAPPY" -> Particle.valueOf("HAPPY_VILLAGER");
|
||||
case "VILLAGER_HAPPY" -> Particle.valueOf(VersionHelper.isOrAbove1_20_5() ? "HAPPY_VILLAGER" : "VILLAGER_HAPPY");
|
||||
default -> Particle.valueOf(particle);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ public class Reflections {
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$HolderLookup$Provider = BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"core.HolderLookup$b",
|
||||
VersionHelper.isOrAbove1_20_5() ? "core.HolderLookup$a" : "core.HolderLookup$b",
|
||||
"core.HolderLookup$Provider"
|
||||
);
|
||||
|
||||
@@ -2076,6 +2076,12 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$PlacedFeature = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.levelgen.placement.PlacedFeature")
|
||||
)
|
||||
);
|
||||
|
||||
// 1.21+
|
||||
public static final Class<?> clazz$JukeboxSong =
|
||||
ReflectionUtils.getClazz(
|
||||
@@ -2092,6 +2098,7 @@ public class Reflections {
|
||||
public static final Object instance$BuiltInRegistries$ENTITY_TYPE;
|
||||
public static final Object instance$BuiltInRegistries$FLUID;
|
||||
public static final Object instance$BuiltInRegistries$RECIPE_TYPE;
|
||||
public static final Object instance$BuiltInRegistries$PLACED_FEATURE;
|
||||
public static final Object instance$InternalRegistries$DIMENSION_TYPE;
|
||||
@Nullable // 1.21+
|
||||
public static final Object instance$InternalRegistries$JUKEBOX_SONG;
|
||||
@@ -2108,6 +2115,7 @@ public class Reflections {
|
||||
public static final Object instance$Registries$RECIPE_TYPE;
|
||||
public static final Object instance$Registries$DIMENSION_TYPE;
|
||||
public static final Object instance$Registries$CONFIGURED_FEATURE;
|
||||
public static final Object instance$Registries$PLACED_FEATURE;
|
||||
@Nullable // 1.21+
|
||||
public static final Object instance$Registries$JUKEBOX_SONG;
|
||||
|
||||
@@ -2128,6 +2136,7 @@ public class Reflections {
|
||||
Object registries$Fluid = null;
|
||||
Object registries$RecipeType = null;
|
||||
Object registries$ConfiguredFeature = null;
|
||||
Object registries$PlacedFeature = null;
|
||||
Object registries$JukeboxSong = null;
|
||||
for (Field field : fields) {
|
||||
Type fieldType = field.getGenericType();
|
||||
@@ -2166,6 +2175,8 @@ public class Reflections {
|
||||
registries$Fluid = field.get(null);
|
||||
} else if (VersionHelper.isOrAbove1_21() && type == clazz$JukeboxSong) {
|
||||
registries$JukeboxSong = field.get(null);
|
||||
} else if (type == clazz$PlacedFeature) {
|
||||
registries$PlacedFeature = field.get(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2184,6 +2195,7 @@ public class Reflections {
|
||||
instance$Registries$FLUID = requireNonNull(registries$Fluid);
|
||||
instance$Registries$RECIPE_TYPE = requireNonNull(registries$RecipeType);
|
||||
instance$Registries$CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature);
|
||||
instance$Registries$PLACED_FEATURE = requireNonNull(registries$PlacedFeature);
|
||||
instance$Registries$JUKEBOX_SONG = registries$JukeboxSong;
|
||||
Object server = method$MinecraftServer$getServer.invoke(null);
|
||||
Object registries = field$MinecraftServer$registries.get(server);
|
||||
@@ -2199,6 +2211,7 @@ public class Reflections {
|
||||
instance$BuiltInRegistries$ENTITY_TYPE = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$EntityType);
|
||||
instance$BuiltInRegistries$FLUID = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$Fluid);
|
||||
instance$BuiltInRegistries$RECIPE_TYPE = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$RecipeType);
|
||||
instance$BuiltInRegistries$PLACED_FEATURE = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$PlacedFeature);
|
||||
if (registries$JukeboxSong == null) instance$InternalRegistries$JUKEBOX_SONG = null;
|
||||
else instance$InternalRegistries$JUKEBOX_SONG = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$JukeboxSong);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
@@ -3587,6 +3600,8 @@ public class Reflections {
|
||||
public static final Object instance$Blocks$FIRE;
|
||||
public static final Object instance$Blocks$SOUL_FIRE;
|
||||
public static final Object instance$Blocks$ICE;
|
||||
public static final Object instance$Blocks$SHORT_GRASS;
|
||||
public static final Object instance$Blocks$SHORT_GRASS$defaultState;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -3602,6 +3617,9 @@ public class Reflections {
|
||||
instance$Blocks$STONE$defaultState = method$Block$defaultBlockState.invoke(instance$Blocks$STONE);
|
||||
Object ice = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", "ice");
|
||||
instance$Blocks$ICE = method$Registry$get.invoke(instance$BuiltInRegistries$BLOCK, ice);
|
||||
Object shortGrass = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||
instance$Blocks$SHORT_GRASS = method$Registry$get.invoke(instance$BuiltInRegistries$BLOCK, shortGrass);
|
||||
instance$Blocks$SHORT_GRASS$defaultState = method$Block$defaultBlockState.invoke(instance$Blocks$SHORT_GRASS);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.4
|
||||
anti_grief_version=0.15
|
||||
nms_helper_version=0.62
|
||||
nms_helper_version=0.64
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.31.23
|
||||
amazon_awssdk_eventstream_version=1.0.1
|
||||
|
||||
Reference in New Issue
Block a user