Maelstrom ADDON City Online Status Colorer for SC

change the color of cities according to online state of the player

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Maelstrom ADDON City Online Status Colorer for SC
// @namespace   http*://prodgame*.alliances.commandandconquer.com/*/index.aspx*
// @description change the color of cities according to online state of the player
// @include     http*://prodgame*.alliances.commandandconquer.com/*/index.aspx*
// @version     0.6.5
// @author      White X Dragon / Debitosphere
// @author      Der_Flake
// ==/UserScript==
/*global PerforceChangelist,window,localStorage, console, ClientLib, MaelstromTools*/
(function () {
    function OnlineStatusCityColor_Main() {
        var localStorageKey = "CCTA_MaelstromTools_CC_OnlineStateColorer";
        var injectionMode = 0;
        switch (PerforceChangelist) {
            case 373715:
                injectionMode = 1;
                break;
            default:
                injectionMode = 2;
                break;
        }
        console.log("Maelstrom_CityOnlineStateColorer " + window.__mscc_version + " loaded, Serverversion " + injectionMode);
        var OnlineState = {
            Online: 1,
            Away: 2,
            Offline: 0,
            Hidden: 3
        };
        var onlineStateColor = {};
        onlineStateColor[OnlineState.Online] = "#00FF00";
        onlineStateColor[OnlineState.Away] = "#FFFF00";
        onlineStateColor[OnlineState.Offline] = "#FF0000";
        onlineStateColor[OnlineState.Hidden] = "#C2C2C2";

        function CityOnlineStateColorerInclude() {
            setInterval(requestOnlineStatusUpdate, 300 * 1000); // update users online status each 5 minutes
            console.log("Maelstrom_CityOnlineStateColorer Include");
            var regionCityPrototype = ClientLib.Vis.Region.RegionCity.prototype;
            regionCityPrototype.CityTextcolor = function (defaultColor) {
                try {
                    var members = ClientLib.Data.MainData.GetInstance().get_Alliance().get_MemberData().d;
                    var playerId = this.get_PlayerId();
                    if (members[playerId] !== undefined) {
                        var onlineState = members[playerId].OnlineState;
                        return onlineStateColor[onlineState];
                    }
                } catch (ex) {
                    console.log("MaelstromTools_CityOnlineStateColorer CityTextcolor error: ", ex);
                }
                return defaultColor;
            };
            regionCityPrototype.CityBackgroundColor = function (backgroundBlock) {
                try {
                    return;
                    var contexd2d = backgroundBlock.getContext("2d");
                    var savedData = [];
                    var item = null;
                    if (localStorage[localStorageKey] !== null && localStorage[localStorageKey] !== "undefined") {
                        savedData = JSON.parse(localStorage[localStorageKey]);
                    }
                    for (item in savedData) {
                        if (savedData[item] instanceof Array && savedData[item].length >= 2) {
                            if (savedData[item][0] === this.get_PlayerName()) {
                                var isColor = /^#[0-9A-F]{6}$/i.test(savedData[item][2]);
                                if (isColor) {
                                    contexd2d.fillStyle = savedData[item][2];
                                } else {
                                    contexd2d.fillStyle = "#000000";
                                }
                                contexd2d.fillRect(0, 0, backgroundBlock.width, backgroundBlock.height);
                                break;
                            } else {
                                if (savedData[item][0] === this.get_AllianceName()) {
                                    var isColor = /^#[0-9A-F]{6}$/i.test(savedData[item][2]);
                                    if (isColor) {
                                        contexd2d.fillStyle = savedData[item][2];
                                    } else {
                                        contexd2d.fillStyle = "#000000";
                                    }
                                    contexd2d.fillRect(0, 0, backgroundBlock.width, backgroundBlock.height);
                                    break;
                                }
                            }
                        }
                    }
                } catch (ex) {
                    console.log("MaelstromTools_CityOnlineStateColorer CityBackgroundColor error: ", ex);
                }
            };

            var updateColorParts = g(regionCityPrototype.UpdateColor, /createHelper;this\.([A-Z]{6})\(/, "ClientLib.Vis.Region.RegionCity UpdateColor", 1);
            var setCanvasValue_Name = updateColorParts[1];
            console.log("setCanvasValue_Name = " + updateColorParts[1]);
            if (updateColorParts === null || setCanvasValue_Name.length !== 6) {
                console.error("Error - ClientLib.Vis.Region.RegionCity.SetCanvasValue undefined");
                return;
            }
            
            regionCityPrototype.SetCanvasValue_ORG = regionCityPrototype[setCanvasValue_Name];
            console.log("regionCityPrototype.SetCanvasValue_ORG = " + regionCityPrototype[setCanvasValue_Name]);
            var setCanvasValueFunctionBody = getFunctionBody(regionCityPrototype.SetCanvasValue_ORG);
            regionCityPrototype.SetCanvasValue_BODY = setCanvasValueFunctionBody;

            //var setCanvasValueFunctionBodyFixed = setCanvasValueFunctionBody.replace(/true;.{0,3}\}.{0,3}this/im, "true; } g=this.CityTextcolor(g); this");
            var setCanvasValueFunctionBodyFixed = setCanvasValueFunctionBody.replace(
                /\{g="#000000";\}/im,
                "{g=\"#000000\";}else{g=this.CityTextcolor(g);}");
            regionCityPrototype[setCanvasValue_Name] = new Function("a", "b", setCanvasValueFunctionBodyFixed);
            regionCityPrototype.SetCanvasValue_FIXED = new Function("a", "b", setCanvasValueFunctionBodyFixed);
            var visUpdateParts = null;
            switch (injectionMode) {
                case 1:
                    visUpdateParts = g(regionCityPrototype.VisUpdate, /Own:\{?this\.(.{6})\(.*Alliance:\{?this\.(.{6})\(/, "ClientLib.Vis.Region.RegionCity.VisUpdate", 2);
                    break;
                default:
                    visUpdateParts = g(regionCityPrototype.VisUpdate, /Own:\{?\$I\.(.{6})\.(.{6})\(.*Alliance:\{?\$I\..{6}\.(.{6})\(/, "ClientLib.Vis.Region.RegionCity.VisUpdate", 3);
                    var G = ClientLib.Vis.Region.Region.prototype;
                    fc = g(G.VisUpdate, /\.(.{6})\(a,n,s\);/, "ClientLib.Vis.Region.Region.VisUpdate", 1);
                    break;
            }
            if (visUpdateParts === null || visUpdateParts[1].length !== 6) {
                console.error("Error - ClientLib.Vis.Region.RegionCity VisUpdate paramter undefined");
                return;
            }

            if (injectionMode > 1) {
                regionCityPrototype[visUpdateParts[2]] = $I[visUpdateParts[1]][visUpdateParts[2]];
                regionCityPrototype[visUpdateParts[3]] = $I[visUpdateParts[1]][visUpdateParts[3]];
                var visUpdate = getFunctionBody(regionCityPrototype.VisUpdate);
                var t = visUpdate.replace(/Own:(\{?).{0,2}\$I\.(.{6})\.(.{6}).{0,2}\(/im, "Own: $1 this.$3(");
                var q = t.replace(/Alliance:(\{?).{0,2}\$I\.(.{6})\.(.{6}).{0,2}\(/im, "Alliance: $1 this.$3(");
                var F = q.replace(/Enemy:(\{?).{0,2}\$I\.(.{6})\.(.{6}).{0,2}\(/im, "Enemy: $1 this.$3(");
                regionCityPrototype[fc[1]] = new Function("a", "b", "c", F);
                regionCityPrototype.VisUpdate = regionCityPrototype[fc[1]];
            }
            try {
                var u = null, Q = null;
                if (injectionMode === 1) {
                    u = getFunctionBody(regionCityPrototype[visUpdateParts[1]]);
                    Q = u.replace(/c\.Font\);/im, "c.Font); this.CityBackgroundColor(a); ");
                    regionCityPrototype[visUpdateParts[1]] = new Function("a", "b", "c", "d", Q);
                } else {
                    u = getFunctionBody(regionCityPrototype[visUpdateParts[2]]);
                    Q = u.replace(/d\.Font\);/im, "d.Font); this.CityBackgroundColor(b);");
                    regionCityPrototype[visUpdateParts[2]] = new Function("a", "b", "c", "d", "e", Q);
                }
            } catch (P) {
                console.log("MaelstromTools_CityOnlineStateColorer Include B error: ", P);
            }
            try {
                if (injectionMode === 1) {
                    var K = getFunctionBody(regionCityPrototype[visUpdateParts[2]]);
                    var J = K.replace(/c.Font\);/im, "c.Font); this.CityBackgroundColor(a); ");
                    regionCityPrototype[visUpdateParts[2]] = new Function("a", "b", "c", "d", "e", J);
                } else {
                    var K = getFunctionBody(regionCityPrototype[visUpdateParts[3]]);
                    var J = K.replace(/d.Font\);/im, "d.Font); this.CityBackgroundColor(b);");
                    regionCityPrototype[visUpdateParts[3]] = new Function("a", "b", "c", "d", "e", "f", "g", J);
                }
            } catch (P) {
                console.log("MaelstromTools_CityOnlineStateColorer Include C error: ", P);
            }
        }

        function g(functionObject, regEx, m, p) {
            var functionBody = functionObject.toString();
            var shrinkedText = functionBody.replace(/\s/gim, "");
            var matches = shrinkedText.match(regEx);
            for (var i = 1; i < (p + 1) ; i++) {
                if (matches !== null && matches[i].length === 6) {
                    console.log(m, i, matches[i]);
                } else {
                    console.error("Error - ", m, i, "not found");
                    console.warn(m, shrinkedText);
                }
            }
            return matches;
        }

        function requestOnlineStatusUpdate()
        {
            console.log("XXX City Color: requesting online status update..Checks every 5 minutes..)");
            var mainData = ClientLib.Data.MainData.GetInstance();
            var alliance = mainData.get_Alliance();
            alliance.RefreshMemberData();
        }

        function getFunctionBody(functionObject) {
            var string = functionObject.toString();
            var singleLine = string.replace(/(\n\r|\n|\r|\t)/gm, " ");
            var spacesShrinked = singleLine.replace(/\s+/gm, " ");
            var headerRemoved = spacesShrinked.replace(/function.*?\{/, "");
            var result = headerRemoved.substring(0, headerRemoved.length - 1); // remove last "}"
            return result;
        }

        function MaelstromTools_CityOnlineStateColorerInclude_checkIfLoaded() {
            try {
                if (typeof ClientLib !== "undefined" && ClientLib.Vis !== undefined && ClientLib.Vis.Region !== undefined && ClientLib.Vis.Region.RegionCity !== undefined) {
                    window.setTimeout(CityOnlineStateColorerInclude, 30000);
                } else {
                    window.setTimeout(MaelstromTools_CityOnlineStateColorerInclude_checkIfLoaded, 1000);
                }
            } catch (ex) {
                console.log("MaelstromTools_CityOnlineStateColorerInclude_checkIfLoaded: ", ex);
            }
        }
        function MaelstromTools_CityOnlineStateColorerTool_checkIfLoaded() {
            try {
                if (typeof ClientLib === "undefined" || typeof MaelstromTools === "undefined") {
                    window.setTimeout(MaelstromTools_CityOnlineStateColorerTool_checkIfLoaded, 1000);
                }
            } catch (ex) {
                console.log("MaelstromTools_CityOnlineStateColorerTool_checkIfLoaded: ", ex);
            }
        }

        if (/commandandconquer\.com/i.test(document.domain)) {
            window.setTimeout(MaelstromTools_CityOnlineStateColorerInclude_checkIfLoaded, 1000);
            window.setTimeout(MaelstromTools_CityOnlineStateColorerTool_checkIfLoaded, 30000);
        }
    }
    try {
        if (/commandandconquer\.com/i.test(document.domain)) {
            var scriptTag = document.createElement("script");
            scriptTag.id = "xxx";
            scriptTag.innerHTML = "(" + OnlineStatusCityColor_Main.toString() + ")();";
            scriptTag.type = "text/javascript";
            document.getElementsByTagName("head")[0].appendChild(scriptTag);
        }
    } catch (c) {
        console.log("MaelstromTools_CityOnlineStateColorer: init error: ", c);
    }
})();