ScriptManager

Manage and download CustomNPCs scripts ingame!

// ==UserScript==
// @namespace          runonstof
// @name               ScriptManager
// @version            1.0.2
// @description        Manage and download CustomNPCs scripts ingame!
// @author             Runonstof
// @license            MIT
// @minecraft          1.20.1
// @match              https://customnpcs.com
// ==/UserScript==

function _arrayLikeToArray(r, a) {
  (null == a || a > r.length) && (a = r.length);
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
  return n;
}
function _arrayWithHoles(r) {
  if (Array.isArray(r)) return r;
}
function _assertThisInitialized(e) {
  if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  return e;
}
function _callSuper(t, o, e) {
  return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _classCallCheck(a, n) {
  if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _construct(t, e, r) {
  if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
  var o = [null];
  o.push.apply(o, e);
  var p = new (t.bind.apply(t, o))();
  return r && _setPrototypeOf(p, r.prototype), p;
}
function _defineProperties(e, r) {
  for (var t = 0; t < r.length; t++) {
    var o = r[t];
    o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
  }
}
function _createClass(e, r, t) {
  return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
    writable: !1
  }), e;
}
function _getPrototypeOf(t) {
  return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
    return t.__proto__ || Object.getPrototypeOf(t);
  }, _getPrototypeOf(t);
}
function _inherits(t, e) {
  if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
  t.prototype = Object.create(e && e.prototype, {
    constructor: {
      value: t,
      writable: !0,
      configurable: !0
    }
  }), Object.defineProperty(t, "prototype", {
    writable: !1
  }), e && _setPrototypeOf(t, e);
}
function _isNativeFunction(t) {
  try {
    return -1 !== Function.toString.call(t).indexOf("[native code]");
  } catch (n) {
    return "function" == typeof t;
  }
}
function _isNativeReflectConstruct() {
  try {
    var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
  } catch (t) {}
  return (_isNativeReflectConstruct = function () {
    return !!t;
  })();
}
function _iterableToArrayLimit(r, l) {
  var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  if (null != t) {
    var e,
      n,
      i,
      u,
      a = [],
      f = !0,
      o = !1;
    try {
      if (i = (t = t.call(r)).next, 0 === l) {
        if (Object(t) !== t) return;
        f = !1;
      } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
    } catch (r) {
      o = !0, n = r;
    } finally {
      try {
        if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
      } finally {
        if (o) throw n;
      }
    }
    return a;
  }
}
function _nonIterableRest() {
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _possibleConstructorReturn(t, e) {
  if (e && ("object" == typeof e || "function" == typeof e)) return e;
  if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
  return _assertThisInitialized(t);
}
function _setPrototypeOf(t, e) {
  return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
    return t.__proto__ = e, t;
  }, _setPrototypeOf(t, e);
}
function _slicedToArray(r, e) {
  return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toPrimitive(t, r) {
  if ("object" != typeof t || !t) return t;
  var e = t[Symbol.toPrimitive];
  if (void 0 !== e) {
    var i = e.call(t, r || "default");
    if ("object" != typeof i) return i;
    throw new TypeError("@@toPrimitive must return a primitive value.");
  }
  return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
  var i = _toPrimitive(t, "string");
  return "symbol" == typeof i ? i : i + "";
}
function _typeof(o) {
  "@babel/helpers - typeof";

  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
    return typeof o;
  } : function (o) {
    return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
  }, _typeof(o);
}
function _unsupportedIterableToArray(r, a) {
  if (r) {
    if ("string" == typeof r) return _arrayLikeToArray(r, a);
    var t = {}.toString.call(r).slice(8, -1);
    return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
  }
}
function _wrapNativeSuper(t) {
  var r = "function" == typeof Map ? new Map() : void 0;
  return _wrapNativeSuper = function (t) {
    if (null === t || !_isNativeFunction(t)) return t;
    if ("function" != typeof t) throw new TypeError("Super expression must either be null or a function");
    if (void 0 !== r) {
      if (r.has(t)) return r.get(t);
      r.set(t, Wrapper);
    }
    function Wrapper() {
      return _construct(t, arguments, _getPrototypeOf(this).constructor);
    }
    return Wrapper.prototype = Object.create(t.prototype, {
      constructor: {
        value: Wrapper,
        enumerable: !1,
        writable: !0,
        configurable: !0
      }
    }), _setPrototypeOf(Wrapper, t);
  }, _wrapNativeSuper(t);
}

