moomoo sounds

Give some sound to moomoo.io!

// ==UserScript==
// @name       moomoo sounds
// @namespace    https://justgamersmoomooscripts.glitch.me
// @version    1.06
// @description Give some sound to moomoo.io!
// @author       Justgamer101
// @match        *://sandbox.moomoo.io/*
// @match        *://dev.moomoo.io/*
// @match        *://moomoo.io/*
// @grant    none
// @require https://greasyfork.org/scripts/423602-msgpack/code/msgpack.js
// ==/UserScript==
//add sound vol by distance


//if you would like the script to intercept packets (bypasses curse filter, with more features to come!)
const ALLOW_PACKET_INTERCEPT = true;

const load_all_sounds = true;

const link = "https://moosounds.justgamer101.repl.co/";

const menuMusic = new Audio(`${link}menu_music.mp3`),
snowWind = new Audio(`${link}in_snow.mp3`)

var curses;

fetch(`${link}curse_words.js`).then(resp => resp.text()).then(txt => curses = txt);

if(curses instanceof String){
    curses = JSON.parse(curses);
}

window.addEventListener("load", function(){
    window.isLoaded = true;
    if(menuMusic.isLoaded){
        menuMusic.play();//only play when both sound and page are loaded
    }
});

menuMusic.addEventListener("canplaythrough", function(){
    menuMusic.isLoaded = true;
    if(window.isLoaded){
        menuMusic.play();//^
    }
});

/**
 * Get the distance between 2 points that have the x and y attribute
 * @param {Object} pos1 begining position
 * @param {Object} pos2 secondary position
 * @returns distance between both points
 */

Math.dist = function (pos1, pos2) {
    var a = pos1.x - pos2.x;
    var b = pos1.y - pos2.y;
    return Math.sqrt(a * a + b * b);
};

const sound = {
    atk: "axe_swing",
    hitBush: "bush_hit1",
    hitStone: "stone_hit",
    eat: "eat",
    musketFire: "musket_fire",
    hitWood: "hit_wood",
    place: "place"
}

var soundCache = [],
    buildings = [],
    players = [],
    cachedSave = [];

    var playerDat = {
        health: 100,
        id: null,
        sid: null
    }

    var joinBtn = document.getElementById("enterGame");

    joinBtn.addEventListener("click", function(e){
       menuMusic.pause();//pause sound when clicked join button
    });

    if(load_all_sounds){
            for(let i in sound){
                playSound(sound[i]);//load all sounds
            }
    }

//minimize the amount of times a player will download a sound
function playSound(src, rep = 0){
    const ind = `${src}${rep}`;
    if(!soundCache[ind]){
        soundCache[ind] = new Audio(`${link}${src}.mp3`);
        soundCache[ind].isLoaded = false;
        soundCache[ind].addEventListener("canplaythrough", function(){
            soundCache[ind].isLoaded = true;
            if(src !== sound.musketFire && src !== sound.place){
                soundCache[ind].volume = 0.5;
            }
        });
        cachedSave[src] = (rep + 1);
        localStorage.cache_save = JSON.stringify(cachedSave);
        console.log("constructing new audio", src, rep);
    } else if(soundCache[ind].isLoaded){
        if(soundCache[ind].currentTime == 0 || soundCache[ind].ended){
            soundCache[ind].play();
        } else playSound(src, rep + 1);
    }
}

function cpc(sid){
    if(!players[sid]) {
        players[sid] = {
            health: 100,
            sid: sid
        };
    }
}

