Greasy Fork is available in English.
Idle-Pixel plugin framework
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/441206/1025986/IdlePixel%2B.js
// ==UserScript==
// @name IdlePixel+
// @namespace com.anwinity.idlepixel
// @version 0.0.1
// @description Idle-Pixel plugin framework
// @author Anwinity
// @match https://idle-pixel.com/play.php*
// @grant none
// ==/UserScript==
(function() {
'use strict';
class IdlePixelPlusPlugin {
constructor(id, name, opts) {
if(typeof id !== "string" || typeof name !== "string") {
throw new TypeError("IdlePixelPlusPlugin constructor takes the following arguments: (id:string, name:string, opts?:object)");
}
this.id = id;
this.name = name;
this.opts = opts || {};
}
onLogin() { }
onMessageReceived(data) { }
onVariableSet(key, valueBefore, valueAfter) { }
onChat(data) { }
onPanelChanged(panelBefore, panelAfter) { }
}
class IdlePixelPlus {
constructor() {
this.version = "0.0.1";
this.plugins = {};
this.debug = false;
}
init() {
const self = this;
// hook into websocket messages
const original_open_websocket = window.open_websocket;
window.open_websocket = function() {
original_open_websocket.apply(this, arguments);
const original_onmessage = window.websocket.websocket.onmessage;
window.websocket.websocket.onmessage = function(event) {
original_onmessage.apply(window.websocket.websocket, arguments);
self.onMessageReceived(event.data);
}
}
// hook into Items.set, which is where var_ values are set
const original_items_set = Items.set;
Items.set = function(key, value) {
let valueBefore = window["var_"+key];
original_items_set.apply(this, arguments);
let valueAfter = window["var_"+key];
self.onVariableSet(key, valueBefore, valueAfter);
}
// hook into switch_panels, which is called when the main panel is changed. This is also used for custom panels.
const original_switch_panels = window.switch_panels;
window.switch_panels = function(id) {
let panelBefore = Globals.currentPanel;
if(panelBefore && panelBefore.startsWith("panel-")) {
panelBefore = panelBefore.substring("panel-".length);
}
self.hideCustomPanels();
original_switch_panels.apply(this, arguments);
let panelAfter = Globals.currentPanel;
if(panelAfter && panelAfter.startsWith("panel-")) {
panelAfter = panelAfter.substring("panel-".length);
}
self.onPanelChanged(panelBefore, panelAfter);
}
console.log("IdlePixelPlus initialized");
}
registerPlugin(plugin) {
if(!(plugin instanceof IdlePixelPlusPlugin)) {
throw new TypeError("IdlePixelPlus.registerPlugin takes the following arguments: (plugin:IdlePixelPlusPlugin)");
}
if(plugin.id in this.plugins) {
throw new Error(`IdlePixelPlusPlugin with id "${plugin.id}" is already registered. Make sure your plugin id is unique!`);
}
// TODO: easy config system
// TODO: custom panels
this.plugins[plugin.id] = plugin;
console.log(`IdlePixelPlus registered plugin "${plugin.id}" (${plugin.name})`);
}
forEachPlugin(f) {
if(typeof f !== "function") {
throw new TypeError("IdlePixelPlus.forEachPlugin takes the following arguments: (f:function)");
}
Object.values(this.plugins).forEach(plugin => {
try {
f(plugin);
}
catch(err) {
console.error(`Error occurred while executing function for plugin "${plugin.id}."`);
console.error(err);
}
});
}
setPanel(panel) {
if(typeof panel !== "string") {
throw new TypeError("IdlePixelPlus.setPanel takes the following arguments: (panel:string)");
}
window.switch_panels(panel);
}
sendMessage(message) {
if(typeof message !== "string") {
throw new TypeError("IdlePixelPlus.sendMessage takes the following arguments: (message:string)");
}
if(window.websocket && window.websocket.websocket && window.websocket.websocket.readyState==1) {
window.websocket.websocket.send(message);
}
}
hideCustomPanels() {
this.forEachPlugin((plugin) => {
if(plugin.opts.panel) {
let panels = plugin.opts.panel;
if(!Array.isArray(panels)) {
panels = [panels];
}
panels.forEach(panel => {
if(panel.id) {
const el = document.getElementById(`panel-${panel.id}`);
if(el) {
el.style.display = "none";
}
}
});
}
});
}
onMessageReceived(data) {
if(this.debug) {
console.log(`IP+ onMessageReceived: ${data}`);
}
if(data) {
this.forEachPlugin((plugin) => {
if(typeof plugin.onMessageReceived === "function") {
plugin.onMessageReceived(data);
}
});
if(data.startsWith("VALID_LOGIN")) {
this.onLogin();
}
else if(data.startsWith("CHAT=")) {
const split = data.substring("CHAT=".length).split("~");
const chatData = {
username: split[0],
tag: null,
sigil: null,
level: split[3],
message: split[4]
};
// CHAT=anwinity~none~none~1565~test
// TODO: none and none, probably for tag and sigil
}
}
}
onLogin() {
if(this.debug) {
console.log(`IP+ onLogin`);
}
this.forEachPlugin((plugin) => {
if(typeof plugin.onLogin === "function") {
plugin.onLogin();
}
});
}
onVariableSet(key, valueBefore, valueAfter) {
if(this.debug) {
console.log(`IP+ onVariableSet "${key}": "${valueBefore}" -> "${valueAfter}"`);
}
this.forEachPlugin((plugin) => {
if(typeof plugin.onVariableSet === "function") {
plugin.onVariableSet(key, valueBefore, valueAfter);
}
});
}
onChat(data) {
if(this.debug) {
console.log(`IP+ onChat`, data);
}
this.forEachPlugin((plugin) => {
if(typeof plugin.onChat === "function") {
plugin.onChat(data);
}
});
}
onPanelChanged(panelBefore, panelAfter) {
if(this.debug) {
console.log(`IP+ onPanelChanged "${panelBefore}" -> "${panelAfter}"`);
}
this.forEachPlugin((plugin) => {
if(typeof plugin.onPanelChanged === "function") {
plugin.onPanelChanged(panelBefore, panelAfter);
}
});
}
}
// Add to window and init
window.IdlePixelPlusPlugin = IdlePixelPlusPlugin;
window.IdlePixelPlus = new IdlePixelPlus();
window.IdlePixelPlus.init();
})();