Hello, I am wondering what is the proper way of getting the arrow's color or removing it. I want to check whether an arrow is colored and if it is, remove the color upon hitting the ground so that the particles aren't visible. I tried doing it this way: Code (Java): protected void handleArrowHitEventCleaning(ProjectileHitEvent event) { if(event.getEntity() instanceof AbstractArrow) { AbstractArrow arr = (AbstractArrow)(event.getEntity()); if(arr instanceof Arrow) { Arrow arrow = (Arrow)arr; Color c = arrow.getColor(); if(c!=null) arrow.setColor(null); } } } However, the getColor() method returns the following exception when an arrow isn't colored: Spoiler: Exception Code (Text): [18:31:13] [Server thread/ERROR]: Could not pass event ProjectileHitEvent to Battlefeast v1.0 org.bukkit.event.EventException: null at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:320) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:529) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:514) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory.callProjectileHitEvent(CraftEventFactory.java:1158) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.EntityArrow.a(EntityArrow.java:276) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.EntityArrow.tick(EntityArrow.java:191) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.EntityTippedArrow.tick(EntityTippedArrow.java:92) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.WorldServer.entityJoinedWorld(WorldServer.java:626) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.World.a(World.java:718) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.WorldServer.doTick(WorldServer.java:395) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.MinecraftServer.b(MinecraftServer.java:1082) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.DedicatedServer.b(DedicatedServer.java:399) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.MinecraftServer.a(MinecraftServer.java:984) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at net.minecraft.server.v1_15_R1.MinecraftServer.run(MinecraftServer.java:824) [spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at java.lang.Thread.run(Unknown Source) [?:1.8.0_231] Caused by: java.lang.IllegalArgumentException: Extrenuous data in: -1 at org.apache.commons.lang.Validate.isTrue(Validate.java:93) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at org.bukkit.Color.fromRGB(Color.java:147) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at org.bukkit.craftbukkit.v1_15_R1.entity.CraftTippedArrow.getColor(CraftTippedArrow.java:124) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] at me.WellyPL.Battlefeast.Items.Abstract.ArrowShootingItem.handleArrowHitEventCleaning(ArrowShootingItem.java:26) ~[?:?] at me.WellyPL.Battlefeast.Items.SubMachineGun.onArrowHit(SubMachineGun.java:229) ~[?:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_231] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_231] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_231] at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_231] at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:316) ~[spigot-1.15.2.jar:git-Spigot-800b93f-8160e29] ... 15 more Moreover, as the argument of setColor() is @NotNull, naturally setColor(null) is wrong. What is the proper way to achieve the result I want then? Edit: The arrow is colored by setColor() method, not by adding effects to it
Unfortunately, clearing the effects leaves an arrow with light blue particles. Any ideas? I'd like to add that the color was given by setColor() method. And what about checking whether an arrow is colored?
Digging into the server code, it looks like there isn't really a way to clear the arrow color, only to set it. The color is stored inside the Entity's DataWatcher object, so it would need to be cleared from there. If you are okay using a little bit of NMS, you can set the Entity's DataWatcher to Code (Java): DataWatcher.a(EntityTippedArrow.class, DataWatcherRegistry.b) and set the hasColor field to false. Spoiler: EntityTippedArrow Methods Code (Java): private static final DataWatcherObject<Integer> COLOR; static { COLOR = DataWatcher.a(EntityTippedArrow.class, DataWatcherRegistry.b); } private void b(int i) { int j = this.getColor(); if (j != -1 && i > 0) { double d0 = (double)(j >> 16 & 255) / 255.0D; double d1 = (double)(j >> 8 & 255) / 255.0D; double d2 = (double)(j >> 0 & 255) / 255.0D; for(int k = 0; k < i; ++k) { this.world.addParticle(Particles.ENTITY_EFFECT, this.d(0.5D), this.cv(), this.g(0.5D), d0, d1, d2); } } } public void setColor(int i) { this.hasColor = true; this.datawatcher.set(COLOR, i); } The other option is to use less NMS and simply get the CraftTippedArrow run getHandle().setColor(null) (Maybe that'll work. Haha.. if using Arrow.setColor(null) doesn't work, I'm skeptical about this solution). The EntityTippedArrow checks for a value of -1 for the color. If it's -1, it doesn't spawn particles. So you could try that too. This might be the preferred method actually. Spoiler: CraftTippedArrow setColor Method Code (Java): public void setColor(Color color) { this.getHandle().setColor(color.asRGB()); } And as a last ditch effort, you could always copy the vector of the arrow, the shooter, and any other relevant information. Then you could remove the current arrow and spawn a new one.
IntelliJ has a built in decompiler that allows you to open up dependencies as if they were just a folder in your file tree. You can poke around and see the code in the different classes. I specifically was looking at the server jar itself instead of the usual API jar.
Thanks, Travja! I replaced this part of code Code (Java): if(arr instanceof Arrow) { Arrow arrow = (Arrow)arr; Color c = arrow.getColor(); if(c!=null) arrow.setColor(null); } With this Code (Text): if(arr instanceof CraftTippedArrow) ((CraftTippedArrow)arr).getHandle().setColor(-1); And so far it's working great! Thank you! Also, if one wanted to check whether an arrow is colored, this code will work, I checked it: Code (Text): if(((CraftTippedArrow)arr).getHandle().getColor()!=-1) { //... }