class ws2 extends WebSocket {
    constructor(url, protocols) {
        super(url, protocols);

        if(ALLOW_PACKET_INTERCEPT){
           this.staticSend = this.send;//using WebSocket.prototype.send.call is slow
            this.send = function(m){
                const data = msgpack.decode(new Uint8Array(m));

                if(data[0] == "ch"){//curse filter bypass
                    var msg = data[1][0];
                    for(let i = 0; i < curses.length; i++){
                        if(~msg.indexOf(curses[i])){
                            msg.replaceAll(curses[i], curses[i].toUpperCase());
                        }
                    }
                    console.log(data, msg)
                    return this.staticSend(new Uint8Array(Array.from(msgpack.encode(["ch", [msg]]))));
                } else this.staticSend(m);
            }
        }

        this.addEventListener("message", function(m){
            const data = msgpack.decode(new Uint8Array(m.data)),
                  payload = data[1];

            switch(data[0]){
                case "7":
                    playSound(sound.atk);
                    break;

                case "6":
                    for (let i = 0; i < payload[0].length / 8; i++) {//keep track of builds to know what sound to play
                        const binf = payload[0].slice(8 * i, 8 * i + 8);
                        let thisBuild = {
                            id: binf[0],
                            x: binf[1],
                            y: binf[2],
                            dir: binf[3],
                            scale: binf[4],
                            type: binf[5],
                            buildType: binf[6],
                            ownerSid: binf[7]
                        }
                        buildings[thisBuild.id] = thisBuild;
                      if(thisBuild.ownerSid == playerDat.sid) playSound(sound.place); //play sound if building placed by player
                    }
                    break;

                case "8":
                    var build = buildings[payload[1]],
                    type = build.type,
                    typeA = build.buildType;
                    if(type == 0 || type == 1 || typeA == 14){//tree and food bush and sapp
                        playSound(sound.hitBush);
                    } else if(type == 2 || type == 3 || typeA == 13){//stone and gold and mine
                        playSound(sound.hitStone);
                    } else if(typeA == 3 || typeA == 6 || typeA == 7 || typeA == 8 || typeA == 10 || typeA == 11 || typeA == 12){//spike and wall and mill
                        playSound(sound.hitWood);
                    }
                    break;

                    case "11":
                        snowWind.pause();
                    players[playerDat.sid] = 100;
                    setTimeout(function(){
                        menuMusic.play();//play music on death
                    }, 2000);
                    break;

                    case "h":
                      //  console.log(payload)
                        cpc(payload[0]);
                        if (payload[1] > players[payload[0]].health) playSound(sound.eat);
                        players[payload[0]].health = payload[1];
                    break;

                    case "1":
                    playerDat.sid = payload[0];
                    break;

                    case "33":
                        for (let i = 0; i < payload[0].length; i += 13) {
                            const plinf = payload[0].slice(i, i + 13);
                            var thisPlayer = {
                                sid: plinf[0],
                                x: plinf[1],
                                y: plinf[2],
                                dir: plinf[3],
                                obj: plinf[4],
                                wep: plinf[5],
                                variant: plinf[6],
                                tribe: plinf[7],
                                isLeader: plinf[8],
                                hat: plinf[9],
                                acc: plinf[10],
                                isSkull: plinf[11],
                                zIndex: plinf[12],
                                dist: null,
                                isMe: plinf[0] == playerDat.sid
                            },
                            sid = thisPlayer.sid, 
                            temp = players[sid] || {};

                          //  thisPlayer.dist = Math.dist(thisPlayer, temp);//distance from last update

                          if(temp.x !== thisPlayer.x || temp.y !== thisPlayer.y){//moved
                         //   playSound(sound.walk);
                          }

                            cpc(sid);

                            for(let i in thisPlayer){
                                players[sid][i] = thisPlayer[i];
                            }

                            if(players[sid].y <= 2400){//in snow
                                players[sid].notInSnow = players[sid].inSnow;
                                players[sid].inSnow = true;
                                players[sid].wasInSnow = false;
                            } else {
                                players[sid].notInSnow = true;
                                players[sid].wasInSnow = players[sid].inSnow;
                                players[sid].inSnow = false;
                            }
                            
                            if(thisPlayer.isMe){
                                if(players[sid].inSnow){
                                    if(players[sid].notInSnow || snowWind.currentTime == 0 || snowWind.ended) {
                                        snowWind.play();
                                    }
                                    if(snowWind.volume < 1) snowWind.volume += 0.05;
                                } else if(snowWind.currentTime !== 0 || snowWind.ended == false){
                                    if(!snowWind.paused){
                                    snowWind.volume -= 0.05;
                                    if(snowWind.volume == 0){
                                        snowWind.pause();
                                    }
                                }
                                }
                            }

                        }
                    break;

                    case "18":
                        //console.log(payload)
                        if(payload[5] == 5){//musket bullet
                            playSound(sound.musketFire);
                        }
                    break;
            }
        });
    }
}

/*
 Apple = 0
  WoodWall = 3
  Spikes = 6
  Windmill = 10
    Cookie = 1
  StoneWall = 4
    PitTrap = 15
  BoostPad = 16
    GreaterSpikes = 7
  FasterWindmill = 11
  Mine = 13
  Sapling = 14
    Cheese = 2
  Turret = 17
  Platform = 18
  HealingPad = 19
  Blocker = 21
  Teleporter = 22
  CastleWall = 5
  PowerMill = 12
    PoisonSpikes = 8
  SpinningSpikes = 9
  SpawnPad = 20
  */

//picoseconds op

WebSocket = ws2;