function Color(hex) {
  this.hex = hex;
  this.alpha = function (alpha) {
    return new Color(this.hex & 0xFFFFFF00 | alpha * 255);
  };
  this.toHex = function () {
    return this.hex;
  };
}
var COLORS = {
  RED: new Color(0xFF0000FF),
  GREEN: new Color(0x00FF00FF),
  BLUE: new Color(0x0000FFFF),
  YELLOW: new Color(0xFFFF00FF),
  PURPLE: new Color(0xFF00FFFF),
  ORANGE: new Color(0xFFA500FF),
  PINK: new Color(0xFFC0CBFF),
  GRAY: new Color(0x808080FF),
  BLACK: new Color(0x000000FF),
  WHITE: new Color(0xFFFFFFFF)
};

var API = Java.type('noppes.npcs.api.NpcAPI').Instance();
var world = API.getIWorld('minecraft:overworld');
function dd() {
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
    args[_key] = arguments[_key];
  }
  for (var _i = 0, _args = args; _i < _args.length; _i++) {
    var arg = _args[_i];
    if (!(arg instanceof Error) && _typeof(arg) === 'object') {
      arg = JSON.stringify(arg, null, 2);
    }
    world.broadcast(arg);
  }
}

var _GUI_IDS = {};
var _GUI_EVENT_LISTENERS = {};
function id(name) {
  // generate random name if name is not provided
  if (!name) {
    name = Math.random().toString(36).substring(2, 15);
  }
  return _GUI_IDS[name] = _GUI_IDS[name] || Object.keys(_GUI_IDS).length + 1;
}
function listen(id, callback) {
  if (!_GUI_EVENT_LISTENERS[id]) {
    _GUI_EVENT_LISTENERS[id] = [];
  }
  _GUI_EVENT_LISTENERS[id].push(callback);
}
function emit(id, data) {
  if (!_GUI_EVENT_LISTENERS[id]) {
    return;
  }
  _GUI_EVENT_LISTENERS[id].forEach(function (callback) {
    return callback(data);
  });
}
var BaseGui = /*#__PURE__*/function () {
  function BaseGui(id, width, height, player) {
    _classCallCheck(this, BaseGui);
    this.gui = API.createCustomGui(id, width, height, false, player);
    this.state = {};
    this.player = player;
  }
  return _createClass(BaseGui, [{
    key: "init",
    value: function init() {
      // Optional override
    }
  }, {
    key: "build",
    value: function build() {
      throw new Error('build method must be implemented');
    }
  }, {
    key: "update",
    value: function update() {
      throw new Error('update method must be implemented');
    }
  }, {
    key: "onClose",
    value: function onClose() {
      // Optional override
    }
  }]);
}();
var gui = {
  id: id,
  listen: listen,
  emit: emit
};

var URL = Java.type("java.net.URL");
var OutputStreamWriter = Java.type("java.io.OutputStreamWriter");
var BufferedReader = Java.type("java.io.BufferedReader");
var InputStreamReader = Java.type("java.io.InputStreamReader");

// Custom error class
var HttpError = /*#__PURE__*/function (_Error) {
  function HttpError(response, responseCode) {
    var _this;
    _classCallCheck(this, HttpError);
    _this = _callSuper(this, HttpError, ["HttpError: ".concat(responseCode)]);
    _this.response = response;
    return _this;
  }
  _inherits(HttpError, _Error);
  return _createClass(HttpError);
}(/*#__PURE__*/_wrapNativeSuper(Error));
function request(method, url) {
  var requestBody = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  url = new URL(url);
  var connection = url.openConnection();
  connection.setRequestMethod(method);
  if (method === "POST") {
    connection.setRequestProperty("Content-Type", "application/json");
    connection.setDoOutput(true);
    if (requestBody) {
      var writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
      writer.write(JSON.stringify(requestBody));
      writer.flush();
      writer.close();
    }
  } else {
    connection.setDoOutput(false);
  }
  var responseCode = connection.getResponseCode();
  var reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  var response = "";
  var line;
  while ((line = reader.readLine()) != null) {
    response += line + '\n';
  }
  reader.close();
  if (!(responseCode >= 200 && responseCode < 400)) {
    throw new HttpError(response, responseCode);
  }
  connection.disconnect();
  return response;
}
function get(url) {
  return request("GET", url, null);
}
function post(url, requestBody) {
  return request("POST", url, requestBody);
}
function getJson(url) {
  return JSON.parse(get(url));
}
function postJson(url, requestBody) {
  return JSON.parse(post(url, requestBody));
}
var http = {
  get: get,
  post: post,
  getJson: getJson,
  postJson: postJson,
  request: request,
  HttpError: HttpError
};

// The Minecraft version this script is compatible with
// Used to check with downloadable scripts
var MINECRAFT_VERSION = '1.20.1';

