#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*(frameTimeCounter*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+frameTimeCounter*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*(frameTimeCounter*.7+worldpos.x*.14+worldpos.z*.07))+
    sin(2*pi*(frameTimeCounter*.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*(frameTimeCounter*.2+worldpos.x*.17+worldpos.z*.10))+
        sin(2*pi*(frameTimeCounter*.1+worldpos.x*.13+worldpos.z*.27));
        return wave*.075;
    }else return 0.;
}

vec3 CalcLanternMove(vec3 position, float mult) {
    vec3 frc = fract(position);
    frc = vec3(frc.x - 0.5, fract(frc.y - 0.001) - 1.0, frc.z - 0.5);
    vec3 flr = position - frc;
    float offset = flr.x * 2.4 + flr.y * 2.7 + flr.z * 2.2;

    float rmult = pi * 0.016 * mult;
    float rx = sin(frameTimeCounter       + offset) * rmult;
    float ry = sin(frameTimeCounter * 1.7 + offset) * rmult;
    float rz = sin(frameTimeCounter * 1.4 + offset) * rmult;
    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, float mult){
    vec3 wave=vec3(0.);
    vec3 worldpos=position+cameraPosition;
    mult = mult * 0.5 + 0.5;

    #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_LIQUID
    #ifdef WAVING_LAVA
    if(mc_Entity.x==10248)
    wave.y+=CalcLavaMove(worldpos);
    #endif
    #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, mult);
    #endif
    
    position+=wave * mult;
    
    return position;
}