diff --git a/src/main/java/com/minelittlepony/unicopia/UTags.java b/src/main/java/com/minelittlepony/unicopia/UTags.java index e8d0b5d7..08da479c 100644 --- a/src/main/java/com/minelittlepony/unicopia/UTags.java +++ b/src/main/java/com/minelittlepony/unicopia/UTags.java @@ -44,6 +44,7 @@ public interface UTags { TagKey CRYSTAL_HEART_BASE = block("crystal_heart_base"); TagKey CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament"); TagKey UNAFFECTED_BY_GROW_ABILITY = block("unaffected_by_grow_ability"); + TagKey KICKS_UP_DUST = block("kicks_up_dust"); TagKey POLEARM_MINEABLE = block("mineable/polearm"); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index 1a5c72ef..e81f5a0d 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.AwaitTickQueue; import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.entity.Living; @@ -17,6 +18,7 @@ import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; import com.minelittlepony.unicopia.util.PosHelper; +import com.minelittlepony.unicopia.util.VecHelper; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -26,6 +28,7 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.particle.BlockStateParticleEffect; import net.minecraft.registry.tag.BlockTags; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; @@ -33,6 +36,7 @@ import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraft.world.WorldEvents; @@ -156,7 +160,10 @@ public class EarthPonyStompAbility implements Ability { spawnEffectAround(player, center, radius, rad); ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0); - ParticleUtils.spawnParticle(player.getWorld(), UParticles.SHOCKWAVE, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0); + BlockState steppingState = player.getSteppingBlockState(); + if (steppingState.isIn(UTags.KICKS_UP_DUST)) { + ParticleUtils.spawnParticle(player.getWorld(), new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), player.getBlockPos().down().toCenterPos(), Vec3d.ZERO); + } iplayer.subtractEnergyCost(rad); iplayer.asEntity().addExhaustion(3); @@ -218,6 +225,12 @@ public class EarthPonyStompAbility implements Ability { } else { w.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state)); } + + if (state.isIn(UTags.KICKS_UP_DUST)) { + if (w.random.nextInt(4) == 0 && w.isAir(pos.up()) && w.getFluidState(pos.up()).isEmpty()) { + ParticleUtils.spawnParticle(w, new BlockStateParticleEffect(UParticles.DUST_CLOUD, state), pos.up().toCenterPos(), VecHelper.supply(() -> w.random.nextTriangular(0, 0.1F))); + } + } } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index ebe72254..0d4509bb 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.block.cloud.CloudChestBlock; import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle; import com.minelittlepony.unicopia.client.particle.CloudsEscapingParticle; import com.minelittlepony.unicopia.client.particle.DiskParticle; +import com.minelittlepony.unicopia.client.particle.DustCloudParticle; import com.minelittlepony.unicopia.client.particle.FloatingBubbleParticle; import com.minelittlepony.unicopia.client.particle.GroundPoundParticle; import com.minelittlepony.unicopia.client.particle.HealthDrainParticle; @@ -80,6 +81,7 @@ public interface URenderers { ParticleFactoryRegistry.getInstance().register(UParticles.GROUND_POUND, GroundPoundParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.CLOUDS_ESCAPING, CloudsEscapingParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.LIGHTNING_BOLT, LightningBoltParticle::new); + ParticleFactoryRegistry.getInstance().register(UParticles.DUST_CLOUD, DustCloudParticle::new); AccessoryFeatureRenderer.register( BraceletFeatureRenderer::new, AmuletFeatureRenderer::new, GlassesFeatureRenderer::new, diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java index 1714d93a..cb5a2c51 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java @@ -11,6 +11,7 @@ import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; public abstract class AbstractGeometryBasedParticle extends Particle { @@ -38,6 +39,16 @@ public abstract class AbstractGeometryBasedParticle extends Particle { te.draw(); } + protected final void renderQuad(MatrixStack matrices, Tessellator te, BufferBuilder buffer, RenderUtil.Vertex[] corners, float alpha, float tickDelta) { + int light = getBrightness(tickDelta); + buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT); + for (RenderUtil.Vertex corner : corners) { + var position = corner.position(matrices.peek().getPositionMatrix()); + buffer.vertex(position.x, position.y, position.z).texture(corner.texture().x, corner.texture().y).color(red, green, blue, alpha).light(light).next(); + } + te.draw(); + } + protected final void renderQuad(Tessellator te, BufferBuilder buffer, RenderUtil.Vertex[] corners, float alpha, float tickDelta) { int light = getBrightness(tickDelta); buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT); @@ -47,7 +58,6 @@ public abstract class AbstractGeometryBasedParticle extends Particle { te.draw(); } - protected final void renderQuad(VertexConsumer buffer, Vector3f[] corners, float alpha, float tickDelta) { int light = getBrightness(tickDelta); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java new file mode 100644 index 00000000..e39bb0b0 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/DustCloudParticle.java @@ -0,0 +1,86 @@ +package com.minelittlepony.unicopia.client.particle; + +import com.minelittlepony.common.util.Color; +import com.minelittlepony.unicopia.client.render.RenderUtil; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.BlockStateParticleEffect; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; + +public class DustCloudParticle extends AbstractBillboardParticle { + //private static final Identifier TEXTURE = new Identifier("textures/particle/big_smoke_3.png"); + + protected static final int SEGMENTS = 20; + protected static final int SEPARATION = 270 / SEGMENTS; + + private float scaleFactor; + + protected Sprite sprite; + private final RenderUtil.Vertex[] vertices; + + public DustCloudParticle(BlockStateParticleEffect effect, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + maxAge = 1000; + gravityStrength = 1; + red = 0.6F; + green = 0.6F; + blue = 0.6F; + alpha = (float)world.getRandom().nextTriangular(0.6, 0.2); + scaleFactor = (float)world.getRandom().nextTriangular(2, 1.2); + sprite = MinecraftClient.getInstance().getBlockRenderManager().getModels().getModelParticleSprite(effect.getBlockState()); + vertices = new RenderUtil.Vertex[]{ + new RenderUtil.Vertex(-1, -1, 0, sprite.getMinU(), sprite.getMinV()), + new RenderUtil.Vertex(-1, 1, 0, sprite.getMaxU(), sprite.getMinV()), + new RenderUtil.Vertex( 1, 1, 0, sprite.getMaxU(), sprite.getMaxV()), + new RenderUtil.Vertex( 1, -1, 0, sprite.getMinU(), sprite.getMaxV()) + }; + if (!effect.getBlockState().isOf(Blocks.GRASS_BLOCK)) { + int i = MinecraftClient.getInstance().getBlockColors().getColor(effect.getBlockState(), world, BlockPos.ofFloored(x, y, z), 0); + red *= Color.r(i); + green *= Color.g(i); + blue *= Color.b(i); + } + } + + @Override + protected Identifier getTexture() { + return sprite.getAtlasId(); + } + + @Override + public void tick() { + super.tick(); + scaleFactor += 0.001F; + scale(MathHelper.clamp(age / 5F, 0, 1) * scaleFactor); + } + + @Override + protected void renderQuads(Tessellator te, BufferBuilder buffer, float x, float y, float z, float tickDelta) { + float scale = getScale(tickDelta); + float alpha = this.alpha * (1 - ((float)age / maxAge)); + MatrixStack matrices = new MatrixStack(); + matrices.translate(x, y, z); + matrices.scale(scale, scale * 0.5F, scale); + + float angle = ((this.age + tickDelta) % 360) / SEGMENTS; + + for (int i = 0; i < SEGMENTS; i++) { + matrices.push(); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((i * angle) % 360)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((SEPARATION * i + angle) % 360)); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((SEPARATION * i + angle) % 360)); + float ringScale = 1 + MathHelper.sin(((i * 10) + age + tickDelta) * 0.05F) * 0.1F; + matrices.scale(ringScale, ringScale, ringScale); + renderQuad(matrices, te, buffer, vertices, alpha, tickDelta); + matrices.pop(); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java index 17554070..9bec2e5c 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.particle; import com.minelittlepony.unicopia.Unicopia; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; +import net.minecraft.particle.BlockStateParticleEffect; import net.minecraft.particle.DefaultParticleType; import net.minecraft.particle.ParticleType; import net.minecraft.registry.Registry; @@ -13,6 +14,7 @@ public interface UParticles { ParticleType UNICORN_MAGIC = register("unicorn_magic", FabricParticleTypes.complex(MagicParticleEffect.FACTORY)); DefaultParticleType CHANGELING_MAGIC = register("changeling_magic", FabricParticleTypes.simple()); DefaultParticleType BUBBLE = register("bubble", FabricParticleTypes.simple()); + ParticleType DUST_CLOUD = register("dust_cloud", FabricParticleTypes.complex(BlockStateParticleEffect.PARAMETERS_FACTORY)); ParticleType RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY)); ParticleType RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.complex(TargetBoundParticleEffect.FACTORY)); diff --git a/src/main/resources/data/c/tags/blocks/concrete_powders.json b/src/main/resources/data/c/tags/blocks/concrete_powders.json new file mode 100644 index 00000000..e3142856 --- /dev/null +++ b/src/main/resources/data/c/tags/blocks/concrete_powders.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "minecraft:white_concrete_powder", + "minecraft:orange_concrete_powder", + "minecraft:magenta_concrete_powder", + "minecraft:light_blue_concrete_powder", + "minecraft:yellow_concrete_powder", + "minecraft:lime_concrete_powder", + "minecraft:pink_concrete_powder", + "minecraft:gray_concrete_powder", + "minecraft:light_gray_concrete_powder", + "minecraft:cyan_concrete_powder", + "minecraft:purple_concrete_powder", + "minecraft:blue_concrete_powder", + "minecraft:brown_concrete_powder", + "minecraft:green_concrete_powder", + "minecraft:red_concrete_powder", + "minecraft:black_concrete_powder" + ] +} diff --git a/src/main/resources/data/unicopia/tags/blocks/kicks_up_dust.json b/src/main/resources/data/unicopia/tags/blocks/kicks_up_dust.json new file mode 100644 index 00000000..5a3a6783 --- /dev/null +++ b/src/main/resources/data/unicopia/tags/blocks/kicks_up_dust.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "values": [ + "#minecraft:sand", + "minecraft:gravel", + "minecraft:suspicious_gravel", + "#c:concrete_powders" + ] +}