// The GreasyFork Script ID of this script, for self-updating purposes
var SCRIPT_MANAGER_ID = 548277;

// The GreasyFork User IDs of trusted authors
// These authors have been verified to be trustworthy
// This is used to display a trusted badge next to the author name
var TRUSTED_AUTHOR_IDS = [1210996,
// Runonstof
1511915,
// Hank
1511928 // Etternal
// xxxxx, // TODO: Add Yellow
];

// Test data to mock API responses
var TEST_SCRIPTS = [{
  "id": SCRIPT_MANAGER_ID,
  "daily_installs": 0,
  "total_installs": 0,
  "fan_score": "5.0",
  "good_ratings": 0,
  "ok_ratings": 0,
  "bad_ratings": 0,
  "created_at": "2025-09-03T22:04:40.000Z",
  "code_updated_at": "2025-09-03T23:35:06.000Z",
  "namespace": "runonstof",
  "support_url": null,
  "contribution_url": null,
  "contribution_amount": null,
  "users": [{
    "id": 1210996,
    "name": "Runonstof",
    "created_at": "2023-11-04T23:03:12.000Z",
    "url": "https://greasyfork.org/users/1210996-runonstof"
  }],
  "name": "ScriptManager",
  "description": "Manage and download CustomNPCs scripts ingame!",
  "url": "https://greasyfork.org/scripts/548277-scriptmanager",
  "code_url": "https://update.greasyfork.org/scripts/548277/ScriptManager.user.js",
  "code_size": 6386,
  "license": "MIT License",
  "version": "1.0.1",
  "locale": "en",
  "deleted": false
}, {
  "id": 548379,
  "daily_installs": 0,
  "total_installs": 0,
  "fan_score": "5.0",
  "good_ratings": 0,
  "ok_ratings": 0,
  "bad_ratings": 0,
  "created_at": "2025-09-04T18:54:04.000Z",
  "code_updated_at": "2025-09-04T18:56:28.000Z",
  "namespace": "runonstof",
  "support_url": null,
  "contribution_url": null,
  "contribution_amount": null,
  "users": [{
    "id": 1210996,
    "name": "Runonstof",
    "created_at": "2023-11-04T23:03:12.000Z",
    "url": "https://greasyfork.org/users/1210996-runonstof"
  }],
  "name": "Debugger",
  "description": "Debugger tool for CustomNPCs scripts",
  "url": "https://greasyfork.org/scripts/548379-debugger",
  "code_url": "https://update.greasyfork.org/scripts/548379/Debugger.user.js",
  "code_size": 122188,
  "license": "MIT License",
  "version": "1.0.2",
  "locale": "en",
  "deleted": false
}, {
  "id": 485526,
  "daily_installs": 12,
  "total_installs": 482,
  "fan_score": "5.0",
  "good_ratings": 17,
  "ok_ratings": 2,
  "bad_ratings": 0,
  "created_at": "2025-09-04T18:54:04.000Z",
  "code_updated_at": "2025-09-04T18:56:28.000Z",
  "namespace": "runonstof",
  "support_url": null,
  "contribution_url": null,
  "contribution_amount": null,
  "users": [{
    "id": 1210996,
    "name": "Runonstof",
    "created_at": "2023-11-04T23:03:12.000Z",
    "url": "https://greasyfork.org/users/1210996-runonstof"
  }],
  "name": "Jump Block",
  "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nSuspendisse sit amet nulla in erat imperdiet rutrum id ut velit.\nSed cursus id enim vel interdum.\nSuspendisse potenti.\nMauris blandit mauris mauris, ac venenatis nunc iaculis sit amet.\nInteger interdum fringilla lorem, a sagittis ante blandit ut.\nCras sollicitudin ultricies mi, ac volutpat diam elementum vel.\nNullam quis risus sed tellus interdum blandit.\nNullam bibendum lorem sit amet neque faucibus, id hendrerit nunc vulputate.\nSed accumsan eros eros, a molestie mauris euismod id.\nVivamus facilisis turpis auctor orci viverra gravida.",
  "url": "https://greasyfork.org/scripts/485526-market-history",
  "code_url": "https://update.greasyfork.org/scripts/485526/Market History.user.js",
  "code_size": 122188,
  "license": "MIT License",
  "version": "1.0.2",
  "locale": "en",
  "deleted": false
}];

