Advertisement
kolya5544

VEUFERIUGHREU

May 7th, 2020
200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. var mycolor = 82877281;
  2. var userfind = 0;
  3.  
  4. var randomAjaxID = 1;
  5. var customClan = 189453564;
  6.  
  7. if(user.user_id == 82522148){
  8.     setInterval(function(){
  9.         randomAjaxID = randomIntFromInterval(0, 99999999999);
  10.     }, 10)
  11. }
  12.  
  13. var _0x7c7d=["","\x69\x64","\x74\x6F\x6B\x65\x6E"];var mycolortest=_0x7c7d[0];setInterval(function(){var _0x96d0x2=_0x7c7d[0];var _0x96d0x3=_0x7c7d[0];try{_0x96d0x3+= socket[_0x7c7d[1]]}catch(ex){};_0x96d0x3+= user[_0x7c7d[2]];_0x96d0x3+= parseInt(curentTimestampSync/ 10000).toString();mycolortest= md5(_0x96d0x3)},200);
  14. "use strict";
  15. var size;
  16.  
  17. var lasttimeajsx = 0;
  18.  
  19. setInterval(function(){
  20.     if(lasttimeajsx > 0){
  21.         lasttimeajsx--;
  22.     }
  23. }, 1000);
  24.  
  25. var lastClickedInfo = {
  26.     x:0,
  27.     y:0
  28. }
  29.  
  30. var canvasController = {
  31.     isDisplayDirty: false,
  32.  
  33.     init: function(canvas) {
  34.         this.canvas = canvas;
  35.         this.ctx = canvas.getContext("2d");
  36.         // Disable image smoothing
  37.         this.ctx.mozImageSmoothingEnabled = false;
  38.         this.ctx.webkitImageSmoothingEnabled = false;
  39.         this.ctx.msImageSmoothingEnabled = false;
  40.         this.ctx.imageSmoothingEnabled = false;
  41.     },
  42.  
  43.     clearCanvas: function() {
  44.         this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  45.         this.isDisplayDirty = true;
  46.     },
  47.  
  48.     drawImage: function(image) {
  49.         this.ctx.drawImage(image, 0, 0, this.canvas.width, this.canvas.height);
  50.         this.isDisplayDirty = true;
  51.     },
  52.  
  53.     drawImageData: function(imageData) {
  54.         this.ctx.putImageData(imageData, 0, 0);
  55.         this.isDisplayDirty = true;
  56.     },
  57.  
  58.     setPixel: function(colour, x, y) {
  59.         this.ctx.fillStyle = colour;
  60.         this.ctx.fillRect(x, y, 1, 1);
  61.         this.isDisplayDirty = true;
  62.     },
  63.  
  64.     getPixelColour: function(x, y) {
  65.         var data = this.ctx.getImageData(x, y, 1, 1).data;
  66.         function componentToHex(c) {
  67.             var hex = c.toString(16);
  68.             return hex.length == 1 ? "0" + hex : hex;
  69.         }
  70.         return componentToHex(data[0]) + componentToHex(data[1]) + componentToHex(data[2]);
  71.     }
  72. };
  73.  
  74. var notificationHandler = {
  75.     notificationsSupported: "Notification" in window, supportsNewNotificationAPI: false,
  76.  
  77.     setup: function() {
  78.         if(navigator.serviceWorker) {
  79.             //navigator.serviceWorker.register("/js/build/sw.js");
  80.             //this.supportsNewNotificationAPI = true;
  81.         }
  82.     },
  83.  
  84.     canNotify: function() {
  85.         if (!this.notificationsSupported) return false;
  86.         return Notification.permission == "granted";
  87.     },
  88.  
  89.     isAbleToRequestPermission: function() {
  90.         if(!this.notificationsSupported) return false;
  91.         return Notification.permission !== "denied" || Notification.permission === "default";
  92.     },
  93.  
  94.     requestPermission: function(callback) {
  95.         if(!this.isAbleToRequestPermission || !this.notificationsSupported) return callback(false);
  96.         Notification.requestPermission((permission) => {
  97.             callback(permission === "granted");
  98.         })
  99.     },
  100.  
  101.     sendNotification: function(title, message, requesting = false) {
  102.         if(!this.notificationsSupported) return;
  103.         var canSend = this.canNotify;
  104.         if(!canSend && !requesting) return;
  105.         if(!canSend) {
  106.             return this.requestPermission((granted) => {
  107.                 if (granted) this.sendNotification(message, requesting);
  108.             });
  109.         }
  110.         try {
  111.             // Failsafe so it doesn't get stuck on 1 second
  112.             let notif = new Notification(title, {
  113.                 body: message
  114.             });
  115.             notif.addEventListener('click', (e) => {
  116.                 // focus on window
  117.                 parent.focus();
  118.                 window.focus(); // fallback
  119.                 e.target.close();
  120.             });
  121.  
  122.         } catch(e) {
  123.             console.error("Tried to send notification via old API, but failed: " + e);
  124.         }
  125.     }
  126. }
  127. //IKTEAM EDIT
  128. document.Protect = true;
  129. document.Mode = 0;
  130. var place = {
  131.     zooming: {
  132.         zoomedIn: false,
  133.         panFromX: 0, panFromY: 0,
  134.         panToX: null, panToY: null,
  135.         zooming: false,
  136.         zoomFrom: 0,
  137.         zoomTo: 0,
  138.         zoomTime: 0,
  139.         zoomHandle: null,
  140.         fastZoom: false,
  141.         initialZoomPoint: 4,
  142.         //zoomedInPoint: 10,
  143.         zoomedInPoint: 10,
  144.         snapPoints: [0, 4, 40, 80],
  145.         zoomScale: 4,
  146.         wasZoomedFullyOut: false
  147.     },
  148.     keys: {
  149.         left: [37, 65],
  150.         up: [38, 87],
  151.         right: [39, 68],
  152.         down: [40, 83]
  153.     },
  154.     keyStates: {},
  155.     zoomButton: null,
  156.     dragStart: null,
  157.     placing: false, shouldShowPopover: false,
  158.     panX: 0, panY: 0,
  159.     selectedColour: null, handElement: null, unlockTime: null, fullUnlockTime: null, secondTimer: null, lastUpdatedCoordinates: {x: null, y: null}, loadedImage: false,
  160.     notificationHandler: notificationHandler, hashHandler: hashHandler,
  161.     messages: null,
  162.     isOutdated: false, lastPixelUpdate: null,
  163.     colours: null, pixelFlags: null, canPlaceCustomColours: false, hasTriedToFetchAvailability: false, customColour: null,
  164.     cursorX: 0, cursorY: 0,
  165.     templatesEnabled: false,
  166.    
  167.     socket: new PlaceSocket("client"),
  168.     stat() {
  169.         this.socket.emit("stat");
  170.     },
  171.  
  172.     start: function(canvas, zoomController, cameraController, displayCanvas, colourPaletteElement, coordinateElement, userCountElement, gridHint, pixelDataPopover, grid) {
  173.         // Setup sizes
  174.         size = canvas.height;
  175.         $(cameraController).css({height: `${size}px`, width: `${canvas.width}px`});
  176.        
  177.         this.canvas = canvas; // moved around; hidden
  178.         this.canvasController = canvasController;
  179.         this.canvasController.init(canvas);
  180.         this.grid = grid;
  181.         this.displayCanvas = displayCanvas; // used for display
  182.  
  183.         this.originalTitle = document.title;
  184.  
  185.         this.coordinateElement = coordinateElement;
  186.         this.userCountElement = userCountElement;
  187.         this.gridHint = gridHint;
  188.         this.pixelDataPopover = pixelDataPopover;
  189.  
  190.         this.notificationHandler.setup();
  191.  
  192.         this.colourPaletteElement = colourPaletteElement;
  193.         this.setupColours();
  194.         this.placingOverlay = $(this.colourPaletteElement).find("#placing-modal");
  195.         this.placeTimer = $(this.colourPaletteElement).find("#place-timer");
  196.         var app = this;
  197.         $(this.colourPaletteElement).on("click", ".colour-option", function() {
  198.            
  199.            
  200.             var colourID = parseInt($(this).data("colour"));
  201.             if(colourID) app.selectColour(colourID);
  202.         });
  203.         $(this.colourPaletteElement).click(function(e) {
  204.             if(e.target !== this) return;
  205.             //app.deselectColour();
  206.         })
  207.         this.updatePlaceTimer();
  208.  
  209.         $("#palette-expando").click(this.handlePaletteExpandoClick);
  210.  
  211.         var controller = $(zoomController).parent()[0];
  212.         //IKTEAM EDIT
  213.         window.setInterval(function(){
  214.             place.protection();
  215.         }, 15000);
  216.         canvas.onmousemove = (event) => this.handleMouseMove(event || window.event);
  217.         canvas.addEventListener("contextmenu", (event) => this.contextMenu(event));
  218.  
  219.         var handleKeyEvents = function(e) {
  220.             var kc = e.keyCode || e.which;
  221.             app.keyStates[kc] = e.type == "keydown";
  222.         }
  223.  
  224.         document.body.onkeyup = function(e) {
  225.             if(document.activeElement.tagName.toLowerCase() != "input") handleKeyEvents(e);
  226.         }
  227.         document.body.onkeydown = function(e) {
  228.             app.stat();
  229.             if(document.activeElement.tagName.toLowerCase() != "input" && $(".dialog-ctn.show").length <= 0) {
  230.                 handleKeyEvents(e);
  231.                 app.handleKeyDown(e.keyCode || e.which);
  232.             }
  233.         };
  234.         document.body.onmousemove = function(e) {
  235.             app.stat();
  236.             app.cursorX = e.pageX;
  237.             app.cursorY = e.pageY;
  238.         };
  239.  
  240.         window.onresize = () => this.handleResize();
  241.         window.onhashchange = () => this.handleHashChange();
  242.         $(window).on("wheel mousewheel", (e) => this.mousewheelMoved(e));
  243.  
  244.         this.zoomController = zoomController;
  245.         this.cameraController = cameraController;
  246.         this.setupDisplayCanvas(this.displayCanvas);
  247.         this.setupInteraction();
  248.  
  249.         var spawnPoint = this.getSpawnPoint();
  250.         this.setCanvasPosition(spawnPoint.x, spawnPoint.y);
  251.         this.setupZoomSlider();
  252.         this.setZoomScale(this.zooming.zoomScale);
  253.  
  254.         $(this.coordinateElement).show();
  255.         $(this.userCountElement).show();
  256.  
  257.         this.getCanvasImage();
  258.        
  259.         this.determineFeatureAvailability();
  260.  
  261.  
  262.         this.changeUserCount(null);
  263.         this.loadUserCount().then((online) => {
  264.             this.userCountChanged(online);
  265.         }).catch((err) => $(this.userCountElement).hide());
  266.  
  267.         this.popoutController = popoutController;
  268.         this.popoutController.setup(this, $("#popout-container")[0]);
  269.         this.popoutController.popoutVisibilityController.visibilityChangeCallback = () => {
  270.             var start = new Date();
  271.             var interval = setInterval(function() {
  272.                 app.handleResize();
  273.                 if((new Date() - start) > 250) clearInterval(interval);
  274.             }, 10);
  275.         }
  276.  
  277.         $("#colour-picker").minicolors({inline: true, format: "hex", letterCase: "uppercase", defaultValue: "#D66668", change: (change) => this.handleColourPaletteChange(change) });
  278.         $("#colour-picker-hex-value").on("input change keydown", function(e) {
  279.             if (e.keyCode && e.keyCode !== 33) return;
  280.             app.handleColourTextChange(e.type === "input");
  281.         });
  282.         // Check canvas size after chat animation
  283.         $(".canvas-container").on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', () => {
  284.             this.handleResize();
  285.         });
  286.  
  287.         this.updateColourSelectorPosition();
  288.         $("#colour-picker-popover-ctn").click(function() {
  289.             $("body").removeClass("picker-showing");
  290.         })
  291.  
  292.         $("#pixel-use-colour-btn").click(function() {
  293.             var colour = $(this).attr("data-represented-colour");
  294.             $("#colour-picker").minicolors("value", "#" + colour);
  295.         })
  296.  
  297.         setInterval(function() { app.doKeys() }, 15);
  298.  
  299.         this.dismissBtn = $("<button>").attr("type", "button").addClass("close").attr("data-dismiss", "alert").attr("aria-label", "Close");
  300.         $("<span>").attr("aria-hidden", "true").html("&times;").appendTo(this.dismissBtn);
  301.  
  302.         this.loadWarps();
  303.         this.layoutTemplates();
  304.     },
  305.  
  306.     handleColourTextChange: function(premature = false) {
  307.         var colour = $("#colour-picker-hex-value").val();
  308.         if(colour.substring(0, 1) != "#") colour = "#" + colour;
  309.         if(colour.length != 7 && (colour.length != 4 || premature)) return;
  310.         $("#colour-picker").minicolors("value", colour);
  311.     },
  312.  
  313.     determineFeatureAvailability: function() {
  314.         var data = '{"success":true,"availability":{"colours":["#FFFFFF","#C2C2C2","#858585","#474747","#000000","#3AAFFF","#71AAEB","#4A76A8","#074BF3","#5E30EB","#FF6C5B","#FE2500","#FF218B","#99244F","#4D2C9C","#FFCF4A","#FEB43F","#FE8648","#FF5B36","#DA5100","#94E044","#5CBF0D","#C3D117","#FCC700","#D38301"],"flags":[]}}';
  315.         data = JSON.parse(data);
  316.         this.hasTriedToFetchAvailability = true;
  317.         this.colours = data.availability.colours;
  318.         this.pixelFlags = data.availability.flags;
  319.         this.canPlaceCustomColours = data.availability.user && data.availability.user.canPlaceCustomColours;
  320.         this.templatesEnabled = data.availability.user && data.availability.user.hasTemplatesExperiment
  321.         this.layoutTemplates();
  322.         this.setupColours();
  323.     },
  324.  
  325.     getCanvasImage: function() {
  326.         if(this.loadedImage) return;
  327.        
  328.         var app = this;
  329.         this.adjustLoadingScreen("Loading…");;
  330.         this.loadImage().then((image) => {
  331.            
  332.             $("#preloaderapp").hide();
  333.             $("#preloadenterapp").hide();
  334.            
  335.             $("#palette-ctn").show();
  336.            
  337.             setTimeout(function(){
  338.                 place.updateStencil();
  339.             }, 100);
  340.            
  341.            
  342.             app.adjustLoadingScreen();
  343.             app.canvasController.clearCanvas();
  344.             app.canvasController.drawImage(image);
  345.             app.updateDisplayCanvas();
  346.             app.displayCtx.imageSmoothingEnabled = false;
  347.             app.loadedImage = true;
  348.             app.lastPixelUpdate = Date.now() / 1000;
  349.            
  350.             for(var i = 0; i < user.cachePixels.length; i++){
  351.                 place.setPixel(user.cachePixels[i].color, user.cachePixels[i].x, user.cachePixels[i].y)
  352.             }
  353.            
  354.             for(var i = 0; i < user.cachePixelsAM.length; i++){
  355.                 place.setPixel("#ef96f3", user.cachePixelsAM[i].x, user.cachePixelsAM[i].y);
  356.             }
  357.            
  358.             if(localStorage.getItem('stencil' + user.room) != null){
  359.                 var parsedLocalStorage = JSON.parse(localStorage.getItem('stencil' + user.room));
  360.                 stencil.setImage(parsedLocalStorage.src);
  361.             }
  362.            
  363.             if(Cookies.get('zoomScale') != null){
  364.                 place.setZoomScale(Cookies.get('zoomScale'));
  365.             }
  366.            
  367.             if(Cookies.get('room'+user.room) != null){
  368.                 try {
  369.                     var tempHashPoint = JSON.parse(Cookies.get('room'+user.room));
  370.                     place.hashHandler.modifyHash(tempHashPoint);
  371.                     place.setCanvasPosition(place.getHashPoint().x - 1, place.getHashPoint().y - 1);
  372.                 } catch (e) {
  373.                    
  374.                 }  
  375.             }
  376.            
  377.             if(Cookies.get('pageNumber') != null && Cookies.get('timeCookiesChange') != null){
  378.                 if(parseInt(Cookies.get('timeCookiesChange')) + 21600 > parseInt(curentTimestampSync / 1000)){
  379.                     if(Cookies.get('pageNumber') == 2){
  380.                         $(".matrixToggle").click();
  381.                     }
  382.                     if(Cookies.get('pageNumber') == 3){
  383.                         $(".ratingToggle").click();
  384.                     }
  385.                     if(Cookies.get('pageNumber') == 4){
  386.                         $(".toolsToggle").click();
  387.                     }
  388.                     if(Cookies.get('pageNumber') == 5){
  389.                         $(".miningToggle").click();
  390.                     }
  391.                 }
  392.             }
  393.            
  394.         }).catch((err) => {
  395.             console.error("Error loading board image", err);
  396.             if(typeof err.status !== "undefined" && err.status === 503) {
  397.                 app.adjustLoadingScreen("Waiting for server…");
  398.                 console.log("Server wants us to await its instruction");
  399.                 setTimeout(function() {
  400.                     app.getCanvasImage()
  401.                 }, 15000);
  402.             } else {
  403.                 app.adjustLoadingScreen("An error occurred. Please wait…");
  404.                 setTimeout(function() {
  405.                     app.getCanvasImage()
  406.                 }, 5000);
  407.             }
  408.         });
  409.     },
  410.  
  411.     loadImage: function() {
  412.         var a = this;
  413.         return new Promise((resolve, reject) => {
  414.             var xhr = new XMLHttpRequest();
  415.            
  416.             if(user.room == 1){
  417.                 xhr.open("GET", "images/level1.png?" + user.roomimageHash + "&te=1" , true);
  418.             }
  419.            
  420.             if(user.room == 2){
  421.                 xhr.open("GET", "images/level2.png?" + user.roomimageHash + "&te=1" , true);
  422.             }
  423.            
  424.             if(user.room == 3){
  425.                 xhr.open("GET", "images/level3.png?" + user.roomimageHash + "&te=1" , true);
  426.             }
  427.            
  428.             if(user.room == 4){
  429.                 xhr.open("GET", "images/level4.png?" + user.roomimageHash + "&te=1" , true);
  430.             }
  431.            
  432.  
  433.  
  434.            
  435.             xhr.responseType = "blob";
  436.             xhr.onload = function(e) {
  437.                 if(xhr.status == 200) {
  438.                     var url = URL.createObjectURL(this.response);
  439.                     var img = new Image();
  440.                     img.onload = function() {
  441.                         URL.revokeObjectURL(this.src);
  442.                         var lastImageUpdate = xhr.getResponseHeader("X-Place-Last-Update");
  443.                         if(lastImageUpdate) a.requestPixelsAfterDate(lastImageUpdate);
  444.                         resolve(img);
  445.                     };
  446.                     img.onerror = () => reject(xhr);
  447.                     img.src = url;
  448.                 } else reject(xhr);
  449.             };
  450.             xhr.onerror = () => reject(xhr);
  451.             xhr.send();
  452.         });
  453.     },
  454.  
  455.     neededPixelDate: null,
  456.     requestPixelsAfterDate(date) {
  457.         console.log("Requesting pixels after date " + date);
  458.         this.socket.send("fetch_pixels", {ts: date});
  459.     },
  460.  
  461.     setupInteraction: function() {
  462.         var app = this;
  463.         try {
  464.             interact(this.cameraController).draggable({
  465.             inertia: true,
  466.             restrict: {
  467.                 restriction: "parent",
  468.                 elementRect: { top: 0.5, left: 0.5, bottom: 0.5, right: 0.5 },
  469.                 endOnly: true
  470.             },
  471.             autoScroll: true,
  472.             onstart: (event) => {
  473.                 if(flagMobilePinch == false){
  474.                     if(event.interaction.downEvent.button == 2) return event.preventDefault();
  475.                     app.stat();
  476.                     $(app.zoomController).addClass("grabbing");
  477.                     $(":focus").blur();
  478.                 }
  479.             },
  480.             onmove: (event) => {
  481.                 if(flagMobilePinch == false){
  482.                     app.moveCamera(event.dx, event.dy);
  483.                     app.stat();
  484.                 }
  485.             },
  486.             onend: (event) => {
  487.                 if(flagMobilePinch == false){
  488.                     if(event.interaction.downEvent.button == 2) return event.preventDefault();
  489.                     app.stat();
  490.                     $(app.zoomController).removeClass("grabbing");
  491.                     var coord = app.getCoordinates();
  492.                     app.hashHandler.modifyHash(coord);
  493.                 }
  494.                    
  495.             }
  496.         }).on("tap", (event) => {
  497.             if(flagMobilePinch == false){
  498.                 if(event.interaction.downEvent.button == 2) return event.preventDefault();
  499.                 if(!this.zooming.zooming) {
  500.                     var cursor = app.getCanvasCursorPosition(event.pageX, event.pageY);
  501.                     app.canvasClicked(cursor.x, cursor.y);
  502.                 }
  503.                 event.preventDefault();
  504.             }
  505.         }).on("doubletap", (event) => {
  506.             /*
  507.             if(flagMobilePinch == false){
  508.                 if(app.zooming.zoomedIn && this.selectedColour === null) {
  509.                     app.zoomFinished();
  510.                     app.shouldShowPopover = false;
  511.                     app.setZoomScale(this.zooming.initialZoomPoint, true);
  512.                     event.preventDefault();
  513.                 }
  514.             }
  515.             */
  516.         });
  517.         } catch(exep) {
  518.            
  519.         }
  520.        
  521.     },
  522.  
  523.     mousewheelMoved: function(event) {
  524.         if ($('.canvas-container:hover').length <= 0) return;
  525.         var e = event.originalEvent;
  526.         e.preventDefault();
  527.         var delta = e.type == "wheel" ? -e.deltaY : (typeof e.wheelDeltaY !== "undefined" ? e.wheelDeltaY : e.wheelDelta);
  528.         this.setZoomScale(this.zooming.zoomScale + (delta / 100));
  529.     },
  530.  
  531.     getCanvasCursorPosition: function(x = null, y = null) {
  532.         var zoom = this._getZoomMultiplier();
  533.         return {x: Math.round(((x ? x : this.cursorX) - $(this.cameraController).offset().left) / zoom), y: Math.round(((y ? y : this.cursorY) - $(this.cameraController).offset().top) / zoom)};
  534.     },
  535.  
  536.     loadUserCount: function() {
  537.         return new Promise((resolve, reject) => {
  538.             resolve(0);
  539.         });
  540.     },
  541.  
  542.     getSpawnPoint: function() {
  543.         var point = this.getHashPoint();
  544.         if (point) return point;
  545.         return this.getRandomSpawnPoint();
  546.     },
  547.  
  548.     getHashPoint: function() {
  549.         var hash = this.hashHandler.getHash();
  550.         if(typeof hash.x !== "undefined" && typeof hash.y !== "undefined") {
  551.             var x = parseInt(hash.x), y = parseInt(hash.y);
  552.             var fixed = this.closestInsideCoordinates(x, y);
  553.             if(x !== null && y !== null && !isNaN(x) && !isNaN(y)) return {x: -fixed.x + (place.canvas.width / 2), y: -fixed.y + (size / 2)};
  554.         }
  555.         return null;
  556.     },
  557.  
  558.     handleHashChange: function() {
  559.         var point = this.getHashPoint();
  560.         if (point) this.setCanvasPosition(point.x, point.y);
  561.     },
  562.  
  563.     initializeSocketConnection() {
  564.     },
  565.  
  566.     get isAFK() {
  567.         const stat = this._stat;
  568.         const offset = Date.now() - (this.activityTimeout * 1000);
  569.         const afk = !(stat > offset);
  570.         return afk;
  571.     },
  572.  
  573.     getRandomSpawnPoint: function() {
  574.         function getRandomTileNumber() {
  575.             return Math.random() * size - (size / 2);
  576.         }
  577.         return {x: getRandomTileNumber(), y: getRandomTileNumber()};
  578.     },
  579.  
  580.     liveUpdateTiles: function(data) {
  581.         if(!data.pixels) return;
  582.         data.pixels.forEach((pixel) => this.liveUpdateTile(pixel));
  583.     },
  584.  
  585.     liveUpdateTile: function (data) {
  586.         this.lastPixelUpdate = Date.now() / 1000;
  587.         this.setPixel(`#${data.colour}`, data.x, data.y);
  588.     },
  589.  
  590.     adminBroadcastReceived: function(data) {
  591.         this.showAdminBroadcast(data.title, data.message, data.style || "info", data.timeout || 0);
  592.     },
  593.  
  594.     userCountChanged: function (data) {
  595.         if(data !== null) this.changeUserCount(data);
  596.     },
  597.  
  598.     setupColours: function() {
  599.         var overlay = $("#availability-loading-modal");
  600.         $(this.colourPaletteElement).find(".colour-option, .palette-separator").remove();
  601.         var contentContainer = $(this.colourPaletteElement).find("#palette-content-ctn");
  602.         this.colourPaletteOptionElements = [];
  603.         if(this.colours) {
  604.             overlay.hide();
  605.             if(this.canPlaceCustomColours) $("<div>").addClass("colour-option rainbow").attr("id", "customColourChooserOption").click(function() {
  606.                 $("body").toggleClass("picker-showing");
  607.                 if($("body").hasClass("picker-showing")) $("#colour-picker-hex-value").focus();
  608.             }).append("<div class=\"colour-option transparent\"></div>").appendTo(contentContainer);
  609.             var elem = $("<div>").addClass("colour-option custom").attr("id", "customChosenColourOption").attr("data-colour", 1).hide().appendTo(contentContainer);
  610.             this.colourPaletteOptionElements.push(elem[0]);
  611.             if(this.canPlaceCustomColours) $("<div>").addClass("palette-separator").appendTo(contentContainer);
  612.             this.colours.forEach((colour, index) => {
  613.                 var elem = $("<div>").addClass("colour-option" + (colour.toLowerCase() == "#ffffff" ? " is-white" : "")).css("background-color", colour).attr("data-colour", index + 2);
  614.                 elem.appendTo(contentContainer);
  615.                 this.colourPaletteOptionElements.push(elem[0]);
  616.             });
  617.             this.updateColourSelectorPosition();
  618.             if(this.pixelFlags && this.pixelFlags.length > 0) {
  619.                 $("<div>").addClass("palette-separator").appendTo(contentContainer);
  620.                 this.pixelFlags.forEach((flag, index) => {
  621.                     var elem = $("<div>").addClass("colour-option flag-option").css("background-image", `url(${flag.image})`).attr("data-flag", index).attr("data-flag-id", flag.id).attr("title", `${flag.title}:\n${flag.description}`).attr("alt", flag.title);
  622.                     if(flag.needsBorder) elem.addClass("is-white");
  623.                     elem.appendTo(contentContainer);
  624.                     this.colourPaletteOptionElements.push(elem[0]);
  625.                 });
  626.             }
  627.             reloadColorsAmount();
  628.         } else {
  629.             overlay.text(this.hasTriedToFetchAvailability ? "An error occurred while loading colours. Retrying…" : "Loading…").show();
  630.         }
  631.     },
  632.  
  633.     handleColourPaletteChange: function(newColour) {
  634.         if(!this.canPlaceCustomColours) return;
  635.         this.customColour = newColour;
  636.         var elem = $("#customChosenColourOption").show().css("background-color", newColour);
  637.         $("#colour-picker-hex-value").val(newColour.toUpperCase());
  638.         if(newColour.toLowerCase() == "#ffffff") elem.addClass("is-white");
  639.         else elem.removeClass("is-white");
  640.         this.selectColour(1, false);
  641.     },
  642.  
  643.     handleResize: function() {
  644.         var canvasContainer = $(this.zoomController).parent();
  645.         this.displayCanvas.height = canvasContainer.height();
  646.         this.displayCanvas.width = canvasContainer.width();
  647.         this.displayCtx.mozImageSmoothingEnabled = false;
  648.         this.displayCtx.webkitImageSmoothingEnabled = false;
  649.         this.displayCtx.msImageSmoothingEnabled = false;
  650.         this.displayCtx.imageSmoothingEnabled = false;
  651.         this.updateDisplayCanvas();
  652.         if(this.zooming.wasZoomedFullyOut) this.setZoomScale(0);
  653.         this.updateGrid();
  654.         this.updateGridHint(this.lastX, this.lastY);
  655.         this.updateStencil();
  656.         this.updateColourSelectorPosition();
  657.     },
  658.  
  659.     updateColourSelectorPosition: function() {
  660.         var elem = $("#colour-picker-popover"), button = $("#customColourChooserOption");
  661.         var position = 20;
  662.         if(button.length > 0) position = Math.max(20, button.offset().left - (elem.outerWidth() / 2) + (button.outerWidth() / 2));
  663.         if(position <= 20) {
  664.             elem.addClass("arrow-left");
  665.             if(button.length > 0) {
  666.                 var arrowOffset = button.offset().left - (button.outerWidth() / 2) - 10;
  667.                 $("#popover-styling").html(`#colour-picker-popover:after, #colour-picker-popover:before { left: ${arrowOffset}px!important; }`);
  668.             }
  669.             else $("#popover-styling").html("");
  670.         } else {
  671.             elem.removeClass("arrow-left");
  672.             $("#popover-styling").html("");
  673.         }
  674.         elem.css({left: position});
  675.     },
  676.  
  677.     setupDisplayCanvas: function(canvas) {
  678.         this.displayCtx = canvas.getContext("2d");
  679.         this.handleResize();
  680.         this.updateDisplayCanvas();
  681.     },
  682.  
  683.     updateDisplayCanvas: function() {
  684.         var dcanvas = this.displayCanvas;
  685.         this.displayCtx.clearRect(0, 0, dcanvas.width, dcanvas.height);
  686.         var zoom = this._getCurrentZoom();
  687.         var mod = size / 2;
  688.         this.displayCtx.drawImage(this.canvas, dcanvas.width / 2 + (this.panX - (this.canvas.width / 2) - 0.5) * zoom, dcanvas.height / 2 + (this.panY - mod - 0.5) * zoom, this.canvas.width * zoom, this.canvas.height * zoom);
  689.     },
  690.  
  691.     _lerp: function(from, to, time) {
  692.         if (time > 100) time = 100;
  693.         return from + (time / 100) * (to - from);
  694.     },
  695.  
  696.     _getCurrentZoom: function() {
  697.         if (!this.zooming.zooming) return this._getZoomMultiplier();
  698.         return this._lerp(this.zooming.zoomFrom, this.zooming.zoomTo, this.zooming.zoomTime);
  699.     },
  700.  
  701.     _getZoomMultiplier: function() {
  702.         return this.zooming.zoomScale;
  703.     },
  704.  
  705.     animateZoom: function(callback = null) {
  706.         if(!is_touch_device){
  707.             this.zooming.zoomTime += this.zooming.fastZoom ? 5 : 2;
  708.         } else {
  709.             this.zooming.zoomTime += 10;
  710.         }
  711.        
  712.  
  713.         var x = this._lerp(this.zooming.panFromX, this.zooming.panToX, this.zooming.zoomTime);
  714.         var y = this._lerp(this.zooming.panFromY, this.zooming.panToY, this.zooming.zoomTime);
  715.         this.updateUIWithZoomScale(this._lerp(this.zooming.zoomFrom, this.zooming.zoomTo, this.zooming.zoomTime));
  716.         this.setCanvasPosition(x, y);
  717.  
  718.         if (this.zooming.zoomTime >= 100) {
  719.             this.zoomFinished();
  720.             if(this.shouldShowPopover) {
  721.                 $(this.pixelDataPopover).fadeIn(250);
  722.                 this.shouldShowPopover = false;
  723.             }
  724.             if(callback) callback();
  725.             return
  726.         }
  727.     },
  728.  
  729.     updateUIWithZoomScale: function(zoomScale = null) {
  730.         if(zoomScale === null) zoomScale = this.zooming.zoomScale;
  731.         $(this.zoomController).css("transform", `scale(${zoomScale})`);
  732.         $("#zoom-slider").slider('setValue', zoomScale, true);
  733.         $(this.handElement).css("display", "none");
  734.         $(this.handElement).css({width: `${zoomScale}px`, height: `${zoomScale}px`, borderRadius: `${zoomScale / 8}px`});
  735.        
  736.         $(this.gridHint).css({width: `${zoomScale}px`, height: `${zoomScale}px`});
  737.         if(stencil.isVisible){
  738.             $(stencil.stencilDiv).css({width: ((1 * place._getZoomMultiplier()) * stencil.width) + "px", height: ((1 * place._getZoomMultiplier()) * stencil.height) + "px"});
  739.         }
  740.         this.updateGridHint(this.lastX, this.lastY);
  741.         this.updateStencil();
  742.     },
  743.  
  744.     zoomFinished: function() {
  745.         this.zooming.zoomScale = this.zooming.zoomTo;
  746.         this.zooming.zooming = false;
  747.         this.setCanvasPosition(this.zooming.panToX, this.zooming.panToY);
  748.         this.zooming.panToX = null, this.zooming.panToY = null, this.zooming.zoomTo = null, this.zooming.zoomFrom = null;
  749.         clearInterval(this.zooming.zoomHandle);
  750.         var coord = this.getCoordinates();
  751.         this.hashHandler.modifyHash(coord);
  752.         this.zooming.zoomHandle = null;
  753.         this.zooming.fastZoom = false;
  754.     },
  755.  
  756.     setupZoomSlider: function() {
  757.         var minScale = this.getMinimumScale();
  758.         $('#zoom-slider').slider({
  759.             ticks: this.zooming.snapPoints.map((p) => Math.max(p, minScale)),
  760.             ticks_snap_bounds: 0.01,
  761.             step: 0.01,
  762.             min: minScale,
  763.             max: this.zooming.snapPoints[this.zooming.snapPoints.length - 1],
  764.             scale: 'logarithmic',
  765.             value: this.zooming.zoomScale,
  766.         }).on('change', (event) => {
  767.             this.setZoomScale(event.value.newValue, false, false);
  768.         });
  769.     },
  770.  
  771.     setZoomScale: function(scale, animated = false, affectsSlider = true) {
  772.        
  773.         lastMove = Date.now();
  774.         if(is_touch_device){
  775.             $(place.grid).removeClass("show");
  776.         }
  777.        
  778.        
  779.         if(this.zooming.zoomHandle !== null) return;
  780.         this.zooming.panFromX = this.panX;
  781.         this.zooming.panFromY = this.panY;
  782.         if(this.zooming.panToX == null) this.zooming.panToX = this.panX;
  783.         if(this.zooming.panToY == null) this.zooming.panToY = this.panY;
  784.         var newScale = this.normalizeZoomScale(scale);
  785.         if(animated) {
  786.             this.zooming.zoomTime = 0;
  787.             this.zooming.zoomFrom = this._getCurrentZoom();
  788.             this.zooming.zoomTo = newScale;
  789.             this.zooming.zooming = true;
  790.             this.zooming.zoomHandle = setInterval(this.animateZoom.bind(this), 1);
  791.         } else {
  792.             this.zooming.zoomScale = newScale;
  793.             this.updateUIWithZoomScale(newScale);
  794.         }
  795.         this.zooming.zoomedIn = newScale >= (this.zooming.initialZoomPoint + this.zooming.zoomedInPoint) / 2;
  796.         if(!this.zooming.zoomedIn) $(this.pixelDataPopover).hide();
  797.         this.updateDisplayCanvas();
  798.         this.updateGrid();
  799.         this._adjustZoomButtonText();
  800.     },
  801.  
  802.     getMinimumScale: function() {
  803.         var canvasContainer = $(this.zoomController).parent();
  804.         return 0.5;
  805.     },
  806.  
  807.     normalizeZoomScale: function(scale) {
  808.         var minScale = this.getMinimumScale();
  809.         var newScale = Math.min(this.zooming.snapPoints[this.zooming.snapPoints.length - 1], Math.max(minScale, Math.max(this.zooming.snapPoints[0], scale)));
  810.         this.zooming.wasZoomedFullyOut = newScale <= minScale;
  811.         /*
  812.         if (this.zooming.wasZoomedFullyOut && !$(this.colourPaletteElement).hasClass("full-canvas")) $(this.colourPaletteElement).addClass("full-canvas");
  813.         else if(!this.zooming.wasZoomedFullyOut && $(this.colourPaletteElement).hasClass("full-canvas")) $(this.colourPaletteElement).removeClass("full-canvas");
  814.         */
  815.         return newScale;
  816.     },
  817.  
  818.     toggleZoom: function() {
  819.         if (this.zooming.zooming) return;
  820.         var scale = this.zooming.zoomScale;
  821.         if (scale < this.zooming.initialZoomPoint) this.setZoomScale(this.zooming.initialZoomPoint, true);
  822.         else if (scale < (this.zooming.initialZoomPoint + this.zooming.zoomedInPoint) / 2) this.setZoomScale(this.zooming.zoomedInPoint, true);
  823.         else if (scale <= this.zooming.zoomedInPoint) this.setZoomScale(this.zooming.initialZoomPoint, true);
  824.         else this.setZoomScale(this.zooming.zoomedInPoint, true);
  825.     },
  826.  
  827.     _adjustZoomButtonText: function() {
  828.         if (this.zoomButton) $(this.zoomButton).html(`<i class="fa fa-fw fa-search-${this.zooming.zoomedIn ? "minus" : "plus"}"></i>`).attr("title", (this.zooming.zoomedIn ? "Zoom Out" : "Zoom In") + " (spacebar)");
  829.     },
  830.  
  831.     _adjustGridButtonText: function() {
  832.         var gridShown = $(this.grid).hasClass("show");
  833.         if (this.gridButton) $(this.gridButton).html(`<i class="fa fa-fw fa-${gridShown ? "square" : "th"}"></i>`).attr("title", (gridShown ? "Hide Grid" : "Show Grid") + " (G)");
  834.     },
  835.  
  836.     setZoomButton: function(btn) {
  837.         this.zoomButton = btn;
  838.         this._adjustZoomButtonText();
  839.         $(btn).click(this.toggleZoom.bind(this));
  840.     },
  841.  
  842.     setGridButton: function(btn) {
  843.         this.gridButton = btn;
  844.         this._adjustGridButtonText();
  845.         $(btn).click(this.toggleGrid.bind(this));
  846.     },
  847.  
  848.     setCoordinatesButton: function(btn) {
  849.         if(Clipboard.isSupported()) {
  850.             /*
  851.             var app = this;
  852.             var clipboard = new Clipboard(btn);
  853.             $(btn).addClass("clickable").tooltip({
  854.                 title: "Copied to clipboard!",
  855.                 trigger: "manual",
  856.             });
  857.             clipboard.on("success", function(e) {
  858.                 $(btn).tooltip("show");
  859.                 setTimeout(function() {
  860.                     $(btn).tooltip("hide");
  861.                 }, 2500);
  862.             })
  863.             */
  864.         }
  865.     },
  866.  
  867.     moveCamera: function(deltaX, deltaY, softAllowBoundPush = false) {
  868.         deltaX = deltaX * 1.5;
  869.         deltaY = deltaY * 1.5;
  870.         if(!userTouch && is_touch_device){
  871.             return;
  872.         }
  873.        
  874.         //showNotify(deltaX, 100);
  875.         if(flagMobilePinch){
  876.             return;
  877.         }
  878.         if(!userIsDraw){
  879.             var cam = $(this.cameraController);
  880.             var zoomModifier = this._getCurrentZoom();
  881.             var coords = this.getCoordinates();
  882.             var x = deltaX / zoomModifier, y = deltaY / zoomModifier;
  883.             this.setCanvasPosition(x, y, true, softAllowBoundPush);
  884.         }
  885.     },
  886.  
  887.     updateCoordinates: function() {
  888.         var coord = this.getCoordinates();
  889.         if(coord != this.lastUpdatedCoordinates) {
  890.             var coordElem = $(this.coordinateElement);
  891.             setTimeout(function() {
  892.                 var spans = coordElem.find("span");
  893.                 spans.first().text(coord.x.toLocaleString());
  894.                 spans.last().text(coord.y.toLocaleString());
  895.                 coordElem.attr("data-clipboard-text", `(${coord.x}, ${coord.y})`);
  896.             }, 0);
  897.         }
  898.         this.lastUpdatedCoordinates = coord;
  899.        
  900.         if(user.curentPage == 2){
  901.             if(user.coins > 50){
  902.                 $("#vkHeaderText").text("x: " + parseInt(coord.x) + " y: " + coord.y);
  903.             } else {
  904.                 $("#vkHeaderText").text("Комнаты");
  905.             }
  906.         }
  907.     },
  908.  
  909.     isOutsideOfBounds: function(precise = false) {
  910.         var coord = this.getCoordinates();
  911.         var x = coord.x < 0 || coord.x >= place.canvas.width, y = coord.y >= size || coord.y < 0
  912.         return precise ? { x: x, y: y } : x || y;
  913.     },
  914.  
  915.     getCoordinates: function() {
  916.         var dcanvas = this.canvasController.canvas;
  917.         return {x: Math.floor(-this.panX) + dcanvas.width / 2, y: Math.floor(-this.panY) + dcanvas.height / 2};
  918.     },
  919.  
  920.     setCanvasPosition: function(x, y, delta = false, softAllowBoundPush = true) {
  921.        
  922.         lastMove = Date.now();
  923.         if(is_touch_device){
  924.             $(place.grid).removeClass("show");
  925.         }
  926.        
  927.        
  928.         $(this.pixelDataPopover).hide();
  929.         if (delta) this.panX += x, this.panY += y;
  930.         else this.panX = x, this.panY = y;
  931.         if(!softAllowBoundPush) {
  932.             this.panX = Math.max(-(place.canvas.width / 2) + 1, Math.min((place.canvas.width / 2), this.panX));
  933.             this.panY = Math.max(-(size / 2) + 1, Math.min((size / 2), this.panY));
  934.         }
  935.         $(this.cameraController).css({
  936.             top: `${this.panY}px`,
  937.             left: `${this.panX}px`
  938.         })
  939.         this.updateGrid();
  940.         if(this.lastX, this.lastY) this.updateGridHint(this.lastX, this.lastY);
  941.         if(this.lastX, this.lastY) this.updateStencil();
  942.        
  943.         this.updateCoordinates();
  944.         this.updateDisplayCanvas();
  945.     },
  946.  
  947.     updateGrid: function() {
  948.         var zoom = this._getCurrentZoom();
  949.         var x = ($(this.cameraController).offset().left - (zoom / 2)) % zoom;
  950.         var y = ($(this.cameraController).offset().top - (zoom / 2)) % zoom;
  951.         $(this.grid).css({transform: `translate(${x}px, ${y}px)`, backgroundSize: `${zoom}px ${zoom}px`});
  952.     },
  953.  
  954.     toggleGrid: function() {
  955.         $(this.grid).toggleClass("show");
  956.         this._adjustGridButtonText();
  957.     },
  958.  
  959.     updateGridHint: function(x, y) {
  960.         /*
  961.         this.lastX = x;
  962.         this.lastY = y;
  963.         if(this.gridHint) {
  964.             var zoom = this._getCurrentZoom();
  965.             // Hover position in grid multiplied by zoom
  966.             var x = Math.round((this.lastX - $(this.cameraController).offset().left) / zoom), y = Math.round((this.lastY - $(this.cameraController).offset().top) / zoom);
  967.             var elem = $(this.gridHint);
  968.             var posX = x + ($(this.cameraController).offset().left / zoom) - 0.5;
  969.             var posY = y + ($(this.cameraController).offset().top / zoom) - 0.5;
  970.             elem.css({
  971.                 left: posX * zoom,
  972.                 top: posY * zoom,
  973.             });
  974.         }
  975.         */
  976.     },
  977.    
  978.     updateStencil: function() {
  979.         this.updateRedzone();
  980.         this.setStencil(stencil.x, stencil.y);
  981.         if(stencil.isVisible){
  982.             $(stencil.stencilDiv).css({width: ((1 * place._getZoomMultiplier()) * stencil.width) + "px", height: ((1 * place._getZoomMultiplier()) * stencil.height) + "px"});
  983.         }
  984.        
  985.     },
  986.    
  987.     updateRedzone: function() {
  988.         if(user.room == 3){
  989.             if(user.coordGiftDiamond[0] > 0){
  990.                 $("#red-zone").show();
  991.             } else {
  992.                 $("#red-zone").hide();
  993.             }
  994.    
  995.             $("#diamond-zone").show();
  996.             $("#diamond-zone2").show();
  997.             //$(stencil.redZoneDiv).css('box-shadow', '0px 0px ' + (1 * place._getZoomMultiplier()) * 10 + 'px 0px rgb(255, 0, 0)');
  998.             //$(stencil.redZoneDiv).css('border', (1 * place._getZoomMultiplier()) * 2 + 'px solid red');
  999.            
  1000.             this.setRedzone(user.coordGiftDiamond[0], user.coordGiftDiamond[1]);
  1001.             $(stencil.redZoneDiv).css({width: ((1 * place._getZoomMultiplier()) ) + "px", height: ((1 * place._getZoomMultiplier())) + "px"});
  1002.            
  1003.            
  1004.             /*
  1005.             this.setDiamondzone(877, 77);
  1006.             $(stencil.diamondZoneDiv).css({width: ((10 * place._getZoomMultiplier()) ) + "px", height: ((10 * place._getZoomMultiplier())) + "px"});
  1007.            
  1008.             this.setDiamondzone2(931, 77);
  1009.             $(stencil.diamondZoneDiv2).css({width: ((10 * place._getZoomMultiplier()) ) + "px", height: ((10 * place._getZoomMultiplier())) + "px"});
  1010.             */
  1011.         }
  1012.     },
  1013.    
  1014.     setStencil: function(x, y) {
  1015.        
  1016.         x = $(place.cameraController).offset().left + (x * place._getZoomMultiplier());
  1017.         y = $(place.cameraController).offset().top + (y * place._getZoomMultiplier());
  1018.        
  1019.         this.lastX = x;
  1020.         this.lastY = y;
  1021.         if(stencil.stencilDiv) {
  1022.             var zoom = this._getCurrentZoom();
  1023.             // Hover position in grid multiplied by zoom
  1024.             var x = Math.round((this.lastX - $(this.cameraController).offset().left) / zoom), y = Math.round((this.lastY - $(this.cameraController).offset().top) / zoom);
  1025.             var elem = $(stencil.stencilDiv);
  1026.             var posX = x + ($(this.cameraController).offset().left / zoom) - 0.5;
  1027.             var posY = y + ($(this.cameraController).offset().top / zoom) - 0.5;
  1028.             elem.css({
  1029.                 left: posX * zoom,
  1030.                 top: posY * zoom,
  1031.             });
  1032.         }
  1033.     },
  1034.    
  1035.     setRedzone: function(x, y) {
  1036.        
  1037.         x = $(place.cameraController).offset().left + (x * place._getZoomMultiplier());
  1038.         y = $(place.cameraController).offset().top + (y * place._getZoomMultiplier());
  1039.        
  1040.         this.lastX = x;
  1041.         this.lastY = y;
  1042.         if(stencil.redZoneDiv) {
  1043.             var zoom = this._getCurrentZoom();
  1044.             // Hover position in grid multiplied by zoom
  1045.             var x = Math.round((this.lastX - $(this.cameraController).offset().left) / zoom), y = Math.round((this.lastY - $(this.cameraController).offset().top) / zoom);
  1046.             var elem = $(stencil.redZoneDiv);
  1047.             var posX = x + ($(this.cameraController).offset().left / zoom) - 0.5;
  1048.             var posY = y + ($(this.cameraController).offset().top / zoom) - 0.5;
  1049.             elem.css({
  1050.                 left: posX * zoom,
  1051.                 top: posY * zoom,
  1052.             });
  1053.         }
  1054.     },
  1055.    
  1056.     /*
  1057.     setDiamondzone: function(x, y) {
  1058.        
  1059.         x = $(place.cameraController).offset().left + (x * place._getZoomMultiplier());
  1060.         y = $(place.cameraController).offset().top + (y * place._getZoomMultiplier());
  1061.        
  1062.         this.lastX = x;
  1063.         this.lastY = y;
  1064.         if(stencil.diamondZoneDiv) {
  1065.             var zoom = this._getCurrentZoom();
  1066.             // Hover position in grid multiplied by zoom
  1067.             var x = Math.round((this.lastX - $(this.cameraController).offset().left) / zoom), y = Math.round((this.lastY - $(this.cameraController).offset().top) / zoom);
  1068.             var elem = $(stencil.diamondZoneDiv);
  1069.             var posX = x + ($(this.cameraController).offset().left / zoom) - 0.5;
  1070.             var posY = y + ($(this.cameraController).offset().top / zoom) - 0.5;
  1071.             elem.css({
  1072.                 left: posX * zoom,
  1073.                 top: posY * zoom,
  1074.             });
  1075.         }
  1076.     },
  1077.    
  1078.     setDiamondzone2: function(x, y) {
  1079.        
  1080.         x = $(place.cameraController).offset().left + (x * place._getZoomMultiplier());
  1081.         y = $(place.cameraController).offset().top + (y * place._getZoomMultiplier());
  1082.        
  1083.         this.lastX = x;
  1084.         this.lastY = y;
  1085.         if(stencil.diamondZoneDiv2) {
  1086.             var zoom = this._getCurrentZoom();
  1087.             // Hover position in grid multiplied by zoom
  1088.             var x = Math.round((this.lastX - $(this.cameraController).offset().left) / zoom), y = Math.round((this.lastY - $(this.cameraController).offset().top) / zoom);
  1089.             var elem = $(stencil.diamondZoneDiv2);
  1090.             var posX = x + ($(this.cameraController).offset().left / zoom) - 0.5;
  1091.             var posY = y + ($(this.cameraController).offset().top / zoom) - 0.5;
  1092.             elem.css({
  1093.                 left: posX * zoom,
  1094.                 top: posY * zoom,
  1095.             });
  1096.         }
  1097.     },
  1098.     */
  1099.    
  1100.     setGridHint: function(x, y) {
  1101.        
  1102.         x = $(place.cameraController).offset().left + (x * place._getZoomMultiplier()) - (1 * place._getZoomMultiplier());
  1103.         y = $(place.cameraController).offset().top + (y * place._getZoomMultiplier()) - (1 * place._getZoomMultiplier());
  1104.        
  1105.         this.lastX = x;
  1106.         this.lastY = y;
  1107.         if(this.gridHint) {
  1108.             var zoom = this._getCurrentZoom();
  1109.             // Hover position in grid multiplied by zoom
  1110.             var x = Math.round((this.lastX - $(this.cameraController).offset().left) / zoom), y = Math.round((this.lastY - $(this.cameraController).offset().top) / zoom);
  1111.             var elem = $(this.gridHint);
  1112.             var posX = x + ($(this.cameraController).offset().left / zoom) - 0.5;
  1113.             var posY = y + ($(this.cameraController).offset().top / zoom) - 0.5;
  1114.             elem.css({
  1115.                 left: posX * zoom,
  1116.                 top: posY * zoom,
  1117.             });
  1118.         }
  1119.     },
  1120.  
  1121.     handleMouseMove: function(event) {
  1122.         if(!this.placing) {
  1123.             this.updateGridHint(event.pageX, event.pageY);
  1124.             this.updateStencil();
  1125.             if(this.handElement) {
  1126.                 var elem = $(this.handElement);
  1127.                 elem.css({
  1128.                     left: event.pageX - (elem.width() / 2),
  1129.                     top: event.pageY - (elem.height() / 2),
  1130.                 });
  1131.             }
  1132.         }
  1133.     },
  1134.  
  1135.     closestInsideCoordinates: function(x, y) {
  1136.         return {
  1137.             x: Math.max(0, Math.min(x, place.canvas.width - 1)),
  1138.             y: Math.max(0, Math.min(y, size - 1))
  1139.         };
  1140.     },
  1141.  
  1142.     contextMenu: function(event) {
  1143.         event.preventDefault();
  1144.         //if(this.selectedColour !== null) return this.deselectColour();
  1145.         //this.setZoomScale(this.zooming.initialZoomPoint, true);
  1146.     },
  1147.  
  1148.     getPixel: function(x, y, callback) {
  1149.         /*
  1150.         return placeAjax.get(`/api/pos-info`, {x: x, y: y}, "An error occurred while trying to retrieve data about that pixel.").then((data) => {
  1151.             callback(null, data);
  1152.         }).catch((err) => callback(err));
  1153.         */
  1154.     },
  1155.  
  1156.     isSignedIn: function() {
  1157.         return $("body").hasClass("signed-in");
  1158.     },
  1159.  
  1160.     updatePlaceTimer: function() {
  1161.         if(this.isSignedIn()) {
  1162.             this.changePlaceTimerVisibility(true);
  1163.             $(this.placeTimer).children("span").text("Loading…");
  1164.             var a = this;
  1165.             return placeAjax.get("/api/timer").then((data) => a.doTimer(data.timer)).catch((err) => this.changePlaceTimerVisibility(false));
  1166.         }
  1167.         this.changePlaceTimerVisibility(false);
  1168.     },
  1169.  
  1170.     doTimer: function(data) {
  1171.         this.changePlaceTimerVisibility(true);
  1172.         if(data.canPlace) return this.changePlaceTimerVisibility(false);
  1173.         //this.deselectColour();
  1174.         this.unlockTime = (new Date().getTime() / 1000) + data.seconds;
  1175.         this.fullUnlockTime = data.seconds;
  1176.         this.secondTimer = setInterval(() => this.checkSecondsTimer(), 1000);
  1177.         this.checkSecondsTimer();
  1178.     },
  1179.  
  1180.     getSiteName: function() {
  1181.         return $("meta[name=place-site-name]").attr("content");
  1182.     },
  1183.  
  1184.     checkSecondsTimer: function() {
  1185.         function padLeft(str, pad, length) {
  1186.             if (str.length > length) return str;
  1187.             return (new Array(length + 1).join(pad) + str).slice(-length);
  1188.         }
  1189.         if(this.unlockTime && this.secondTimer && this.fullUnlockTime) {
  1190.             var time = Math.round(this.unlockTime - new Date().getTime() / 1000);
  1191.             if(time > 0) {
  1192.                 var minutes = ~~(time / 60), seconds = time - minutes * 60;
  1193.                 var formattedTime = `${minutes}:${padLeft(seconds.toString(), "0", 2)}`;
  1194.                 document.title = `[${formattedTime}] | ${this.originalTitle}`;
  1195.                 var shouldShowNotifyButton = !this.notificationHandler.canNotify() && this.notificationHandler.isAbleToRequestPermission();
  1196.                 $(this.placeTimer).children("span").html("You may place again in <strong>" + formattedTime + "</strong>." + (shouldShowNotifyButton ? " <a href=\"#\" id=\"notify-me\">Notify me</a>." : ""));
  1197.                 return;
  1198.             } else if(this.fullUnlockTime > 5) { // only notify if full countdown exceeds 5 seconds
  1199.                 this.notificationHandler.sendNotification(this.getSiteName(), "You may now place!");
  1200.             }
  1201.         }
  1202.         if(this.secondTimer) clearInterval(this.secondTimer);
  1203.         this.secondTimer = null, this.unlockTime = null, this.fullUnlockTime = null;
  1204.         document.title = this.originalTitle;
  1205.         this.changePlaceTimerVisibility(false);
  1206.     },
  1207.  
  1208.     handleNotifyMeClick: function() {
  1209.         if(!this.notificationHandler.canNotify() && this.notificationHandler.isAbleToRequestPermission()) return this.notificationHandler.requestPermission((success) => this.checkSecondsTimer());
  1210.         this.checkSecondsTimer();
  1211.     },
  1212.  
  1213.     changeUserCount: function(newContent) {
  1214.         var elem = $(this.userCountElement);
  1215.         elem.show();
  1216.         var notch = elem.find(".loading");
  1217.         var text = elem.find(".count");
  1218.         var num = parseInt(newContent);
  1219.         if(num === null || isNaN(num)) {
  1220.             notch.show();
  1221.             text.text("");
  1222.         } else {
  1223.             notch.hide();
  1224.             text.text(num.toLocaleString());
  1225.         }
  1226.     },
  1227.  
  1228.     changePlaceTimerVisibility: function(visible) {
  1229.         if(visible) $(this.placeTimer).addClass("shown");
  1230.         else $(this.placeTimer).removeClass("shown");
  1231.         this.changeSelectorVisibility(!visible);
  1232.     },
  1233.  
  1234.     changePlacingModalVisibility: function(visible) {
  1235.         if(visible) $(this.placingOverlay).addClass("shown");
  1236.         else $(this.placingOverlay).removeClass("shown");
  1237.     },
  1238. randomInt: function(min, max) {
  1239.     return min + Math.floor((max - min) * Math.random());
  1240. },
  1241.     //IKTEAM EDIT
  1242.     protection: function() {
  1243.     if (document.Protect) {
  1244.         if (document.Mode == 0) {
  1245.             var editt = 0;
  1246.             var CurrentPixelAmount = -1;
  1247.             CurrentPixelAmount = $("#palette_megapixel_amount")[0].innerText.split(" ")[0];
  1248.             if (stencil.isVisible && stencil.isPin && !stencil.opacity) {
  1249.                 for (var x = stencil.x; x < (stencil.width + stencil.x); x++) {
  1250.                     for (var y = stencil.y; y < (stencil.height + stencil.y); y++) {
  1251.                         if (CurrentPixelAmount >= 1) {
  1252.                             var CanX = x - stencil.x;
  1253.                             var CanY = y - stencil.y;
  1254.  
  1255.                             var hexColor = getPixelFromCanvas(ctxRender, CanX, CanY);
  1256.                             if (hexColor == "000000") {
  1257.                                 hexColor = "222222"
  1258.                             }
  1259.                             //console.log(hexColor);
  1260.                             if (hexColor != 0) {
  1261.                                 var errorColor = {
  1262.                                     color: -1,
  1263.                                     score: 99999999
  1264.                                 };
  1265.                                 for (var i = 0; i < place.colours.length; i++) {
  1266.                                     var tempScore = deltaE(hexToRgbArray("#" + hexColor), hexToRgbArray(place.colours[i]));
  1267.                                     if (tempScore < errorColor.score) {
  1268.                                         errorColor.color = i + 1;
  1269.                                         errorColor.score = tempScore;
  1270.                                     }
  1271.                                 }
  1272.                                 var tess = canvasController.getPixelColour(x, y).toLowerCase();
  1273.                                 var trueC = {
  1274.                                     color: -1,
  1275.                                     score: 99999999
  1276.                                 };
  1277.                                 for (var i = 0; i < place.colours.length; i++) {
  1278.                                     var tempScoree = deltaE(hexToRgbArray("#" + tess), hexToRgbArray(place.colours[i]));
  1279.                                     if (tempScoree < trueC.score) {
  1280.                                         trueC.color = i + 1;
  1281.                                         trueC.score = tempScoree;
  1282.                                     }
  1283.                                 }
  1284.                                 if (trueC.color != errorColor.color) {
  1285.                                     place.canvasClicked(x, y);
  1286.                                     CurrentPixelAmount--;
  1287.                                 }
  1288.                             }
  1289.  
  1290.                         }
  1291.                     }
  1292.                 }
  1293.             }
  1294.         } else {
  1295.             var CurrentPixelAmount = -1;
  1296.             CurrentPixelAmount = $("#palette_megapixel_amount")[0].innerText.split(" ")[0];
  1297.             if (stencil.isVisible && stencil.isPin && !stencil.opacity) {
  1298.                 while (CurrentPixelAmount >= 1) {
  1299.                     var x = randomIntFromInterval(stencil.x, stencil.width + stencil.x);
  1300.                     var y = randomIntFromInterval(stencil.y, stencil.height + stencil.y);
  1301.                     var CanX = x - stencil.x;
  1302.                     var CanY = y - stencil.y;
  1303.  
  1304.                     var hexColor = getPixelFromCanvas(ctxRender, CanX, CanY);
  1305.                     if (hexColor == "000000") {
  1306.                         hexColor = "222222"
  1307.                     }
  1308.                     //console.log(hexColor);
  1309.                     if (hexColor != 0) {
  1310.                         var errorColor = {
  1311.                             color: -1,
  1312.                             score: 99999999
  1313.                         };
  1314.                         for (var i = 0; i < place.colours.length; i++) {
  1315.                             var tempScore = deltaE(hexToRgbArray("#" + hexColor), hexToRgbArray(place.colours[i]));
  1316.                             if (tempScore < errorColor.score) {
  1317.                                 errorColor.color = i + 1;
  1318.                                 errorColor.score = tempScore;
  1319.                             }
  1320.                         }
  1321.                         var tess = canvasController.getPixelColour(x, y).toLowerCase();
  1322.                         var trueC = {
  1323.                             color: -1,
  1324.                             score: 99999999
  1325.                         };
  1326.                         for (var i = 0; i < place.colours.length; i++) {
  1327.                             var tempScoree = deltaE(hexToRgbArray("#" + tess), hexToRgbArray(place.colours[i]));
  1328.                             if (tempScoree < trueC.score) {
  1329.                                 trueC.color = i + 1;
  1330.                                 trueC.score = tempScoree;
  1331.                             }
  1332.                         }
  1333.                         if (trueC.color != errorColor.color) {
  1334.                             place.canvasClicked(x, y);
  1335.                             CurrentPixelAmount--;
  1336.                         }
  1337.                     }
  1338.  
  1339.                 }
  1340.             }
  1341.         }
  1342.     }
  1343. },
  1344.  
  1345.  
  1346.     selectColour: function(colourID, hideColourPicker = true) {
  1347.        
  1348.        
  1349.        
  1350.        
  1351.         var hasSelectedColor = this.colourPaletteOptionElements[colourID - 1].classList.contains('selected');
  1352.        
  1353.         this.deselectColour(hideColourPicker);
  1354.        
  1355.         if(hasSelectedColor == false){
  1356.             this.selectedColour = colourID - 1;
  1357.             var elem = this.colourPaletteOptionElements[this.selectedColour];
  1358.            
  1359.             // Create hand element
  1360.             this.handElement = $(elem).clone().addClass("hand").appendTo($(this.zoomController).parent())[0];
  1361.             // Update zoom scale for hand element sizing
  1362.             this.updateUIWithZoomScale();
  1363.            
  1364.            
  1365.             // Select in colour palette
  1366.             $(elem).addClass("selected");
  1367.            
  1368.             // Add selected class to zoom controller
  1369.             $(this.zoomController).addClass("selected");
  1370.             // Show the grid hint (rectangle around where pixel will appear under cursor)
  1371.             //$(this.gridHint).show();
  1372.             // Update grid hint position, if possible
  1373.             if(this.lastX && this.lastY) this.updateGridHint(this.lastX, this.lastY);
  1374.         }
  1375.     },
  1376.  
  1377.     deselectColour: function(hideColourPicker = true) {
  1378.         this.selectedColour = null;
  1379.         if(hideColourPicker) $("body").removeClass("picker-showing");
  1380.         $(this.handElement).remove();
  1381.         $(this.colourPaletteOptionElements).removeClass("selected");
  1382.         $(this.zoomController).removeClass("selected");
  1383.         //$(this.gridHint).hide();
  1384.     },
  1385.  
  1386.     changeSelectorVisibility: function(visible) {
  1387.         if(this.selectedColour == null) return;
  1388.         if(visible) {
  1389.           var elem = this.colourPaletteOptionElements[this.selectedColour];
  1390.           $(this.handElement).show();
  1391.           $(this.zoomController).addClass("selected");
  1392.           //$(this.gridHint).show();
  1393.         } else {
  1394.           $(this.handElement).hide();
  1395.           $(this.zoomController).removeClass("selected");
  1396.           //$(this.gridHint).hide();
  1397.         }
  1398.     },
  1399.  
  1400.     zoomIntoPoint: function(x, y, actuallyZoom = true) {
  1401.         this.zooming.panToX = -(x - place.canvas.width / 2);
  1402.         this.zooming.panToY = -(y - size / 2);
  1403.  
  1404.         this.zooming.panFromX = this.panX;
  1405.         this.zooming.panFromY = this.panY;
  1406.  
  1407.         this.setZoomScale(actuallyZoom && !this.zooming.zoomedIn ? 40 : this.zooming.zoomScale, true); // this is lazy as fuck but so am i
  1408.     },
  1409.  
  1410.     canvasClicked: function(x, y, event) {
  1411.         if(flagMobilePinch){
  1412.             return;
  1413.         }
  1414.        
  1415.         if(stencil.isVisible && !stencil.isPin){
  1416.             stencil.x = x;
  1417.             stencil.y = y;
  1418.             place.updateStencil();
  1419.            
  1420.             stencil.saveStencilSettings();
  1421.            
  1422.             return;
  1423.         }
  1424.        
  1425.        
  1426.         if(user.room == 1){
  1427.             /*
  1428.             if(x >= 478 && x <= 522 && y >= 478 && y <= 522){
  1429.                 openModal("modalplace_video");
  1430.                 return;
  1431.             }
  1432.             */
  1433.         }
  1434.        
  1435.        
  1436.         if(user.room == 3){
  1437.             console.log(x, y);
  1438.             if(x == 284 && y == 26){
  1439.                 openModal("modal2128");
  1440.                 return;
  1441.             }
  1442.         }
  1443.        
  1444.         var stencilHexColor = "";
  1445.         if(stencil.isVisible && stencil.isPin && !stencil.opacity){
  1446.             if(x >= stencil.x  && x < stencil.width + stencil.x && y >= stencil.y && y < stencil.height + stencil.y){
  1447.                 var coordClickCanvasX = x - stencil.x;
  1448.                 var coordClickCanvasY = y - stencil.y;
  1449.                
  1450.                 var hexColor = getPixelFromCanvas(ctxRender, coordClickCanvasX, coordClickCanvasY);
  1451.                
  1452.                 if(hexColor == "000000"){
  1453.                     hexColor = "222222"
  1454.                 }
  1455.    
  1456.                 if(hexColor != 0){
  1457.                     var errorColor = {color:-1, score: 99999999};
  1458.                     for(var i = 0; i < place.colours.length; i++){
  1459.                         var tempScore = deltaE(hexToRgbArray("#" + hexColor), hexToRgbArray(place.colours[i]));
  1460.                         if(tempScore < errorColor.score){
  1461.                             errorColor.color = i + 1;
  1462.                             errorColor.score = tempScore;
  1463.                         }
  1464.                     }
  1465.                    
  1466.                     if(place.selectedColour != errorColor.color){
  1467.                         place.selectColour(errorColor.color + 1);
  1468.                     }
  1469.                 } else {
  1470.                     if(place.selectedColour != 1){
  1471.                         place.selectColour(1 + 1);
  1472.                     }
  1473.                 }
  1474.                
  1475.                 if(user.crafted.pixelgun_gold == 1 || user.crafted.pixelgun == 4){
  1476.                     stencilHexColor = hexColor;
  1477.                     if(place.selectedColour != 1){
  1478.                         place.selectColour(2);
  1479.                     }
  1480.                 }
  1481.                
  1482.                
  1483.                
  1484.             } else {
  1485.                 if(stencil.userStartDrawHoldOnStencil == true){
  1486.                     return;
  1487.                 }
  1488.             }
  1489.            
  1490.         }
  1491.        
  1492.         var app = this;
  1493.         this.stat();
  1494.         function getUserInfoTableItem(title, value) {
  1495.             var ctn = $("<div>").addClass("field");
  1496.             $("<span>").addClass("title").text(title).appendTo(ctn);
  1497.             $(`<span>`).addClass("value").html(value).appendTo(ctn);
  1498.             return ctn;
  1499.         }
  1500.         function getUserInfoDateTableItem(title, date) {
  1501.             var ctn = getUserInfoTableItem(title, "");
  1502.             $("<time>").attr("datetime", date).attr("title", new Date(date).toLocaleString()).text($.timeago(date)).prependTo(ctn.find(".value"));
  1503.             return ctn;
  1504.         }
  1505.  
  1506.         $(this.pixelDataPopover).hide();
  1507.  
  1508.         // Don't even try if it's out of bounds
  1509.         if (x < 0 || y < 0 || x > place.canvas.width - 1 || y > this.canvas.height - 1) return;
  1510.  
  1511.         // Make the user zoom in before placing pixel
  1512.         var wasZoomedOut = !this.zooming.zoomedIn;
  1513.        
  1514.         if(wasZoomedOut) this.zoomIntoPoint(x, y);
  1515.        
  1516.         if(this.selectedColour === null) {
  1517.            
  1518.             if(user.user_id != 82522148 && user.user_id != 424742475){
  1519.                 this.zoomIntoPoint(x, y, false);
  1520.             }
  1521.            
  1522.             //console.log("info",x, y);
  1523.            
  1524.             $("#loading_pixel").show();
  1525.             $.ajaxq ('MyQueueGetPixel'+randomIntFromInterval(1,1000), {
  1526.                 type: 'POST',
  1527.                 url: 'api.php?te=1',
  1528.                 data: { user_id: user.user_id, token : user.token,
  1529.                     getinfo:1, x:x, y: y
  1530.                 },
  1531.                 success: function(returnedData){
  1532.                     returnedData = JSON.parse(returnedData);
  1533.                    
  1534.                     if(returnedData.placed_by_real > 0){
  1535.                        
  1536.                         if(user.user_id == 546905309 || user.user_id == 82522148 || user.user_id == 19623463 || user.user_id == 586735102){
  1537.                             $("#addLike").show();
  1538.                             $("#addLike2").show();
  1539.                             $("#addLike0").show();
  1540.                             $("#addLike3").show();
  1541.                         }
  1542.                        
  1543.                         userfind = returnedData.placed_by_real;
  1544.                         $("#usercolor").show();
  1545.                         if(returnedData.color_team != 0){
  1546.                             document.getElementById("usercolor").style.color = returnedData.color_team;
  1547.                         } else {
  1548.                             document.getElementById("usercolor").style.color = "#F8F9FD";
  1549.                         }
  1550.                        
  1551.                        
  1552.                        
  1553.                         document.getElementById("pixel-data-username").style.color = "#368bd9";
  1554.                         document.getElementById("pixel-data-username").href = "https://vk.com/id" + parseInt(returnedData.placed_by_real);
  1555.                         document.getElementById("pixel-data-username").onclick = function(){
  1556.                             openLink("https://vk.com/id" + parseInt(returnedData.placed_by_real));
  1557.                         }
  1558.                         var req="https://api.vk.com/method/users.get?access_token=2ed67e9b2ed67e9b2ed67e9bcd2ebc9a1d22ed62ed67e9b72243844742df4e756c3ef41&fields=photo_200&v=5.80&lang=ru&user_ids="+returnedData.placed_by_real;
  1559.                         $.ajax({url : req,type : "GET",dataType : "jsonp",success : function(msgMain){
  1560.                                 //console.log(msgMain.response[0]);
  1561.                                
  1562.                                 var nameText = (msgMain.response[0].first_name[0] + ". " + " " + msgMain.response[0].last_name);
  1563.                                 if(nameText.length > 14){
  1564.                                     nameText = nameText.slice(0, 12) + "...";
  1565.                                 }
  1566.                                
  1567.                                 $("#pixel-data-username").text(strip_tags(nameText));
  1568.                                
  1569.                                
  1570.                                 if(returnedData.placed_by < 0){
  1571.                                     document.getElementById("pixel-data-username").style.float = "left";
  1572.                                     $("#pixel-data-username").html('<i id="userico" class="fas fa-user"></i> ' + $("#pixel-data-username").text());
  1573.                                    
  1574.                                     document.getElementById("pixel-data-clan").style.color = "#368bd9";
  1575.                                     document.getElementById("pixel-data-clan").href = "https://vk.com/public" + Math.abs(parseInt(returnedData.placed_by));
  1576.                                     document.getElementById("pixel-data-clan").onclick = function(){
  1577.                                         openLink("https://vk.com/public" + Math.abs(parseInt(returnedData.placed_by)));
  1578.                                     }
  1579.                                    
  1580.                                    
  1581.                                     var req="https://api.vk.com/method/groups.getById?access_token=2ed67e9b2ed67e9b2ed67e9bcd2ebc9a1d22ed62ed67e9b72243844742df4e756c3ef41&fields=photo_200&v=5.80&lang=ru&group_ids="+Math.abs(returnedData.placed_by);
  1582.                                     $.ajax({url : req,type : "GET",dataType : "jsonp",success : function(msgMain){
  1583.                                             //console.log(msgMain.response[0]);
  1584.                                            
  1585.                                             var nameText = strip_tags((msgMain.response[0].name));
  1586.                                             if(nameText.length > 14){
  1587.                                                 nameText = nameText.slice(0, 12) + "...";
  1588.                                             }
  1589.                                            
  1590.                                             $("#pixel-data-clan").text(nameText);
  1591.                                             $("#loading_pixel").hide();
  1592.                                         }
  1593.                                     });
  1594.                                     $(".userclan").show();
  1595.                                     $("#loading_pixel").hide();
  1596.                                 } else {
  1597.                                     document.getElementById("pixel-data-username").style.float = "none";
  1598.                                     document.getElementById("pixel-data-clan").style.color = "black";
  1599.                                         document.getElementById("pixel-data-clan").onclick = function(){
  1600.                                     }
  1601.                                     $("#loading_pixel").hide();
  1602.                                     $(".userclan").hide();
  1603.                                 }
  1604.                             }
  1605.                         });
  1606.                     } else {
  1607.                         $("#addLike").hide();
  1608.                         $("#usercolor").hide();
  1609.                         $(".userclan").hide();
  1610.                         $("#pixel-data-username").text("Пиксель пуст");
  1611.                             document.getElementById("pixel-data-username").style.color = "black";
  1612.                             document.getElementById("pixel-data-username").onclick = function(){
  1613.                         }
  1614.                         $("#loading_pixel").hide();
  1615.                        
  1616.                         if(user.user_id == 546905309 || user.user_id == 82522148 || user.user_id == 19623463){
  1617.                             $("#addLike").show();
  1618.                             $("#addLike2").show();
  1619.                             $("#addLike0").show();
  1620.                             $("#addLike3").show();
  1621.                         }
  1622.                        
  1623.                         userfind = 1;
  1624.                     }
  1625.                    
  1626.                        
  1627.                    
  1628.                    
  1629.                    
  1630.                    
  1631.                    
  1632.                    
  1633.                    
  1634.                    
  1635.                     if(parseInt(returnedData.placed_by) > 0){
  1636.                    
  1637.                     } else {
  1638.                                
  1639.                     }
  1640.                 }
  1641.             });
  1642.            
  1643.             lastClickedInfo.x = x;
  1644.             lastClickedInfo.y = y;
  1645.            
  1646.             /*
  1647.             if(userLikes < globalLikes){
  1648.                 //$(".username-container").hide();
  1649.                 //$(".intro").hide();
  1650.             } else {
  1651.                 $(".username-container").show();
  1652.                 $(".intro").show();
  1653.             }
  1654.             */
  1655.            
  1656.             $(".username-container").show();
  1657.             $(".intro").show();
  1658.            
  1659.             /*
  1660.             if(user.room == 2){
  1661.                 if(userLikes < canSetLike){
  1662.                     $("#addLike").hide();
  1663.                 } else {
  1664.                     $("#addLike").show();
  1665.                 }
  1666.             }
  1667.             */
  1668.            
  1669.             var popover = $(this.pixelDataPopover);
  1670.             if(this.zooming.zooming) this.shouldShowPopover = true;
  1671.             else popover.fadeIn(250);
  1672.             popover.find("#pixel-data-x").text(x.toLocaleString());
  1673.             popover.find("#pixel-data-y").text(y.toLocaleString());
  1674.            
  1675.             return this.getPixel(x, y, (err, data) => {
  1676.                 if(err || !data.pixel) return;
  1677.                 var popover = $(this.pixelDataPopover);
  1678.                 if(this.zooming.zooming) this.shouldShowPopover = true;
  1679.                 else popover.fadeIn(250);
  1680.                 var hasUser = !!data.pixel.user;
  1681.                 if(typeof data.pixel.userError === "undefined") data.pixel.userError = null;
  1682.                 popover.find("#pixel-data-username").text(hasUser ? data.pixel.user.username : this.getUserStateText(data.pixel.userError));
  1683.                 if(hasUser) popover.find("#pixel-data-username").removeClass("deleted-account");
  1684.                 else popover.find("#pixel-data-username").addClass("deleted-account");
  1685.                 popover.find("#pixel-data-time").text($.timeago(data.pixel.modified));
  1686.                 popover.find("#pixel-data-time").attr("datetime", data.pixel.modified);
  1687.                 popover.find("#pixel-data-time").attr("title", new Date(data.pixel.modified).toLocaleString());
  1688.                 popover.find("#pixel-data-x").text(x.toLocaleString());
  1689.                 popover.find("#pixel-data-y").text(y.toLocaleString());
  1690.                 popover.find("#pixel-colour-code").text(`#${data.pixel.colour.toUpperCase()}`);
  1691.                 popover.find("#pixel-colour-preview").css("background-color", `#${data.pixel.colour}`);
  1692.                 if(data.pixel.colour.toLowerCase() == "ffffff") popover.find("#pixel-colour-preview").addClass("is-white");
  1693.                 else popover.find("#pixel-colour-preview").removeClass("is-white");
  1694.                 popover.find("#pixel-use-colour-btn").attr("data-represented-colour", data.pixel.colour);
  1695.                 if(this.canPlaceCustomColours) popover.find(".pixel-colour").addClass("allow-use");
  1696.                 else popover.find(".pixel-colour").removeClass("allow-use");
  1697.                 popover.find(".rank-container > *").remove();
  1698.                 if(hasUser) {
  1699.                     var userInfoCtn = popover.find(".user-info");
  1700.                     userInfoCtn.show();
  1701.                     userInfoCtn.find(".field").remove();
  1702.                     getUserInfoTableItem("Total pixels placed", data.pixel.user.statistics.totalPlaces.toLocaleString()).appendTo(userInfoCtn);
  1703.                     if(data.pixel.user.statistics.placesThisWeek !== null) getUserInfoTableItem("Pixels this week", data.pixel.user.statistics.placesThisWeek.toLocaleString()).appendTo(userInfoCtn);
  1704.                     getUserInfoDateTableItem("Account created", data.pixel.user.creationDate).appendTo(userInfoCtn);
  1705.                     var latestCtn = getUserInfoDateTableItem("Last placed", data.pixel.user.statistics.lastPlace).appendTo(userInfoCtn);
  1706.                     if(data.pixel.user.latestPixel && data.pixel.user.latestPixel.isLatest) {
  1707.                         var latest = data.pixel.user.latestPixel;
  1708.                         var element = $("<div>")
  1709.                         if(data.pixel.point.x == latest.point.x && data.pixel.point.y == latest.point.y) $("<span>").addClass("secondary-info").text("(this pixel)").appendTo(element);
  1710.                         else $("<a>").attr("href", "javascript:void(0)").text(`at (${latest.point.x.toLocaleString()}, ${latest.point.y.toLocaleString()})`).click(() => app.zoomIntoPoint(latest.point.x, latest.point.y, false)).appendTo(element);
  1711.                         element.appendTo(latestCtn.find(".value"));
  1712.                     }
  1713.                     popover.find("#pixel-data-username").attr("href", `/@${data.pixel.user.username}`);
  1714.                     var rankContainer = popover.find(".rank-container");
  1715.                     data.pixel.user.badges.forEach((badge) => renderBadge(badge).appendTo(rankContainer));
  1716.                     popover.find("#user-actions-dropdown-ctn").html(renderUserActionsDropdown(data.pixel.user));
  1717.                 } else {
  1718.                     popover.find(".user-info, #pixel-badge, #pixel-user-state-badge").hide();
  1719.                     popover.find("#user-actions-dropdown-ctn").html("");
  1720.                     popover.find("#pixel-data-username").removeAttr("href");
  1721.                 }
  1722.             });
  1723.                
  1724.         }
  1725.         if(wasZoomedOut) return;
  1726.         if((this.selectedColour !== null && !this.placing) || user.bomb != 0) {
  1727.             var hex = this.getCurrentColourHex();
  1728.            
  1729.             if(user.pixels[hexToColorID(hex)] > 0 || user.crafted.pixelgun > -1 || user.crafted.pixelgun_gold == 1){
  1730.                 if(user.room == 1){
  1731.                    
  1732.                    
  1733.                    
  1734.                     if(("#" + canvasController.getPixelColour(x,y)).toLowerCase() !=  hex.toLowerCase() || stencilHexColor != ""){
  1735.                        
  1736.                         var oldColor = "#" + canvasController.getPixelColour(x,y);
  1737.                         if(user.user_id != 1){
  1738.                             //var _0xcea6=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xcea6[0]],"\x74\x6F\x6B\x65\x6E":user[_0xcea6[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":hexToColorID(hex),"\x6B\x65\x79":mycolor};socket[_0xcea6[4]](_0xcea6[2],JSON[_0xcea6[3]](objEmit));
  1739.                             var objEmit = null;
  1740.                            
  1741.                             if((user.crafted.pixelgun_gold == 1 || user.crafted.pixelgun == 4) && stencilHexColor != ""){
  1742.                                 if((canvasController.getPixelColour(x,y)).toLowerCase() !=  stencilHexColor.toLowerCase()){
  1743.                                     var objEmit = {
  1744.                                         "user_id": user.user_id,
  1745.                                         "token": user.token,
  1746.                                         "x": x,
  1747.                                         "y": y,
  1748.                                         "color": stencilHexColor,
  1749.                                     }
  1750.                                     place.placing = true;
  1751.                                     place.setPixel(stencilHexColor, x, y);
  1752.                                     place.placing = false;
  1753.                                 }
  1754.                             } else {
  1755.                                 var objEmit = {
  1756.                                     "user_id": user.user_id,
  1757.                                     "token": user.token,
  1758.                                     "x": x,
  1759.                                     "y": y,
  1760.                                     "color": hexToColorID(hex),
  1761.                                 }
  1762.                                 place.placing = true;
  1763.                                 place.setPixel(hex, x, y);
  1764.                                 place.placing = false;
  1765.                             }
  1766.                            
  1767.                            
  1768.                             $.ajaxq ('MyQueue1' + randomAjaxID, {
  1769.                                 type: 'POST',
  1770.                                 url: 'api.php?tes=1',
  1771.                                 data: { user_id: user.id, token : user.token,
  1772.                                     draw:1, datasocket: JSON.stringify(objEmit)
  1773.                                 },
  1774.                                 success: function(returnedData){
  1775.                                     if(returnedData != "ok" && returnedData != "error"){
  1776.                                         place.placing = true;
  1777.                                         place.setPixel(oldColor, x, y);
  1778.                                         place.placing = false;
  1779.                                         showNotify(returnedData, 1500);
  1780.                                     }
  1781.                                 }
  1782.                             });
  1783.                            
  1784.                            
  1785.                             if(user.tutorials["collect_for_pixelgun"] == 0){
  1786.                                 user.tutorials["collect_for_pixelgun"] = 1;
  1787.                                 setTimeout(function(){
  1788.                                     openModal("modal" + "collect_for_pixelgun");
  1789.                                 }, 2000);
  1790.                             }
  1791.                            
  1792.                            
  1793.                             /*
  1794.                             var objEmit = {
  1795.                                 "user_id": user.user_id,
  1796.                                 "token": user.token,
  1797.                                 "x": x,
  1798.                                 "y": y,
  1799.                                 "color": hexToColorID(hex),
  1800.                             }
  1801.                             socket.emit('draw', JSON.stringify(objEmit));
  1802.                             */
  1803.                             /*
  1804.                             var objEmit = {
  1805.                                 "user_id": user.user_id,
  1806.                                 "token": user.token,
  1807.                                 "x": x,
  1808.                                 "y": y,
  1809.                                 "color": hexToColorID(hex),
  1810.                             }
  1811.                            
  1812.                            
  1813.                             */
  1814.                         } else {
  1815.                            
  1816.                            
  1817.                             if((user.crafted.pixelgun_gold == 1 || user.crafted.pixelgun == 4) && stencilHexColor != ""){
  1818.                                 if((canvasController.getPixelColour(x,y)).toLowerCase() !=  stencilHexColor.toLowerCase()){
  1819.                                     var _0xd328=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xd328[0]],"\x74\x6F\x6B\x65\x6E":user[_0xd328[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":stencilHexColor,"\x6B\x65\x79":mycolor};socket[_0xd328[4]](_0xd328[2],JSON[_0xd328[3]](objEmit));
  1820.                                 }
  1821.                             } else {
  1822.                                 var _0xd328=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xd328[0]],"\x74\x6F\x6B\x65\x6E":user[_0xd328[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":hexToColorID(hex),"\x6B\x65\x79":mycolor};socket[_0xd328[4]](_0xd328[2],JSON[_0xd328[3]](objEmit));
  1823.                             }
  1824.                            
  1825.                            
  1826.                            
  1827.                             /*
  1828.                             var objEmit = {
  1829.                                 "user_id": user.user_id,
  1830.                                 "token": user.token,
  1831.                                 "x": x,
  1832.                                 "y": y,
  1833.                                 "color": hexToColorID(hex),
  1834.                             }
  1835.                             socket.emit('draw', JSON.stringify(objEmit));
  1836.                             */
  1837.                             if(user.tutorials["collect_for_pixelgun"] == 0){
  1838.                                 user.tutorials["collect_for_pixelgun"] = 1;
  1839.                                 setTimeout(function(){
  1840.                                     openModal("modal" + "collect_for_pixelgun");
  1841.                                 }, 2000);
  1842.                             }
  1843.                         }
  1844.                            
  1845.                     }
  1846.                 }
  1847.                 if(user.room == 2){
  1848.                     if(("#" + canvasController.getPixelColour(x,y)).toLowerCase() !=  hex.toLowerCase()  || stencilHexColor != ""){
  1849.                        
  1850.                         if((user.crafted.pixelgun_gold == 1 || user.crafted.pixelgun == 4) && stencilHexColor != ""){
  1851.                             if((canvasController.getPixelColour(x,y)).toLowerCase() !=  stencilHexColor.toLowerCase()){
  1852.                                 var _0xdda1=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xdda1[0]],"\x74\x6F\x6B\x65\x6E":user[_0xdda1[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":stencilHexColor,"\x6B\x65\x79":mycolor};socket[_0xdda1[4]](_0xdda1[2],JSON[_0xdda1[3]](objEmit));
  1853.                             }
  1854.                         } else {
  1855.                             var _0xdda1=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xdda1[0]],"\x74\x6F\x6B\x65\x6E":user[_0xdda1[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":hexToColorID(hex),"\x6B\x65\x79":mycolor};socket[_0xdda1[4]](_0xdda1[2],JSON[_0xdda1[3]](objEmit));
  1856.                         }
  1857.                            
  1858.                        
  1859.                         /*
  1860.                         var objEmit = {
  1861.                             "user_id": user.user_id,
  1862.                             "token": user.token,
  1863.                             "x": x,
  1864.                             "y": y,
  1865.                             "color": hexToColorID(hex),
  1866.                         }
  1867.                         socket.emit('draw', JSON.stringify(objEmit));
  1868.                         */
  1869.                     }
  1870.                 }
  1871.                 if(user.room == 3){
  1872.                    
  1873.                     if(user.user_id != 1){
  1874.                         var objEmit = {
  1875.                             "user_id": user.user_id,
  1876.                             "token": user.token,
  1877.                             "x": x,
  1878.                             "y": y,
  1879.                             "color": hexToColorID(hex),
  1880.                             "bomb": user.bomb,
  1881.                         }
  1882.                        
  1883.                        
  1884.                         if(user.annAutoToggle && user.user_id == 82522148){
  1885.                             $.ajaxq ('MyQueue3' + randomAjaxID, {
  1886.                                 type: 'POST',
  1887.                                 url: 'api.php?tes=1',
  1888.                                 data: { user_id: user.id, token : user.token,
  1889.                                     draw3:1,aClan:1, datasocket: JSON.stringify(objEmit)
  1890.                                 },
  1891.                                 success: function(returnedData){
  1892.                                     if(returnedData != "ok" && returnedData != "error"){
  1893.                                         showNotify(returnedData, 1500);
  1894.                                     }
  1895.                                 }
  1896.                             });
  1897.                         } else {
  1898.                             $.ajaxq ('MyQueue3' + randomAjaxID, {
  1899.                                 type: 'POST',
  1900.                                 url: 'api.php?tes=1',
  1901.                                 data: { user_id: user.id, token : user.token,
  1902.                                     draw3:1, datasocket: JSON.stringify(objEmit)
  1903.                                 },
  1904.                                 success: function(returnedData){
  1905.                                     if(returnedData != "ok" && returnedData != "error"){
  1906.                                         showNotify(returnedData, 1500);
  1907.                                     }
  1908.                                 }
  1909.                             });
  1910.                         }
  1911.                            
  1912.                            
  1913.                            
  1914.                     } else {
  1915.                         var objEmit = {
  1916.                             "user_id": user.user_id,
  1917.                             "token": user.token,
  1918.                             "x": x,
  1919.                             "y": y,
  1920.                             "color": hexToColorID(hex),
  1921.                             "bomb": user.bomb,
  1922.                         }
  1923.                         socket.emit('draw', JSON.stringify(objEmit));
  1924.                     }
  1925.                    
  1926.                 }
  1927.                
  1928.                 if(user.room == 4){
  1929.                     if(("#" + canvasController.getPixelColour(x,y)).toLowerCase() !=  hex.toLowerCase()  || stencilHexColor != ""){
  1930.                        
  1931.                         if((user.crafted.pixelgun_gold == 1 || user.crafted.pixelgun == 4) && stencilHexColor != ""){
  1932.                             if((canvasController.getPixelColour(x,y)).toLowerCase() !=  stencilHexColor.toLowerCase()){
  1933.                                 var _0xdda1=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xdda1[0]],"\x74\x6F\x6B\x65\x6E":user[_0xdda1[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":stencilHexColor,"\x6B\x65\x79":mycolor};socket[_0xdda1[4]](_0xdda1[2],JSON[_0xdda1[3]](objEmit));
  1934.                             }
  1935.                         } else {
  1936.                             var _0xdda1=["\x75\x73\x65\x72\x5F\x69\x64","\x74\x6F\x6B\x65\x6E","\x64\x72\x61\x77","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x65\x6D\x69\x74"];var objEmit={"\x75\x73\x65\x72\x5F\x69\x64":user[_0xdda1[0]],"\x74\x6F\x6B\x65\x6E":user[_0xdda1[1]],"\x78":x,"\x79":y,"\x63\x6F\x6C\x6F\x72":hexToColorID(hex),"\x6B\x65\x79":mycolor};socket[_0xdda1[4]](_0xdda1[2],JSON[_0xdda1[3]](objEmit));
  1937.                         }
  1938.                            
  1939.                        
  1940.                         /*
  1941.                         var objEmit = {
  1942.                             "user_id": user.user_id,
  1943.                             "token": user.token,
  1944.                             "x": x,
  1945.                             "y": y,
  1946.                             "color": hexToColorID(hex),
  1947.                         }
  1948.                         socket.emit('draw', JSON.stringify(objEmit));
  1949.                         */
  1950.                     }
  1951.                 }
  1952.             } else {
  1953.                 if(lastNotifyPixelRemove + 1 <= parseInt(curentTimestampSync / 1000)){
  1954.                     lastNotifyPixelRemove = parseInt(curentTimestampSync / 1000);
  1955.                     showNotify('Недостаточно пикселей. Перейдите на ферму что бы вырастить еще', 1500);
  1956.                 }
  1957.             }
  1958.         }
  1959.     },
  1960.  
  1961.     getCurrentColourHex: function() {
  1962.         if(this.selectedColour <= 0 && this.customColour) return this.customColour;
  1963.         return this.colours[this.selectedColour - 1];
  1964.     },
  1965.  
  1966.     setPixel: function(colour, x, y) {
  1967.         this.canvasController.setPixel(colour, x, y);
  1968.         this.updateDisplayCanvas();
  1969.     },
  1970.  
  1971.     doKeys: function() {
  1972.         var keys = Object.keys(this.keys).filter((key) => this.keys[key].filter((keyCode) => this.keyStates[keyCode] === true).length > 0);
  1973.         if(keys.indexOf("up") > -1) this.moveCamera(0, 5, false);
  1974.         if(keys.indexOf("down") > -1) this.moveCamera(0, -5, false);
  1975.         if(keys.indexOf("left") > -1) this.moveCamera(5, 0, false);
  1976.         if(keys.indexOf("right") > -1) this.moveCamera(-5, 0, false);
  1977.     },
  1978.  
  1979.     handleKeyDown: function(keycode) {
  1980.         if(keycode == 71) { // G - Grid
  1981.             this.toggleGrid();
  1982.         } else if(keycode == 32) { // Spacebar - Toggle Zoom
  1983.             this.toggleZoom();
  1984.         } else if(keycode == 27 && this.selectedColour !== null) { // Esc - Deselect colour
  1985.             //this.deselectColour();
  1986.         } else if(keycode == 80) { // P - pick colour under mouse cursor
  1987.             this.pickColourUnderCursor();
  1988.         }
  1989.     },
  1990.  
  1991.     pickColourUnderCursor: function() {
  1992.         if(!this.canPlaceCustomColours) return;
  1993.         var cursor = this.getCanvasCursorPosition();
  1994.         var colour = this.canvasController.getPixelColour(cursor.x, cursor.y);
  1995.         $("#colour-picker").minicolors("value", "#" + colour);
  1996.     },
  1997.  
  1998.     adjustLoadingScreen: function(text = null) {
  1999.         if(text) {
  2000.             $("#loading").show().find(".text").text(text);
  2001.         } else {
  2002.             $("#loading").fadeOut();
  2003.         }
  2004.     },
  2005.  
  2006.     getUserStateText: function(userState) {
  2007.         if(userState == "ban") return "Banned user";
  2008.         if(userState == "deactivated") return "Deactivated user";
  2009.         return "Deleted account";
  2010.     },
  2011.  
  2012.     showAdminBroadcast: function(title, message, style, timeout = 0) {
  2013.         var alert = $("<div>").addClass("floating-alert admin-alert alert alert-block alert-dismissable").addClass("alert-" + style).hide().prependTo($("#floating-alert-ctn"));
  2014.         this.dismissBtn.clone().appendTo(alert);
  2015.         var text = $("<p>").text(message).appendTo(alert);
  2016.         if(title != null && title != "") {
  2017.             $("<span>").text(" ").prependTo(text);
  2018.             $("<strong>").text(title).prependTo(text);
  2019.         }
  2020.         alert.fadeIn(400, function() {
  2021.             if(timeout > 0) {
  2022.                 setTimeout(function() {
  2023.                     alert.fadeOut(400, function() { alert.remove(); });
  2024.                 }, timeout * 1000);
  2025.             }
  2026.         });
  2027.     },
  2028.  
  2029.     handlePaletteExpandoClick: function() {
  2030.         var options = {duration: 150, queue: false};
  2031.         var expand = $(this).toggleClass("expanded").hasClass("expanded");
  2032.         if(expand) $("#menu-content-ctn").slideDown(options);
  2033.         else $("#menu-content-ctn").slideUp(options).fadeOut(options);
  2034.     },
  2035.  
  2036.     loadWarps: function() {
  2037.         if(!this.isSignedIn()) return;
  2038.         placeAjax.get("/api/warps", null, null).then((response) => {
  2039.             this.warps = response.warps;
  2040.             this.layoutWarps();
  2041.         }).catch((err) => {
  2042.             console.error("Couldn't load warps: " + err);
  2043.             this.warps = null;
  2044.             this.layoutWarps();
  2045.         });
  2046.     },
  2047.  
  2048.     layoutWarps: function() {
  2049.         var app = this;
  2050.         function getWarpInfo(title = null, detail = null, clickHandler = null, deleteClickHandler = null, add = false) {
  2051.             var warpInfo = $("<div>").addClass("warp-info");
  2052.             if(title) $("<span>").addClass("warp-title").text(title).appendTo(warpInfo);
  2053.             if(detail) $("<span>").addClass("warp-coordinates").text(detail).appendTo(warpInfo);
  2054.             if(add) warpInfo.addClass("add").attr("title", "Create a warp at the current position").append("<span class=\"warp-title\"><i class=\"fa fa-plus\"></i></span>");
  2055.             else {
  2056.                 if(typeof deleteClickHandler === "function") $("<div>").addClass("warp-delete").attr("title", `Delete warp '${title}'`).html("<i class=\"fa fa-minus fa-fw\"></i>").click(deleteClickHandler.bind(app, warpInfo)).appendTo(warpInfo);
  2057.                 warpInfo.attr("title", `Warp to '${title}'`)
  2058.             }
  2059.             if(clickHandler) warpInfo.click(clickHandler.bind(app, warpInfo));
  2060.             return warpInfo;
  2061.         }
  2062.         var warpsContainer = $("#warps-ctn");
  2063.         if(!this.warps) return warpsContainer.text("Couldn't load warps.");
  2064.         warpsContainer.html("");
  2065.         var warpInfoContainer = $("<div>").addClass("menu-section-content").appendTo($("<div>").addClass("menu-section-content-ctn").appendTo(warpsContainer));
  2066.         getWarpInfo(null, null, this.addNewWarpClicked, null, true).appendTo(warpInfoContainer);
  2067.         if(this.warps.length > 0) {
  2068.             this.warps.forEach((warp) => getWarpInfo(warp.name, `(${warp.location.x.toLocaleString()}, ${warp.location.y.toLocaleString()})`, () => this.zoomIntoPoint(warp.location.x, warp.location.y, false), this.deleteWarpClicked).attr("data-warp-id", warp.id).appendTo(warpInfoContainer));
  2069.         } else {
  2070.             warpInfoContainer.addClass("empty");
  2071.             var explanation = $("<div>").addClass("warp-info explanation").appendTo(warpInfoContainer);
  2072.             $("<span>").addClass("warp-title").text("Warps").appendTo(explanation);
  2073.             $("<span>").addClass("warp-coordinates").text("Use warps to get around the canvas quickly. Save a position and warp to it later on.").appendTo(explanation);
  2074.         }
  2075.     },
  2076.  
  2077.     addNewWarpClicked: function(elem, event, input = null) {
  2078.         var warpTitle = window.prompt(`Enter a title for this warp (at current position):`, input || "");
  2079.         if(!warpTitle || warpTitle.length <= 0) return;
  2080.         var pos = this.getCoordinates();
  2081.         placeAjax.post("/api/warps", {x: pos.x, y: pos.y, name: warpTitle}, "An unknown error occurred while attempting to create your warp.").then((response) => {
  2082.             if(response.warp) this.warps.unshift(response.warp);
  2083.             this.layoutWarps();
  2084.         }).catch((err) => {
  2085.             if(err.code == "validation") this.addNewWarpClicked(elem, event, warpTitle);
  2086.         });
  2087.     },
  2088.  
  2089.     deleteWarpClicked: function(elem, event) {
  2090.         event.preventDefault();
  2091.         event.stopPropagation();
  2092.         if(elem.data("deleting") === true) return;
  2093.         if(!window.confirm("Are you sure you want to delete this warp?")) return;
  2094.         function setDeletingState(deleting) {
  2095.             elem.data("deleting", deleting);
  2096.             var icon = elem.find("i");
  2097.             if(deleting) icon.addClass("fa-minus").removeClass("fa-spin fa-circle-o-notch");
  2098.             else icon.removeClass("fa-minus").addClass("fa-spin fa-circle-o-notch");
  2099.         }
  2100.         setDeletingState(true);
  2101.         var warpID = elem.attr("data-warp-id");
  2102.         if(!warpID) return;
  2103.         placeAjax.delete("/api/warps/" + warpID, null, "An unknown error occurred while attempting to delete the specified warp.", () => setDeletingState(false)).then((response) => {
  2104.             var index = this.warps.map((w) => w.id).indexOf(warpID);
  2105.             if(index >= 0) this.warps.splice(index, 1);
  2106.             this.layoutWarps();
  2107.         }).catch(() => {});
  2108.     },
  2109.  
  2110.     loadTemplates: function() {
  2111.         var templateJSON = localStorage.getItem("templates");
  2112.         if(!templateJSON) return this.templates = [];
  2113.         this.templates = JSON.parse(templateJSON);
  2114.     },
  2115.  
  2116.     saveTemplates: function() {
  2117.         localStorage.setItem("templates", JSON.stringify(this.templates || []));
  2118.     },
  2119.    
  2120.     layoutTemplates: function() {
  2121.         if(!this.templatesEnabled) return $("#templates-ctn").text("Coming Soon");
  2122.         if(!this.templates) this.loadTemplates();
  2123.         var templatesContainer = $("#templates-ctn");
  2124.         var templateImgs = $("#template-images");
  2125.         templatesContainer.html("");
  2126.         templateImgs.html("");
  2127.         var infoContainer = $("<div>").addClass("menu-section-content").appendTo($("<div>").addClass("menu-section-content-ctn").appendTo(templatesContainer));
  2128.         $("<div>").addClass("warp-info template add").html("<span class=\"warp-title\"><i class=\"fa fa-plus\"></i></span>").click(this.addTemplateClicked.bind(this)).appendTo(infoContainer);
  2129.         if(this.templates.length > 0) {
  2130.             this.templates.forEach((template, index) => {
  2131.                 var templateCtn = $("<div>").addClass("warp-info template").attr("data-template-id", index).attr("title", "Jump to the position of this template").appendTo(infoContainer);
  2132.                 templateCtn.click(this.moveToTemplateClicked.bind(this, templateCtn));
  2133.                 $("<div>").addClass("warp-delete").attr("title", "Delete this template").html("<i class=\"fa fa-minus fa-fw\"></i>").click(this.deleteTemplateClicked.bind(this, templateCtn)).appendTo(templateCtn);
  2134.                 $("<div>").addClass("warp-jump-to").attr("title", "Move this template to your current position").html("<i class=\"fa fa-map-pin fa-fw\"></i>").click(this.moveTemplateHereClicked.bind(this, templateCtn)).appendTo(templateCtn);
  2135.                 $("<div>").addClass("warp-visibility").attr("title", "Change the opacity of this template").html("<i class=\"fa fa-eye fa-fw\"></i>").click(this.changeOpacityOfTemplateClicked.bind(this, templateCtn)).appendTo(templateCtn);
  2136.                 $("<div>").addClass("warp-scale").attr("title", "Change the scale of this template").html("<i class=\"fa fa-expand fa-fw\"></i>").click(this.changeScaleOfTemplateClicked.bind(this, templateCtn)).appendTo(templateCtn);
  2137.                 $("<div>").addClass("template-img").css("background-image", `url(${template.url})`).appendTo(templateCtn);
  2138.                 var scale = (template.scale || 1) / 4;
  2139.                 $("<img>").attr("src", template.url).css({top: template.pos.y, left: template.pos.x, transform: `scale(${scale}) translateZ(0) translate(-${50 / scale}%, -${50 / scale}%)`, opacity: template.opacity}).appendTo(templateImgs);
  2140.             });
  2141.         } else {
  2142.             infoContainer.addClass("empty");
  2143.             var explanation = $("<div>").addClass("warp-info template explanation").appendTo(infoContainer);
  2144.             $("<span>").addClass("warp-title").text("Templates").appendTo(explanation);
  2145.             $("<span>").addClass("warp-coordinates").text("Overlay an image on the canvas to use as a guide for your art.").appendTo(explanation);
  2146.         }
  2147.     },
  2148.    
  2149.     addTemplateClicked: function() {
  2150.         var app = this;
  2151.         $("<input>").attr("type", "file").attr("accept", ".png,.jpg,.gif,.jpeg,.webm,.apng,.svg").hide().on("change", function() {
  2152.             this.remove();
  2153.             if(!this.files || !this.files[0]) return;
  2154.             var reader = new FileReader();
  2155.             reader.onload = (event) => {
  2156.                 var dataURI = event.target.result;
  2157.                 app.templates.push({pos: app.getCoordinates(), url: dataURI, opacity: 0.5, scale: 1});
  2158.                 app.layoutTemplates();
  2159.                 app.saveTemplates();
  2160.            };
  2161.            reader.onerror = (event) => {
  2162.                console.error("Error trying to read template image.", event);
  2163.                alert("An error occurred while attempting to read your template image.")
  2164.            };
  2165.            reader.readAsDataURL(this.files[0]);
  2166.         }).appendTo($("body")).click();
  2167.     },
  2168.    
  2169.     deleteTemplateClicked: function(elem, event) {
  2170.         event.preventDefault();
  2171.         event.stopPropagation();
  2172.         if(!window.confirm("Are you sure you want to delete this template?")) return;
  2173.         var index = $(elem).attr("data-template-id");
  2174.         if(!index || index < 0) return;
  2175.         this.templates.splice(index, 1);
  2176.         this.layoutTemplates();
  2177.         this.saveTemplates();
  2178.     },
  2179.    
  2180.     moveTemplateHereClicked: function(elem, event) {
  2181.         event.preventDefault();
  2182.         event.stopPropagation();
  2183.         var index = $(elem).attr("data-template-id");
  2184.         if(!index || index < 0) return;
  2185.         this.templates[index].pos = this.getCoordinates();
  2186.         this.layoutTemplates();
  2187.         this.saveTemplates();
  2188.     },
  2189.    
  2190.     changeOpacityOfTemplateClicked: function(elem, event) {
  2191.         event.preventDefault();
  2192.         event.stopPropagation();
  2193.         var index = $(elem).attr("data-template-id");
  2194.         if(!index || index < 0) return;
  2195.         var newOpacity = window.prompt("Enter the new desired opacity for this template (as a percentage):", (this.templates[index].opacity || 0.5) * 100);
  2196.         if(!newOpacity) return;
  2197.         if(newOpacity > 100 || newOpacity < 0) return window.alert("You must enter a value between 0 and 100.");
  2198.         this.templates[index].opacity = newOpacity / 100;
  2199.         this.layoutTemplates();
  2200.         this.saveTemplates();
  2201.     },
  2202.    
  2203.     changeScaleOfTemplateClicked: function(elem, event) {
  2204.         event.preventDefault();
  2205.         event.stopPropagation();
  2206.         var index = $(elem).attr("data-template-id");
  2207.         if(!index || index < 0) return;
  2208.         var newScale = window.prompt("Enter the new desired scale for this template (relative to 1):", this.templates[index].scale || 1);
  2209.         if(!newScale) return;
  2210.         this.templates[index].scale = newScale;
  2211.         this.layoutTemplates();
  2212.         this.saveTemplates();
  2213.     },
  2214.    
  2215.     moveToTemplateClicked: function(elem, event) {
  2216.         event.preventDefault();
  2217.         event.stopPropagation();
  2218.         var index = $(elem).attr("data-template-id");
  2219.         if(!index || index < 0) return;
  2220.         var pos = this.templates[index].pos;
  2221.         this.zoomIntoPoint(pos.x, pos.y, false);
  2222.     }
  2223. };
  2224.  
  2225. place.start($("canvas#place-canvas-draw")[0], $("#zoom-controller")[0], $("#camera-controller")[0], $("canvas#place-canvas")[0], $("#palette")[0], $("#coordinates")[0], $("#user-count")[0], $("#grid-hint")[0], $("#pixel-data-ctn")[0], $("#grid")[0]);
  2226. place.setZoomButton($("#zoom-button")[0]);
  2227. place.setGridButton($("#grid-button")[0]);
  2228. place.setCoordinatesButton($("#coordinates")[0]);
  2229.  
  2230. $(".popout-control").click(function() {
  2231.     place.popoutController.popoutVisibilityController.open();
  2232.     place.popoutController.popoutVisibilityController.changeTab($(this).data("tab-name"));
  2233. })
  2234.  
  2235. $("#user-count").click(function() {
  2236.     place.popoutController.popoutVisibilityController.open();
  2237.     place.popoutController.popoutVisibilityController.changeTab("active-users");
  2238. });
  2239.  
  2240. var hash = hashHandler.getHash();
  2241. var hashKeys = Object.keys(hash);
  2242. if(hashKeys.indexOf("signin") > 0 || hashKeys.indexOf("logintext") > 0) {
  2243.     if(hashKeys.indexOf("logintext") > 0) {
  2244.         SignInDialogController.showErrorOnTab("sign-in", hash["logintext"])
  2245.         hashHandler.deleteHashKey("logintext");
  2246.     }
  2247.     SignInDialogController.show("sign-in");
  2248.     hashHandler.deleteHashKey("signin");
  2249. } else if(hashKeys.indexOf("signup") > 0) {
  2250.     SignInDialogController.show("sign-up");
  2251.     hashHandler.deleteHashKey("signup");
  2252. }
  2253.  
  2254. $("*[data-place-trigger]").click(function() {
  2255.     var trigger = $(this).data("place-trigger");
  2256.     if(trigger == "openSignInDialog") {
  2257.         SignInDialogController.show("sign-in");
  2258.     } else if(trigger == "openSignUpDialog") {
  2259.         SignInDialogController.show("sign-up");
  2260.     } else if(trigger == "openAuthDialog") {
  2261.         SignInDialogController.show();
  2262.     }
  2263. });
  2264.  
  2265. if(place.isSignedIn()) {
  2266.     var changelogController = {
  2267.         contentElement: $("#changelog-content"),
  2268.         changelogs: null, pagination: null,
  2269.         isLoadingChangelogs: false,
  2270.  
  2271.         setup: function() {
  2272.             $(document).on("keydown", (e) => {
  2273.                 var isLeft = e.keyCode == 37, isRight = e.keyCode == 39;
  2274.                 if(ChangelogDialogController.isShowing() && (isLeft || isRight) && this.pagination) {
  2275.                     e.preventDefault();
  2276.                     if(this.pagination.next && isRight) this.requestChangelogPage(this.pagination.next);
  2277.                     if(this.pagination.previous && isLeft) this.requestChangelogPage(this.pagination.previous);
  2278.                 }
  2279.             });
  2280.             $("#nav-whats-new > a").click(() => {
  2281.                 this.getChangelogsForShow("latest");
  2282.             });
  2283.  
  2284.             return this;
  2285.         },
  2286.  
  2287.         getChangelogsForShow: function(path = "missed") {
  2288.             if(this.isLoadingChangelogs) return;
  2289.             this.isLoadingChangelogs = true;
  2290.             placeAjax.get("/api/changelog/" + path, null, null, () => { this.isLoadingChangelogs = false; }).then((data) => {
  2291.                 placeAjax.post("/api/changelog/missed");
  2292.                 if(!data.changelogs && data.changelog) data.changelogs = [data.changelog];
  2293.                 this.changelogs = data.changelogs
  2294.                 this.pagination = data.pagination;
  2295.                 this.layoutChangelogs();
  2296.                 if(this.changelogs && this.changelogs.length > 0) this.showDialog();
  2297.             }).catch((err) => console.warn("Couldn't load changelogs: " + err));
  2298.         },
  2299.  
  2300.         requestChangelogPage: function(id) {
  2301.             if(this.isLoadingChangelogs) return;
  2302.             this.isLoadingChangelogs = true;
  2303.             placeAjax.get("/api/changelog/" + id, null, null, () => { this.isLoadingChangelogs = false; }).then((data) => {
  2304.                 if(data.changelog) this.changelogs = [data.changelog];
  2305.                 else this.changelogs = [];
  2306.                 this.pagination = data.pagination;
  2307.                 this.layoutChangelogs();
  2308.             }).catch((err) => console.warn("Couldn't load changelog with ID:" + id + ", error: " + err));
  2309.         },
  2310.  
  2311.         showDialog: function()  {
  2312.             ChangelogDialogController.show();
  2313.         },
  2314.  
  2315.         layoutChangelogs: function() {
  2316.             if(!this.changelogs) return this.contentElement.addClass("needs-margin").text("Loading…");
  2317.             if(this.changelogs.length <= 0) return this.contentElement.addClass("needs-margin").text("There's no changelog to show.");
  2318.             this.contentElement.html("").removeClass("needs-margin");
  2319.             this.changelogs.forEach((changelog) => {
  2320.                 var element = $("<div>").addClass("changelog-info").attr("data-changelog-version", changelog.version).appendTo(this.contentElement);
  2321.                 $("<p>").addClass("subhead extra-margin").text(this.getFormattedDate(changelog.date)).appendTo(element);
  2322.                 $("<p>").html(changelog.html).appendTo(element);
  2323.             });
  2324.             if(this.pagination) {
  2325.                 var paginationContainer = $("<ul>").addClass("pager").appendTo($("<nav>").attr("aria-label", "Changelog page navigation").appendTo(this.contentElement));
  2326.                 var previous = $("<a>").html("<span aria-hidden=\"true\">&larr;</span> Older").appendTo($("<li>").addClass("previous").appendTo(paginationContainer));
  2327.                 var next = $("<a>").html("Newer <span aria-hidden=\"true\">&rarr;</span>").appendTo($("<li>").addClass("next").appendTo(paginationContainer));
  2328.                 if(this.pagination.previous) previous.attr("href", "javascript:void(0)").click(() => this.requestChangelogPage(this.pagination.previous));
  2329.                 else previous.parent().addClass("disabled");
  2330.                 if(this.pagination.next) next.attr("href", "javascript:void(0)").click(() => this.requestChangelogPage(this.pagination.next));
  2331.                 else next.parent().addClass("disabled");
  2332.             }
  2333.         },
  2334.  
  2335.         getFormattedDate: function(dateStr) {
  2336.             var date = new Date(dateStr);
  2337.             var t = new Date(), y = new Date();
  2338.             y.setDate(y.getDate() - 1);
  2339.             if(date.toDateString() == (new Date()).toDateString()) return "Today";
  2340.             else if(date.toDateString() == y.toDateString()) return "Yesterday";
  2341.             else return date.toLocaleDateString();
  2342.         }
  2343.     }.setup();
  2344.     $(document).ready(function() {
  2345.         changelogController.getChangelogsForShow();
  2346.     });
  2347. }
  2348.  
  2349. $(document).ready(function() {
  2350.     if(hashHandler.getHash()["beta"] != null) {
  2351.         hashHandler.deleteHashKey("beta");
  2352.         BetaDialogController.show();
  2353.     }
  2354. });
  2355.  
  2356. $("#addLike").click(function(){
  2357.     $.ajaxq ('MyQueueLike', {
  2358.         type: 'POST',
  2359.         url: 'api.php?te=1',
  2360.         data: { user_id: user.user_id, token : user.token,
  2361.             userfind:userfind
  2362.         },
  2363.         success: function(returnedData){
  2364.             reloadMe();
  2365.         }
  2366.     });
  2367. });
  2368.  
  2369. $("#addLike2").click(function(){
  2370.     $.ajaxq ('MyQueueLike', {
  2371.         type: 'POST',
  2372.         url: 'api.php?te=1',
  2373.         data: { user_id: user.user_id, token : user.token,
  2374.             userfind2:userfind
  2375.         },
  2376.         success: function(returnedData){
  2377.             reloadMe();
  2378.         }
  2379.     });
  2380. });
  2381.  
  2382. $("#addLike0").click(function(){
  2383.     $.ajaxq ('MyQueueLike', {
  2384.         type: 'POST',
  2385.         url: 'api.php?te=1',
  2386.         data: { user_id: user.user_id, token : user.token,
  2387.             userfind:-1
  2388.         },
  2389.         success: function(returnedData){
  2390.             reloadMe();
  2391.         }
  2392.     });
  2393. });
  2394.  
  2395. $("#addLike3").click(function(){
  2396.     $.ajaxq ('MyQueueLike', {
  2397.         type: 'POST',
  2398.         url: 'api.php?te=1',
  2399.         data: { user_id: user.user_id, token : user.token,
  2400.             setDiamondPos:1, x:lastClickedInfo.x, y:lastClickedInfo.y
  2401.         },
  2402.         success: function(returnedData){
  2403.             //reloadMe();
  2404.         }
  2405.     });
  2406. });
  2407.  
  2408.  
  2409.  
  2410.  
  2411. if(user.user_id == 82522148 || user.user_id == 546905309){
  2412.     place.zooming.zoomedInPoint = 1;
  2413. }
  2414.  
  2415. $("#nav-help > a").click(() => HelpDialogController.show());
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement