Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ artifact = particle
description = ParticleLib
author = GeorgeV22
version = 1.3.2
mcVersion = 1.21.4
mcVersion = 1.21.10
39 changes: 28 additions & 11 deletions src/main/java/com/georgev22/particle/ParticleBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public ParticleBuilder(ParticleEffect particle, Location location) {
*/
public ParticleBuilder(ParticleEffect particle) {
this.particle = particle;
this.location = null;
location = null;
}


Expand Down Expand Up @@ -238,9 +238,9 @@ public ParticleBuilder setOffsetY(float offsetY) {
* @return the current instance to support building operations
*/
public ParticleBuilder setOffset(Vector offset) {
this.offsetX = (float) offset.getX();
this.offsetY = (float) offset.getY();
this.offsetZ = (float) offset.getZ();
offsetX = (float) offset.getX();
offsetY = (float) offset.getY();
offsetZ = (float) offset.getZ();
return this;
}

Expand Down Expand Up @@ -339,8 +339,25 @@ public ParticleBuilder setParticleData(ParticleData particleData) {
* @return the current instance to support building operations
*/
public ParticleBuilder setColor(Color color) {
if (this.particle.hasProperty(PropertyType.COLORABLE))
this.particleData = new RegularColor(color);
if (particle.hasProperty(PropertyType.COLORABLE))
particleData = new RegularColor(color);
return this;
}

/**
* Sets the color of the particle. Note that particle
* needs the {@link PropertyType#COLORABLE} PropertyType
* to work.
*
* @param color the {@link Color} of the particle.
* @param alpha the alpha/brightness value of the color.
* A value of 1f means full brightness. (Introduced in 1.20.5)
* Using this parameter below 1.20.5 will have no effect.
* @return the current instance to support building operations
*/
public ParticleBuilder setColor(Color color, float alpha) {
if (particle.hasProperty(PropertyType.COLORABLE))
particleData = new RegularColor(color, alpha);
return this;
}

Expand All @@ -353,10 +370,10 @@ public ParticleBuilder setColor(Color color) {
public Object toPacket() {
if (location == null)
throw new IllegalStateException("Missing location of particle.");
if (this.particleData != null)
this.particleData.setEffect(this.particle);
ParticlePacket packet = new ParticlePacket(this.particle, this.offsetX, this.offsetY, this.offsetZ, this.speed, this.amount, this.particleData);
return packet.createPacket(this.location);
if (particleData != null)
particleData.setEffect(particle);
ParticlePacket packet = new ParticlePacket(particle, offsetX, offsetY, offsetZ, speed, amount, particleData);
return packet.createPacket(location);
}

/**
Expand All @@ -374,7 +391,7 @@ public void display() {
* @param players The players that should see the particle.
*/
public void display(Player... players) {
this.display(Arrays.asList(players));
display(Arrays.asList(players));
}

/**
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/georgev22/particle/ParticleConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ public final class ParticleConstants {
*/
public static final Class TRAIL_PARTICLE_OPTION_CLASS;

/**
* Represents the ColorParticleOption class.
*/
public static final Class COLOR_PARTICLE_OPTION_CLASS;

/* ---------------- Methods ---------------- */

/**
Expand Down Expand Up @@ -208,6 +213,11 @@ public final class ParticleConstants {
*/
public static final Method MINECRAFT_KEY_METHOD;

/**
* Represents the ColorParticleOption#create(); method.
*/
public static final Method COLOR_PARTICLE_OPTION_CREATE_METHOD;

/* ---------------- Fields ---------------- */

/**
Expand Down Expand Up @@ -282,6 +292,11 @@ public final class ParticleConstants {
*/
public static final Constructor TRAIL_PARTICLE_OPTION_CONSTRUCTOR;

/**
* Represents the ColorParticleOption constructor.
*/
public static final Constructor COLOR_PARTICLE_OPTION_CONSTRUCTOR;


/* ---------------- Object constants ---------------- */

Expand Down Expand Up @@ -333,6 +348,7 @@ public final class ParticleConstants {
PARTICLE_PARAM_SHRIEK_CLASS = getMappedClass("ParticleParamShriek");
PARTICLE_PARAM_SCULK_CHARGE_CLASS = getMappedClass("ParticleParamSculkCharge");
TRAIL_PARTICLE_OPTION_CLASS = getMappedClass("TrailParticleOption");
COLOR_PARTICLE_OPTION_CLASS = getMappedClass("ColorParticleOption");

// Methods
REGISTRY_GET_METHOD = getMappedMethod(REGISTRY_CLASS, "Registry.get", MINECRAFT_KEY_CLASS);
Expand All @@ -342,6 +358,10 @@ public final class ParticleConstants {
BLOCK_GET_BLOCK_DATA_METHOD = getMappedMethod(BLOCK_CLASS, "Block.getBlockData");
CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD = getMethodOrNull(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
MINECRAFT_KEY_METHOD = getMappedMethod(MINECRAFT_KEY_CLASS, "MinecraftKey.parse", String.class);
COLOR_PARTICLE_OPTION_CREATE_METHOD = version < 20.5 ? null : getMappedMethod(COLOR_PARTICLE_OPTION_CLASS, "ColorParticleOption.create", PARTICLE_CLASS, int.class);
if (COLOR_PARTICLE_OPTION_CREATE_METHOD != null) {
COLOR_PARTICLE_OPTION_CREATE_METHOD.setAccessible(true); // Make accessible in case it's not public
}

// Fields
ENTITY_PLAYER_PLAYER_CONNECTION_FIELD = getMappedField(ENTITY_PLAYER_CLASS, "EntityPlayer.playerConnection", false);
Expand Down Expand Up @@ -401,6 +421,10 @@ else if (version < 19)
? getConstructorOrNull(TRAIL_PARTICLE_OPTION_CLASS, VEC_3D_CLASS, int.class)
: getConstructorOrNull(TRAIL_PARTICLE_OPTION_CLASS, VEC_3D_CLASS, int.class, int.class));

COLOR_PARTICLE_OPTION_CONSTRUCTOR = version < 20.5
? null
: getConstructorOrNull(COLOR_PARTICLE_OPTION_CLASS, PARTICLE_CLASS, int.class);

// Constants
PARTICLE_TYPE_REGISTRY = readField(
version < 19.3
Expand Down
45 changes: 41 additions & 4 deletions src/main/java/com/georgev22/particle/ParticleEffect.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
* <li>{@link #CHERRY_LEAVES}</li>
* <li>{@link #CLOUD}</li>
* <li>{@link #COMPOSTER}</li>
* <li>{@link #COPPER_FIRE_FLAME}</li>
* <li>{@link #CRIMSON_SPORE}</li>
* <li>{@link #CRIT}</li>
* <li>{@link #CRIT_MAGIC}</li>
Expand Down Expand Up @@ -94,6 +95,7 @@
* <li>{@link #FALLING_NECTAR}</li>
* <li>{@link #FALLING_OBSIDIAN_TEAR}</li>
* <li>{@link #FALLING_SPORE_BLOSSOM}</li>
* <li>{@link #FIREFLY}</li>
* <li>{@link #FIREWORKS_SPARK}</li>
* <li>{@link #FLAME}</li>
* <li>{@link #FLASH}</li>
Expand Down Expand Up @@ -148,6 +150,7 @@
* <li>{@link #SUSPENDED}</li>
* <li>{@link #SUSPENDED_DEPTH}</li>
* <li>{@link #SWEEP_ATTACK}</li>
* <li>{@link #TINTED_LEAVES}</li>
* <li>{@link #TOTEM}</li>
* <li>{@link #TOWN_AURA}</li>
* <li>{@link #TRAIL}</li>
Expand Down Expand Up @@ -311,7 +314,7 @@ public enum ParticleEffect {
* <li>Speed value: Doesn't influence the particle.</li>
* </ul>
*/
CHERRY_LEAVES(version -> version < 19.4 ? "NONE" : version < 20 ? "falling_cherry_leaves" : "cherry_leaves", DIRECTIONAL),
CHERRY_LEAVES(version -> version < 19.4 ? "NONE" : (version < 20 ? "falling_cherry_leaves" : "cherry_leaves"), DIRECTIONAL),
/**
* In vanilla, this particle is displayed when an entity dies.
* <p>
Expand All @@ -334,6 +337,17 @@ public enum ParticleEffect {
* </ul>
*/
COMPOSTER(version -> version < 14 ? "NONE" : "composter"),
/**
* In vanilla, this particle is randomly displayed by copper torches.
* <p>
* <b>Information</b>:
* <ul>
* <li>Appearance: Green flame.</li>
* <li>Speed value: Influences the velocity at which the particle flies off.</li>
* <li>Extra: The velocity of this particle can be set. The amount has to be 0.</li>
* </ul>
*/
COPPER_FIRE_FLAME(version -> version < 21.9 ? "NONE" : "copper_fire_flame", DIRECTIONAL),
/**
* In vanilla, this particle is displayed in the crimson forest
* nether biome.
Expand Down Expand Up @@ -665,6 +679,17 @@ public enum ParticleEffect {
* </ul>
*/
FALLING_SPORE_BLOSSOM(version -> version < 17 ? "NONE" : "falling_spore_blossom"),
/**
* In vanilla, this particle is displayed by firefly
* bushes.
* <p>
* <b>Information</b>:
* <ul>
* <li>Appearance: Flashing white square.</li>
* <li>Speed value: Influences the velocity at which the particle flies off.</li>
* </ul>
*/
FIREFLY(version -> version < 21.5 ? "NONE" : "firefly", DIRECTIONAL),
/**
* In vanilla, this particle is displayed when a firework is
* launched.
Expand Down Expand Up @@ -1194,7 +1219,7 @@ public enum ParticleEffect {
* <li>Extra: offsetX, offsetY and offsetZ represent the rgb values of the particle. The amount has to be 0 or the color won't work.</li>
* </ul>
*/
SPELL_MOB(version -> version < 8 ? "NONE" : (version < 13 ? "SPELL_MOB" : "entity_effect"), COLORABLE),
SPELL_MOB(version -> version < 8 ? "NONE" : (version < 13 ? "SPELL_MOB" : "entity_effect"), COLORABLE, REGULAR_COLOR),
/**
* In vanilla, this particle is displayed when an entity has
* an active potion effect from a nearby beacon.
Expand All @@ -1206,7 +1231,7 @@ public enum ParticleEffect {
* <li>Extra: offsetX, offsetY and offsetZ represent the rgb values of the particle. The amount has to be 0 or the color won't work.</li>
* </ul>
*/
SPELL_MOB_AMBIENT(version -> version < 8 ? "NONE" : (version < 13 ? "SPELL_MOB_AMBIENT" : version > 20.4 ? "NONE" : "ambient_entity_effect"), COLORABLE),
SPELL_MOB_AMBIENT(version -> version < 8 ? "NONE" : (version < 13 ? "SPELL_MOB_AMBIENT" : (version < 20.5 ? "ambient_entity_effect" : "entity_effect")), COLORABLE, REGULAR_COLOR),
/**
* In vanilla, this particle is displayed randomly by witches.
* <p>
Expand Down Expand Up @@ -1285,6 +1310,17 @@ public enum ParticleEffect {
* </ul>
*/
SWEEP_ATTACK(version -> version < 9 ? "NONE" : (version < 13 ? "SWEEP_ATTACK" : "sweep_attack"), RESIZEABLE),
/**
* In vanilla, this particle is displayed falling from trees.
* <p>
* <b>Information</b>:
* <ul>
* <li>Appearance: A colored leaf.</li>
* <li>Speed value: Represents the lightness of the color.</li>
* <li>Extra: offsetX, offsetY and offsetZ represent the rgb values of the particle. The amount has to be 0 or the color won't work.</li>
* </ul>
*/
TINTED_LEAVES(version -> version < 21.5 ? "NONE" : "tinted_leaves", COLORABLE, REGULAR_COLOR),
/**
* In vanilla, this particle is displayed when a totem of
* undying is used.
Expand Down Expand Up @@ -1613,7 +1649,8 @@ public boolean isCorrectColor(ParticleColor color) {
return this == DUST_COLOR_TRANSITION;
if (color instanceof DustData)
return hasProperty(DUST);
return hasProperty(COLORABLE) && (this.equals(ParticleEffect.NOTE) ? color instanceof NoteColor : color instanceof RegularColor);

return hasProperty(COLORABLE) && (equals(NOTE) ? color instanceof NoteColor : color instanceof RegularColor);
}

/**
Expand Down
97 changes: 66 additions & 31 deletions src/main/java/com/georgev22/particle/ParticlePacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ public ParticleData getParticleData() {
*/
public Object createPacket(Location location) {
try {
ParticleEffect effect = getParticle();
ParticleData data = getParticleData();
ParticleEffect effect = particle;
ParticleData data = particleData;
double version = ReflectionUtils.MINECRAFT_VERSION;
if (effect == null || effect.getFieldName().equals("NONE"))
return null;
Expand All @@ -276,8 +276,8 @@ public Object createPacket(Location location) {
} else if (!effect.hasProperty(PropertyType.REQUIRES_BLOCK) && !effect.hasProperty(PropertyType.REQUIRES_ITEM))
return createPacket(effect.getNMSObject(),
(float) location.getX(), (float) location.getY(), (float) location.getZ(),
getOffsetX(), getOffsetY(), getOffsetZ(),
getSpeed(), getAmount(), new int[0]);
offsetX, offsetY, offsetZ,
speed, amount, new int[0]);
} catch (Exception ignored) {
}
return null;
Expand All @@ -296,8 +296,8 @@ public Object createPacket(Location location) {
private Object createGenericParticlePacket(Location location, Object param) {
return createPacket(param,
(float) location.getX(), (float) location.getY(), (float) location.getZ(),
getOffsetX(), getOffsetY(), getOffsetZ(),
getSpeed(), getAmount(), new int[0]
offsetX, offsetY, offsetZ,
speed, amount, new int[0]
);
}

Expand All @@ -314,12 +314,11 @@ private Object createGenericParticlePacket(Location location, Object param) {
* @see PropertyType#REQUIRES_ITEM
*/
private Object createTexturedParticlePacket(Location location, Object param) {
ParticleEffect effect = getParticle();
double version = ReflectionUtils.MINECRAFT_VERSION;
return createPacket(version < 13 ? effect.getNMSObject() : param,
return createPacket(version < 13 ? particle.getNMSObject() : param,
(float) location.getX(), (float) location.getY(), (float) location.getZ(),
getOffsetX(), getOffsetY(), getOffsetZ(),
getSpeed(), getAmount(), version < 13 ? (int[]) param : new int[0]
offsetX, offsetY, offsetZ,
speed, amount, version < 13 ? (int[]) param : new int[0]
);
}

Expand All @@ -335,30 +334,66 @@ private Object createTexturedParticlePacket(Location location, Object param) {
* @see PropertyType#COLORABLE
*/
private Object createColoredParticlePacket(Location location, Object param) {
ParticleEffect effect = getParticle();
ParticleData data = getParticleData();
if (data instanceof NoteColor && effect.equals(ParticleEffect.NOTE)) {
ParticleEffect effect = particle;
ParticleData data = particleData;

float x = (float) location.getX();
float y = (float) location.getY();
float z = (float) location.getZ();


if (data instanceof NoteColor && effect == ParticleEffect.NOTE) {
return createPacket(effect.getNMSObject(),
(float) location.getX(), (float) location.getY(), (float) location.getZ(),
x, y, z,
((NoteColor) data).getRed(), 0f, 0f,
getSpeed(), getAmount(), new int[0]
speed, amount, new int[0]
);
} else if (data instanceof RegularColor) {
RegularColor color = ((RegularColor) data);
if (ReflectionUtils.MINECRAFT_VERSION < 13 || !effect.equals(ParticleEffect.REDSTONE)) {
return createPacket(effect.getNMSObject(),
(float) location.getX(), (float) location.getY(), (float) location.getZ(),
(effect.equals(ParticleEffect.REDSTONE) && color.getRed() == 0 ? Float.MIN_NORMAL : color.getRed()), color.getGreen(), color.getBlue(),
1f, 0, new int[0]
);
} else {
return createPacket(param,
(float) location.getX(), (float) location.getY(), (float) location.getZ(),
getOffsetX(), getOffsetY(), getOffsetZ(),
getSpeed(), getAmount(), new int[0]
);
}
} else return null;
}

if (!(data instanceof RegularColor)) {
return null;
}

RegularColor colorData = (RegularColor) data;

float r = colorData.getRed();
float g = colorData.getGreen();
float b = colorData.getBlue();

// 1.20.5+: Use ColorParticleOption param for regular colored particles
// Alpha/brightness is encoded in the ALPHA byte (0..255).
if (effect.hasProperty(PropertyType.REGULAR_COLOR) && ReflectionUtils.MINECRAFT_VERSION >= 20.5) {
// When using a ParticleParam, count/offset/speed are ignored client-side.
return createPacket(
param,
x, y, z,
0f, 0f, 0f,
0f, 0,
new int[0]
);
}

// Other colored particles
if (ReflectionUtils.MINECRAFT_VERSION < 13 || effect != ParticleEffect.REDSTONE) {
return createPacket(
effect.getNMSObject(),
x,y,z,
(effect == ParticleEffect.REDSTONE && r == 0 ? Float.MIN_NORMAL : r),
g,
b,
1f,
0,
new int[0]
);
} else {
return createPacket(
param,
x, y, z,
offsetX, offsetY, offsetZ,
speed, amount,
new int[0]
);
}
}

/**
Expand Down
Loading