Skip to content

Commit

Permalink
Adds entity sound expression and test
Browse files Browse the repository at this point in the history
  • Loading branch information
cheeezburga committed Aug 31, 2024
1 parent c8cd975 commit 348e0ac
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
154 changes: 154 additions & 0 deletions src/main/java/ch/njol/skript/expressions/ExprEntitySound.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package ch.njol.skript.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
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.Material;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Event;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.Set;

public class ExprEntitySound extends SimpleExpression<String> {

static {
if (Skript.methodExists(LivingEntity.class, "getDeathSound")) {
Skript.registerExpression(ExprEntitySound.class, String.class, ExpressionType.COMBINED,
"[the] (damage|hurt) sound[s] of %livingentities%",
"%livingentities%'[s] (damage|hurt) sound[s]",

"[the] death sound[s] of %livingentities%",
"%livingentities%'[s] death sound[s]",

"[the] [high:(tall|high)|(low|normal)] fall [damage] sound[s] [from [[a] height [of]] %-number%] of %livingentities%",
"%livingentities%'[s] [high:(tall|high)|low:(low|normal)] fall [damage] sound[s] [from [[a] height [of]] %-number%]",

"[the] swim[ming] sound[s] of %livingentities%",
"%livingentities%'[s] swim[ming] sound[s]",

"[the] [fast:(fast|speedy)] splash sound[s] of %livingentities%",
"%livingentities%'[s] [fast:(fast|speedy)] splash sound[s]",

"[the] eat[ing] sound of %livingentities% [(with|using|[while] eating [a]) %-itemtype%]",
"%livingentities%'[s] eat[ing] sound",

"[the] drink[ing] sound of %livingentities% [(with|using|[while] drinking [a]) %-itemtype%]",
"%livingentities%'[s] drink[ing] sound");
}
}

private static final int DAMAGE = 0;
private static final int DEATH = 2;
private static final int FALL = 4;
private static final int SWIM = 6;
private static final int SPLASH = 8;
private static final int EAT_WITH_ITEM = 10;
private static final int EAT = 11;
private static final int DRINK_WITH_ITEM = 12;
private static final int DRINK = 13;

private int sound;
private boolean big;
@SuppressWarnings("NotNullFieldNotInitialized")
private Expression<Number> height;
@SuppressWarnings("NotNullFieldNotInitialized")
private Expression<LivingEntity> entities;
@SuppressWarnings("NotNullFieldNotInitialized")
private Expression<ItemType> item;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
sound = matchedPattern;
big = parseResult.hasTag("high") || parseResult.hasTag("fast");
if (matchedPattern == FALL || matchedPattern == FALL + 1)
height = (Expression<Number>) exprs[0];
if (matchedPattern == EAT_WITH_ITEM || matchedPattern == DRINK_WITH_ITEM)
item = (Expression<ItemType>) exprs[1];
entities = (Expression<LivingEntity>) ((matchedPattern == FALL) ? exprs[1] : exprs[0]);
return true;
}

@Override
protected String @Nullable [] get(Event event) {
Set<String> sounds = new HashSet<>();
for (LivingEntity entity : entities.getArray(event)) {
Sound sound = getEntitySound(entity, event);
if (sound != null)
sounds.add(sound.name());
}
return sounds.toArray(String[]::new);
}

private @Nullable Sound getEntitySound(LivingEntity entity, Event event) {
Sound sound = null;
switch (this.sound) {
case DAMAGE, DAMAGE + 1 -> sound = entity.getHurtSound();
case DEATH, DEATH + 1 -> sound = entity.getDeathSound();
case FALL, FALL + 1 -> sound = getFallSound(entity, event);
case SWIM, SWIM + 1 -> sound = entity.getSwimSound();
case SPLASH, SPLASH + 1 -> sound = big ? entity.getSwimHighSpeedSplashSound() : entity.getSwimSplashSound();
case EAT_WITH_ITEM, DRINK_WITH_ITEM -> sound = getConsumeSound(entity, event);
case EAT -> sound = entity.getEatingSound(new ItemStack(Material.COOKED_BEEF));
case DRINK -> sound = entity.getDrinkingSound(new ItemStack(Material.POTION));
}
return sound;
}