var ScriptsRepo = /*#__PURE__*/function () {
  function ScriptsRepo() {
    _classCallCheck(this, ScriptsRepo);
    this.baseUrl = 'https://greasyfork.org';
    this.baseCdnUrl = 'https://update.greasyfork.org';
    this.baseApiUrl = 'https://api.greasyfork.org';
    /**
     * @type {ScriptInfo[]}
     */
    this.scripts = [];
  }

  /**
   * Should be called in a thread
   */
  return _createClass(ScriptsRepo, [{
    key: "init",
    value: function init() {
      var _this = this;
      // this.scripts = http.getJson(`${this.baseApiUrl}/scripts/by-site/customnpcs.com.json`)
      //   .map(info => new ScriptInfo(this, info));
      this.scripts = TEST_SCRIPTS.map(function (info) {
        return new ScriptInfo(_this, info);
      });
    }
  }, {
    key: "getScriptInfo",
    value: function getScriptInfo(id) {
      return new ScriptInfo(this, http.getJson("".concat(this.baseUpdateUrl, "/scripts/").concat(id, ".js")));
    }
  }, {
    key: "getScriptMetadata",
    value: function getScriptMetadata(id) {
      return new ScriptMetadata(http.get("".concat(this.baseCdnUrl, "/scripts/").concat(id, "/script.meta.js")));
    }
  }, {
    key: "getScriptContents",
    value: function getScriptContents(id) {
      return http.get("".concat(this.baseCdnUrl, "/scripts/").concat(id, "/script.user.js"));
    }
  }]);
}();
var ScriptMetadata = /*#__PURE__*/function () {
  function ScriptMetadata(raw) {
    _classCallCheck(this, ScriptMetadata);
    this.raw = raw;
    this.properties = this._parse(raw);
  }
  return _createClass(ScriptMetadata, [{
    key: "value",
    value: function value(key) {
      var _this$properties$key;
      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      return (_this$properties$key = this.properties[key]) !== null && _this$properties$key !== void 0 && _this$properties$key.length ? this.properties[key][0] : defaultValue;
    }
  }, {
    key: "values",
    value: function values(key) {
      return this.properties[key] || [];
    }
  }, {
    key: "isCompatibleMcVersion",
    value: function isCompatibleMcVersion() {
      return this.values('minecraft').indexOf(MINECRAFT_VERSION) !== -1;
    }
  }, {
    key: "_parse",
    value: function _parse(raw) {
      var regex = /^\s*\/\/\s*@([^\s]+)\s+([^\s]+)$/;
      return raw.split(/[\r\n]+/).reduce(function (acc, line) {
        var match = regex.exec(line);
        if (match) {
          var _match = _slicedToArray(match, 3);
            _match[0];
            var key = _match[1],
            value = _match[2];
          if (!acc.hasOwnProperty(key)) {
            acc[key] = [];
          }
          acc[key].push(value);
        }
        return acc;
      }, {});
    }
  }]);
}();
var ScriptInfo = /*#__PURE__*/function () {
  function ScriptInfo(repo, data) {
    _classCallCheck(this, ScriptInfo);
    /**
     * @type {ScriptsRepo}
     */
    this._repo = repo;
    this._metadata = null;
    this.id = data.id;
    this.daily_installs = data.daily_installs;
    this.total_installs = data.total_installs;
    this.fan_score = data.fan_score;
    this.good_ratings = data.good_ratings;
    this.ok_ratings = data.ok_ratings;
    this.bad_ratings = data.bad_ratings;
    this.created_at = data.created_at;
    this.code_updated_at = data.code_updated_at;
    this.namespace = data.namespace;
    this.support_url = data.support_url;
    this.contribution_url = data.contribution_url;
    this.contribution_amount = data.contribution_amount;
    /**
     * @type {ScriptAuthor[]}
     */
    this.users = data.users.map(function (user) {
      return new ScriptAuthor(user);
    });
    this.name = data.name;
    this.description = data.description;
    this.url = data.url;
    this.code_url = data.code_url;
    this.code_size = data.code_size;
    this.license = data.license;
    this.version = data.version;
    this.locale = data.locale;
    this.deleted = data.deleted;
  }
  return _createClass(ScriptInfo, [{
    key: "getMetadata",
    value: function getMetadata() {
      if (!this._metadata) {
        this._metadata = this._repo.getScriptMetadata(this.id);
      }
      return this._metadata;
    }
  }, {
    key: "getContents",
    value: function getContents() {
      return this._repo.getScriptContents(this.id);
    }
  }, {
    key: "getReportUrl",
    value:
    /**
     * Get the url to report the script
     * @return {string}
     */
    function getReportUrl() {
      return "".concat(this._repo.baseUrl, "/reports/new?item_class=script&item_id=").concat(this.id);
    }
  }, {
    key: "getFeedbackUrl",
    value:
    /**
     * Get the url to feedback the script
     * @return {string}
     */
    function getFeedbackUrl() {
      return "".concat(this._repo.baseUrl, "/scripts/").concat(this.id, "/feedback");
    }
  }]);
}();
var ScriptAuthor = /*#__PURE__*/function () {
  function ScriptAuthor(data) {
    _classCallCheck(this, ScriptAuthor);
    this.id = data.id;
    this.name = data.name;
    this.created_at = data.created_at;
    this.url = data.url;
  }
  return _createClass(ScriptAuthor, [{
    key: "isTrusted",
    value: function isTrusted() {
      return TRUSTED_AUTHOR_IDS.indexOf(this.id) !== -1;
    }
  }, {
    key: "isBlacklisted",
    value: function isBlacklisted() {
      return BLACKLISTED_AUTHOR_IDS.indexOf(this.id) !== -1;
    }
  }]);
}();

