f37812be3e
I may have got a bit behind with version control. A lot behind, in fact. Maybe I'll go back and split this sometime - then again, I probably won't. But hey, at least it's here!
118 lines
4.3 KiB
Java
118 lines
4.3 KiB
Java
package electroblob.wizardry.client.audio;
|
|
|
|
import electroblob.wizardry.data.DispenserCastingData;
|
|
import electroblob.wizardry.registry.WizardrySounds;
|
|
import electroblob.wizardry.spell.Spell;
|
|
import electroblob.wizardry.util.WizardryUtilities;
|
|
import net.minecraft.client.audio.PositionedSound;
|
|
import net.minecraft.entity.EntityLivingBase;
|
|
import net.minecraft.tileentity.TileEntity;
|
|
import net.minecraft.tileentity.TileEntityDispenser;
|
|
import net.minecraft.util.SoundEvent;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.world.World;
|
|
|
|
/** Abstract base class for sound loops associated with spells; see subclasses below for implementations. */
|
|
public abstract class SoundLoopSpell extends SoundLoop {
|
|
|
|
private final Spell spell;
|
|
|
|
public SoundLoopSpell(SoundEvent start, SoundEvent loop, SoundEvent end, ISoundFactory factory, Spell spell){
|
|
super(start, loop, end, WizardrySounds.SPELLS, factory);
|
|
this.spell = spell;
|
|
}
|
|
|
|
@Override
|
|
public void update(){
|
|
// This may be a bit overkill but I might as well put functionality in superclasses where possible
|
|
if(stillCasting(spell)){
|
|
// This can't called in the same tick as endLoop because otherwise, if the spell casting stops during the
|
|
// same tick as the transition to the loop sound it will try and stop the loop immediately after it has
|
|
// started - and for whatever reason, this causes the 'Channel null in method stop' error.
|
|
super.update();
|
|
}else{
|
|
endLoop();
|
|
}
|
|
}
|
|
|
|
protected abstract boolean stillCasting(Spell spell);
|
|
|
|
/** Implements a sound loop for continuous spells cast by entities. */
|
|
public static class SoundLoopSpellEntity extends SoundLoopSpell {
|
|
|
|
private final EntityLivingBase source;
|
|
|
|
public SoundLoopSpellEntity(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, EntityLivingBase source, float volume, float pitch){
|
|
super(start, loop, end, (sound, category, repeat) -> new MovingSoundEntity<>(source, sound, category, volume, pitch, repeat), spell);
|
|
this.source = source;
|
|
}
|
|
|
|
@Override
|
|
protected boolean stillCasting(Spell spell){
|
|
return WizardryUtilities.isCasting(source, spell);
|
|
}
|
|
}
|
|
|
|
public static abstract class SoundLoopSpellPosition extends SoundLoopSpell {
|
|
|
|
public SoundLoopSpellPosition (SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell,
|
|
double x, double y, double z, float sndVolume, float sndPitch){
|
|
// Huh, I actually found a use for a non-static initialiser block - hence the double curly brackets...
|
|
super(start, loop, end, (sound, category, r) -> new PositionedSound(sound, category){{
|
|
// ...et voila, we can just set protected fields as we please using external variables
|
|
this.xPosF = (float)x;
|
|
this.yPosF = (float)y;
|
|
this.zPosF = (float)z;
|
|
this.repeat = r;
|
|
this.volume = sndVolume;
|
|
this.pitch = sndPitch;
|
|
}}, spell);
|
|
}
|
|
}
|
|
|
|
/** Implements a sound loop for continuous spells cast by dispensers. */
|
|
public static class SoundLoopSpellDispenser extends SoundLoopSpellPosition {
|
|
|
|
private final TileEntityDispenser source;
|
|
|
|
public SoundLoopSpellDispenser(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, World world,
|
|
double x, double y, double z, float sndVolume, float sndPitch){
|
|
super(start, loop, end, spell, x, y, z, sndVolume, sndPitch);
|
|
|
|
TileEntity tileentity = world.getTileEntity(new BlockPos(x, y, z));
|
|
|
|
if(tileentity instanceof TileEntityDispenser) this.source = (TileEntityDispenser)tileentity;
|
|
else throw new NullPointerException(String.format("Playing continuous spell sound: no dispenser found at %s, %s, %s", x, y, z));
|
|
}
|
|
|
|
@Override
|
|
protected boolean stillCasting(Spell spell){
|
|
return DispenserCastingData.get(source).currentlyCasting() == spell;
|
|
}
|
|
|
|
}
|
|
|
|
/** Implements a sound loop for continuous spells cast at a position (via commands). */
|
|
public static class SoundLoopSpellPosTimed extends SoundLoopSpellPosition {
|
|
|
|
private int timeLeft;
|
|
|
|
public SoundLoopSpellPosTimed(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, int duration,
|
|
double x, double y, double z, float sndVolume, float sndPitch){
|
|
super(start, loop, end, spell, x, y, z, sndVolume, sndPitch);
|
|
this.timeLeft = duration;
|
|
}
|
|
|
|
@Override
|
|
public void update(){
|
|
super.update();
|
|
timeLeft--;
|
|
}
|
|
|
|
@Override
|
|
protected boolean stillCasting(Spell spell){
|
|
return timeLeft > 0;
|
|
}
|
|
}
|
|
}
|