private Sound getFallSound(LivingEntity entity, Event event) {
//noinspection ConstantValue
int height = this.height == null ? -1 : this.height.getOptionalSingle(event).orElse(-1).intValue();
return height != -1 ? entity.getFallDamageSound(height) :
(big ? entity.getFallDamageSoundBig() : entity.getFallDamageSoundSmall());
}

private Sound getConsumeSound(LivingEntity entity, Event event) {
ItemStack defaultItem = new ItemStack(sound == EAT_WITH_ITEM ? Material.COOKED_BEEF : Material.POTION);
//noinspection ConstantValue
ItemStack item = this.item == null ? defaultItem : this.item.getOptionalSingle(event).orElse(new ItemType(defaultItem)).getRandom();
if (item == null)
item = defaultItem;
return sound == EAT_WITH_ITEM ? entity.getEatingSound(item) : entity.getDrinkingSound(item);
}

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

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

@Override
@SuppressWarnings("ConstantValue")
public String toString(@Nullable Event event, boolean debug) {
String name = "unknown";
switch (sound) {
case DAMAGE, DAMAGE + 1 -> name = "damage";
case DEATH, DEATH + 1 -> name = "death";
case FALL, FALL + 1 -> {
if (this.height == null) {
name = big ? "high fall damage" : "normal fall damage";
} else {
name = "fall damage from a height of " + this.height.toString(event, debug);
}
}
case SWIM, SWIM + 1 -> name = "swim";
case SPLASH, SPLASH + 1 -> name = big ? "speedy splash" : "splash";
case EAT_WITH_ITEM, DRINK_WITH_ITEM -> name = (sound == EAT_WITH_ITEM ? "eating" : "drinking") + (this.item == null ? " with default item" : " " + this.item.toString(event, debug));
case EAT, DRINK -> name = sound == EAT ? "eating" : "drinking";
}
return name + " sound of " + entities.toString(event, debug);
}

}
19 changes: 19 additions & 0 deletions src/test/skript/tests/syntaxes/expressions/ExprEntitySound.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
test "entity sounds":
spawn a zombie at (spawn of world "world"):
set {_z} to entity

assert damage sound of {_z} is "ENTITY_ZOMBIE_HURT" with "damage sound of zombie should return ENTITY_ZOMBIE_HURT"
assert death sound of {_z} is "ENTITY_ZOMBIE_DEATH" with "death sound of zombie should return ENTITY_ZOMBIE_DEATH"
assert swim sound of {_z} is "ENTITY_HOSTILE_SWIM" with "swim sound of zombie should return ENTITY_HOSTILE_SWIM"
assert normal fall sound of {_z} is "ENTITY_HOSTILE_SMALL_FALL" with "fall sound of zombie should return ENTITY_HOSTILE_SMALL_FALL"
assert high fall sound of {_z} is "ENTITY_HOSTILE_BIG_FALL" with "high fall sound of zombie should return ENTITY_HOSTILE_BIG_FALL"
assert fall sound from a height of 10 of {_z} is "ENTITY_HOSTILE_BIG_FALL" with "fall sound from height of 10 sound of zombie should return ENTITY_HOSTILE_BIG_FALL"
assert fall sound from a height of {_none} of {_z} is "ENTITY_HOSTILE_SMALL_FALL" with "fall sound from invalid height sound of zombie should return ENTITY_HOSTILE_SMALL_FALL"
assert splash sound of {_z} is "ENTITY_HOSTILE_SPLASH" with "splash sound of zombie should return ENTITY_HOSTILE_SPLASH"
assert speedy splash sound of {_z} is "ENTITY_GENERIC_SPLASH" with "speedy splash sound of zombie should return ENTITY_GENERIC_SPLASH"
assert eating sound of {_z} is "ENTITY_GENERIC_EAT" with "eating sound of zombie should return ENTITY_GENERIC_EAT"
assert eating sound of {_z} using golden apple is "ENTITY_GENERIC_EAT" with "eating sound of zombie using golden apple should return ENTITY_GENERIC_EAT"
assert drinking sound of {_z} is "ENTITY_GENERIC_DRINK" with "drinking sound of zombie should return ENTITY_GENERIC_DRINK"
assert drinking sound of {_z} using potion is "ENTITY_GENERIC_DRINK" with "drinking sound of zombie using potion should return ENTITY_GENERIC_DRINK"

delete entity within {_z}

0 comments on commit 348e0ac

Please sign in to comment.