renyunzhong
1.13之后的红石粒子颜色使用DustOption进行控制,但是只能指定一种颜色
对应到原版就是/particle dust 0~1 0~1 0~1这个区间
众所周知这个区间里面跳出来的白色粒子是淡灰色的
原版里头可以使用/particle dust -0.01 -0.01 -0.01 1 ~ ~ ~ 1 1 1 1 100调出接近于纯白的粒子
所以有大佬知道怎么弄吗?
我尝试过给玩家发包粒子效果,但是里头第十个数据是ParticleParam类型的,直接获取出来的是

net.minecraft.server.v1_16_R2.ParticleParamRedstone@123abc56一类的,不知道里面什么结构也不知道发包时怎么写

William_Shi
首先解释ParticleParam的问题
这玩意是NMS里面的,经过CraftBukkit反混淆得到的类名,里面的结构我想你必须去自己看反混淆,更推荐Forge反混淆,但是考虑到Forge开发环境搭建可能略微有点复杂(其实直接下载离线包没什么复杂的)所以你也可以看看CraftBukkit反混淆。
获得ParticleParam的方法我推荐从OBC走
摘自CraftParticle类

  1.   public static <T> ParticleParam toNMS(Particle particle, T obj) {
  2.     Particle canonical = particle;
  3.     if (aliases.containsKey(particle))
  4.       canonical = aliases.get(particle);
  5.     Particle nms = (Particle)IRegistry.PARTICLE_TYPE.get((MinecraftKey)particles.get(canonical));
  6.     Preconditions.checkArgument((nms != null), "No NMS particle %s", particle);
  7.     if (particle.getDataType().equals(Void.class))
  8.       return (ParticleParam)nms;
  9.     Preconditions.checkArgument((obj != null), "Particle %s requires data, null provided", particle);
  10.     if (particle.getDataType().equals(ItemStack.class)) {
  11.       ItemStack itemStack = (ItemStack)obj;
  12.       return (ParticleParam)new ParticleParamItem(nms, CraftItemStack.asNMSCopy(itemStack));
  13.     }
  14.     if (particle.getDataType() == MaterialData.class) {
  15.       MaterialData data = (MaterialData)obj;
  16.       return (ParticleParam)new ParticleParamBlock(nms, CraftMagicNumbers.getBlock(data));
  17.     }
  18.     if (particle.getDataType() == BlockData.class) {
  19.       BlockData data = (BlockData)obj;
  20.       return (ParticleParam)new ParticleParamBlock(nms, ((CraftBlockData)data).getState());
  21.     }
  22.     if (particle.getDataType() == Particle.DustOptions.class) {
  23.       Particle.DustOptions data = (Particle.DustOptions)obj;
  24.       Color color = data.getColor();
  25.       return (ParticleParam)new ParticleParamRedstone(color.getRed() / 255.0F, color.getGreen() / 255.0F, color.getBlue() / 255.0F, data.getSize());
  26.     }
  27.     throw new IllegalArgumentException(particle.getDataType().toString());
  28.   }
  29.   
复制代码


什么是OBC、NMS的问题,可以考虑看我的教程。bdn也有类似的教程,写得也非常好。
至于那个@加上一些十六进制数字的,那个叫做HashCode,估计你的Java基础没学好。

William_Shi
本帖最后由 William_Shi 于 2020-10-24 22:12 编辑

然后我再解释发包的问题
我推荐直接https://bukkit.windit.net/javado ... le-double-double-T-

那么
https://bukkit.windit.net/javado ... .html#getDataType--
这个是什么?

我们看看Particle


  1.   @NotNull
  2.   public Class<?> getDataType() {
  3.     return this.dataType;
  4.   }
  5.   
复制代码

  1.   Particle(Class<?> data) {
  2.     this.dataType = data;
  3.   }
  4.   
复制代码

  1.   REDSTONE(DustOptions.class),
复制代码

注:Particle是枚举类。

所以这样,所谓的T data
在你生成红石粒子的情况下,就是
https://bukkit.windit.net/javado ... le.DustOptions.html
然后就是指定
https://bukkit.windit.net/javadoc/org/bukkit/Color.html

renyunzhong
本帖最后由 renyunzhong 于 2020-10-26 23:15 编辑

感谢大佬,去弄了一下NMS纯白粒子的确可以显示了,但是使用反射时在constructor那里遇到点问题:
  1.     public static Class packet;
  2.     public static Class particleParam;
  3.     public static Class particles;

  4.     static Class packetPlayOutWorldParticles;

  5.     //Register all class for NMS
  6.     public void setAllClass(){
  7.         try {
  8.             particleParam = ClassRegister.getNMSClass("ParticleParam");
  9.             particles = ClassRegister.getNMSClass("Particles");
  10.             packet = ClassRegister.getNMSClass("Packet");
  11.             packetPlayOutWorldParticles = ClassRegister.getNMSClass("PacketPlayOutWorldParticles");
  12.         } catch (ClassNotFoundException e) {
  13.             e.printStackTrace();
  14.         }
  15.     }

  16.     //Packet Register
  17.     //sendParticle
  18.     public static void sendParticle(Player p, Location loc, float ofx, float ofy, float ofz, float ex, int num, boolean isF, Object param) {
  19.         try {

  20.             Object PacketPlayOutWorldParticles = new net.minecraft.server.v1_16_R2.PacketPlayOutWorldParticles((ParticleParam) param, isF, loc.getX(), loc.getY(), loc.getZ(), ofx, ofy, ofz, ex, num);
  21.             //Object PacketPlayOutWorldParticles = ClassRegister.getNMSClass("PacketListener").cast(packetPlayOutWorldParticles.getConstructor(Object.class, boolean.class, double.class, double.class, double.class, float.class, float.class, float.class, float.class, int.class).newInstance(particleParam.cast(param), isF, loc.getX(), loc.getY(), loc.getZ(), ofx, ofy, ofz, ex, num));         这个不工作,检查了一下实在getConstructor那里报NullPointerException

  22.             Object craftPlayer = ClassRegister.getCBClass("entity.CraftPlayer").cast(p);
  23.             Object entityPlayer = craftPlayer.getClass().getMethod("getHandle").invoke(craftPlayer);

  24.             Object playerConnection = entityPlayer.getClass().getField("playerConnection").get(entityPlayer);
  25.             System.out.println("DEBUGEntity: "+entityPlayer+" - "+loc+" - "+ofx+" - "+ofy+" - "+ofz+" - "+ex+" - "+num+" - "+isF+" - "+param); //debug显示


  26.             ((CraftPlayer) craftPlayer).getHandle().playerConnection.sendPacket((Packet<?>) PacketPlayOutWorldParticles);

  27.             //playerConnection.getClass().getMethod("sendPacket",packet).invoke(playerConnection,PacketPlayOutWorldParticles);        这个换掉上面一行同样不工作,显示NoSuchMethodException: net.minecraft.server.v1_16_R2.PlayerConnection.sendPacket(null)


  28.         } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException | NoSuchFieldException | InstantiationException | NullPointerException e) {
  29.             e.printStackTrace();
  30.         }
  31.     }
复制代码

EDIT
2小时后,解决了NullPointer的问题,是由于Class采用static导致的,换掉所有Class变量就没问题了,目前发包一切正常
不过其他Class使用这个方法时需要引用static类型的,而static类型方法下面的变量也只能是static类型,有什么比较好的解决办法么