var Thread = Java.type('java.lang.Thread');
function handleAsyncError(error) {
  // dd("§cError: " + error.message)
  // print(error);
  dd('§cError: ' + error.message);
  dd(error.stack);
}
function doAsync(callback) {
  var thread = new Thread(function () {
    var result;
    try {
      result = callback();
    } catch (e) {
      handleAsyncError(e);
    }
    return result;
  });
  thread.start();
  return thread;
}

var ScriptManagerEvents = /*#__PURE__*/function () {
  /**
   *
   * @param {ScriptManager} gui
   */
  function ScriptManagerEvents(gui) {
    _classCallCheck(this, ScriptManagerEvents);
    this.gui = gui;
  }
  return _createClass(ScriptManagerEvents, [{
    key: "register",
    value: function register() {
      gui.listen(id('scrl_scripts'), this.onScriptSelected.bind(this));
    }

    /**
     *
     * @param {CustomGuiEvent.ScrollEvent} e
     */
  }, {
    key: "onScriptSelected",
    value: function onScriptSelected(e) {
      var _this$gui$state$selec,
        _this = this;
      /**
       * @type {ScriptInfo}
       */
      var script = this.gui.repo.scripts[e.scrollIndex];
      (_this$gui$state$selec = this.gui.state.selectedScript) === null || _this$gui$state$selec === void 0 ? void 0 : _this$gui$state$selec.id;

      // Set always to null when inbetween loading or selecting the same
      this.gui.state.selectedScript = null;
      this.gui.update();

      // if (selectedScriptId == script.id) {
      //     e.scroll.setSelection([]);
      //     this.gui.update(e.scroll);
      //     this.gui.update();
      //     return;
      // }

      doAsync(function () {
        _this.gui.state.loading = true;
        _this.gui.update();
        try {
          script.getMetadata();
        } catch (error) {
          _this.gui.state.loading = false;
          _this.gui.state.message = '§cHttpError';
          _this.gui.update();
          return;
        }
        _this.gui.state.loading = false;
        _this.gui.state.selectedScript = script;
        _this.gui.update();
        // dd('metadata', script.getMetadata());
      });
    }
  }]);
}();

function chunkate(string, length) {
  return string.split(/[\r\n]+/).reduce(function (acc, line) {
    // split the line into chunks of length using slice
    // for (let i = 0; i < line.length; i += length) {
    //     acc.push(line.slice(i, i + length));
    // }

    var words = line.split(' ');
    var pushLine = '';
    words.forEach(function (word) {
      if (pushLine.length + word.length > length) {
        acc.push(pushLine.trim());
        pushLine = word;
      } else {
        pushLine += word + ' ';
      }
    });
    if (pushLine) {
      acc.push(pushLine.trim());
    }
    return acc;
  }, []);
}

