This commit is contained in:
Esophose 2020-05-11 13:04:11 -06:00
parent 80a4613725
commit 9567b06e23
147 changed files with 1811 additions and 1406 deletions

View file

@ -0,0 +1,3 @@
dependencies {
shadow 'org.spigotmc:spigot:1.15.2-R0.1-SNAPSHOT'
}

View file

@ -0,0 +1,19 @@
package dev.esophose.playerparticles.nms.wrapper;
import dev.esophose.playerparticles.particles.ParticleEffect;
import dev.esophose.playerparticles.particles.version.VersionMapping;
import java.util.Collection;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public abstract class ParticleHandler {
protected VersionMapping versionMapping;
public ParticleHandler(VersionMapping versionMapping) {
this.versionMapping = versionMapping;
}
public abstract void spawnParticle(ParticleEffect particleEffect, Collection<Player> players, Location location, int count, float offsetX, float offsetY, float offsetZ, float extra, Object data);
}

View file

@ -0,0 +1,103 @@
package dev.esophose.playerparticles.particles;
import java.util.Arrays;
import java.util.List;
public enum ParticleEffect {
AMBIENT_ENTITY_EFFECT(ParticleProperty.REQUIRES_COLOR_DATA),
ANGRY_VILLAGER,
ASH,
BARRIER,
BLOCK(ParticleProperty.REQUIRES_BLOCK_DATA),
BUBBLE,
BUBBLE_COLUMN_UP,
BUBBLE_POP,
CAMPFIRE_COSY_SMOKE,
CAMPFIRE_SIGNAL_SMOKE,
CLOUD,
COMPOSTER,
CRIMSON_SPORE,
CRIT,
CURRENT_DOWN,
DAMAGE_INDICATOR,
DOLPHIN,
DRAGON_BREATH,
DRIPPING_HONEY,
DRIPPING_LAVA,
DRIPPING_OBSIDIAN_TEAR,
DRIPPING_WATER,
DUST(ParticleProperty.REQUIRES_COLOR_DATA),
ELDER_GUARDIAN,
ENCHANT,
ENCHANTED_HIT,
END_ROD,
ENTITY_EFFECT(ParticleProperty.REQUIRES_COLOR_DATA),
EXPLOSION,
EXPLOSION_EMITTER,
FALLING_DUST(ParticleProperty.REQUIRES_BLOCK_DATA),
FALLING_HONEY,
FALLING_LAVA,
FALLING_NECTAR,
FALLING_OBSIDIAN_TEAR,
FALLING_WATER,
FIREWORK,
FISHING,
FLAME,
FLASH,
FOOTSTEP,
HAPPY_VILLAGER,
HEART,
INSTANT_EFFECT,
ITEM(ParticleProperty.REQUIRES_ITEM_DATA),
ITEM_SLIME,
ITEM_SNOWBALL,
LANDING_HONEY,
LANDING_LAVA,
LANDING_OBSIDIAN_TEAR,
LARGE_SMOKE,
LAVA,
MYCELIUM,
NAUTILUS,
NOTE(ParticleProperty.REQUIRES_COLOR_DATA),
POOF,
PORTAL,
RAIN,
SMOKE,
SNEEZE,
SOUL,
SOUL_FIRE_FLAME,
SPELL, // The Minecraft internal name for this is actually "effect", but that's the command name, so it's SPELL for the plugin instead
SPIT,
SPLASH,
SQUID_INK,
SWEEP_ATTACK,
TOTEM_OF_UNDYING,
UNDERWATER,
WARPED_SPORE,
WITCH;
private List<ParticleProperty> properties;
ParticleEffect(ParticleProperty... properties) {
this.properties = Arrays.asList(properties);
}
/**
* Determine if this particle effect has a specific property
*
* @param property The property to check
* @return Whether it has the property or not
*/
public boolean hasProperty(ParticleProperty property) {
return this.properties.contains(property);
}
/**
* @return true if this ParticleEffect has properties, otherwise false
*/
public boolean hasProperties() {
return !this.properties.isEmpty();
}
}

