// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
using System;
using OpenTK;
namespace ClassicalSharp.Entities {
/// Entity component that plays block step sounds.
public sealed class SoundComponent {
LocalPlayer p;
Game game;
Predicate checkSoundNonSolid, checkSoundSolid;
public SoundComponent( Game game, Entity entity ) {
this.game = game;
p = (LocalPlayer)entity;
checkSoundNonSolid = CheckSoundNonSolid;
checkSoundSolid = CheckSoundSolid;
lastSoundPos = -Utils.MaxPos();
}
Vector3 lastSoundPos;
public void Tick( bool wasOnGround ) {
Vector3 soundPos = p.nextPos;
GetSound();
if( !anyNonAir ) soundPos = Utils.MaxPos();
if( p.onGround && (DoPlaySound( soundPos ) || !wasOnGround) ) {
game.AudioPlayer.PlayStepSound( sndType );
lastSoundPos = soundPos;
}
}
bool DoPlaySound( Vector3 soundPos ) {
float distSq = (lastSoundPos - soundPos).LengthSquared;
bool enoughDist = distSq > 1.75f * 1.75f;
// just play every certain block interval when not animating
if( p.curSwing < 0.999f ) return enoughDist;
// have our legs just crossed over the '0' point?
float oldLegRot = (float)Math.Cos( p.anim.walkTimeO );
float newLegRot = (float)Math.Cos( p.anim.walkTimeN );
return Math.Sign( oldLegRot ) != Math.Sign( newLegRot );
}
bool anyNonAir = false;
SoundType sndType = SoundType.None;
void GetSound() {
Vector3 pos = p.nextPos;
AABB bounds = p.Bounds;
sndType = SoundType.None;
anyNonAir = false;
// first check surrounding liquids/gas for sounds
p.TouchesAny( bounds, checkSoundNonSolid );
if( sndType != SoundType.None ) return;
// then check block standing on
pos.Y -= 0.01f;
Vector3I feetPos = Vector3I.Floor( pos );
byte blockUnder = game.World.SafeGetBlock( feetPos );
float maxY = feetPos.Y + game.BlockInfo.MaxBB[blockUnder].Y;
SoundType typeUnder = game.BlockInfo.StepSounds[blockUnder];
CollideType collideType = game.BlockInfo.Collide[blockUnder];
if( maxY >= pos.Y && collideType == CollideType.Solid && typeUnder != SoundType.None ) {
anyNonAir = true; sndType = typeUnder; return;
}
// then check all solid blocks at feet
bounds.Max.Y = bounds.Min.Y = pos.Y;
p.TouchesAny( bounds, checkSoundSolid );
}
bool CheckSoundNonSolid( byte b ) {
SoundType newType = game.BlockInfo.StepSounds[b];
CollideType collide = game.BlockInfo.Collide[b];
if( newType != SoundType.None && collide != CollideType.Solid )
sndType = newType;
if( !game.BlockInfo.IsAir[b] )
anyNonAir = true;
return false;
}
bool CheckSoundSolid( byte b ) {
SoundType newType = game.BlockInfo.StepSounds[b];
if( newType != SoundType.None ) sndType = newType;
if( !game.BlockInfo.IsAir[b] )
anyNonAir = true;
return false;
}
}
}