Skip to content

ExprAttachedBlock Plural Support #7897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: dev/feature
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 64 additions & 23 deletions src/main/java/ch/njol/skript/expressions/ExprAttachedBlock.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,81 @@
package ch.njol.skript.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.expressions.base.SimplePropertyExpression;
import ch.njol.skript.doc.*;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import org.bukkit.block.Block;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Arrow Attached Block")
@Description("Returns the attached block of an arrow.")
@Examples("set hit block of last shot arrow to diamond block")
@Since("2.8.0")
public class ExprAttachedBlock extends SimplePropertyExpression<Projectile, Block> {
import java.util.ArrayList;
import java.util.List;

private static final boolean HAS_ABSTRACT_ARROW = Skript.classExists("org.bukkit.entity.AbstractArrow");
@Name("Arrow Attached Block")
@Description({
"Returns the attached block of an arrow.",
"If running Paper 1.21.4+, the plural version of the expression should be used as it is more reliable compared to the single version."
})
@Example("set hit block of last shot arrow to diamond block")
@Example("""
on projectile hit:
wait 1 tick
break attached blocks of event-projectile
kill event-projectile
""")
@Since("2.8.0, INSERT VERSION (multiple blocks)")
public class ExprAttachedBlock extends SimpleExpression<Block> {

static {
register(ExprAttachedBlock.class, Block.class, "(attached|hit) block", "projectiles");
Skript.registerExpression(ExprAttachedBlock.class, Block.class, ExpressionType.PROPERTY,
"[the] (attached|hit) block[multiple:s] of %projectiles%",
"%projectiles%'[s] (attached|hit) block[multiple:s]"
);
}

// TODO - remove this when 1.21.4 is the minimum supported version
private static final boolean SUPPORTS_MULTIPLE = Skript.methodExists(AbstractArrow.class, "getAttachedBlocks");

private boolean isMultiple;
private Expression<Projectile> projectiles;

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
isMultiple = parseResult.hasTag("multiple");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe there should be a warning if running 1.21.4+ to use the multiple

projectiles = (Expression<Projectile>) expressions[0];

if (!SUPPORTS_MULTIPLE && isMultiple) {
Skript.error("The plural version of this expression is only available in Paper 1.21.4+.");
return false;
}

return true;
}

@Override
@Nullable
public Block convert(Projectile projectile) {
if (HAS_ABSTRACT_ARROW) {
if (projectile instanceof AbstractArrow) {
return ((AbstractArrow) projectile).getAttachedBlock();
protected Block @Nullable [] get(Event event) {
List<Block> blocks = new ArrayList<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on making this a Set to remove duplicate blocks?
I could see it both ways

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel that'd make more sense


for (Projectile projectile : projectiles.getAll(event)) {
if (projectile instanceof AbstractArrow abstractArrow) {
if (isMultiple) {
blocks.addAll(abstractArrow.getAttachedBlocks());
} else {
blocks.add(abstractArrow.getAttachedBlock());
}
}
} else if (projectile instanceof Arrow) {
return ((Arrow) projectile).getAttachedBlock();
}
return null;
return blocks.toArray(new Block[0]);
}

@Override
public boolean isSingle() {
return !isMultiple;
}

@Override
Expand All @@ -43,8 +84,8 @@ public Class<? extends Block> getReturnType() {
}

@Override
public String getPropertyName() {
return "attached block";
public String toString(@Nullable Event event, boolean debug) {
return "attached block" + (isMultiple ? "s" : "") + " of " + projectiles.toString(event, debug);
}

}