NanoPi / chunkbase - POI collector

// ==UserScript==
// @name         chunkbase - POI collector
// @oldname      Copy to clipboard button for Seed Map [chunkbase]
// @namespace    https://openuserjs.org/users/NanoPi
// @version      0.3
// @license      MIT
// @description  Gather points of interest from your world's seed and import them as waypoints.
// @author       NanoPi
// @match        https://www.chunkbase.com/apps/seed-map
// @grant        none
// @updateURL https://openuserjs.org/meta/NanoPi/chunkbase_-_POI_collector.meta.js
// ==/UserScript==
// changelog
// 0.1        initial release, voxelmap format.
// 0.2        add /tp, xaeromap and journeymap formats.
// 0.2.1      split waypoint sharing formats.
// 0.3        override options, add waypoint file format, rename script, add update url.
(function () {
    'use strict';
    var dimensionsV = {
        overworld: "overworld",
        nether: "the_nether",
        end: "the_end"
    };
    var dimensionsX = {
        overworld: "overworld",
        nether: "the-nether",
        end: "the-end"
    };
    var dimensionsJ = {
        overworld: "0",
        nether: "-1",
        end: "1"
    };
    function mkbutton(text){
        var button = document.createElement('button');
        button.textContent = text;
        button.style = "font-size: unset;";
        button.title = "copy";
        return button;
    }
    var copyT = mkbutton("/tp");
    var tpcmd = "";
    var copyV = mkbutton("\u{1F4CD}V");
    var voxelmap = "";
    var copyX = mkbutton("\u{1F4CD}X");
    var xaerosminimap = "";
    var copyJ = mkbutton("\u{1F4CD}J");
    var journeymap = "";
    var copyA = mkbutton("\u{1F4CD}A");
    var allformats = "";

    function gettippy(e){
        //console.log(e);
        var tippyboxes = document.getElementsByClassName("tippy-box");
        var tippycontent = document.getElementsByClassName("tippy-content");
        var dimselect = document.getElementById("biome-dimension-select");
        if (tippyboxes.length > 0 && tippycontent.length > 0) {
            var tippybox = tippyboxes[0];
            var text = tippycontent[0].innerText;
            var r, name, x, y, z, dim;
            r = text.match(/^(.+)\nX: ([-,0-9]+) Z: ([-,0-9]+)$/);
            if (r) {
                name=r[1]; x=r[2].replace(/,/g, ''); z=r[3].replace(/,/g, ''); dim=dimselect.value;
                voxelmap = `[name:${name.replace(/,/g,"\uFE50")}, x:${x}, z:${z}, dim:minecraft:${dimensionsV[dim]}]`;
                xaerosminimap = `xaero-waypoint:${name.replace(/:/g,"^col^")}:${name.substr(0,1)}:${x}:64:${z}:6:false:0:Internal-${dimensionsX[dim]}-waypoints`;
                tpcmd = `/tp @s ${x} ~ ${z}`;
                journeymap = `[name:${name.replace(/,/g,"").replace(/\"/g,"").replace(/\'/g,"")}, x:${x}, z:${z}, dim:${dimensionsJ[dim]}]`;
                allformats = `${voxelmap} ${journeymap} ${xaerosminimap}`;
                updatebutton();
            }
            r = text.match(/^(.+)\nX: ([-,0-9]+) Y: ([-,0-9]+) Z: ([-,0-9]+)$/);
            if (r) {
                name=r[1]; x=r[2].replace(/,/g, ''); y=r[3].replace(/,/g, ''); z=r[4].replace(/,/g, ''); dim=dimselect.value;
                voxelmap = `[name:${name.replace(/,/g,"\uFE50")}, x:${x}, y:${y}, z:${z}, dim:minecraft:${dimensionsV[dim]}]`;
                xaerosminimap = `xaero-waypoint:${name.replace(/:/g,"^col^")}:${name.substr(0,1)}:${x}:${y}:${z}:6:false:0:Internal-${dimensionsX[dim]}-waypoints`;
                tpcmd = `/tp @s ${x} ${y} ${z}`;
                journeymap = `[name:${name.replace(/,/g,"").replace(/\"/g,"").replace(/\'/g,"")}, x:${x}, y:${y}, z:${z}, dim:${dimensionsJ[dim]}]`;
                allformats = `${voxelmap} ${journeymap} ${xaerosminimap}`;
                updatebutton();
            }
        }
    }

    function updatebutton(){
        var tippyboxes = document.getElementsByClassName("tippy-box");
        var tippycontent = document.getElementsByClassName("tippy-content");
        if (tippyboxes.length > 0 && tippycontent.length > 0) {
            var tippybox = tippyboxes[0];
            if (!tippybox.dataset.hasOwnProperty("addedbutton")) {
                var lfc = tippybox.firstChild;
                tippybox.insertBefore(document.createTextNode("\u{1F4CB}"),lfc);
                tippybox.insertBefore(copyA,lfc);
                copyA.addEventListener('click',copytextA,true);
                tippybox.insertBefore(copyT,lfc);
                copyT.addEventListener('click',copytextT,true);
                tippybox.insertBefore(copyV,lfc);
                copyV.addEventListener('click',copytextV,true);
                tippybox.insertBefore(copyX,lfc);
                copyX.addEventListener('click',copytextX,true);
                tippybox.insertBefore(copyJ,lfc);
                copyJ.addEventListener('click',copytextJ,true);
                tippybox.dataset.addedbutton=true;
            }
            copyJ.title = journeymap;
            copyT.title = tpcmd;
            copyV.title = voxelmap;
            copyX.title = xaerosminimap;
            copyA.title = `VoxelMap: ${voxelmap}\nJourneyMap: ${journeymap}\nXaero's Minimap: ${xaerosminimap}`
        }
    }

    function copytextA(e){
        navigator.clipboard.writeText(allformats);
    }
    function copytextJ(e){
        navigator.clipboard.writeText(journeymap);
    }
    function copytextT(e){
        navigator.clipboard.writeText(tpcmd);
    }
    function copytextV(e){
        navigator.clipboard.writeText(voxelmap);
    }
    function copytextX(e){
        navigator.clipboard.writeText(xaerosminimap);
    }

    function attachlistener () {
        var app = document.getElementById("app");
        app.addEventListener('click', gettippy, true);
    }

    attachlistener();

    var dimselect = document.getElementById("biome-dimension-select");
    var onPoiDrawnOriginal, onParamsChangedOriginal;
    var POIs = {};
    window.POIs = POIs;
    function POIcollector(a,b,d,f,g,h,i,j,k) {
        if (POIs[a] === undefined) {
            POIs[a] = {dim:dimselect.value};
            if (a=="endCity"){
                POIs.endCityShip = {dim:dimselect.value};
                POIs.endCityNoShip = {dim:dimselect.value};
            }
            addoption(a);
        }
        POIs[a][b]={xyz:d,meta:f};
        if (a=="endCity"){
            if (f[2].hasShip){
                POIs.endCityShip[b]={xyz:d,meta:f};
            } else {
                POIs.endCityNoShip[b]={xyz:d,meta:f};
            }
        }
        //console.log(b,d,f);
        //console.log({a:a,b:b,d:d,f:f,g:g,h:h,i:i,j:j,k:k});
        onPoiDrawnOriginal(a,b,d,f,g,h,i,j,k);
    }
    function ParameterPerimeter(){
        POIs = {};
        io.POIclass.innerHTML = "";
        onParamsChangedOriginal();
    }
    if (CB3TooltipManager) {
        onPoiDrawnOriginal = CB3TooltipManager.onPoiDrawn;
        CB3TooltipManager.onPoiDrawn = POIcollector;
        onParamsChangedOriginal = CB3TooltipManager.onParamsChanged;
        CB3TooltipManager.onParamsChanged = ParameterPerimeter;
    }
    function addoption(a){
        var io = document.io;
        var opt = document.createElement("option");
        opt.value = a;
        opt.textContent = a;
        io.POIclass.appendChild(opt);
        if (a=="endCity"){
            addoption("endCityShip");
            addoption("endCityNoShip");
        }
    }
    function mkui(elm){
        var f = document.createElement("form");
        f.name = "io";
        f.innerHTML = `
        <div class="fancy-box">
        <div class="fancy-row">
        <label for="voxelmapfile" class="fancy-size">Feature:</label>
        <div class="fancy-inputs">
		<select name="POIclass">  </select>
        </div>
        </div>
        <div class="fancy-row">
        <label for="voxelmapfile" class="fancy-size">WP File:</label>
        <div class="fancy-inputs">
        <input name="voxelmapfile" class="gh-button" type="button" value = "VoxelMap.points" title="for .minecraft/voxelmap/savefile.points:\nthese files are loaded from disk at startup.\nbe sure to close minecraft before editing.">
        <input name="name" type="text" value="" placeholder="override name">
        <input name="color" class="mini" type="color" value="#000000" title="Color override. Set to black (#000000) to use default color.">
        </div>
        </div>
        <div class="fancy-row">
        <label for="voxelmapfile" class="fancy-size">WP Chat:</label>
        <div class="fancy-inputs">
        <input name="voxelmapchat" class="gh-button" type="button" value = "VoxelMap chat" title="for in-game chat to share with your friends">
        <input name="noname" type="checkbox"><label for="noname" id="nonamelabel"> suppress name field</label>
        <input name="nodim" type="checkbox"><label for="nodim" id="nodimlabel"> suppress dimension field</label>
        </div>
        </div>
        <div class="fancy-row">
        </div>
        </div>
		<textarea name="teo" cols="114" rows="30"></textarea>
        `;
        elm.appendChild(f);
    }

    function voxfilter(t) {
        return t.replace(/,/g,"~comma~").replace(/:/g,"~colon~");
    }
    var maptools = {
        voxelmapfile:function() {
            var io = document.io;
            //lines = io.tei.value.split("\n");
            var POIclass = io.POIclass.value;
            if (POIclass == "") return;
            var lines = POIs[POIclass];
            var r, name, x, y, z, dim;
            var res = Array();
            var c, oc=false, ovn=io.name.value;
            if (io.color.value === "#000000"){
                c = {red:1.0,green:1.0,blue:1.0};
            } else {
                var color_re = /#(..)(..)(..)/;
                var re_res = io.color.value.match(color_re);
                if (re_res) {
                    oc=true;
                    c = {
                        red: parseInt(re_res[1],16)/256,
                        green: parseInt(re_res[2],16)/256,
                        blue: parseInt(re_res[3],16)/256
                    }
                }
            }
            if (POIclass == "endCityShip") { c = {red:0.75,green:0.0,blue:1.0}; }
            if (POIclass == "endCityNoShip") { c = {red:0.25,green:0.0,blue:1.0}; }
            dim=POIs[POIclass].dim;
            for (var i in lines) {
                if (typeof lines[i] === "object") {
                    var entry = i.split(";");
                    name=entry[0];
                    x=lines[i].xyz[0]
                    y=lines[i].xyz[1];y=y?y:64;
                    z=lines[i].xyz[2];
                    if (dim=="nether") {x*=8;z*=8}
                    if (entry[0]=="endCity"){
                        y=140;
                        if (lines[i].meta[2].hasShip==true){ name="CityS"; if(!oc)c = {red:0.75,green:0.0,blue:1.0}; }
                        else { name="City"; if(!oc)c = {red:0.25,green:0.0,blue:1.0}; }
                    }
                    if (entry[0]=="endGateway") { name="Gateway"; y=72; }
                    if (ovn!="") name = ovn;
                    res.push(`name:${voxfilter(name)},x:${x},y:${y},z:${z},enabled:true,red:${c.red},green:${c.green},blue:${c.blue},suffix:,world:,dimensions:${dimensionsV[dim]}#`);
                }
            }
            res.push("");
            io.teo.value = res.join("\n");
        }

    }

    function convert(maptool) {
        maptools[maptool]();
    }
    function voxelmapfile() {
        maptools.voxelmapfile();
    }
    function voxelmapchat() {
    }

    mkui(document.getElementById("seed-controls"));
    document.io.voxelmapfile.addEventListener('click', voxelmapfile, true);
    document.io.voxelmapchat.addEventListener('click', voxelmapchat, true);
    document.getElementById("nonamelabel").addEventListener('click', function(e){document.io.noname.click();}, true);
    document.getElementById("nodimlabel").addEventListener('click', function(e){document.io.nodim.click();}, true);

}());
/* eslint no-undef: off */