//LiteLoaderScript Dev Helper
/// <reference path="F:\molingbao\llse_development\Library/JS/Api.js" /> 


//Arnol梧桐的第五个插件
//注释很详细，逻辑很简单。大家就当作插件入门教程吧，希望能够帮助大伙快速上手llse插件开发。

//由于总有玩家用两个对着的侦测器+活塞的办法，做高频卡服机
//卡服装置多了，一加载那个区块，全服务器的TPS会急剧降低，甚至会崩服。

//这个插件会检测服务器内的侦测器推动活塞的频率
//禁止使用侦测器+活塞制作高频卡服装置
//插件检测到有侦测器+活塞卡服装置时，就会把推动活塞过快的的侦测器击落成掉落物


//【插件注册】向加载器提供一些插件相关的信息
let PLUGIN_NAME = "AntiObserver";      //插件名称
let PLUGIN_DESCRIPTION = "LLSE 清理侦测器卡服装置 [输入 ll plugins AntiObserver 查看具体信息]";     //插件描述
let VERSION = [1,0,2];      //插件版本号
let Publishing_website = "https://www.minebbs.com/resources/antiobserver.4212/";   //插件发布地址
let AUTHOR = "Arnol梧桐";       //插件作者

logger.setTitle(`${PLUGIN_NAME}`);       //插件日志消息标头
logger.setConsole(true, 4);         //设置日志是否输出到控制台,默认等级为4；可以输出 严重错误、错误、警告、提示信息
logger.info(`${PLUGIN_NAME} Loaded, Version:${VERSION.join(".")}, Publishing website:${Publishing_website},Author: ${AUTHOR}`);  //显示插件版本号，作者等信息
logger.info(`${PLUGIN_NAME} 加载成功, 版本号:${VERSION.join(".")}, 发布网站:${Publishing_website},插件作者: ${AUTHOR}`);  //显示插件版本号，作者等信息

ll.registerPlugin(PLUGIN_NAME, PLUGIN_DESCRIPTION, VERSION, {
    "Publishing website":Publishing_website,
    "发布地址":Publishing_website,
    "Author":AUTHOR,
    "作者":AUTHOR
});

//【配置文件】创建或读取配置文件
let config=new JsonConfigFile(".\\plugins\\AntiObserver\\config.json");

//三秒之内允许最高侦测器激活活塞推动次数
//默认值为3秒内侦测器激活活塞推动最多9次,超过即判定频率过高，将侦测器破坏为掉落物
//Maximum number of detection-activated piston pushes allowed in 3 seconds
config.init("三秒之内允许最高侦测器激活活塞推动次数",9);


//创建活塞推动计次数组，用来临时保存每个坐标活塞3秒内推动了多少次
var PistonPushCount = new Array();


//活塞推动时间数组，用来临时保存每个坐标活塞推动的时间
//后续用来DetectingPistonTimer函数计算第一次某坐标的活塞推动时间，
//和这次某坐标的活塞推动时间的时间差值是否超过3s
var PistonPushTime = new Array();


//活塞检测计时器，某坐标前后两次推动时间超过3s就从数组里删除
function DetectingPistonTimer() {
    let nowtime = Date.now();
    for (let i in PistonPushTime) {
        let time_lag = nowtime - PistonPushTime[i];
        if (time_lag >= 3000) {
            delete PistonPushTime[i];
            delete PistonPushCount[i];
        }
    }
};

//创建自定义函数 DetectNearbyBlocks(block_pos,block_type)
//这个函数是用来查看某坐标的上下左右前后等，紧挨着这个方块的坐标是否包含某种方块
//如果包含，就返回这个方块对象
//如果没发现这种方块就返回undefined

//eg : DetectNearbyBlocks(pistonPos,"minecraft:observer")
//如果检测到这个坐标附近有侦测器，就返回这个侦测器方块对象

