How to create the swirly particle potion effect

Discussion in 'Resources' started by nisovin, Jan 22, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    nisovin

    I spent a couple hours today trying to figure out how to force a player to see the potion effect on another entity (that swirly particle effect that appears when you drink a potion). I finally figured it out, so I thought I'd share.

    Code:java
    1.  
    2. protected void playPotionEffect(final Player player, final LivingEntity entity, int color, int duration) {
    3. final DataWatcher dw = new DataWatcher();
    4. dw.a(8, Integer.valueOf(0));
    5. dw.watch(8, Integer.valueOf(color));
    6.  
    7. Packet40EntityMetadata packet = new Packet40EntityMetadata(entity.getEntityId(), dw);
    8. ((CraftPlayer)player).getHandle().netServerHandler.sendPacket(packet);
    9.  
    10. Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
    11. public void run() {
    12. DataWatcher dwReal = ((CraftLivingEntity)entity).getHandle().getDataWatcher();
    13. dw.watch(8, dwReal.getInt(8));
    14. Packet40EntityMetadata packet = new Packet40EntityMetadata(entity.getEntityId(), dw);
    15. ((CraftPlayer)player).getHandle().netServerHandler.sendPacket(packet);
    16. }
    17. }, duration);
    18. }
    19.  


    The effect will only show up for the player provided, and it will show up on the entity you specify. The color is a standard hex color, and the duration is in ticks. For example:

    Code:java
    1.  
    2. playPotionEffect(player, entity, 0x0000FF, 40);
    3.  


    That would show a blue potion swirl effect on the entity for two seconds.

    Update 5/2/2012:

    A bit after creating this, I modified it a bit (after reading the comments) so that it would be displayed for everyone nearby.

    Code:java
    1.  
    2. public void addPotionGraphicalEffect(LivingEntity entity, int color, int duration) {
    3. final EntityLiving el = ((CraftLivingEntity)entity).getHandle();
    4. final DataWatcher dw = el.getDataWatcher();
    5. dw.watch(8, Integer.valueOf(color));
    6.  
    7. Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
    8. public void run() {
    9. int c = 0;
    10. if (!el.effects.isEmpty()) {
    11. c = net.minecraft.server.PotionBrewer.a(el.effects.values());
    12. }
    13. dw.watch(8, Integer.valueOf(c));
    14. }
    15. }, duration);
    16. }
    17.  
     
  2. Offline

    ArcheCane

    Thanks.
     
  3. Offline

    Sir Savary

    You are amazing, tons of uses for this. Will come in handy when I finish my dungeon plugin, great for highlighting loot.
     
  4. Offline

    bergerkiller

    This has potential, Bukkit should really implement wrapper functions around Packet40EntityMetadata.

    Btw: Packet40Metadata simply transfer the 'datawatcher' data set for the entity. Using this packet it is also possible to make minecarts smoke. (it's the first time I encountered it)

    If you don't want to send packets, you can set the data of the DataWatcher object (entity.getDataWatcher()). The entity tracker will automatically send a meta data packet to all nearby players. (including self)
     
    emericask8ur likes this.
  5. Offline

    Don Redhorse

    code please :) I really hate that part of the classes...
     
  6. Offline

    nisovin

    Basically this:

    ((CraftLivingEntity)entity).getHandle().getDataWatcher().watch(int, Object);
     
  7. Offline

    Don Redhorse

    ah thanks... hmm and to keep the effect going I probably have to use a scheduler...
     
  8. Offline

    nisovin

    I believe it should actually stay until it's overwritten by another effect (like if the player drinks a potion that causes a new effect).
     
  9. Offline

    Don Redhorse

    ahh... that would be cool... I want to use that with an afk plugin.. when I ever get that time
     
    MakerofRobots likes this.
  10. Offline

    DrBowe

    Is it safe to assume that this can't be used to play the particle effect at any given location, and only at that of an entity?
     
  11. Offline

    nisovin

    Right. It uses entity metadata.
     
  12. Offline

    iPhysX

    nisovin
    You don't happen to know portal effects do you?
    I skimmed the post, this sort of stuff is new to me.
     
  13. Offline

    thehutch

    Nice work nisovin I will add this to my spells plugin, any chance of more EPIC effects? maybe something mixed with DrBowe 's rocket physics
     
  14. Offline

    DrBowe

    thehutch
    That was one of the first things I was curious about, but in order to do that, there'd need to be an entity for the effect to latch onto. It may be possible by faking entities at each location, but it'll eventually become more hacky than it's worth. (If it's possible at all, for that matter)
     
  15. Offline

    heisan213

    I can't figure out how to send the sit(or ride an entity) packet with nisovin 's method. The index is 2 and the Bit mask is 0x04. This page gives some info about the metadata.
    Imma tag everyone xD
    bergerkiller
    DrBowe




    So far, not so good:
    Code:
        public static void playerSitPacketSender(CraftLivingEntity player) {
       
            DataWatcher dw = new DataWatcher();
            dw.watch(player.getEntityId(), Integer.valueOf(0x04));
            dw.a(2, Integer.valueOf(0));
       
            new Packet40EntityMetadata();
            Packet40EntityMetadata sitPacket = new Packet40EntityMetadata(player.getEntityId(), dw);
       
            player.getHandle().getDataWatcher().watch(2, sitPacket);
     
  16. Offline

    bergerkiller

    heisan213 not like that :)
    Do it like this:
    Code:
    player.getHandle().datawatcher.a(2, 0);
    OR:
    player.getHandle().getDataWatcher().a(2, 0);
    And that's IT. No packets are needed at all; that is done by the entity tracker, which listens for meta data changes on the entity directly.

    Though, I am not sure what the 2 and 0 denote, you'll have to look at the native source code for a bit. (or look at the potion source code)
     
    heisan213 likes this.
  17. Offline

    heisan213

    <3 Thanks (giving like) I'll poke around some more :D Spendt hours yesterday scanning MC server source...

    I think I have to trick the client into believing it is in a minecart or something to make the effect appear. The code runs without errors at least :D
     
  18. Hmmm, isn't there an easier way to do this now with the new Potions API?
     
  19. Offline

    nisovin

    Yes, if you want the actual potion effect applied as well. This is for if you want to apply the particle effect without the potion effect.
     
  20. Offline

    thehutch

    nisovin
    @bergerkiller
    Ok so I had a little attepmt at combining your code with DrBowe and came up with this but I am having some trouble creating a fake entity any ideas on how to do it? I know Packet24MobSpawn is used to spawn a mob but giving it a fake value I couldn't think of :(
    Here is what I have but it probably is just a joke atm :D:

    Code:java
    1.  
    2. public class ArcaneEffect implements Runnable{
    3.  
    4. private Location startLoc;
    5. private Location endLoc;
    6. private ArrayList<ParticleData> locationsForProjection;
    7. private double turningPoint;
    8. private World world;
    9. private iSpells plugin;
    10. private double radius;
    11. private float effectThickness;
    12. private int i;
    13.  
    14.  
    15. public ArcaneEffect(iSpells instance,Location loc1, Location loc2, double turningPoint, float effectThickness, double radius) {
    16. this.locationsForProjection = calculateLocsForProjections();
    17. this.effectThickness = effectThickness;
    18. this.turningPoint = turningPoint;
    19. this.world = loc1.getWorld();
    20. this.plugin = instance;
    21. this.radius = radius;
    22. this.startLoc = loc1;
    23. this.endLoc = loc2;
    24. this.i = 0;
    25. }
    26.  
    27. @Override
    28. public void run() {
    29. if (i > locationsForProjection.size()-1) {
    30. return;
    31. }
    32. final ParticleData data = locationsForProjection.get(i);
    33. if (!data.isPastTurningPoint()) {
    34. final DataWatcher dw = new DataWatcher();
    35. dw.a(8, Integer.valueOf(0));
    36. //dw.watch(8, Integer.valueOf(10));
    37. for (int x=0 ; x<effectThickness ; x++) {
    38. final Packet24MobSpawn packet = new Packet24MobSpawn();
    39. for(Player p : data.getLocation().getWorld().getPlayers()) {
    40. ((CraftPlayer)p).getHandle().netServerHandler.sendPacket(packet);
    41. }
    42. Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
    43. @Override
    44. public void run() {
    45. // temp variables
    46. CraftServer cs = null; // <== are null
    47. EntityLiving el = null; // <==
    48. DataWatcher dwReal = new CraftLivingEntity(cs, el).getHandle().getDataWatcher();
    49. dw.watch(8, dwReal.getInt(8));
    50. for(Player p : data.getLocation().getWorld().getPlayers()) {
    51. ((CraftPlayer)p).getHandle().netServerHandler.sendPacket(packet);
    52.  
    53. }
    54. }, i);
    55. }
    56. i++;
    57. } else {
    58. if (data.getLocation() == endLoc) {
    59. Block centre = world.getBlockAt(endLoc);
    60. double accuracy = 0.1 * Math.PI;
    61. int dx, dz;
    62. for(double d=0 ; d<Math.PI*2 ; d+=accuracy) {
    63. dx = (int) (radius * Math.cos(d));
    64. dz = (int) (radius * Math.sin(d));
    65. if (centre.getRelative(dx, 1, dz).getType() == Material.AIR) {
    66. centre.getRelative(dx, 1, dz).setType(Material.FIRE);
    67. }
    68. }
    69. }
    70. }
    71. }
    72.  
    73. private ArrayList<ParticleData> calculateLocsForProjections() {
    74. double distance = startLoc.distance(endLoc);
    75. double x1,y1,z1,x2,y2,z2,xVect,yVect,zVect;
    76.  
    77. x1 = endLoc.getX();
    78. y1 = endLoc.getY();
    79. z1 = endLoc.getZ();
    80.  
    81. x2 = endLoc.getX();
    82. y2 = endLoc.getY();
    83. z2 = endLoc.getZ();
    84.  
    85. xVect = x2-x1;
    86. yVect = y2-y1;
    87. zVect = z2-z1;
    88.  
    89. ArrayList<ParticleData> tmp = new ArrayList<ParticleData>((int)Math.floor(distance));
    90. for(double t=0 ; t<=1 ; t+= 1/distance) {
    91. tmp.add(new ParticleData(new Location(world, x2-(xVect*t) , y2-(yVect*t) , z2-(zVect*t)), t>turningPoint));
    92. }
    93. return tmp;
    94. }
    95. }
    96.  


    iPhysX Do you know of anyway to create this fake entity? You must be good with PhysiX's right :D

    Ok I added this bit awell to replace the craftServer, although I still need an Entityliving

    Code:
    CraftServer cs = (CraftServer)plugin.getServer();
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
    iPhysX likes this.
  21. Ok, didn't realise that.
     
  22. Offline

    iPhysX

    sorry thehutch if i had some info, or i knew how to achieve it, I would help out. But I'm not good for any of this stuff. Sorry!
    I'm watching the thread though, so if there is a breakthrough, I can learn.
    :D
     
  23. Offline

    thehutch

  24. Offline

    iPhysX

    thehutch you should post a screeny of the effect? It works i assume? :)
     
  25. Offline

    thehutch

    iPhysX Unfortunately it isn't working atm for some reason :( I am trying to make a fix
     
    iPhysX likes this.
  26. Offline

    heisan213

    I actually can't figure out how to trick the client into beliving there is a minecart under the player that I want to add the sitting effect to... Any ideas bergerkiller ?
    nisovin ?
     
  27. Offline

    bergerkiller

    heisan213 I've been looking into this as well. It is possible, but replicating it is pretty hard. You need to make the client believe he is sitting in a destroyed minecart. (you can use packets)

    Still don't really know how it works though. You can try setting the player passenger of an item first.
     
  28. Offline

    heisan213

    The player would pick up the item (unless you cancel that) and wouldn't be able to move.

    Forgo to tag you, bergerkiller
     
  29. Offline

    dillyg10

    Does this show for everyone on the server (like can everyone see the palyer with the potions) or just the player?

    Ughh, so I added this into my class, and I"m getting soo many errors, It doens't know what the Packet40 is, or what datawatcher is... I have 0 idea on how to fix it. Am I missing an import? Implemtation, extension?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  30. Offline

    stelar7

    CraftBukkit, I think....
     
Thread Status:
Not open for further replies.

Share This Page