mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-04 15:41:38 +00:00
优化粒子行为实现
This commit is contained in:
@@ -34,7 +34,8 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key BOUNCING_BLOCK = Key.from("craftengine:bouncing_block");
|
||||
public static final Key DIRECTIONAL_ATTACHED_BLOCK = Key.from("craftengine:directional_attached_block");
|
||||
public static final Key LIQUID_FLOWABLE_BLOCK = Key.from("craftengine:liquid_flowable_block");
|
||||
public static final Key PARTICLE_BLOCK = Key.from("craftengine:particle_block");
|
||||
public static final Key SIMPLE_PARTICLE_BLOCK = Key.from("craftengine:simple_particle_block");
|
||||
public static final Key WALL_TORCH_PARTICLE_BLOCK = Key.from("craftengine:wall_torch_particle_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -67,6 +68,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(BOUNCING_BLOCK, BouncingBlockBehavior.FACTORY);
|
||||
register(DIRECTIONAL_ATTACHED_BLOCK, DirectionalAttachedBlockBehavior.FACTORY);
|
||||
register(LIQUID_FLOWABLE_BLOCK, LiquidFlowableBlockBehavior.FACTORY);
|
||||
register(PARTICLE_BLOCK, ParticleBlockBehavior.FACTORY);
|
||||
register(SIMPLE_PARTICLE_BLOCK, SimpleParticleBlockBehavior.FACTORY);
|
||||
register(WALL_TORCH_PARTICLE_BLOCK, WallTorchParticleBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.BaseParticleBlockEntity;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.ParticleBlockEntity;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.WallParticleBlockEntity;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ParticleBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final List<ParticleData> particles;
|
||||
private final boolean inWall;
|
||||
|
||||
public ParticleBlockBehavior(CustomBlock customBlock, List<ParticleData> particles, boolean inWall) {
|
||||
super(customBlock);
|
||||
this.particles = particles;
|
||||
this.inWall = inWall;
|
||||
}
|
||||
|
||||
public List<ParticleData> particles() {
|
||||
return particles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
||||
return EntityBlockBehavior.blockEntityTypeHelper(this.inWall ? BukkitBlockEntityTypes.WALL_PARTICLE : BukkitBlockEntityTypes.PARTICLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
||||
return this.inWall ? new WallParticleBlockEntity(pos, state) : new ParticleBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType<T> blockEntityType) {
|
||||
if (this.particles().isEmpty()) return null;
|
||||
return EntityBlockBehavior.createTickerHelper(BaseParticleBlockEntity::tick);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<ParticleData> particles = ResourceConfigUtils.parseConfigAsList(arguments.getOrDefault("particles", List.of()), ParticleData::fromMap);
|
||||
boolean inWall = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("in-wall", false), "in-wall");
|
||||
return new ParticleBlockBehavior(block, particles, inWall);
|
||||
}
|
||||
}
|
||||
|
||||
public record ParticleData(Key particle, Vec3d locationOffset, Vec3d offset, int count, double speed) {
|
||||
|
||||
public static ParticleData fromMap(Map<String, Object> arguments) {
|
||||
Key particle = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("type"), "warning.config.block.behavior.particle.missing_type"));
|
||||
Vec3d locationOffset = ResourceConfigUtils.getAsVec3d(arguments.get("location-offset"), "location-offset");
|
||||
Vec3d offset = ResourceConfigUtils.getAsVec3d(arguments.get("offset"), "offset");
|
||||
int count = ResourceConfigUtils.getAsInt(arguments.getOrDefault("count", 1), "count");
|
||||
double speed = ResourceConfigUtils.getAsDouble(arguments.get("speed"), "speed");
|
||||
return new ParticleData(particle, locationOffset, offset, count, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.SimpleParticleBlockEntity;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleParticleBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public final ParticleConfig[] particles;
|
||||
public final int tickInterval;
|
||||
|
||||
public SimpleParticleBlockBehavior(CustomBlock customBlock, ParticleConfig[] particles, int tickInterval) {
|
||||
super(customBlock);
|
||||
this.particles = particles;
|
||||
this.tickInterval = tickInterval;
|
||||
}
|
||||
|
||||
public ParticleConfig[] particles() {
|
||||
return this.particles;
|
||||
}
|
||||
|
||||
public int tickInterval() {
|
||||
return tickInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
||||
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SIMPLE_PARTICLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
||||
return new SimpleParticleBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType<T> blockEntityType) {
|
||||
if (this.particles.length == 0) return null;
|
||||
return EntityBlockBehavior.createTickerHelper(SimpleParticleBlockEntity::tick);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<ParticleConfig> particles = ResourceConfigUtils.parseConfigAsList(ResourceConfigUtils.get(arguments, "particles", "particle"), ParticleConfig::fromMap$blockEntity);
|
||||
int tickInterval = ResourceConfigUtils.getAsInt(arguments.getOrDefault("tick-interval", 10), "tick-interval");
|
||||
return new SimpleParticleBlockBehavior(block, particles.toArray(new ParticleConfig[0]), tickInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.WallTorchParticleBlockEntity;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class WallTorchParticleBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public final ParticleConfig[] particles;
|
||||
public final int tickInterval;
|
||||
public final Property<HorizontalDirection> facingProperty;
|
||||
|
||||
public WallTorchParticleBlockBehavior(CustomBlock customBlock, ParticleConfig[] particles, int tickInterval, Property<HorizontalDirection> facingProperty) {
|
||||
super(customBlock);
|
||||
this.particles = particles;
|
||||
this.tickInterval = tickInterval;
|
||||
this.facingProperty = facingProperty;
|
||||
}
|
||||
|
||||
public ParticleConfig[] particles() {
|
||||
return this.particles;
|
||||
}
|
||||
|
||||
public int tickInterval() {
|
||||
return tickInterval;
|
||||
}
|
||||
|
||||
public Property<HorizontalDirection> facingProperty() {
|
||||
return facingProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityType<T> blockEntityType() {
|
||||
return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.WALL_TORCH_PARTICLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) {
|
||||
return new WallTorchParticleBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType<T> blockEntityType) {
|
||||
if (this.particles.length == 0) return null;
|
||||
return EntityBlockBehavior.createTickerHelper(WallTorchParticleBlockEntity::tick);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<ParticleConfig> particles = ResourceConfigUtils.parseConfigAsList(ResourceConfigUtils.get(arguments, "particles", "particle"), ParticleConfig::fromMap$blockEntity);
|
||||
int tickInterval = ResourceConfigUtils.getAsInt(arguments.getOrDefault("tick-interval", 10), "tick-interval");
|
||||
Property<HorizontalDirection> directionProperty = (Property<HorizontalDirection>) block.getProperty("facing");
|
||||
if (directionProperty == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.behavior.wall_torch_particle.missing_facing");
|
||||
}
|
||||
return new WallTorchParticleBlockBehavior(block, particles.toArray(new ParticleConfig[0]), tickInterval, directionProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
|
||||
public abstract class AbstractAnimateTickBlockEntity extends BlockEntity {
|
||||
protected int tickCount;
|
||||
|
||||
public AbstractAnimateTickBlockEntity(BlockEntityType<? extends BlockEntity> type, BlockPos pos, ImmutableBlockState blockState) {
|
||||
super(type, pos, blockState);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.ParticleBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
public abstract class BaseParticleBlockEntity extends BlockEntity {
|
||||
protected final ParticleBlockBehavior behavior;
|
||||
protected int tickCount;
|
||||
|
||||
public BaseParticleBlockEntity(BlockEntityType<? extends BlockEntity> type, BlockPos pos, ImmutableBlockState blockState) {
|
||||
super(type, pos, blockState);
|
||||
this.behavior = super.blockState.behavior().getAs(ParticleBlockBehavior.class).orElseThrow();
|
||||
}
|
||||
|
||||
public static void tick(CEWorld ceWorld, BlockPos blockPos, ImmutableBlockState state, BaseParticleBlockEntity particle) {
|
||||
particle.tickCount++;
|
||||
if (particle.tickCount % 10 != 0) return;
|
||||
particle.animateTick(state, ceWorld.world(), blockPos);
|
||||
}
|
||||
|
||||
public abstract void animateTick(ImmutableBlockState state, World level, BlockPos pos);
|
||||
}
|
||||
@@ -6,6 +6,6 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityTypes;
|
||||
|
||||
public class BukkitBlockEntityTypes extends BlockEntityTypes {
|
||||
public static final BlockEntityType<SimpleStorageBlockEntity> SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new);
|
||||
public static final BlockEntityType<ParticleBlockEntity> PARTICLE = register(BlockEntityTypeKeys.PARTICLE, ParticleBlockEntity::new);
|
||||
public static final BlockEntityType<WallParticleBlockEntity> WALL_PARTICLE = register(BlockEntityTypeKeys.WALL_PARTICLE, WallParticleBlockEntity::new);
|
||||
public static final BlockEntityType<SimpleParticleBlockEntity> SIMPLE_PARTICLE = register(BlockEntityTypeKeys.SIMPLE_PARTICLE, SimpleParticleBlockEntity::new);
|
||||
public static final BlockEntityType<WallTorchParticleBlockEntity> WALL_TORCH_PARTICLE = register(BlockEntityTypeKeys.WALL_TORCH_PARTICLE, WallTorchParticleBlockEntity::new);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.ParticleBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
public class ParticleBlockEntity extends BaseParticleBlockEntity {
|
||||
|
||||
public ParticleBlockEntity(BlockPos pos, ImmutableBlockState blockState) {
|
||||
super(BukkitBlockEntityTypes.PARTICLE, pos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateTick(ImmutableBlockState state, World level, BlockPos pos) {
|
||||
for (ParticleBlockBehavior.ParticleData particle : behavior.particles()) {
|
||||
Vec3d location = particle.locationOffset().add(pos.x(), pos.y(), pos.z());
|
||||
level.spawnParticle(
|
||||
location,
|
||||
particle.particle(),
|
||||
particle.count(),
|
||||
particle.offset().x(),
|
||||
particle.offset().y(),
|
||||
particle.offset().z(),
|
||||
particle.speed(),
|
||||
null, null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.SimpleParticleBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.SimpleContext;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleConfig;
|
||||
|
||||
public class SimpleParticleBlockEntity extends AbstractAnimateTickBlockEntity {
|
||||
private final SimpleParticleBlockBehavior behavior;
|
||||
private final Context context = SimpleContext.of(ContextHolder.empty());
|
||||
|
||||
public SimpleParticleBlockEntity(BlockPos pos, ImmutableBlockState blockState) {
|
||||
super(BukkitBlockEntityTypes.SIMPLE_PARTICLE, pos, blockState);
|
||||
this.behavior = blockState.behavior().getAs(SimpleParticleBlockBehavior.class).orElseThrow();
|
||||
}
|
||||
|
||||
public void animateTick(ImmutableBlockState state, World level, BlockPos pos) {
|
||||
for (ParticleConfig particle : this.behavior.particles) {
|
||||
Vec3d location = new Vec3d(super.pos.x() + particle.x.getDouble(context), super.pos.y() + particle.y.getDouble(context), super.pos.z() + particle.z.getDouble(context));
|
||||
level.spawnParticle(
|
||||
location,
|
||||
particle.particleType,
|
||||
particle.count.getInt(context),
|
||||
particle.xOffset.getDouble(context),
|
||||
particle.yOffset.getDouble(context),
|
||||
particle.zOffset.getDouble(context),
|
||||
particle.speed.getDouble(context),
|
||||
particle.particleData,
|
||||
context
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick(CEWorld ceWorld, BlockPos blockPos, ImmutableBlockState state, SimpleParticleBlockEntity particle) {
|
||||
particle.tickCount++;
|
||||
if (particle.tickCount % particle.behavior.tickInterval != 0) return;
|
||||
particle.animateTick(state, ceWorld.world(), blockPos);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.ParticleBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
public class WallParticleBlockEntity extends BaseParticleBlockEntity {
|
||||
|
||||
public WallParticleBlockEntity(BlockPos pos, ImmutableBlockState blockState) {
|
||||
super(BukkitBlockEntityTypes.WALL_PARTICLE, pos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateTick(ImmutableBlockState state, World level, BlockPos pos) {
|
||||
Direction direction = null;
|
||||
for (Property<?> property : state.getProperties()) {
|
||||
if (!property.name().equals("facing")) continue;
|
||||
if (property.valueClass() == Direction.class) {
|
||||
direction = (Direction) state.get(property);
|
||||
break;
|
||||
} else if (property.valueClass() == HorizontalDirection.class) {
|
||||
direction = ((HorizontalDirection) state.get(property)).toDirection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (direction != null) {
|
||||
direction = direction.opposite();
|
||||
}
|
||||
for (ParticleBlockBehavior.ParticleData particle : behavior.particles()) {
|
||||
Vec3d location = particle.locationOffset().add(pos.x(), pos.y(), pos.z());
|
||||
if (direction != null) {
|
||||
location = location.add(0.27 * direction.stepX(), 0.22, 0.27 * direction.stepZ());
|
||||
}
|
||||
level.spawnParticle(
|
||||
location,
|
||||
particle.particle(),
|
||||
particle.count(),
|
||||
particle.offset().x(),
|
||||
particle.offset().y(),
|
||||
particle.offset().z(),
|
||||
particle.speed(),
|
||||
null, null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.momirealms.craftengine.bukkit.block.entity;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.WallTorchParticleBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.plugin.context.SimpleContext;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleConfig;
|
||||
|
||||
public class WallTorchParticleBlockEntity extends AbstractAnimateTickBlockEntity {
|
||||
private final WallTorchParticleBlockBehavior behavior;
|
||||
private final Context context = SimpleContext.of(ContextHolder.empty());
|
||||
|
||||
public WallTorchParticleBlockEntity(BlockPos pos, ImmutableBlockState blockState) {
|
||||
super(BukkitBlockEntityTypes.WALL_TORCH_PARTICLE, pos, blockState);
|
||||
this.behavior = blockState.behavior().getAs(WallTorchParticleBlockBehavior.class).orElseThrow();
|
||||
}
|
||||
|
||||
public void animateTick(ImmutableBlockState state, World level, BlockPos pos) {
|
||||
HorizontalDirection direction = state.get(this.behavior.facingProperty);
|
||||
if (direction == null) return;
|
||||
Vec3d center = Vec3d.atCenterOf(pos);
|
||||
HorizontalDirection opposite = direction.opposite();
|
||||
for (ParticleConfig particle : this.behavior.particles) {
|
||||
Vec3d location = new Vec3d(
|
||||
center.x() + particle.x.getDouble(context) * opposite.stepX(),
|
||||
center.y() + particle.y.getDouble(context),
|
||||
center.z() + particle.z.getDouble(context) * opposite.stepZ()
|
||||
);
|
||||
level.spawnParticle(
|
||||
location,
|
||||
particle.particleType,
|
||||
particle.count.getInt(context),
|
||||
particle.xOffset.getDouble(context),
|
||||
particle.yOffset.getDouble(context),
|
||||
particle.zOffset.getDouble(context),
|
||||
particle.speed.getDouble(context),
|
||||
particle.particleData,
|
||||
context
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick(CEWorld ceWorld, BlockPos blockPos, ImmutableBlockState state, WallTorchParticleBlockEntity particle) {
|
||||
particle.tickCount++;
|
||||
if (particle.tickCount % particle.behavior.tickInterval != 0) return;
|
||||
particle.animateTick(state, ceWorld.world(), blockPos);
|
||||
}
|
||||
}
|
||||
@@ -106,11 +106,11 @@ public class BukkitWorld implements World {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Position location, Key particle, int count, double xOffset, double yOffset, double zOffset, double speed, @Nullable ParticleData extraData, @Nullable Context context) {
|
||||
public void spawnParticle(Position location, Key particle, int count, double xOffset, double yOffset, double zOffset, double speed, @Nullable ParticleData extraData, @NotNull Context context) {
|
||||
Particle particleType = ParticleUtils.getParticle(particle);
|
||||
if (particleType == null) return;
|
||||
org.bukkit.World platformWorld = platformWorld();
|
||||
platformWorld.spawnParticle(particleType, location.x(), location.y(), location.z(), count, xOffset, yOffset, zOffset, speed, extraData == null || context == null ? null : ParticleUtils.toBukkitParticleData(extraData, context, platformWorld, location.x(), location.y(), location.z()));
|
||||
platformWorld.spawnParticle(particleType, location.x(), location.y(), location.z(), count, xOffset, yOffset, zOffset, speed, extraData == null ? null : ParticleUtils.toBukkitParticleData(extraData, context, platformWorld, location.x(), location.y(), location.z()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,12 +70,18 @@ blocks:
|
||||
support-types:
|
||||
- center
|
||||
- type: liquid_flowable_block
|
||||
- type: particle_block
|
||||
- type: simple_particle_block
|
||||
tick-interval: 10
|
||||
particles:
|
||||
- type: smoke
|
||||
location-offset: 0.5,0.7,0.5
|
||||
- type: flame
|
||||
location-offset: 0.5,0.7,0.5
|
||||
- particle: smoke
|
||||
x: 0.5
|
||||
y: 0.7
|
||||
z: 0.5
|
||||
- particle: dust
|
||||
color: 138,43,226
|
||||
x: 0.5
|
||||
y: 0.7
|
||||
z: 0.5
|
||||
default:amethyst_wall_torch:
|
||||
loot:
|
||||
template: default:loot_table/basic
|
||||
@@ -94,13 +100,17 @@ blocks:
|
||||
behavior:
|
||||
- type: directional_attached_block
|
||||
- type: liquid_flowable_block
|
||||
- type: particle_block
|
||||
in-wall: true
|
||||
- type: wall_torch_particle_block
|
||||
particles:
|
||||
- type: smoke
|
||||
location-offset: 0.5,0.7,0.5
|
||||
- type: flame
|
||||
location-offset: 0.5,0.7,0.5
|
||||
- particle: smoke
|
||||
x: 0.27
|
||||
y: 0.42
|
||||
z: 0.27
|
||||
- particle: dust
|
||||
color: 138,43,226
|
||||
x: 0.27
|
||||
y: 0.42
|
||||
z: 0.27
|
||||
states:
|
||||
properties:
|
||||
facing:
|
||||
|
||||
@@ -320,7 +320,7 @@ warning.config.block.behavior.grass.missing_feature: "<yellow>Issue found in fil
|
||||
warning.config.block.behavior.double_high.missing_half: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'half' property for 'double_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.change_over_time.missing_next_block: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'next_block' argument for 'change_over_time_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.surface_attached.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'surface_attached_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.particle.missing_type: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'type' argument for 'particle_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.wall_torch_particle.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'wall_torch_particle_block' behavior.</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid display position '<arg:2>' in 'generation.display' section. Allowed display positions: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -314,7 +314,7 @@ warning.config.block.behavior.grass.missing_feature: "<yellow>在文件 <arg:0>
|
||||
warning.config.block.behavior.double_high.missing_half: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'double_block' 行为缺少必需的 'half' 属性</yellow>"
|
||||
warning.config.block.behavior.change_over_time.missing_next_block: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'change_over_time_block' 行为缺少必需的 'next-block' 参数</yellow>"
|
||||
warning.config.block.behavior.surface_attached.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'surface_attached_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.particle.missing_type: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'particle' 段落缺少必需的 'type' 参数</yellow>"
|
||||
warning.config.block.behavior.wall_torch_particle.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'wall_torch_particle_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'generation' 段落缺少必需的 'parent' 参数</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 发现问题 - 无法为 '<arg:1>' 生成模型 存在多个配置尝试使用相同路径 '<arg:2>' 生成不同的 JSON 模型</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 在 'generation.display' 区域使用了无效的 display 位置类型 '<arg:2>'. 可用展示类型: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -7,6 +7,6 @@ public final class BlockEntityTypeKeys {
|
||||
|
||||
public static final Key UNSAFE_COMPOSITE = Key.of("craftengine:unsafe_composite");
|
||||
public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage");
|
||||
public static final Key PARTICLE = Key.of("craftengine:particle");
|
||||
public static final Key WALL_PARTICLE = Key.of("craftengine:wall_particle");
|
||||
public static final Key SIMPLE_PARTICLE = Key.of("craftengine:simple_particle");
|
||||
public static final Key WALL_TORCH_PARTICLE = Key.of("craftengine:wall_torch_particle");
|
||||
}
|
||||
|
||||
@@ -1,115 +1,25 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.function;
|
||||
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Color;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.LazyReference;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.Position;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
import net.momirealms.craftengine.core.world.particle.*;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleConfig;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ParticleFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||
public static final Map<Key, java.util.function.Function<Map<String, Object>, ParticleData>> DATA_TYPES = new HashMap<>();
|
||||
private final ParticleConfig config;
|
||||
|
||||
static {
|
||||
registerParticleData(map -> new BlockStateData(
|
||||
LazyReference.lazyReference(new Supplier<>() {
|
||||
final String blockState = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("block-state"), "warning.config.function.particle.missing_block_state");
|
||||
@Override
|
||||
public BlockStateWrapper get() {
|
||||
return CraftEngine.instance().blockManager().createBlockState(this.blockState);
|
||||
}
|
||||
})),
|
||||
ParticleTypes.BLOCK, ParticleTypes.FALLING_DUST, ParticleTypes.DUST_PILLAR, ParticleTypes.BLOCK_CRUMBLE, ParticleTypes.BLOCK_MARKER);
|
||||
registerParticleData(map -> new ColorData(
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("color"), "warning.config.function.particle.missing_color").split(","))),
|
||||
ParticleTypes.ENTITY_EFFECT, ParticleTypes.TINTED_LEAVES);
|
||||
registerParticleData(map -> new JavaTypeData(
|
||||
ResourceConfigUtils.getAsFloat(map.get("charge"), "charge")),
|
||||
ParticleTypes.SCULK_CHARGE);
|
||||
registerParticleData(map -> new JavaTypeData(
|
||||
ResourceConfigUtils.getAsInt(map.get("shriek"), "shriek")),
|
||||
ParticleTypes.SHRIEK);
|
||||
registerParticleData(map -> new DustData(
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("color"), "warning.config.function.particle.missing_color").split(",")),
|
||||
ResourceConfigUtils.getAsFloat(map.getOrDefault("scale", 1), "scale")),
|
||||
ParticleTypes.DUST);
|
||||
registerParticleData(map -> new DustTransitionData(
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("from"), "warning.config.function.particle.missing_from").split(",")),
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("to"), "warning.config.function.particle.missing_to").split(",")),
|
||||
ResourceConfigUtils.getAsFloat(map.getOrDefault("scale", 1), "scale")),
|
||||
ParticleTypes.DUST_COLOR_TRANSITION);
|
||||
registerParticleData(map -> new ItemStackData(
|
||||
LazyReference.lazyReference(new Supplier<>() {
|
||||
final Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("item"), "warning.config.function.particle.missing_item"));
|
||||
@Override
|
||||
public Item<?> get() {
|
||||
return CraftEngine.instance().itemManager().createWrappedItem(this.itemId, null);
|
||||
}
|
||||
})
|
||||
),
|
||||
ParticleTypes.ITEM);
|
||||
registerParticleData(map -> new VibrationData(
|
||||
NumberProviders.fromObject(map.getOrDefault("target-x", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-y", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-z", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("arrival-time", 10))),
|
||||
ParticleTypes.VIBRATION);
|
||||
registerParticleData(map -> new TrailData(
|
||||
NumberProviders.fromObject(map.getOrDefault("target-x", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-y", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-z", 0)),
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("color"), "warning.config.function.particle.missing_color").split(",")),
|
||||
NumberProviders.fromObject(map.getOrDefault("duration", 10))),
|
||||
ParticleTypes.TRAIL);
|
||||
}
|
||||
|
||||
public static void registerParticleData(java.util.function.Function<Map<String, Object>, ParticleData> function, Key... types) {
|
||||
for (Key type : types) {
|
||||
DATA_TYPES.put(type, function);
|
||||
}
|
||||
}
|
||||
|
||||
private final Key particleType;
|
||||
private final NumberProvider x;
|
||||
private final NumberProvider y;
|
||||
private final NumberProvider z;
|
||||
private final NumberProvider count;
|
||||
private final NumberProvider xOffset;
|
||||
private final NumberProvider yOffset;
|
||||
private final NumberProvider zOffset;
|
||||
private final NumberProvider speed;
|
||||
private final ParticleData particleData;
|
||||
|
||||
public ParticleFunction(Key particleType, NumberProvider x, NumberProvider y, NumberProvider z, NumberProvider count,
|
||||
NumberProvider xOffset, NumberProvider yOffset, NumberProvider zOffset, NumberProvider speed, ParticleData particleData, List<Condition<CTX>> predicates) {
|
||||
public ParticleFunction(ParticleConfig config, List<Condition<CTX>> predicates) {
|
||||
super(predicates);
|
||||
this.particleType = particleType;
|
||||
this.count = count;
|
||||
this.xOffset = xOffset;
|
||||
this.yOffset = yOffset;
|
||||
this.zOffset = zOffset;
|
||||
this.speed = speed;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.particleData = particleData;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,8 +27,8 @@ public class ParticleFunction<CTX extends Context> extends AbstractConditionalFu
|
||||
Optional<WorldPosition> optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION);
|
||||
if (optionalWorldPosition.isPresent()) {
|
||||
World world = optionalWorldPosition.get().world();
|
||||
Position position = new Vec3d(this.x.getDouble(ctx), this.y.getDouble(ctx), this.z.getDouble(ctx));
|
||||
world.spawnParticle(position, this.particleType, this.count.getInt(ctx), this.xOffset.getDouble(ctx), this.yOffset.getDouble(ctx), this.zOffset.getDouble(ctx), this.speed.getDouble(ctx), this.particleData, ctx);
|
||||
Position position = new Vec3d(config.x.getDouble(ctx), config.y.getDouble(ctx), config.z.getDouble(ctx));
|
||||
world.spawnParticle(position, config.particleType, config.count.getInt(ctx), config.xOffset.getDouble(ctx), config.yOffset.getDouble(ctx), config.zOffset.getDouble(ctx), config.speed.getDouble(ctx), config.particleData, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,17 +45,7 @@ public class ParticleFunction<CTX extends Context> extends AbstractConditionalFu
|
||||
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
Key particleType = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("particle"), "warning.config.function.particle.missing_particle"));
|
||||
NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "<arg:position.x>"));
|
||||
NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "<arg:position.y>"));
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "<arg:position.z>"));
|
||||
NumberProvider count = NumberProviders.fromObject(arguments.getOrDefault("count", 1));
|
||||
NumberProvider xOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-x", 0));
|
||||
NumberProvider yOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-y", 0));
|
||||
NumberProvider zOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-z", 0));
|
||||
NumberProvider speed = NumberProviders.fromObject(arguments.getOrDefault("speed", 0));
|
||||
return new ParticleFunction<>(particleType, x, y, z, count, xOffset, yOffset, zOffset, speed,
|
||||
Optional.ofNullable(ParticleFunction.DATA_TYPES.get(particleType)).map(it -> it.apply(arguments)).orElse(null), getPredicates(arguments));
|
||||
return new ParticleFunction<>(ParticleConfig.fromMap$function(arguments), getPredicates(arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,26 @@ package net.momirealms.craftengine.core.util;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum HorizontalDirection {
|
||||
NORTH,
|
||||
SOUTH,
|
||||
WEST,
|
||||
EAST;
|
||||
NORTH(0, -1),
|
||||
SOUTH(0, 1),
|
||||
WEST(-1, 0),
|
||||
EAST(1, 0);
|
||||
|
||||
private final int adjX;
|
||||
private final int adjZ;
|
||||
|
||||
HorizontalDirection(int adjX, int adjZ) {
|
||||
this.adjX = adjX;
|
||||
this.adjZ = adjZ;
|
||||
}
|
||||
|
||||
public int stepX() {
|
||||
return this.adjX;
|
||||
}
|
||||
|
||||
public int stepZ() {
|
||||
return this.adjZ;
|
||||
}
|
||||
|
||||
public Direction toDirection() {
|
||||
return switch (this) {
|
||||
|
||||
@@ -58,7 +58,7 @@ public interface World {
|
||||
|
||||
void levelEvent(int id, BlockPos pos, int data);
|
||||
|
||||
void spawnParticle(Position location, Key particle, int count, double xOffset, double yOffset, double zOffset, double speed, @Nullable ParticleData extraData, @Nullable Context context);
|
||||
void spawnParticle(Position location, Key particle, int count, double xOffset, double yOffset, double zOffset, double speed, @Nullable ParticleData extraData, @NotNull Context context);
|
||||
|
||||
long time();
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package net.momirealms.craftengine.core.world.particle;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ParticleConfig {
|
||||
public final Key particleType;
|
||||
public final NumberProvider x;
|
||||
public final NumberProvider y;
|
||||
public final NumberProvider z;
|
||||
public final NumberProvider count;
|
||||
public final NumberProvider xOffset;
|
||||
public final NumberProvider yOffset;
|
||||
public final NumberProvider zOffset;
|
||||
public final NumberProvider speed;
|
||||
public final ParticleData particleData;
|
||||
|
||||
public ParticleConfig(Key particleType, NumberProvider x, NumberProvider y, NumberProvider z, NumberProvider count, NumberProvider xOffset, NumberProvider yOffset, NumberProvider zOffset, NumberProvider speed, ParticleData particleData) {
|
||||
this.particleType = particleType;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.count = count;
|
||||
this.xOffset = xOffset;
|
||||
this.yOffset = yOffset;
|
||||
this.zOffset = zOffset;
|
||||
this.speed = speed;
|
||||
this.particleData = particleData;
|
||||
}
|
||||
|
||||
public static ParticleConfig fromMap$function(Map<String, Object> arguments) {
|
||||
Key particleType = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("particle"), "warning.config.function.particle.missing_particle"));
|
||||
NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "<arg:position.x>"));
|
||||
NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "<arg:position.y>"));
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "<arg:position.z>"));
|
||||
NumberProvider count = NumberProviders.fromObject(arguments.getOrDefault("count", 1));
|
||||
NumberProvider xOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-x", 0));
|
||||
NumberProvider yOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-y", 0));
|
||||
NumberProvider zOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-z", 0));
|
||||
NumberProvider speed = NumberProviders.fromObject(arguments.getOrDefault("speed", 0));
|
||||
return new ParticleConfig(particleType, x, y, z, count, xOffset, yOffset, zOffset, speed, Optional.ofNullable(ParticleDataTypes.TYPES.get(particleType)).map(it -> it.apply(arguments)).orElse(null));
|
||||
}
|
||||
|
||||
public static ParticleConfig fromMap$blockEntity(Map<String, Object> arguments) {
|
||||
Key particleType = Key.of(arguments.getOrDefault("particle", "flame").toString());
|
||||
NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", 0));
|
||||
NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", 0));
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", 0));
|
||||
NumberProvider count = NumberProviders.fromObject(arguments.getOrDefault("count", 1));
|
||||
NumberProvider xOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-x", 0));
|
||||
NumberProvider yOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-y", 0));
|
||||
NumberProvider zOffset = NumberProviders.fromObject(arguments.getOrDefault("offset-z", 0));
|
||||
NumberProvider speed = NumberProviders.fromObject(arguments.getOrDefault("speed", 0));
|
||||
return new ParticleConfig(particleType, x, y, z, count, xOffset, yOffset, zOffset, speed, Optional.ofNullable(ParticleDataTypes.TYPES.get(particleType)).map(it -> it.apply(arguments)).orElse(null));
|
||||
}
|
||||
|
||||
public Key particleType() {
|
||||
return particleType;
|
||||
}
|
||||
|
||||
public NumberProvider x() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public NumberProvider y() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public NumberProvider z() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public NumberProvider count() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public NumberProvider xOffset() {
|
||||
return xOffset;
|
||||
}
|
||||
|
||||
public NumberProvider yOffset() {
|
||||
return yOffset;
|
||||
}
|
||||
|
||||
public NumberProvider zOffset() {
|
||||
return zOffset;
|
||||
}
|
||||
|
||||
public NumberProvider speed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public ParticleData particleData() {
|
||||
return particleData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package net.momirealms.craftengine.core.world.particle;
|
||||
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.util.Color;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.LazyReference;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class ParticleDataTypes {
|
||||
public static final Map<Key, java.util.function.Function<Map<String, Object>, ParticleData>> TYPES = new HashMap<>();
|
||||
|
||||
static {
|
||||
registerParticleData(map -> new BlockStateData(
|
||||
LazyReference.lazyReference(new Supplier<>() {
|
||||
final String blockState = ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("block-state"), "warning.config.function.particle.missing_block_state");
|
||||
@Override
|
||||
public BlockStateWrapper get() {
|
||||
return CraftEngine.instance().blockManager().createBlockState(this.blockState);
|
||||
}
|
||||
})),
|
||||
ParticleTypes.BLOCK, ParticleTypes.FALLING_DUST, ParticleTypes.DUST_PILLAR, ParticleTypes.BLOCK_CRUMBLE, ParticleTypes.BLOCK_MARKER);
|
||||
registerParticleData(map -> new ColorData(
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("color"), "warning.config.function.particle.missing_color").split(","))),
|
||||
ParticleTypes.ENTITY_EFFECT, ParticleTypes.TINTED_LEAVES);
|
||||
registerParticleData(map -> new JavaTypeData(
|
||||
ResourceConfigUtils.getAsFloat(map.get("charge"), "charge")),
|
||||
ParticleTypes.SCULK_CHARGE);
|
||||
registerParticleData(map -> new JavaTypeData(
|
||||
ResourceConfigUtils.getAsInt(map.get("shriek"), "shriek")),
|
||||
ParticleTypes.SHRIEK);
|
||||
registerParticleData(map -> new DustData(
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("color"), "warning.config.function.particle.missing_color").split(",")),
|
||||
ResourceConfigUtils.getAsFloat(map.getOrDefault("scale", 1), "scale")),
|
||||
ParticleTypes.DUST);
|
||||
registerParticleData(map -> new DustTransitionData(
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("from"), "warning.config.function.particle.missing_from").split(",")),
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("to"), "warning.config.function.particle.missing_to").split(",")),
|
||||
ResourceConfigUtils.getAsFloat(map.getOrDefault("scale", 1), "scale")),
|
||||
ParticleTypes.DUST_COLOR_TRANSITION);
|
||||
registerParticleData(map -> new ItemStackData(
|
||||
LazyReference.lazyReference(new Supplier<>() {
|
||||
final Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("item"), "warning.config.function.particle.missing_item"));
|
||||
@Override
|
||||
public Item<?> get() {
|
||||
return CraftEngine.instance().itemManager().createWrappedItem(this.itemId, null);
|
||||
}
|
||||
})
|
||||
),
|
||||
ParticleTypes.ITEM);
|
||||
registerParticleData(map -> new VibrationData(
|
||||
NumberProviders.fromObject(map.getOrDefault("target-x", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-y", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-z", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("arrival-time", 10))),
|
||||
ParticleTypes.VIBRATION);
|
||||
registerParticleData(map -> new TrailData(
|
||||
NumberProviders.fromObject(map.getOrDefault("target-x", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-y", 0)),
|
||||
NumberProviders.fromObject(map.getOrDefault("target-z", 0)),
|
||||
Color.fromStrings(ResourceConfigUtils.requireNonEmptyStringOrThrow(map.get("color"), "warning.config.function.particle.missing_color").split(",")),
|
||||
NumberProviders.fromObject(map.getOrDefault("duration", 10))),
|
||||
ParticleTypes.TRAIL);
|
||||
}
|
||||
|
||||
public static void registerParticleData(java.util.function.Function<Map<String, Object>, ParticleData> function, Key... types) {
|
||||
for (Key type : types) {
|
||||
TYPES.put(type, function);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user