From d9aa50fe1c5860dc8d97451531ad1a93b48a406c Mon Sep 17 00:00:00 2001 From: Aleksey Date: Sun, 22 Nov 2020 18:18:23 +0300 Subject: [PATCH] Infusion particles --- .../betterend/particle/InfusionParticle.java | 63 +++++++++++++++ .../particle/InfusionParticleType.java | 78 +++++++++++++++++++ .../ru/betterend/registry/EndParticles.java | 10 +++ .../ru/betterend/rituals/InfusionRitual.java | 21 ++--- .../java/ru/betterend/util/ColorUtil.java | 26 ++++++- .../assets/betterend/particles/infusion.json | 12 +++ 6 files changed, 193 insertions(+), 17 deletions(-) create mode 100644 src/main/java/ru/betterend/particle/InfusionParticle.java create mode 100644 src/main/java/ru/betterend/particle/InfusionParticleType.java create mode 100644 src/main/resources/assets/betterend/particles/infusion.json diff --git a/src/main/java/ru/betterend/particle/InfusionParticle.java b/src/main/java/ru/betterend/particle/InfusionParticle.java new file mode 100644 index 00000000..8f6d75e2 --- /dev/null +++ b/src/main/java/ru/betterend/particle/InfusionParticle.java @@ -0,0 +1,63 @@ +package ru.betterend.particle; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleFactory; +import net.minecraft.client.particle.ParticleTextureSheet; +import net.minecraft.client.particle.SpriteBillboardParticle; +import net.minecraft.client.particle.SpriteProvider; +import net.minecraft.client.world.ClientWorld; + +public class InfusionParticle extends SpriteBillboardParticle { + + private final SpriteProvider spriteProvider; + + public InfusionParticle(ClientWorld clientWorld, double x, double y, double z, double velocityX, double velocityY, double velocityZ, float[] palette, SpriteProvider spriteProvider) { + super(clientWorld, x, y, z, 0.0, 0.0, 0.0); + this.setSpriteForAge(spriteProvider); + this.spriteProvider = spriteProvider; + this.setColor(palette[0], palette[1], palette[2]); + this.setColorAlpha(palette[3]); + this.velocityX = velocityX * 0.1D; + this.velocityY = velocityY * 0.1D; + this.velocityZ = velocityZ * 0.1D; + this.maxAge = (int) (3.0F / (this.random.nextFloat() * 0.9F + 0.1F)); + this.scale *= 0.9F; + } + + @Override + public ParticleTextureSheet getType() { + return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT; + } + + @Override + public void tick() { + this.prevPosX = this.x; + this.prevPosY = this.y; + this.prevPosZ = this.z; + if (this.age++ >= this.maxAge) { + this.markDead(); + } else { + this.setSpriteForAge(spriteProvider); + double velocityX = 2.0D * this.velocityX * this.random.nextDouble(); + double velocityY = 3.0D * this.velocityY * this.random.nextDouble(); + double velocityZ = 2.0D * this.velocityZ * this.random.nextDouble(); + this.move(velocityX, velocityY, velocityZ); + } + } + + @Environment(EnvType.CLIENT) + public static class DefaultFactory implements ParticleFactory { + private final SpriteProvider spriteProvider; + + public DefaultFactory(SpriteProvider spriteProvider) { + this.spriteProvider = spriteProvider; + } + + public Particle createParticle(InfusionParticleType particleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) { + return new InfusionParticle(clientWorld, d, e, f, g, h, i, particleType.getPalette(), this.spriteProvider); + } + } +} diff --git a/src/main/java/ru/betterend/particle/InfusionParticleType.java b/src/main/java/ru/betterend/particle/InfusionParticleType.java new file mode 100644 index 00000000..7518fe12 --- /dev/null +++ b/src/main/java/ru/betterend/particle/InfusionParticleType.java @@ -0,0 +1,78 @@ +package ru.betterend.particle; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import net.minecraft.command.argument.ItemStackArgument; +import net.minecraft.command.argument.ItemStringReader; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleType; +import net.minecraft.util.registry.Registry; + +import ru.betterend.registry.EndParticles; +import ru.betterend.util.ColorUtil; + +public class InfusionParticleType extends ParticleType implements ParticleEffect { + public static final Codec CODEC = ItemStack.CODEC.xmap(itemStack -> { + return new InfusionParticleType(EndParticles.INFUSION, itemStack); + }, infusionParticleType -> { + return infusionParticleType.itemStack; + }); + public static final ParticleEffect.Factory PARAMETERS_FACTORY = new ParticleEffect.Factory() { + public InfusionParticleType read(ParticleType particleType, StringReader stringReader) throws CommandSyntaxException { + stringReader.expect(' '); + ItemStringReader itemStringReader = new ItemStringReader(stringReader, false).consume(); + ItemStack itemStack = new ItemStackArgument(itemStringReader.getItem(), itemStringReader.getTag()).createStack(1, false); + return new InfusionParticleType(particleType, itemStack); + } + + public InfusionParticleType read(ParticleType particleType, PacketByteBuf packetByteBuf) { + return new InfusionParticleType(particleType, packetByteBuf.readItemStack()); + } + }; + + private ParticleType type; + private ItemStack itemStack; + + public InfusionParticleType(ParticleType particleType, ItemStack stack) { + super(true, PARAMETERS_FACTORY); + this.type = particleType; + this.itemStack = stack; + } + + public InfusionParticleType(ItemStack stack) { + this(EndParticles.INFUSION, stack); + } + + @Environment(EnvType.CLIENT) + public float[] getPalette() { + int color = ColorUtil.extractColor(itemStack.getItem()); + return ColorUtil.toFloatArray(color); + } + + @Override + public ParticleType getType() { + return this.type; + } + + @Override + public void write(PacketByteBuf buffer) { + buffer.writeItemStack(itemStack); + } + + @Override + public String asString() { + return Registry.PARTICLE_TYPE.getId(this).toString(); + } + + @Override + public Codec getCodec() { + return CODEC; + } +} diff --git a/src/main/java/ru/betterend/registry/EndParticles.java b/src/main/java/ru/betterend/registry/EndParticles.java index 7bb41175..2b569659 100644 --- a/src/main/java/ru/betterend/registry/EndParticles.java +++ b/src/main/java/ru/betterend/registry/EndParticles.java @@ -3,21 +3,31 @@ package ru.betterend.registry; import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; import net.minecraft.particle.DefaultParticleType; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleType; import net.minecraft.util.registry.Registry; import ru.betterend.BetterEnd; +import ru.betterend.particle.InfusionParticle; +import ru.betterend.particle.InfusionParticleType; import ru.betterend.particle.ParticleGlowingSphere; import ru.betterend.particle.PaticlePortalSphere; public class EndParticles { public static final DefaultParticleType GLOWING_SPHERE = register("glowing_sphere"); public static final DefaultParticleType PORTAL_SPHERE = register("portal_sphere"); + public static final ParticleType INFUSION = register("infusion", FabricParticleTypes.complex(InfusionParticleType.PARAMETERS_FACTORY)); public static void register() { ParticleFactoryRegistry.getInstance().register(GLOWING_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new); ParticleFactoryRegistry.getInstance().register(PORTAL_SPHERE, PaticlePortalSphere.FactoryPortalSphere::new); + ParticleFactoryRegistry.getInstance().register(INFUSION, InfusionParticle.DefaultFactory::new); } private static DefaultParticleType register(String name) { return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple()); } + + private static ParticleType register(String name, ParticleType type) { + return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), type); + } } diff --git a/src/main/java/ru/betterend/rituals/InfusionRitual.java b/src/main/java/ru/betterend/rituals/InfusionRitual.java index c68ec1f1..b88de68c 100644 --- a/src/main/java/ru/betterend/rituals/InfusionRitual.java +++ b/src/main/java/ru/betterend/rituals/InfusionRitual.java @@ -8,14 +8,14 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; -import net.minecraft.particle.ItemStackParticleEffect; -import net.minecraft.particle.ParticleTypes; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; + import ru.betterend.blocks.entities.InfusionPedestalEntity; import ru.betterend.blocks.entities.PedestalBlockEntity; +import ru.betterend.particle.InfusionParticleType; import ru.betterend.recipe.builders.InfusionRecipe; public class InfusionRitual implements Inventory { @@ -65,11 +65,7 @@ public class InfusionRitual implements Inventory { InfusionRecipe recipe = this.world.getRecipeManager().getFirstMatch(InfusionRecipe.TYPE, this, world).orElse(null); if (hasRecipe()) { if (recipe == null) { - this.activeRecipe = null; - this.hasRecipe = false; - this.progress = 0; - this.time = 0; - this.markDirty(); + this.stop(); return false; } else if (recipe.getInfusionTime() != time) { this.activeRecipe = recipe; @@ -115,16 +111,12 @@ public class InfusionRitual implements Inventory { for (PedestalBlockEntity catalyst : catalysts) { catalyst.removeStack(world, world.getBlockState(catalyst.getPos())); } - this.activeRecipe = null; - this.hasRecipe = false; - this.progress = 0; - this.time = 0; - this.markDirty(); + this.stop(); } else { ServerWorld world = (ServerWorld) this.world; BlockPos target = this.worldPos.up(); double tx = target.getX() + 0.5; - double ty = target.getY() + 1.75; + double ty = target.getY() + 0.5; double tz = target.getZ() + 0.5; for (PedestalBlockEntity catalyst : catalysts) { ItemStack stack = catalyst.getStack(0); @@ -133,8 +125,7 @@ public class InfusionRitual implements Inventory { double sx = start.getX() + 0.5; double sy = start.getY() + 1.25; double sz = start.getZ() + 0.5; - ItemStackParticleEffect catalystParticle = new ItemStackParticleEffect(ParticleTypes.ITEM, stack); - world.spawnParticles(catalystParticle, sx, sy, sz, 0, tx - sx, ty - sy, tz - sz, 0.125); + world.spawnParticles(new InfusionParticleType(stack), sx, sy, sz, 0, tx - sx, ty - sy, tz - sz, 0.5); } } } diff --git a/src/main/java/ru/betterend/util/ColorUtil.java b/src/main/java/ru/betterend/util/ColorUtil.java index 771c94a6..49749cc7 100644 --- a/src/main/java/ru/betterend/util/ColorUtil.java +++ b/src/main/java/ru/betterend/util/ColorUtil.java @@ -3,6 +3,9 @@ package ru.betterend.util; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; + +import com.google.common.collect.Maps; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -10,10 +13,13 @@ import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper; import net.minecraft.client.MinecraftClient; import net.minecraft.client.texture.NativeImage; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.registry.Registry; import ru.betterend.BetterEnd; @@ -186,7 +192,20 @@ public class ColorUtil { return MHelper.pow2(r1 - r2) + MHelper.pow2(g1 - g2) + MHelper.pow2(b1 - b2); } - public static int extractColor(Identifier texture) { + private static Map colorPalette = Maps.newHashMap(); + + public static int extractColor(Item item) { + Identifier id = Registry.ITEM.getId(item); + if (id.equals(Registry.ITEM.getDefaultId())) return -1; + if (colorPalette.containsKey(id)) { + return colorPalette.get(id); + } + Identifier texture; + if (item instanceof BlockItem) { + texture = new Identifier(id.getNamespace(), "textures/block/" + id.getPath() + ".png"); + } else { + texture = new Identifier(id.getNamespace(), "textures/item/" + id.getPath() + ".png"); + } NativeImage image = loadImage(texture, 16, 16); List colors = new ArrayList<>(); for (int i = 0; i < image.getWidth(); i++) { @@ -202,7 +221,10 @@ public class ColorUtil { if (colors.size() == 0) return -1; ColorExtractor extractor = new ColorExtractor(colors); - return extractor.analize(); + int color = extractor.analize(); + colorPalette.put(id, color); + + return color; } public static NativeImage loadImage(Identifier image, int w, int h) { diff --git a/src/main/resources/assets/betterend/particles/infusion.json b/src/main/resources/assets/betterend/particles/infusion.json new file mode 100644 index 00000000..7af4e687 --- /dev/null +++ b/src/main/resources/assets/betterend/particles/infusion.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:spell_7", + "minecraft:spell_6", + "minecraft:spell_5", + "minecraft:spell_4", + "minecraft:spell_3", + "minecraft:spell_2", + "minecraft:spell_1", + "minecraft:spell_0" + ] +} \ No newline at end of file