View file

@ -0,0 +1,12 @@
package dev.esophose.playerparticles.particles;
/**
* Represents a property of a particle effect
*/
public enum ParticleProperty {
REQUIRES_BLOCK_DATA,
REQUIRES_ITEM_DATA,
REQUIRES_COLOR_DATA
}

View file

@ -0,0 +1,43 @@
package dev.esophose.playerparticles.particles.version;
import dev.esophose.playerparticles.particles.ParticleEffect;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("StaticInitializerReferencesSubClass")
public abstract class VersionMapping {
public static final VersionMapping _16 = new VersionMapping16();
public static final VersionMapping _15 = new VersionMapping15();
private final Map<ParticleEffect, Integer> particleEffectNameMapping;
public VersionMapping() {
this.particleEffectNameMapping = new HashMap<>();
}
public abstract Map<Integer, ParticleEffect> getParticleEffectIdMapping();
public Map<ParticleEffect, Integer> getParticleEffectNameMapping() {
if (this.particleEffectNameMapping.isEmpty())
this.getParticleEffectIdMapping().forEach((key, value) -> this.particleEffectNameMapping.put(value, key));
return this.particleEffectNameMapping;
}
public static VersionMapping getVersionMapping(int version) {
switch (version) {
case 16:
return _16;
case 15:
return _15;
}
return new VersionMapping() {
@Override
public Map<Integer, ParticleEffect> getParticleEffectIdMapping() {
return new HashMap<>();
}
};
}
}

View file

@ -0,0 +1,83 @@
package dev.esophose.playerparticles.particles.version;
import dev.esophose.playerparticles.particles.ParticleEffect;
import java.util.HashMap;
import java.util.Map;
public class VersionMapping15 extends VersionMapping {
private final Map<Integer, ParticleEffect> particleEffectNameMapping;
public VersionMapping15() {
this.particleEffectNameMapping = new HashMap<Integer, ParticleEffect>() {{
this.put(0, ParticleEffect.AMBIENT_ENTITY_EFFECT);
this.put(1, ParticleEffect.ANGRY_VILLAGER);
this.put(2, ParticleEffect.BARRIER);
this.put(3, ParticleEffect.BLOCK);
this.put(4, ParticleEffect.BUBBLE);
this.put(5, ParticleEffect.CLOUD);
this.put(6, ParticleEffect.CRIT);
this.put(7, ParticleEffect.DAMAGE_INDICATOR);
this.put(8, ParticleEffect.DRAGON_BREATH);
this.put(9, ParticleEffect.DRIPPING_LAVA);
this.put(10, ParticleEffect.FALLING_LAVA);
this.put(11, ParticleEffect.LANDING_LAVA);
this.put(12, ParticleEffect.DRIPPING_WATER);
this.put(13, ParticleEffect.FALLING_WATER);
this.put(14, ParticleEffect.DUST);
this.put(15, ParticleEffect.SPELL);
this.put(16, ParticleEffect.ELDER_GUARDIAN);
this.put(17, ParticleEffect.ENCHANTED_HIT);
this.put(18, ParticleEffect.ENCHANT);
this.put(19, ParticleEffect.END_ROD);
this.put(20, ParticleEffect.ENTITY_EFFECT);
this.put(21, ParticleEffect.EXPLOSION_EMITTER);
this.put(22, ParticleEffect.EXPLOSION);
this.put(23, ParticleEffect.FALLING_DUST);
this.put(24, ParticleEffect.FIREWORK);
this.put(25, ParticleEffect.FISHING);
this.put(26, ParticleEffect.FLAME);
this.put(27, ParticleEffect.FLASH);
this.put(28, ParticleEffect.HAPPY_VILLAGER);
this.put(29, ParticleEffect.COMPOSTER);
this.put(30, ParticleEffect.HEART);
this.put(31, ParticleEffect.INSTANT_EFFECT);
this.put(32, ParticleEffect.ITEM);
this.put(33, ParticleEffect.ITEM_SLIME);
this.put(34, ParticleEffect.ITEM_SNOWBALL);
this.put(35, ParticleEffect.LARGE_SMOKE);
this.put(36, ParticleEffect.LAVA);
this.put(37, ParticleEffect.MYCELIUM);
this.put(38, ParticleEffect.NOTE);
this.put(39, ParticleEffect.POOF);
this.put(40, ParticleEffect.PORTAL);
this.put(41, ParticleEffect.RAIN);
this.put(42, ParticleEffect.SMOKE);
this.put(43, ParticleEffect.SNEEZE);
this.put(44, ParticleEffect.SPIT);
this.put(45, ParticleEffect.SQUID_INK);
this.put(46, ParticleEffect.SWEEP_ATTACK);
this.put(47, ParticleEffect.TOTEM_OF_UNDYING);
this.put(48, ParticleEffect.UNDERWATER);
this.put(49, ParticleEffect.SPLASH);
this.put(50, ParticleEffect.WITCH);
this.put(51, ParticleEffect.BUBBLE_POP);
this.put(52, ParticleEffect.CURRENT_DOWN);
this.put(53, ParticleEffect.BUBBLE_COLUMN_UP);
this.put(54, ParticleEffect.NAUTILUS);
this.put(55, ParticleEffect.DOLPHIN);
this.put(56, ParticleEffect.CAMPFIRE_COSY_SMOKE);
this.put(57, ParticleEffect.CAMPFIRE_SIGNAL_SMOKE);
this.put(58, ParticleEffect.DRIPPING_HONEY);
this.put(59, ParticleEffect.FALLING_HONEY);
this.put(60, ParticleEffect.LANDING_HONEY);
this.put(61, ParticleEffect.FALLING_NECTAR);
}};
}
@Override
public Map<Integer, ParticleEffect> getParticleEffectIdMapping() {
return this.particleEffectNameMapping;
}
}