function DetectNearbyBlocks(block_pos,block_type){

    var NearbyBlocks = new Array();

    //经常调用的部分，用常量（const）存起来，方便后续调用，提升代码性能
    const block_pos_x = block_pos.x;
    const block_pos_x_minus_1 = block_pos.x-1;
    const block_pos_x_plus_1 = block_pos.x+1;
    const block_pos_y = block_pos.y;
    const block_pos_y_minus_1 = block_pos.y-1;
    const block_pos_y_plus_1 = block_pos.y+1;
    const block_pos_z = block_pos.z;
    const block_pos_z_minus_1 = block_pos.z-1;
    const block_pos_z_plus_1 = block_pos.z+1;
    const block_pos_dimid = block_pos.dimid;

    //附近的方块对象数组
    NearbyBlocks[0] = mc.getBlock(block_pos_x,block_pos_y,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[1] = mc.getBlock(block_pos_x,block_pos_y,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[2] = mc.getBlock(block_pos_x,block_pos_y_minus_1,block_pos_z,block_pos_dimid);
    NearbyBlocks[3] = mc.getBlock(block_pos_x,block_pos_y_minus_1,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[4] = mc.getBlock(block_pos_x,block_pos_y_minus_1,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[5] = mc.getBlock(block_pos_x,block_pos_y_plus_1,block_pos_z,block_pos_dimid);
    NearbyBlocks[6] = mc.getBlock(block_pos_x,block_pos_y_plus_1,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[7] = mc.getBlock(block_pos_x,block_pos_y_plus_1,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[8] = mc.getBlock(block_pos_x_minus_1,block_pos_y,block_pos_z,block_pos_dimid);
    NearbyBlocks[9] = mc.getBlock(block_pos_x_minus_1,block_pos_y,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[10] = mc.getBlock(block_pos_x_minus_1,block_pos_y,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[11] = mc.getBlock(block_pos_x_minus_1,block_pos_y_minus_1,block_pos_z,block_pos_dimid);
    NearbyBlocks[12] = mc.getBlock(block_pos_x_minus_1,block_pos_y_minus_1,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[13] = mc.getBlock(block_pos_x_minus_1,block_pos_y_minus_1,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[14] = mc.getBlock(block_pos_x_minus_1,block_pos_y_plus_1,block_pos_z,block_pos_dimid);
    NearbyBlocks[15] = mc.getBlock(block_pos_x_minus_1,block_pos_y_plus_1,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[16] = mc.getBlock(block_pos_x_minus_1,block_pos_y_plus_1,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[17] = mc.getBlock(block_pos_x_plus_1,block_pos_y,block_pos_z,block_pos_dimid);
    NearbyBlocks[18] = mc.getBlock(block_pos_x_plus_1,block_pos_y,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[19] = mc.getBlock(block_pos_x_plus_1,block_pos_y,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[20] = mc.getBlock(block_pos_x_plus_1,block_pos_y_minus_1,block_pos_z,block_pos_dimid);
    NearbyBlocks[21] = mc.getBlock(block_pos_x_plus_1,block_pos_y_minus_1,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[22] = mc.getBlock(block_pos_x_plus_1,block_pos_y_minus_1,block_pos_z_plus_1,block_pos_dimid);
    NearbyBlocks[23] = mc.getBlock(block_pos_x_plus_1,block_pos_y_plus_1,block_pos_z,block_pos_dimid);
    NearbyBlocks[24] = mc.getBlock(block_pos_x_plus_1,block_pos_y_plus_1,block_pos_z_minus_1,block_pos_dimid);
    NearbyBlocks[25] = mc.getBlock(block_pos_x_plus_1,block_pos_y_plus_1,block_pos_z_plus_1,block_pos_dimid);

    //遍历输出，查看是否有对应的方块类型
    for(let i=0;i<NearbyBlocks.length;i++){
        if (NearbyBlocks[i].type == block_type){
            return NearbyBlocks[i];     //如果有，则返回这个方块对象
        }
    }
    return undefined;       //如果没有，则返回undefined
};

//创建自定义函数，活塞推动次数检测
//如果检测到侦测器激活活塞，3秒内活塞推动次数超过设定值（默认是12次）
//就破坏这个侦测器为掉落物
function PistonPushTimesDetection(block_pos,block_type){

    let observer_blocks = DetectNearbyBlocks(block_pos,block_type);

        if(PistonPushCount[block_pos] >= config.get("三秒之内允许最高侦测器激活活塞推动次数") && observer_blocks != undefined){
            observer_blocks.destroy(true);
            return true;
        }
        else {
            if (PistonPushCount[block_pos] == null) {
                PistonPushCount[block_pos] = 1;
                PistonPushTime[block_pos] = Date.now();
            } 
            else {
                PistonPushCount[block_pos] += 1;
            }
        }
    
};

//活塞推动监听
mc.listen("onPistonPush",function(pistonPos,block){

    if(PistonPushTimesDetection(pistonPos,"minecraft:observer")){

        log(`检测到侦测器卡服装置，坐标在${pistonPos}附近，已执行清理！`);

    }
});

//设置周期执行函数DetectingPistonTimer（活塞检测计时器，推动时间超过3s就从数组里删除）
//每1000ms执行一次
setInterval(DetectingPistonTimer, 1000);
