Infusion particles

This commit is contained in:
Aleksey 2020-11-22 18:18:23 +03:00
parent 6dccc0bf32
commit d9aa50fe1c
6 changed files with 193 additions and 17 deletions

View file

@ -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<InfusionParticleType> {
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);
}
}
}

View file

@ -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<InfusionParticleType> implements ParticleEffect {
public static final Codec<InfusionParticleType> CODEC = ItemStack.CODEC.xmap(itemStack -> {
return new InfusionParticleType(EndParticles.INFUSION, itemStack);
}, infusionParticleType -> {
return infusionParticleType.itemStack;
});
public static final ParticleEffect.Factory<InfusionParticleType> PARAMETERS_FACTORY = new ParticleEffect.Factory<InfusionParticleType>() {
public InfusionParticleType read(ParticleType<InfusionParticleType> 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<InfusionParticleType> particleType, PacketByteBuf packetByteBuf) {
return new InfusionParticleType(particleType, packetByteBuf.readItemStack());
}
};
private ParticleType<InfusionParticleType> type;
private ItemStack itemStack;
public InfusionParticleType(ParticleType<InfusionParticleType> 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<InfusionParticleType> getCodec() {
return CODEC;
}
}

View file

@ -3,21 +3,31 @@ package ru.betterend.registry;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes;
import net.minecraft.particle.DefaultParticleType; import net.minecraft.particle.DefaultParticleType;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleType;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import ru.betterend.BetterEnd; import ru.betterend.BetterEnd;
import ru.betterend.particle.InfusionParticle;
import ru.betterend.particle.InfusionParticleType;
import ru.betterend.particle.ParticleGlowingSphere; import ru.betterend.particle.ParticleGlowingSphere;
import ru.betterend.particle.PaticlePortalSphere; import ru.betterend.particle.PaticlePortalSphere;
public class EndParticles { public class EndParticles {
public static final DefaultParticleType GLOWING_SPHERE = register("glowing_sphere"); public static final DefaultParticleType GLOWING_SPHERE = register("glowing_sphere");
public static final DefaultParticleType PORTAL_SPHERE = register("portal_sphere"); public static final DefaultParticleType PORTAL_SPHERE = register("portal_sphere");
public static final ParticleType<InfusionParticleType> INFUSION = register("infusion", FabricParticleTypes.complex(InfusionParticleType.PARAMETERS_FACTORY));
public static void register() { public static void register() {
ParticleFactoryRegistry.getInstance().register(GLOWING_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new); ParticleFactoryRegistry.getInstance().register(GLOWING_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new);
ParticleFactoryRegistry.getInstance().register(PORTAL_SPHERE, PaticlePortalSphere.FactoryPortalSphere::new); ParticleFactoryRegistry.getInstance().register(PORTAL_SPHERE, PaticlePortalSphere.FactoryPortalSphere::new);
ParticleFactoryRegistry.getInstance().register(INFUSION, InfusionParticle.DefaultFactory::new);
} }
private static DefaultParticleType register(String name) { private static DefaultParticleType register(String name) {
return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple()); return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), FabricParticleTypes.simple());
} }
private static <T extends ParticleEffect> ParticleType<T> register(String name, ParticleType<T> type) {
return Registry.register(Registry.PARTICLE_TYPE, BetterEnd.makeID(name), type);
}
} }

View file

@ -8,14 +8,14 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory; import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.particle.ItemStackParticleEffect;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.World; import net.minecraft.world.World;
import ru.betterend.blocks.entities.InfusionPedestalEntity; import ru.betterend.blocks.entities.InfusionPedestalEntity;
import ru.betterend.blocks.entities.PedestalBlockEntity; import ru.betterend.blocks.entities.PedestalBlockEntity;
import ru.betterend.particle.InfusionParticleType;
import ru.betterend.recipe.builders.InfusionRecipe; import ru.betterend.recipe.builders.InfusionRecipe;
public class InfusionRitual implements Inventory { 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); InfusionRecipe recipe = this.world.getRecipeManager().getFirstMatch(InfusionRecipe.TYPE, this, world).orElse(null);
if (hasRecipe()) { if (hasRecipe()) {
if (recipe == null) { if (recipe == null) {
this.activeRecipe = null; this.stop();
this.hasRecipe = false;
this.progress = 0;
this.time = 0;
this.markDirty();
return false; return false;
} else if (recipe.getInfusionTime() != time) { } else if (recipe.getInfusionTime() != time) {
this.activeRecipe = recipe; this.activeRecipe = recipe;
@ -115,16 +111,12 @@ public class InfusionRitual implements Inventory {
for (PedestalBlockEntity catalyst : catalysts) { for (PedestalBlockEntity catalyst : catalysts) {
catalyst.removeStack(world, world.getBlockState(catalyst.getPos())); catalyst.removeStack(world, world.getBlockState(catalyst.getPos()));
} }
this.activeRecipe = null; this.stop();
this.hasRecipe = false;
this.progress = 0;
this.time = 0;
this.markDirty();
} else { } else {
ServerWorld world = (ServerWorld) this.world; ServerWorld world = (ServerWorld) this.world;
BlockPos target = this.worldPos.up(); BlockPos target = this.worldPos.up();
double tx = target.getX() + 0.5; double tx = target.getX() + 0.5;
double ty = target.getY() + 1.75; double ty = target.getY() + 0.5;
double tz = target.getZ() + 0.5; double tz = target.getZ() + 0.5;
for (PedestalBlockEntity catalyst : catalysts) { for (PedestalBlockEntity catalyst : catalysts) {
ItemStack stack = catalyst.getStack(0); ItemStack stack = catalyst.getStack(0);
@ -133,8 +125,7 @@ public class InfusionRitual implements Inventory {
double sx = start.getX() + 0.5; double sx = start.getX() + 0.5;
double sy = start.getY() + 1.25; double sy = start.getY() + 1.25;
double sz = start.getZ() + 0.5; double sz = start.getZ() + 0.5;
ItemStackParticleEffect catalystParticle = new ItemStackParticleEffect(ParticleTypes.ITEM, stack); world.spawnParticles(new InfusionParticleType(stack), sx, sy, sz, 0, tx - sx, ty - sy, tz - sz, 0.5);
world.spawnParticles(catalystParticle, sx, sy, sz, 0, tx - sx, ty - sy, tz - sz, 0.125);
} }
} }
} }

View file

@ -3,6 +3,9 @@ package ru.betterend.util;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; 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.MinecraftClient;
import net.minecraft.client.texture.NativeImage; 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.Resource;
import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.registry.Registry;
import ru.betterend.BetterEnd; import ru.betterend.BetterEnd;
@ -186,7 +192,20 @@ public class ColorUtil {
return MHelper.pow2(r1 - r2) + MHelper.pow2(g1 - g2) + MHelper.pow2(b1 - b2); return MHelper.pow2(r1 - r2) + MHelper.pow2(g1 - g2) + MHelper.pow2(b1 - b2);
} }
public static int extractColor(Identifier texture) { private static Map<Identifier, Integer> 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); NativeImage image = loadImage(texture, 16, 16);
List<Integer> colors = new ArrayList<>(); List<Integer> colors = new ArrayList<>();
for (int i = 0; i < image.getWidth(); i++) { for (int i = 0; i < image.getWidth(); i++) {
@ -202,7 +221,10 @@ public class ColorUtil {
if (colors.size() == 0) return -1; if (colors.size() == 0) return -1;
ColorExtractor extractor = new ColorExtractor(colors); 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) { public static NativeImage loadImage(Identifier image, int w, int h) {

View file

@ -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"
]
}