View file

@ -0,0 +1,91 @@
package dev.esophose.playerparticles.particles.version;
import dev.esophose.playerparticles.particles.ParticleEffect;
import java.util.HashMap;
import java.util.Map;
public class VersionMapping16 extends VersionMapping {
private final Map<Integer, ParticleEffect> particleEffectNameMapping;
public VersionMapping16() {
this.particleEffectNameMapping = new HashMap<Integer, ParticleEffect>() {{
this.put(0, ParticleEffect.AMBIENT_ENTITY_EFFECT);
this.put(1, ParticleEffect.ANGRY_VILLAGER);
this.put(2, ParticleEffect.BARRIER);
this.put(3, ParticleEffect.BLOCK);
this.put(4, ParticleEffect.BUBBLE);
this.put(5, ParticleEffect.CLOUD);
this.put(6, ParticleEffect.CRIT);
this.put(7, ParticleEffect.DAMAGE_INDICATOR);
this.put(8, ParticleEffect.DRAGON_BREATH);
this.put(9, ParticleEffect.DRIPPING_LAVA);
this.put(10, ParticleEffect.FALLING_LAVA);
this.put(11, ParticleEffect.LANDING_LAVA);
this.put(12, ParticleEffect.DRIPPING_WATER);
this.put(13, ParticleEffect.FALLING_WATER);
this.put(14, ParticleEffect.DUST);
this.put(15, ParticleEffect.SPELL);
this.put(16, ParticleEffect.ELDER_GUARDIAN);
this.put(17, ParticleEffect.ENCHANTED_HIT);
this.put(18, ParticleEffect.ENCHANT);
this.put(19, ParticleEffect.END_ROD);
this.put(20, ParticleEffect.ENTITY_EFFECT);
this.put(21, ParticleEffect.EXPLOSION_EMITTER);
this.put(22, ParticleEffect.EXPLOSION);
this.put(23, ParticleEffect.FALLING_DUST);
this.put(24, ParticleEffect.FIREWORK);
this.put(25, ParticleEffect.FISHING);
this.put(26, ParticleEffect.FLAME);
this.put(27, ParticleEffect.SOUL_FIRE_FLAME);
this.put(28, ParticleEffect.SOUL);
this.put(29, ParticleEffect.FLASH);
this.put(30, ParticleEffect.HAPPY_VILLAGER);
this.put(31, ParticleEffect.COMPOSTER);
this.put(32, ParticleEffect.HEART);
this.put(33, ParticleEffect.INSTANT_EFFECT);
this.put(34, ParticleEffect.ITEM);
this.put(35, ParticleEffect.ITEM_SLIME);
this.put(36, ParticleEffect.ITEM_SNOWBALL);
this.put(37, ParticleEffect.LARGE_SMOKE);
this.put(38, ParticleEffect.LAVA);
this.put(39, ParticleEffect.MYCELIUM);
this.put(40, ParticleEffect.NOTE);
this.put(41, ParticleEffect.POOF);
this.put(42, ParticleEffect.PORTAL);
this.put(43, ParticleEffect.RAIN);
this.put(44, ParticleEffect.SMOKE);
this.put(45, ParticleEffect.SNEEZE);
this.put(46, ParticleEffect.SPIT);
this.put(47, ParticleEffect.SQUID_INK);
this.put(48, ParticleEffect.SWEEP_ATTACK);
this.put(49, ParticleEffect.TOTEM_OF_UNDYING);
this.put(50, ParticleEffect.UNDERWATER);
this.put(51, ParticleEffect.SPLASH);
this.put(52, ParticleEffect.WITCH);
this.put(53, ParticleEffect.BUBBLE_POP);
this.put(54, ParticleEffect.CURRENT_DOWN);
this.put(55, ParticleEffect.BUBBLE_COLUMN_UP);
this.put(56, ParticleEffect.NAUTILUS);
this.put(57, ParticleEffect.DOLPHIN);
this.put(58, ParticleEffect.CAMPFIRE_COSY_SMOKE);
this.put(59, ParticleEffect.CAMPFIRE_SIGNAL_SMOKE);
this.put(60, ParticleEffect.DRIPPING_HONEY);
this.put(61, ParticleEffect.FALLING_HONEY);
this.put(62, ParticleEffect.LANDING_HONEY);
this.put(63, ParticleEffect.FALLING_NECTAR);
this.put(64, ParticleEffect.ASH);
this.put(65, ParticleEffect.CRIMSON_SPORE);
this.put(66, ParticleEffect.WARPED_SPORE);
this.put(67, ParticleEffect.DRIPPING_OBSIDIAN_TEAR);
this.put(68, ParticleEffect.FALLING_OBSIDIAN_TEAR);
this.put(69, ParticleEffect.LANDING_OBSIDIAN_TEAR);
}};
}
@Override
public Map<Integer, ParticleEffect> getParticleEffectIdMapping() {
return this.particleEffectNameMapping;
}
}