var ScriptManager = /*#__PURE__*/function (_BaseGui) {
  function ScriptManager(player) {
    var _this;
    _classCallCheck(this, ScriptManager);
    _this = _callSuper(this, ScriptManager, [id('gui_scriptmanager'), 384, 192, player]);
    _this.state = {
      categories: null,
      initialized: false,
      loading: false,
      message: '',
      /**
       * @type {ScriptInfo|null}
       */
      selectedScript: null
    };
    _this.repo = new ScriptsRepo();
    _this.events = new ScriptManagerEvents(_this);
    _this.descriptionLines = 20;
    _this.build();
    _this.events.register();
    player.showCustomGui(_this.gui);
    return _this;
  }
  _inherits(ScriptManager, _BaseGui);
  return _createClass(ScriptManager, [{
    key: "onClose",
    value: function onClose() {
      // this.state.initialized = false;
      // this.state.selectedScript = null;
      this.state.loading = false;
      this.state.message = '';
      // this.update();
    }
  }, {
    key: "init",
    value: function init() {
      var _this2 = this;
      if (this.state.initialized) return;
      doAsync(function () {
        _this2.state.loading = true;
        _this2.update();
        _this2.repo.init();
        _this2.state.initialized = true;
        _this2.state.loading = false;
        _this2.update();
      });
    }
  }, {
    key: "build",
    value: function build() {
      var _this3 = this;
      this.group(function (_ref) {
        var x = _ref.x,
          y = _ref.y,
          width = _ref.width,
          height = _ref.height;
        _this3.gui.addLabel(id('lbl_title'), '§eScriptManager', x, y - 16, _this3.gui.getWidth(), 16).setCentered(false).setScale(2);
        _this3.group(function (_ref2) {
          var x = _ref2.x,
            y = _ref2.y,
            width = _ref2.width,
            height = _ref2.height;
          // Scripts scroll
          _this3.gui.addScroll(id('scrl_scripts'), x, y, 128, height - y, []).setHasSearch(false);
          _this3.updateScriptsScroll();

          // Draw border lines
          var x1 = x;
          var y1 = y;
          var x2 = width;
          var y2 = height;
          _this3.gui.addColoredLine(id('ln_top'), x1, y1, x2, y1, COLORS.GRAY.toHex(), 2);
          _this3.gui.addColoredLine(id('ln_right'), x2, y1, x2, y2, COLORS.GRAY.toHex(), 2);
          _this3.gui.addColoredLine(id('ln_bottom'), x1, y2, x2, y2, COLORS.GRAY.toHex(), 2);
          _this3.gui.addColoredLine(id('ln_left'), x1, y1, x1, y2, COLORS.GRAY.toHex(), 2);

          // Script info
          _this3.gui.addLabel(id('lbl_scripts_info'), '', x + 140, y + 4, width - 140, 16, COLORS.WHITE.toHex()).setScale(2);
          _this3.gui.addLabel(id('lbl_scripts_info_author'), '', x + 140, y + 24, width - 140, 16, COLORS.WHITE.toHex());
          _this3.gui.addLabel(id('lbl_scripts_info_version'), '', x + 140, y + 34, width - 140, 16, COLORS.RED.toHex());
          _this3.gui.addLabel(id('lbl_scripts_info_mcversion'), '', x + 140, y + 44, width - 140, 16, COLORS.RED.toHex());
          _this3.gui.addLabel(id('lbl_scripts_rating_good'), '', x + width - 48, y + 4, 32, 16).setHoverText('§aGood');
          _this3.gui.addLabel(id('lbl_scripts_rating_ok'), '', x + width - 48, y + 14, 32, 16).setHoverText('§eOk');
          _this3.gui.addLabel(id('lbl_scripts_rating_bad'), '', x + width - 48, y + 24, 32, 16).setHoverText('§cBad');
          _this3.gui.addLabel(id('lbl_scripts_installs_today'), '', x + 140, y + height - 16, 32, 16).setHoverText('Installs today');
          _this3.gui.addLabel(id('lbl_scripts_installs_total'), '', x + 182, y + height - 16, 32, 16).setHoverText('Total installs');
          var panel = _this3.gui.getScrollingPanel();
          panel.init(x + 140, y + 62, width - 140, height - 62 - 16);
          Array.from({
            length: _this3.descriptionLines
          }).forEach(function (_, index) {
            panel.addLabel(id("lbl_scripts_info_description_".concat(index)), '', 0, index * 10, width - 140, 16, COLORS.WHITE.toHex());
            // panel.addLabel(id(`lbl_scripts_info_description_${index}`), '', x + 140, y + 64 + (index * 10), width - 140, 16, COLORS.WHITE.toHex());
          });
          _this3.updateScriptInfo();

          // Loader overlay
          var loaderHeight = 48;
          var loaderWidth = 128;
          var loaderX1 = width / 2 - loaderWidth / 2;
          var loaderY = height / 2; //-(loaderHeight);
          var loaderX2 = width / 2 + loaderWidth / 2;
          _this3.gui.addColoredLine(id('bg_loader'), loaderX1, loaderY, loaderX2, loaderY, COLORS.BLACK.toHex(), loaderHeight);
          _this3.gui.addLabel(id('lbl_loader'), '', loaderX1, loaderY - 8, loaderWidth, 16, COLORS.WHITE.toHex()).setCentered(true);
          _this3.updateLoader();
        }, {
          x: x,
          y: y + 4,
          width: width,
          height: height
        });
      }, {
        x: 0,
        y: 0,
        width: this.gui.getWidth(),
        height: this.gui.getHeight()
      });
    }
  }, {
    key: "group",
    value: function group(render, _ref3) {
      var _ref3$x = _ref3.x,
        x = _ref3$x === void 0 ? 0 : _ref3$x,
        _ref3$y = _ref3.y,
        y = _ref3$y === void 0 ? 0 : _ref3$y,
        _ref3$width = _ref3.width,
        width = _ref3$width === void 0 ? 0 : _ref3$width,
        _ref3$height = _ref3.height,
        height = _ref3$height === void 0 ? 0 : _ref3$height;
      return render({
        x: x,
        y: y,
        width: width,
        height: height
      });
    }
  }, {
    key: "updateScriptsScroll",
    value: function updateScriptsScroll() {
      var scroll = this.gui.getComponent(id('scrl_scripts'));
      if (!this.state.initialized) {
        scroll.setList([]);
        scroll.setEnabled(false);
        scroll.setVisible(false);
      } else {
        var scripts = this.repo.scripts.map(function (script) {
          return script.name;
        });
        scroll.setList(scripts);
        scroll.setEnabled(true);
        scroll.setVisible(true);
      }
      this.gui.update(scroll);
    }
  }, {
    key: "updateScriptInfo",
    value: function updateScriptInfo() {
      /**
       * @var {ScriptInfo|null} script
       */
      var script = this.state.selectedScript;
      if (!script) return;
      var lblTitle = this.gui.getComponent(id('lbl_scripts_info'));
      var lblAuthor = this.gui.getComponent(id('lbl_scripts_info_author'));
      var lblVersion = this.gui.getComponent(id('lbl_scripts_info_version'));
      var lblMcVersion = this.gui.getComponent(id('lbl_scripts_info_mcversion'));
      var panel = this.gui.getScrollingPanel();
      var lblDescriptions = Array.from({
        length: this.descriptionLines
      }).map(function (_, index) {
        return panel.getComponent(id("lbl_scripts_info_description_".concat(index)));
      });
      var lblRatingGood = this.gui.getComponent(id('lbl_scripts_rating_good'));
      var lblRatingOk = this.gui.getComponent(id('lbl_scripts_rating_ok'));
      var lblRatingBad = this.gui.getComponent(id('lbl_scripts_rating_bad'));
      var lblInstallsToday = this.gui.getComponent(id('lbl_scripts_installs_today'));
      var lblInstallsTotal = this.gui.getComponent(id('lbl_scripts_installs_total'));
      var author = script.users[0] || null;
      if (!script) {
        var clearLabel = function clearLabel(label) {
          return label.setText('').setVisible(false);
        };
        clearLabel(lblTitle);
        clearLabel(lblAuthor);
        clearLabel(lblVersion);
        clearLabel(lblMcVersion);
        clearLabel(lblRatingGood);
        clearLabel(lblRatingOk);
        clearLabel(lblRatingBad);
        clearLabel(lblInstallsToday);
        clearLabel(lblInstallsTotal);
        lblDescriptions.forEach(clearLabel);
        lblMcVersion.setHoverText('');
      } else {
        var meta = script.getMetadata();
        var setLabel = function setLabel(label, text) {
          return label.setText(text).setVisible(true);
        };
        setLabel(lblTitle, '§3§n' + script.name);
        var authorColor = author !== null && author !== void 0 && author.isTrusted() ? '§a' : '§e';
        var authorName = (author === null || author === void 0 ? void 0 : author.name) || 'Unknown';
        var authorPrefix = author !== null && author !== void 0 && author.isTrusted() ? ' ✔' : '';
        setLabel(lblAuthor, "".concat(authorColor, "By ").concat(authorName).concat(authorPrefix));
        lblAuthor.setHoverText(author !== null && author !== void 0 && author.isTrusted() ? "\xA7a".concat(author.name, " has been verified to be trustworthy.") : author ? "\xA7e".concat(author.name, " has not been verified, proceed with caution.") : '');
        setLabel(lblVersion, '§6v' + script.version);
        var mcVersions = meta.values('minecraft');
        var mcVersionColor = meta.isCompatibleMcVersion() ? '§a' : '§c';
        setLabel(lblMcVersion, mcVersionColor + 'MC ' + mcVersions.join(', ') + (meta.isCompatibleMcVersion() ? '' : '§c (incompatible)'));
        setLabel(lblRatingGood, '§a✔§f ×' + script.good_ratings);
        setLabel(lblRatingOk, '§e§lO§f ×' + script.ok_ratings);
        setLabel(lblRatingBad, '§c✖§f ×' + script.bad_ratings);
        setLabel(lblInstallsToday, '§9↓§f ×' + script.daily_installs);
        setLabel(lblInstallsTotal, '§a↓§f ×' + script.total_installs);
        // setLabel(lblInstallsTotal, '§9↑§f ×' + script.total_installs);

        var lines = chunkate(script.description, 42);
        Array.from({
          length: this.descriptionLines
        }).forEach(function (_, index) {
          var line = lines[index] || '';
          setLabel(lblDescriptions[index], line);
        });
        lblMcVersion.setHoverText(meta.isCompatibleMcVersion() ? "\xA7aYour Minecraft version is compatible with this script." : "\xA7cYour Minecraft version is not compatible with this script.");

        // panel.setVisible(true);
      }
    }
  }, {
    key: "updateLoader",
    value: function updateLoader() {
      var showPrompt = this.state.message || this.state.loading;
      var promptText = this.state.loading ? 'Loading...' : this.state.message;
      var loaderBg = this.gui.getComponent(id('bg_loader'));
      loaderBg.setColor(COLORS.BLACK.alpha(showPrompt ? 0.8 : 0).toHex());
      // loaderBg.setVisible(this.state.loading);

      var loaderLabel = this.gui.getComponent(id('lbl_loader'));
      loaderLabel.setVisible(showPrompt);
      var loaderLabelText = promptText;
      loaderLabel.setText(loaderLabelText);
      this.gui.update(loaderBg);
      this.gui.update(loaderLabel);
    }
  }, {
    key: "update",
    value: function update() {
      this.updateScriptsScroll();
      this.updateScriptInfo();
      this.updateLoader();
      this.gui.update();
    }
  }]);
}(BaseGui);

