function create(renderer, beam, color, map) {
    if (typeof beam === "string") {
        beam = renderer.createResource("BEAM_RENDERER", beam);
    }

    var effects = [];

    for (var i = 0; i < map.length; ++i) {
        var shape = renderer.createResource("SHAPE", null);
        var effect = renderer.createEffect("fiskheroes:lines").setShape(shape);
        var scale = [16.0, 16.0, 16.0];
        var lines = [];
        
        if (map[i].hasOwnProperty("anchor")) {
            effect.anchor.set(map[i].anchor);
        }
        
        if (map[i].hasOwnProperty("mirror")) {
            effect.mirror = map[i].mirror;
        }

        if (map[i].hasOwnProperty("offset") && Array.isArray(map[i].offset)) {
            effect.setOffset(map[i].offset[0], map[i].offset[1], map[i].offset[2]);
        }

        if (map[i].hasOwnProperty("rotation") && Array.isArray(map[i].rotation)) {
            effect.setRotation(map[i].rotation[0], map[i].rotation[1], map[i].rotation[2]);
        }

        if (map[i].hasOwnProperty("scale")) {
            if (Array.isArray(map[i].scale)) {
                scale = map[i].scale;
            }
            else if (typeof map[i].scale === "number") {
                scale = [map[i].scale, map[i].scale, map[i].scale];
            }
        }

        if (Array.isArray(map[i].entries)) {
            for (var j = 0; j < map[i].entries.length; ++j) {
                var entry = map[i].entries[j];

                if (entry.hasOwnProperty("start") && Array.isArray(entry.start)) {
                    for (var k = 0; k < entry.start.length; ++k) {
                        entry.start[k] = entry.start[k] / scale[k];
                    }
                }
                
                if (entry.hasOwnProperty("end") && Array.isArray(entry.end)) {
                    for (var k = 0; k < entry.end.length; ++k) {
                        entry.end[k] = entry.end[k] / scale[k];
                    }
                }

                lines[j] = shape.bindLine(entry);
            }
        }

        effect.color.set(color);
        effect.setScale(scale[0], scale[1], scale[2]);
        effect.setRenderer(beam);
        effects[i] = {
            renderLayer: map[i].renderLayer,
            effect: effect,
            lines: lines
        };
    }

    var obj = {
        opacity: 1.0,
        progress: 1.0,
        effects: effects,
        render: renderLayer => {
            effects.forEach(element => {
                if (element.renderLayer == renderLayer) {
                    element.effect.opacity = obj.opacity;
                    element.effect.progress = obj.progress;
                    element.effect.render();
                }
            });
        }
    };
    return obj;
}
function init(renderer, color) {
    //Head
    var head_beam = create(renderer, "ahhp:lantern_glow", color, [
        { anchor: "head", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [0.0, 0.5, -0.0], "end": [0.0, -9.5, 0.0], "size": [8.5, 8.5] }
        ]}
    ]);
    //Body
    var body_beam = create(renderer, "ahhp:lantern_glow", color, [
        { anchor: "body", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [0.0, 0.0, 0.0], "end": [0.0, 12.0, 0.0], "size": [4.5, 8.0] }
        ]}
    ]);
    //Right arm
    var armRight_beam = create(renderer, "ahhp:lantern_glow", color, [
        { anchor: "rightArm", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [-1.0, 11.0, 0.0], "end": [-1.0, -3.0, 0.0], "size": [4.25, 4.25] }
        ]}
    ]);
    //Left arm
    var armLeft_beam = create(renderer, "ahhp:lantern_glow", color, [
        { anchor: "leftArm", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [1.0, 11.0, 0.0], "end": [1.0, -3.0, 0.0], "size": [4.25, 4.25] }
        ]}
    ]);
    //Left Leg
    var legLeft_beam = create(renderer, "ahhp:lantern_glow", color, [
        { anchor: "leftLeg", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [0.0, 0.0, 0.0], "end": [0.0, 12.75, 0.0], "size": [4.25, 4.25] }
        ]}
    ]);
    //Right Leg
    var legRight_beam = create(renderer, "ahhp:lantern_glow", color, [
        { anchor: "rightLeg", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [0.0, 0.0, 0.0], "end": [0.0, 12.75, 0.0], "size": [4.25, 4.25] }
        ]}
    ]);
    //Hair
    var ring_beam = create(renderer, "ahhp:lantern_ring_glow", color, [
        { anchor: "rightArm", renderLayer: "CHESTPLATE", mirror: false, entries: [
            { "start": [-1.5, 10.0, -0.5], "end": [-1.5, 12.0, -0.5], "size": [1.0, 1.0] }
        ]}
    ]);
    return {
        head_beam: head_beam,
        body_beam: body_beam,
        armRight_beam: armRight_beam,
        armLeft_beam: armLeft_beam,
        legRight_beam: legRight_beam,
        legLeft_beam: legLeft_beam,
        ring_beam: ring_beam,
        render: (entity, renderLayer) => {
            if (renderLayer == "CHESTPLATE" && entity.getData("ahhp:dyn/lantern_timer") > 0 || entity.isDisplayStand()) {
                head_beam.progress = 1.0;
                head_beam.render(renderLayer);
                body_beam.progress = 1.0;
                body_beam.render(renderLayer);
                armRight_beam.progress = 1.0;
                armRight_beam.render(renderLayer);
                armLeft_beam.progress = 1.0;
                armLeft_beam.render(renderLayer);
                legRight_beam.progress = 1.0;
                legRight_beam.render(renderLayer);
                legLeft_beam.progress = 1.0;
                legLeft_beam.render(renderLayer);
            }
            if (renderLayer == "CHESTPLATE" || entity.isDisplayStand()) {
                ring_beam.progress = 1.0;
                ring_beam.render(renderLayer);
            }
        }
    };
}