View file

@ -0,0 +1,5 @@
dependencies {
implementation project(':NMS-Wrapper')
shadow 'org.spigotmc:spigot:1.15.2-R0.1-SNAPSHOT'
shadow 'com.comphenix.protocol:ProtocolLib:4.5.0'
}

View file

@ -0,0 +1,52 @@
package dev.esophose.playerparticles.nms.v1_15_R1;
import net.minecraft.server.v1_15_R1.PacketDataSerializer;
import net.minecraft.server.v1_15_R1.PacketPlayOutWorldParticles;
import net.minecraft.server.v1_15_R1.ParticleParam;
class ModifiedPacketPlayOutWorldParticles extends PacketPlayOutWorldParticles {
private int particleId;
private double x;
private double y;
private double z;
private float offsetX;
private float offsetY;
private float offsetZ;
private float extra;
private int count;
private boolean longDistance;
private ParticleParam particleParam;
public <T extends ParticleParam> ModifiedPacketPlayOutWorldParticles(int particleId, T particalParam, boolean longDistance, double x, double y, double z, float offsetX, float offsetY, float offsetZ, float extra, int count) {
this.particleId = particleId;
this.particleParam = particalParam;
this.longDistance = longDistance;
this.x = x;
this.y = y;
this.z = z;
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
this.extra = extra;
this.count = count;
}
@Override
public void b(PacketDataSerializer var0) {
var0.writeInt(this.particleId);
var0.writeBoolean(this.longDistance);
var0.writeDouble(this.x);
var0.writeDouble(this.y);
var0.writeDouble(this.z);
var0.writeFloat(this.offsetX);
var0.writeFloat(this.offsetY);
var0.writeFloat(this.offsetZ);
var0.writeFloat(this.extra);
var0.writeInt(this.count);
if (this.particleParam != null)
this.particleParam.a(var0);
}
}

