-
-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds block sound expression and test (#7040)
* Adds block sound syntax - Allows getting the break, fall, hit, place, and step sound of a block/blockdata/itemtype * Suggestions * Suggestion Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> * Implements SoundType enum to get a sound given a group, and makes tests better - This also reduces some annoying switch stuff with the soundType from before * Fixes tests failing due to 1.19 not using INTENTIONALLY_EMPTY sound --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com>
- Loading branch information
1 parent
97055a2
commit 99731b0
Showing
2 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
137 changes: 137 additions & 0 deletions
137
src/main/java/ch/njol/skript/expressions/ExprBlockSound.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package ch.njol.skript.expressions; | ||
|
||
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.expressions.base.SimplePropertyExpression; | ||
import ch.njol.skript.lang.Expression; | ||
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.", | ||
"This will return a string in the form of \"SOUND_EXAMPLE\", which can be used in the play sound syntax.", | ||
"", | ||
"Check out <a href=\"https://minecraft.wiki/w/Sounds.json\">this website</a> for a list of sounds in Minecraft, " + | ||
"or <a href=\"https://minecraft.wiki/w/Sound\">this one</a> to go to the Sounds wiki page." | ||
}) | ||
@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> { | ||
|
||
public enum SoundType { | ||
BREAK { | ||
@Override | ||
public Sound getSound(SoundGroup group) { | ||
return group.getBreakSound(); | ||
} | ||
}, | ||
|
||
FALL { | ||
@Override | ||
public Sound getSound(SoundGroup group) { | ||
return group.getFallSound(); | ||
} | ||
}, | ||
|
||
HIT { | ||
@Override | ||
public Sound getSound(SoundGroup group) { | ||
return group.getHitSound(); | ||
} | ||
}, | ||
|
||
PLACE { | ||
@Override | ||
public Sound getSound(SoundGroup group) { | ||
return group.getPlaceSound(); | ||
} | ||
}, | ||
|
||
STEP { | ||
@Override | ||
public Sound getSound(SoundGroup group) { | ||
return group.getStepSound(); | ||
} | ||
}; | ||
|
||
public abstract @Nullable Sound getSound(SoundGroup group); | ||
} | ||
|
||
static { | ||
SimplePropertyExpression.register(ExprBlockSound.class, String.class, "(1:break|2:fall|3:hit|4:place|5:step) sound[s]", "blocks/blockdatas/itemtypes"); | ||
} | ||
|
||
@SuppressWarnings("NotNullFieldNotInitialized") | ||
private SoundType soundType; | ||
@SuppressWarnings("NotNullFieldNotInitialized") | ||
private Expression<?> objects; | ||
|
||
@Override | ||
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { | ||
soundType = SoundType.values()[parseResult.mark - 1]; | ||
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 SoundGroup getSoundGroup(Object object) { | ||
if (object instanceof Block block) { | ||
return block.getBlockData().getSoundGroup(); | ||
} else if (object instanceof BlockData data) { | ||
return data.getSoundGroup(); | ||
} else if (object instanceof ItemType item) { | ||
if (item.hasBlock()) | ||
return item.getMaterial().createBlockData().getSoundGroup(); | ||
} | ||
return null; | ||
} | ||
|
||
private @Nullable Sound convertAndGetSound(Object object) { | ||
SoundGroup group = getSoundGroup(object); | ||
if (group == null) | ||
return null; | ||
return this.soundType.getSound(group); | ||
} | ||
|
||
@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 this.soundType.name().toLowerCase() + " sound of " + objects.toString(event, debug); | ||
} | ||
|
||
} |
46 changes: 46 additions & 0 deletions
46
src/test/skript/tests/syntaxes/expressions/ExprBlockSound.sk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
test "block sounds (1.20+)": | ||
|
||
# === SETUP === | ||
|
||
set {_before} to blockdata of (block at (spawn of world "world")) | ||
set {_20} to whether running minecraft "1.20" | ||
set {_empty} to "INTENTIONALLY_EMPTY" if running minecraft "1.20" else "BLOCK_STONE_PLACE" | ||
|
||
# === TESTS === | ||
|
||
set {_stone::*} to getObjects(stone) | ||
assert break sound of {_stone::*} is "BLOCK_STONE_BREAK" with "break sound of stone wasn't BLOCK_STONE_BREAK" | ||
assert fall sound of {_stone::*} is "BLOCK_STONE_FALL" with "fall sound of stone wasn't BLOCK_STONE_FALL" | ||
assert hit sound of {_stone::*} is "BLOCK_STONE_HIT" with "hit sound of stone wasn't BLOCK_STONE_HIT" | ||
assert place sound of {_stone::*} is "BLOCK_STONE_PLACE" with "place sound of stone wasn't BLOCK_STONE_PLACE" | ||
assert step sound of {_stone::*} is "BLOCK_STONE_STEP" with "step sound of stone wasn't BLOCK_STONE_STEP" | ||
|
||
set {_wool::*} to getObjects(wool) | ||
assert break sound of {_wool::*} is "BLOCK_WOOL_BREAK" with "break sound of stone wasn't BLOCK_WOOL_BREAK" | ||
assert fall sound of {_wool::*} is "BLOCK_WOOL_FALL" with "fall sound of stone wasn't BLOCK_WOOL_FALL" | ||
assert hit sound of {_wool::*} is "BLOCK_WOOL_HIT" with "hit sound of stone wasn't BLOCK_WOOL_HIT" | ||
assert place sound of {_wool::*} is "BLOCK_WOOL_PLACE" with "place sound of stone wasn't BLOCK_WOOL_PLACE" | ||
assert step sound of {_wool::*} is "BLOCK_WOOL_STEP" with "step sound of stone wasn't BLOCK_WOOL_STEP" | ||
|
||
assert break sound of (water, lava and bubble column) is ("INTENTIONALLY_EMPTY" if {_20} is true else "BLOCK_STONE_BREAK") with "break sound of water, lava, or bubble column wasn't INTENTIONALLY_EMPTY" | ||
assert fall sound of (water, lava and bubble column) is ("INTENTIONALLY_EMPTY" if {_20} is true else "BLOCK_STONE_FALL") with "fall sound of water, lava, or bubble column wasn't INTENTIONALLY_EMPTY" | ||
assert hit sound of (water, lava and bubble column) is ("INTENTIONALLY_EMPTY" if {_20} is true else "BLOCK_STONE_HIT") with "hit sound of water, lava, or bubble column wasn't INTENTIONALLY_EMPTY" | ||
assert place sound of (water, lava and bubble column) is ("INTENTIONALLY_EMPTY" if {_20} is true else "BLOCK_STONE_PLACE") with "place sound of water, lava, or bubble column wasn't INTENTIONALLY_EMPTY" | ||
assert step sound of (water, lava and bubble column) is ("INTENTIONALLY_EMPTY" if {_20} is true else "BLOCK_STONE_STEP") with "step sound of water, lava, or bubble column wasn't INTENTIONALLY_EMPTY" | ||
|
||
assert break sound of (diamond, diamond sword and {_none}) is not set with "break sound of non-block item shouldn't be set" | ||
assert fall sound of (diamond, diamond sword and {_none}) is not set with "fall sound of non-block item shouldn't be set" | ||
assert hit sound of (diamond, diamond sword and {_none}) is not set with "hit sound of non-block item shouldn't be set" | ||
assert place sound of (diamond, diamond sword and {_none}) is not set with "place sound of non-block item shouldn't be set" | ||
assert step sound of (diamond, diamond sword and {_none}) is not set with "step sound of non-block item shouldn't be set" | ||
|
||
# === CLEANUP === | ||
|
||
set blockdata of {_block} to {_before} | ||
|
||
local function getObjects(i: itemtype) :: objects: | ||
if (block at (spawn of world "world")) is not {_i}: | ||
set block at (spawn of world "world") to {_i} | ||
set {_block} to block at (spawn of world "world") | ||
set {_data} to blockdata of {_block} | ||
return {_block}, {_data} and {_i} |