diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index 0ccb79370..f6cc1c58e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -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); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ParticleBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ParticleBlockBehavior.java deleted file mode 100644 index 548b159c9..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ParticleBlockBehavior.java +++ /dev/null @@ -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 particles; - private final boolean inWall; - - public ParticleBlockBehavior(CustomBlock customBlock, List particles, boolean inWall) { - super(customBlock); - this.particles = particles; - this.inWall = inWall; - } - - public List particles() { - return particles; - } - - @Override - public BlockEntityType 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 BlockEntityTicker createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType 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 arguments) { - List 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 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); - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleParticleBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleParticleBlockBehavior.java new file mode 100644 index 000000000..d52bda8a4 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SimpleParticleBlockBehavior.java @@ -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 BlockEntityType blockEntityType() { + return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.SIMPLE_PARTICLE); + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) { + return new SimpleParticleBlockEntity(pos, state); + } + + @Override + public BlockEntityTicker createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType 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 arguments) { + List 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); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WallTorchParticleBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WallTorchParticleBlockBehavior.java new file mode 100644 index 000000000..84a2d19fb --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WallTorchParticleBlockBehavior.java @@ -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 facingProperty; + + public WallTorchParticleBlockBehavior(CustomBlock customBlock, ParticleConfig[] particles, int tickInterval, Property 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 facingProperty() { + return facingProperty; + } + + @Override + public BlockEntityType blockEntityType() { + return EntityBlockBehavior.blockEntityTypeHelper(BukkitBlockEntityTypes.WALL_TORCH_PARTICLE); + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) { + return new WallTorchParticleBlockEntity(pos, state); + } + + @Override + public BlockEntityTicker createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType 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 arguments) { + List particles = ResourceConfigUtils.parseConfigAsList(ResourceConfigUtils.get(arguments, "particles", "particle"), ParticleConfig::fromMap$blockEntity); + int tickInterval = ResourceConfigUtils.getAsInt(arguments.getOrDefault("tick-interval", 10), "tick-interval"); + Property directionProperty = (Property) 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); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/AbstractAnimateTickBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/AbstractAnimateTickBlockEntity.java new file mode 100644 index 000000000..90f863944 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/AbstractAnimateTickBlockEntity.java @@ -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 type, BlockPos pos, ImmutableBlockState blockState) { + super(type, pos, blockState); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BaseParticleBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BaseParticleBlockEntity.java deleted file mode 100644 index fb8d63c83..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BaseParticleBlockEntity.java +++ /dev/null @@ -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 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); -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java index 75c449fa9..7c0456145 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java @@ -6,6 +6,6 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityTypes; public class BukkitBlockEntityTypes extends BlockEntityTypes { public static final BlockEntityType SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new); - public static final BlockEntityType PARTICLE = register(BlockEntityTypeKeys.PARTICLE, ParticleBlockEntity::new); - public static final BlockEntityType WALL_PARTICLE = register(BlockEntityTypeKeys.WALL_PARTICLE, WallParticleBlockEntity::new); + public static final BlockEntityType SIMPLE_PARTICLE = register(BlockEntityTypeKeys.SIMPLE_PARTICLE, SimpleParticleBlockEntity::new); + public static final BlockEntityType WALL_TORCH_PARTICLE = register(BlockEntityTypeKeys.WALL_TORCH_PARTICLE, WallTorchParticleBlockEntity::new); } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/ParticleBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/ParticleBlockEntity.java deleted file mode 100644 index 485eb0c85..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/ParticleBlockEntity.java +++ /dev/null @@ -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 - ); - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleParticleBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleParticleBlockEntity.java new file mode 100644 index 000000000..30acd0be6 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SimpleParticleBlockEntity.java @@ -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); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/WallParticleBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/WallParticleBlockEntity.java deleted file mode 100644 index 7de011fb9..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/WallParticleBlockEntity.java +++ /dev/null @@ -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 - ); - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/WallTorchParticleBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/WallTorchParticleBlockEntity.java new file mode 100644 index 000000000..f571661e8 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/WallTorchParticleBlockEntity.java @@ -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); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java index 28b39712d..2624bc78d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java @@ -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 diff --git a/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml b/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml index 1ee3349c5..a83504d42 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks/amethyst_torch.yml @@ -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: diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index d57a7cc15..4fa46057b 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -320,7 +320,7 @@ warning.config.block.behavior.grass.missing_feature: "Issue found in fil warning.config.block.behavior.double_high.missing_half: "Issue found in file - The block '' is missing the required 'half' property for 'double_block' behavior." warning.config.block.behavior.change_over_time.missing_next_block: "Issue found in file - The block '' is missing the required 'next_block' argument for 'change_over_time_block' behavior." warning.config.block.behavior.surface_attached.missing_facing: "Issue found in file - The block '' is missing the required 'facing' property for 'surface_attached_block' behavior." -warning.config.block.behavior.particle.missing_type: "Issue found in file - The block '' is missing the required 'type' argument for 'particle_block' behavior." +warning.config.block.behavior.wall_torch_particle.missing_facing: "Issue found in file - The block '' is missing the required 'facing' property for 'wall_torch_particle_block' behavior." warning.config.model.generation.missing_parent: "Issue found in file - The config '' is missing the required 'parent' argument in 'generation' section." warning.config.model.generation.conflict: "Issue found in file - Failed to generate model for '' as two or more configurations attempt to generate different json models with the same path: ''." warning.config.model.generation.invalid_display_position: "Issue found in file - The config '' is using an invalid display position '' in 'generation.display' section. Allowed display positions: []" diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 902056cd9..8a5413621 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -314,7 +314,7 @@ warning.config.block.behavior.grass.missing_feature: "在文件 warning.config.block.behavior.double_high.missing_half: "在文件 发现问题 - 方块 '' 的 'double_block' 行为缺少必需的 'half' 属性" warning.config.block.behavior.change_over_time.missing_next_block: "在文件 发现问题 - 方块 '' 的 'change_over_time_block' 行为缺少必需的 'next-block' 参数" warning.config.block.behavior.surface_attached.missing_facing: "在文件 发现问题 - 方块 '' 的 'surface_attached_block' 行为缺少必需的 'facing' 属性" -warning.config.block.behavior.particle.missing_type: "在文件 发现问题 - 配置项 '' 的 'particle' 段落缺少必需的 'type' 参数" +warning.config.block.behavior.wall_torch_particle.missing_facing: "在文件 发现问题 - 配置项 '' 的 'wall_torch_particle_block' 行为缺少必需的 'facing' 属性" warning.config.model.generation.missing_parent: "在文件 发现问题 - 配置项 '' 的 'generation' 段落缺少必需的 'parent' 参数" warning.config.model.generation.conflict: "在文件 发现问题 - 无法为 '' 生成模型 存在多个配置尝试使用相同路径 '' 生成不同的 JSON 模型" warning.config.model.generation.invalid_display_position: "在文件 发现问题 - 配置项 '' 在 'generation.display' 区域使用了无效的 display 位置类型 ''. 可用展示类型: []" diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java index 6bc44620d..720da9e20 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java @@ -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"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ParticleFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ParticleFunction.java index c97d47bd3..4893d19f8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ParticleFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ParticleFunction.java @@ -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 extends AbstractConditionalFunction { - public static final Map, 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, 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> predicates) { + public ParticleFunction(ParticleConfig config, List> 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 extends AbstractConditionalFu Optional 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 extends AbstractConditionalFu @Override public Function create(Map arguments) { - Key particleType = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("particle"), "warning.config.function.particle.missing_particle")); - NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); - NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); - NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("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)); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/HorizontalDirection.java b/core/src/main/java/net/momirealms/craftengine/core/util/HorizontalDirection.java index cc8143e12..d0a6ec27c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/HorizontalDirection.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/HorizontalDirection.java @@ -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) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/World.java b/core/src/main/java/net/momirealms/craftengine/core/world/World.java index 40dd01f58..bc6181c8b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/World.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/World.java @@ -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(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/particle/ParticleConfig.java b/core/src/main/java/net/momirealms/craftengine/core/world/particle/ParticleConfig.java new file mode 100644 index 000000000..b96863555 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/world/particle/ParticleConfig.java @@ -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 arguments) { + Key particleType = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("particle"), "warning.config.function.particle.missing_particle")); + NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "")); + NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "")); + NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("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 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; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/particle/ParticleDataTypes.java b/core/src/main/java/net/momirealms/craftengine/core/world/particle/ParticleDataTypes.java new file mode 100644 index 000000000..094a83daa --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/world/particle/ParticleDataTypes.java @@ -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, 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, ParticleData> function, Key... types) { + for (Key type : types) { + TYPES.put(type, function); + } + } +}