#define WAVING_CROPS
#define WAVING_FIRE
#define WAVING_GRASS
#define WAVING_LAVA
#define WAVING_LEAVES
#define WAVING_LILYPAD
#define WAVING_TALL_PLANT
#define WAVING_PLANT
#define WAVING_VINES

const float pi=3.1415927;
float pi2wt=6.2831854*(frametime*24.);

float GetNoise(vec2 pos){
    return fract(sin(dot(pos,vec2(12.9898,4.1414)))*43758.5453);
}

float Noise2D(vec2 pos){
    vec2 flr=floor(pos);
    vec2 frc=fract(pos);
    frc=frc*frc*(3.-2.*frc);
    
    float n00=GetNoise(flr);
    float n01=GetNoise(flr+vec2(0.,1.));
    float n10=GetNoise(flr+vec2(1.,0.));
    float n11=GetNoise(flr+vec2(1.,1.));
    
    float n0=mix(n00,n01,frc.y);
    float n1=mix(n10,n11,frc.y);
    
    return mix(n0,n1,frc.x)-.5;
}

vec3 CalcMove(vec3 pos,float density,float speed,vec2 mult){
    pos=pos*density+frametime*speed;
    vec3 wave=vec3(Noise2D(pos.yz),Noise2D(pos.xz+.333),Noise2D(pos.xy+.667));
    return wave*vec3(mult,mult.x);
}

float CalcLilypadMove(vec3 worldpos){
    float wave=sin(2*pi*(frametime*.7+worldpos.x*.14+worldpos.z*.07))+
    sin(2*pi*(frametime*.5+worldpos.x*.10+worldpos.z*.20));
    return wave*.025;
}

float CalcLavaMove(vec3 worldpos){
    float fy=fract(worldpos.y+.005);
    
    if(fy>.01){
        float wave=sin(2*pi*(frametime*.2+worldpos.x*.17+worldpos.z*.10))+
        sin(2*pi*(frametime*.1+worldpos.x*.13+worldpos.z*.27));
        return wave*.075;
    }else return 0.;
}

vec3 CalcLanternMove(vec3 position){
    vec3 frc=fract(position);
    frc=vec3(frc.x-.5,fract(frc.y-.001)-1.,frc.z-.5);
    vec3 flr=position-frc;
    float offset=flr.x*2.4+flr.y*2.7+flr.z*2.2;
    
    float rx=sin(frametime+offset)*pi*.016;
    float ry=sin(frametime*1.7+offset)*pi*.016;
    float rz=sin(frametime*1.4+offset)*pi*.016;
    mat3 rotx=mat3(
        1,0,0,
        0,cos(rx),-sin(rx),
        0,sin(rx),cos(rx)
    );
    mat3 roty=mat3(
        cos(ry),0,sin(ry),
        0,1,0,
        -sin(ry),0,cos(ry)
    );
    mat3 rotz=mat3(
        cos(rz),-sin(rz),0,
        sin(rz),cos(rz),0,
        0,0,1
    );
    frc=rotx*roty*rotz*frc;
    
    return flr+frc-position;
}

vec3 WavingBlocks(vec3 position,float istopv){
    vec3 wave=vec3(0.);
    vec3 worldpos=position+cameraPosition;
    
    #ifdef WAVING_GRASS
    if(mc_Entity.x==10100&&istopv>.9)
    wave+=CalcMove(worldpos,.35,1.,vec2(.25,.06));
    #endif
    #ifdef WAVING_CROPS
    if((mc_Entity.x==10102||mc_Entity.x==10108)&&(istopv>.9||fract(worldpos.y+.0675)>.01))
    wave+=CalcMove(worldpos,.35,1.,vec2(.15,.06));
    #endif
    #ifdef WAVING_PLANT
    if(mc_Entity.x==10101&&(istopv>.9||fract(worldpos.y+.005)>.01))
    wave+=CalcMove(worldpos,.7,1.5,vec2(.12,.06));
    #endif
    #ifdef WAVING_TALL_PLANT
    if(mc_Entity.x==10103||(mc_Entity.x==10104&&(istopv>.9||fract(worldpos.y+.005)>.01)))
    wave+=CalcMove(worldpos,.7,1.25,vec2(.12,.06));
    #endif
    #ifdef WAVING_LEAVES
    if(mc_Entity.x==10105)
    wave+=CalcMove(worldpos,.35,1.,vec2(.08,.08));
    #endif
    #ifdef WAVING_VINES
    if(mc_Entity.x==10106)
    wave+=CalcMove(worldpos,.35,1.25,vec2(.06,.12));
    #endif
    #ifdef WAVING_LILYPAD
    if(mc_Entity.x==10107)
    wave.y+=CalcLilypadMove(worldpos);
    #endif
    #ifdef WAVING_FIRE
    if((mc_Entity.x==10249||mc_Entity.x==10252)&&istopv>.9)
    wave+=CalcMove(worldpos,1.,1.5,vec2(0.,.37));
    #endif
    #ifdef WAVING_LAVA
    if(mc_Entity.x==10248)
    wave.y+=CalcLavaMove(worldpos);
    #endif
    #ifdef WAVING_CHAIN
    if(mc_Entity.x==10110)
    wave+=CalcMove(worldpos,.35,1.25,vec2(.01,.06));
    #endif
    #ifdef WAVING_LANTERN
    if(mc_Entity.x==10251||mc_Entity.x==10253)
    wave+=CalcLanternMove(worldpos);
    #endif
    
    position+=wave;
    
    return position;
}