View file

@ -0,0 +1,85 @@
package dev.esophose.playerparticles.nms.v1_15_R1;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import dev.esophose.playerparticles.nms.wrapper.ParticleHandler;
import dev.esophose.playerparticles.particles.ParticleEffect;
import dev.esophose.playerparticles.particles.version.VersionMapping;
import io.netty.buffer.Unpooled;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import net.minecraft.server.v1_15_R1.IRegistry;
import net.minecraft.server.v1_15_R1.PacketDataSerializer;
import net.minecraft.server.v1_15_R1.PacketPlayOutWorldParticles;
import net.minecraft.server.v1_15_R1.Particle;
import net.minecraft.server.v1_15_R1.ParticleParam;
import net.minecraft.server.v1_15_R1.ParticleParamBlock;
import net.minecraft.server.v1_15_R1.ParticleParamItem;
import net.minecraft.server.v1_15_R1.ParticleParamRedstone;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle.DustOptions;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_15_R1.util.CraftMagicNumbers;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.util.Vector;
@SuppressWarnings("deprecation")
public class ParticleHandlerImpl extends ParticleHandler {
public ParticleHandlerImpl(VersionMapping versionMapping) {
super(versionMapping);
}
@Override
public void spawnParticle(ParticleEffect particleEffect, Collection<Player> players, Location location, int count, float offsetX, float offsetY, float offsetZ, float extra, Object data) {
int particleId = this.versionMapping.getParticleEffectNameMapping().get(particleEffect);
Particle nms = IRegistry.PARTICLE_TYPE.fromId(particleId);
ParticleParam particleParam = null;
if (data instanceof ItemStack) {
ItemStack itemStack = (ItemStack) data;
particleParam = new ParticleParamItem(nms, CraftItemStack.asNMSCopy(itemStack));
} else if (data instanceof MaterialData) {
MaterialData materialData = (MaterialData) data;
particleParam = new ParticleParamBlock(nms, CraftMagicNumbers.getBlock(materialData));
} else if (data instanceof BlockData) {
BlockData blockData = (BlockData) data;
particleParam = new ParticleParamBlock(nms, ((CraftBlockData) blockData).getState());
} else if (data instanceof DustOptions) {
DustOptions dustOptions = (DustOptions) data;
Color color = dustOptions.getColor();
particleParam = new ParticleParamRedstone((float) color.getRed() / 255.0F, (float) color.getGreen() / 255.0F, (float) color.getBlue() / 255.0F, dustOptions.getSize());
}
PacketPlayOutWorldParticles packetplayoutworldparticles = new ModifiedPacketPlayOutWorldParticles(particleId, particleParam, true, location.getX(), location.getY(), location.getZ(), offsetX, offsetY, offsetZ, extra, count);
PacketDataSerializer dataSerializer = new PacketDataSerializer(Unpooled.buffer());
try {
packetplayoutworldparticles.b(dataSerializer);
} catch (IOException e) {
e.printStackTrace();
}
ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
byte[] bytes = new byte[dataSerializer.readableBytes()];
dataSerializer.readBytes(bytes);
try {
for (Player player : players) {
protocolManager.sendWirePacket(player, 0x24, bytes);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}