Skip to content
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

Adds block sound expression and test #7040

Merged
merged 10 commits into from
Oct 13, 2024
125 changes: 125 additions & 0 deletions src/main/java/ch/njol/skript/expressions/ExprBlockSound.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package ch.njol.skript.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
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.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import org.bukkit.Sound;
import org.bukkit.SoundGroup;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;

@Name("Block Sound")
@Description("Gets the sound that a given block, blockdata, or itemtype will use in a specific scenario.")
cheeezburga marked this conversation as resolved.
Show resolved Hide resolved
@Examples({
"play sound (break sound of dirt) at all players",
"set {_sounds::*} to place sounds of dirt, grass block, blue wool and stone"
})
@Since("INSERT VERSION")
public class ExprBlockSound extends SimpleExpression<String> {

static {
Skript.registerExpression(ExprBlockSound.class, String.class, ExpressionType.COMBINED,
"[the] break sound[s] of %blocks/blockdatas/itemtypes%",
"%blocks/blockdatas/itemtypes%'[s] break sound[s]",

"[the] fall sound[s] of %blocks/blockdatas/itemtypes%",
"%blocks/blockdatas/itemtypes%'[s] fall sound[s]",

"[the] hit sound[s] of %blocks/blockdatas/itemtypes%",
"%blocks/blockdatas/itemtypes%'[s] hit sound[s]",

"[the] place sound[s] of %blocks/blockdatas/itemtypes%",
"%blocks/blockdatas/itemtypes%'[s] place sound[s]",

"[the] step sound[s] of %blocks/blockdatas/itemtypes%",
"%blocks/blockdatas/itemtypes%'[s] step sound[s]");
cheeezburga marked this conversation as resolved.
Show resolved Hide resolved
}

private static final int BREAK = 0;
private static final int FALL = 2;
private static final int HIT = 4;
private static final int PLACE = 6;
private static final int STEP = 8;
cheeezburga marked this conversation as resolved.
Show resolved Hide resolved

private int soundPattern;
@SuppressWarnings("NotNullFieldNotInitialized")
private Expression<?> objects;

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
soundPattern = matchedPattern;
objects = exprs[0];
return true;
}

@Override
protected String @Nullable [] get(Event event) {
return objects.stream(event)
.map(this::convertAndGetSound)
.filter(Objects::nonNull)
.distinct()
.map(Sound::name)
.toArray(String[]::new);
}

private @Nullable Sound convertAndGetSound(Object object) {
SoundGroup group = null;

if (object instanceof Block block) {
group = block.getBlockData().getSoundGroup();
} else if (object instanceof BlockData data) {
group = data.getSoundGroup();
} else if (object instanceof ItemType item) {
if (item.hasBlock())
group = item.getMaterial().createBlockData().getSoundGroup();
}

if (group == null)
return null;

return switch (this.soundPattern) {
case BREAK, BREAK + 1 -> group.getBreakSound();
case FALL, FALL + 1 -> group.getFallSound();
case HIT, HIT + 1 -> group.getHitSound();
case PLACE, PLACE + 1 -> group.getPlaceSound();
case STEP, STEP + 1 -> group.getStepSound();
default -> null;
};
}

@Override
public boolean isSingle() {
return objects.isSingle();
}

@Override
public @NotNull Class<? extends String> getReturnType() {
return String.class;
}

@Override
public @NotNull String toString(@Nullable Event event, boolean debug) {
return switch (this.soundPattern) {
case BREAK, BREAK + 1 -> "break";
case FALL, FALL + 1 -> "fall";
case HIT, HIT + 1 -> "hit";
case PLACE, PLACE + 1 -> "place";
case STEP, STEP + 1 -> "step";
default -> null;
} + " sound of " + objects.toString(event, debug);
}

}
22 changes: 22 additions & 0 deletions src/test/skript/tests/syntaxes/expressions/ExprBlockSound.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
test "block sounds":

# === SETUP ===

set {_block} to block at (spawn of world "world")
set {_before} to blockdata of {_block}
set blockdata of {_block} to stone[]
set {_data} to blockdata of {_block}

set {_itemtype} to stone

# === TESTS ===

assert break sound of {_block}, {_data} and {_itemtype} is "BLOCK_STONE_BREAK" with "break sound of stone wasn't BLOCK_STONE_BREAK"
assert fall sound of {_block}, {_data} and {_itemtype} is "BLOCK_STONE_FALL" with "fall sound of stone wasn't BLOCK_STONE_FALL"
assert hit sound of {_block}, {_data} and {_itemtype} is "BLOCK_STONE_HIT" with "hit sound of stone wasn't BLOCK_STONE_HIT"
assert place sound of {_block}, {_data} and {_itemtype} is "BLOCK_STONE_PLACE" with "place sound of stone wasn't BLOCK_STONE_PLACE"
assert step sound of {_block}, {_data} and {_itemtype} is "BLOCK_STONE_STEP" with "step sound of stone wasn't BLOCK_STONE_STEP"

cheeezburga marked this conversation as resolved.
Show resolved Hide resolved
# === CLEANUP ===

set blockdata of {_block} to {_before}