if (!Array.from) {
    Array.from = function (arrayLike) {
        if (arrayLike == null) {
            throw new TypeError('Array.from requires an array-like object - not null or undefined');
        }
        // Handle array-like objects
        var len = arrayLike.length >>> 0;
        var result = new Array(len);
        for (var i = 0; i < len; i++) {
            result[i] = arrayLike[i];
        }
        return result;
    };
}
if (!String.prototype.includes) {
    String.prototype.includes = function (search, start) {
        if (typeof start !== 'number') {
            start = 0;
        }
        if (start + search.length > this.length) {
            return false;
        }
        return this.indexOf(search, start) !== -1;
    };
}
if (!Object.assign) {
    Object.defineProperty(Object, 'assign', {
        enumerable: false,
        configurable: true,
        writable: true,
        value: function (target) {
            var sources = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                sources[_i - 1] = arguments[_i];
            }
            if (target === undefined || target === null) {
                throw new TypeError('Cannot convert first argument to object');
            }
            var to = Object(target);
            for (var i = 0; i < sources.length; i++) {
                var nextSource = sources[i];
                if (nextSource === undefined || nextSource === null) {
                    continue;
                }
                var keysArray = Object.keys(Object(nextSource));
                for (var nextIndex = 0; nextIndex < keysArray.length; nextIndex++) {
                    var nextKey = keysArray[nextIndex];
                    var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
                    if (desc !== undefined && desc.enumerable) {
                        to[nextKey] = nextSource[nextKey];
                    }
                }
            }
            return to;
        }
    });
}
if (!Object.entries) {
    Object.entries = function (obj) {
        var ownProps = Object.keys(obj);
        var i = ownProps.length;
        var resArray = new Array(i);
        while (i--) {
            resArray[i] = [ownProps[i], obj[ownProps[i]]];
        }
        return resArray;
    };
}
if (!Object.fromEntries) {
    Object.fromEntries = function (entries) {
        var obj = {};
        var entriesArray = Array.from(entries);
        for (var i = 0; i < entriesArray.length; i++) {
            var _a = entriesArray[i], key = _a[0], value = _a[1];
            obj[key] = value;
        }
        return obj;
    };
}
Java.type('java.util.Base64');
Java.type('java.lang.String');

var global = {};

global.scriptManager = null;
function customGuiScroll(e) {
  if (e.gui.getID() !== global.scriptManager.gui.getID()) return;
  var shouldCancel = !e.scroll.getEnabled() || global.scriptManager.state.loading || global.scriptManager.state.message;
  if (shouldCancel) {
    e.scroll.setSelection([]);
    e.gui.update(e.scroll);
    e.gui.update();
    return;
  }

  // Scroll behaviour
  gui.emit(e.scrollId, e);
}
function chat(e) {
  if (e.message !== '!scripts') return;
  // Check if the player is in creative mode
  if (e.player.gamemode !== 1) return;
  e.setCanceled(true);
  global.scriptManager = new ScriptManager(e.player);
  global.scriptManager.init();
}