SkriptLang / Skript

Skript is a Spigot plugin which allows server admins to customize their server easily, but without the hassle of programming a plugin or asking/paying someone to program a plugin for them.
https://docs.skriptlang.org
GNU General Public License v3.0
1.08k stars 372 forks source link

`nearest entity` expression throws stack trace when used as a LivingEntity #6612

Closed cheeezburga closed 4 months ago

cheeezburga commented 7 months ago

Skript/Server Version

[00:01:43 INFO]: [Skript] Skript's aliases can be found here: https://github.com/SkriptLang/skript-aliases
[00:01:43 INFO]: [Skript] Skript's documentation can be found here: https://docs.skriptlang.org/
[00:01:43 INFO]: [Skript] Skript's tutorials can be found here: https://docs.skriptlang.org/tutorials
[00:01:43 INFO]: [Skript] Server Version: git-Paper-318 (MC: 1.20.2)
[00:01:43 INFO]: [Skript] Skript Version: 2.8.4 (selfbuilt-unknown)
[00:01:43 INFO]: [Skript] Installed Skript Addons:
[00:01:43 INFO]: [Skript]  - skript-gui v1.3 (https://github.com/APickledWalrus/skript-gui)
[00:01:43 INFO]: [Skript]  - skript-reflect v2.4 (https://github.com/SkriptLang/skript-reflect)
[00:01:43 INFO]: [Skript]  - SkBee v3.1.0 (https://github.com/ShaneBeee/SkBee)
[00:01:43 INFO]: [Skript] Installed dependencies: None

Bug Description

I was testing some stuff with an effect I was making and tried passing nearest armor stand in where %livingentities% were accepted and it threw a stack trace (see the errors section of this). If I use target instead, it works as intended.

I tested with the following syntax, as well as with my own effect:

make %livingentities% [a[n]] (charged|powered|((un|non[-])charged|(un|non[-])powered)) [creeper[s]]

make target charged # works
make (nearest creeper) charged # throws stack trace

Expected Behavior

Nearest entity was supposed to work as intended. Not super sure what else to say, as I have no idea why the error is occurring.

Steps to Reproduce

This is how I reproduced it, but I imagine it works with any effect that takes livingentities when nearest x is used:

  1. Spawn a creeper
  2. Run make (nearest creeper) charged
  3. Enjoy the stack trace

Errors or Screenshots

[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! [Skript] Severe Error:
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Something went horribly wrong with Skript.
[00:08:27 ERROR]: #!#! This issue is NOT your fault! You probably can't fix it yourself, either.
[00:08:27 ERROR]: #!#! It looks like you are using some plugin(s) that alter how Skript works (addons).
[00:08:27 ERROR]: #!#! Here is full list of them:
[00:08:27 ERROR]: #!#! skript-reflect v2.4 (https://github.com/SkriptLang/skript-reflect) skript-gui v1.3 (https://github.com/APickledWalrus/skript-gui) SkBee v3.1.0 (https://github.com/ShaneBeee/SkBee)
[00:08:27 ERROR]: #!#! We could not identify which of those are specially related, so this might also be Skript issue.
[00:08:27 ERROR]: #!#! You should try disabling those plugins one by one, trying to find which one causes it.
[00:08:27 ERROR]: #!#! If the error doesn't disappear even after disabling all listed plugins, it is probably Skript issue.
[00:08:27 ERROR]: #!#! In that case, you will be given instruction on how should you report it.
[00:08:27 ERROR]: #!#! On the other hand, if the error disappears when disabling some plugin, report it to author of that plugin.
[00:08:27 ERROR]: #!#! Only if the author tells you to do so, report it to Skript's issue tracker.
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Stack trace:
[00:08:27 ERROR]: #!#! java.lang.ClassCastException: class [Lorg.bukkit.entity.Entity; cannot be cast to class [Lorg.bukkit.entity.LivingEntity; ([Lorg.bukkit.entity.Entity; and [Lorg.bukkit.entity.LivingEntity; are in unnamed module of loader java.net.URLClassLoader @3d82c5f3)
[00:08:27 ERROR]: #!#!     at Skript.jar//ch.njol.skript.effects.EffChargeCreeper.execute(EffChargeCreeper.java:64)
[00:08:27 ERROR]: #!#!     at Skript.jar//ch.njol.skript.lang.Effect.run(Effect.java:49)
[00:08:27 ERROR]: #!#!     at Skript.jar//ch.njol.skript.lang.TriggerItem.walk(TriggerItem.java:61)
[00:08:27 ERROR]: #!#!     at Skript.jar//ch.njol.skript.lang.TriggerItem.walk(TriggerItem.java:88)
[00:08:27 ERROR]: #!#!     at Skript.jar//ch.njol.skript.command.Commands.handleEffectCommand(Commands.java:201)
[00:08:27 ERROR]: #!#!     at Skript.jar//ch.njol.skript.command.Commands$2.lambda$onPlayerChat$0(Commands.java:300)
[00:08:27 ERROR]: #!#!     at org.bukkit.craftbukkit.v1_20_R2.scheduler.CraftFuture.run(CraftFuture.java:88)
[00:08:27 ERROR]: #!#!     at org.bukkit.craftbukkit.v1_20_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:480)
[00:08:27 ERROR]: #!#!     at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1470)
[00:08:27 ERROR]: #!#!     at net.minecraft.server.dedicated.DedicatedServer.b(DedicatedServer.java:446)
[00:08:27 ERROR]: #!#!     at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:1379)
[00:08:27 ERROR]: #!#!     at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1156)
[00:08:27 ERROR]: #!#!     at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:315)
[00:08:27 ERROR]: #!#!     at java.base/java.lang.Thread.run(Thread.java:840)
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Version Information:
[00:08:27 ERROR]: #!#!   Skript: 2.8.4 (custom version)
[00:08:27 ERROR]: #!#!     Flavor: selfbuilt-unknown
[00:08:27 ERROR]: #!#!     Date: unknown
[00:08:27 ERROR]: #!#!   Bukkit: 1.20.2-R0.1-SNAPSHOT
[00:08:27 ERROR]: #!#!   Minecraft: 1.20.2
[00:08:27 ERROR]: #!#!   Java: 17.0.10 (OpenJDK 64-Bit Server VM 17.0.10+7-LTS)
[00:08:27 ERROR]: #!#!   OS: Windows 11 amd64 10.0
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Server platform: Paper
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Current node: null
[00:08:27 ERROR]: #!#! Current item: make nearest creeper relative to event-entity charged
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Thread: Server thread
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! Language: english
[00:08:27 ERROR]: #!#! Link parse mode: DISABLED
[00:08:27 ERROR]: #!#!
[00:08:27 ERROR]: #!#! End of Error.
[00:08:27 ERROR]: #!#!

Other

Sovde and I had a chat about this which lasted a few messages here (very useless). Most of the messages are about the effect I was trying to make, but Sovde found out that, to quote, "weirdly it's only for nearest x and not nearest entity", which I think might be worth mentioning.

Agreement

Moderocky commented 7 months ago

This is being caused because nearest entity is an Expression returning an array of Entities, being cast to an Expression that wants to return an array of LivingEntities, and an array of Entities is not an array of LivingEntities, so it's failing.

Here at Skript, our policy is to do these unchecked, unverified casts without properly checking and just suppress the warning, which is why this is occurring as a problem.

The easy fix is to just make the charge effect not do that cast, since it isn't necessary, but the larger question is why the %livingentities% input is accepting %entities% without any kind of conversion, since this will run into the same problem elsewhere.

sovdeeth commented 7 months ago

This is being caused because nearest entity is an Expression returning an array of Entities, being cast to an Expression that wants to return an array of LivingEntities, and an array of Entities is not an array of LivingEntities, so it's failing.

Here at Skript, our policy is to do these unchecked, unverified casts without properly checking and just suppress the warning, which is why this is occurring as a problem.

The easy fix is to just make the charge effect not do that cast, since it isn't necessary, but the larger question is why the %livingentities% input is accepting %entities% without any kind of conversion, since this will run into the same problem elsewhere.

I feel like it might be a bit more complicated than that, since nearest entity works fine, and player's spectator target, which is an Expression\<Entity>, also worked fine in tests.

Moderocky commented 7 months ago

I feel like it might be a bit more complicated than that, since nearest entity works fine, and player's spectator target, which is an Expression, also worked fine in tests.

No, it's exactly this, and it happens with a bunch of other syntax -- I'm testing it right now to find the whole list.

Basically, %livingentities% permits Expression<Entity>s and doesn't apply any kind of conversion, and because of the generic <LivingEntity> type, when getArray is called it tries to cast the array to a LivingEntity[] which, clearly, it won't be, since it's an entity expression, so it's throwing the class cast exception.

What probably ought to be happening is that it should sub in some kind of converted Expression that filters out the incorrect elements and returns the array that's been asked for.

Moderocky commented 7 months ago

Having chased this issue down the rabbit hole, we discovered its cause is some expressions wrongly reporting their returntype as being different from the array type they return in get..., so in this issue the charge the nearest creeper fails because the expression promises to return a Creeper (a LivingEntity) but actually returns an array of Entities. This means the parser doesn't convert the expression.

I have a fix for this in the pipeline but I'd also like to find a way to address the more pervasive issue in future.